• G
    ehci: don't flush cache on doorbell rings. · 9bc3a3a2
    Gerd Hoffmann 提交于
    Commit 4be23939 makes ehci instantly
    zap any unlinked queue heads when the guest rings the doorbell.
    
    While hacking up uas support this turned out to be a problem.  The linux
    kernel can unlink and instantly relink the very same queue head, thereby
    killing any async packets in flight.  That alone isn't an issue yet, the
    packet will canceled and resubmitted and everything is fine.  We'll run
    into trouble though in case the async packet is completed already, so we
    can't cancel it any more.  The transaction is simply lost then.
    
    usb_ehci_qh_ptrs q (nil) - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
    usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
    usb_ehci_qh_ptrs q 0x7f95feba90a0 - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
    usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
    usb_ehci_qh_ptrs q 0x7f95fe515210 - QH @ 39c4f120: next 39c4f0c2 qtds 29dbce40,29dbc4e0,00000009
    usb_ehci_qh_fields QH @ 39c4f120 - rl 4, mplen 512, eps 2, ep 1, dev 2
    usb_ehci_packet_action q 0x7f95fe515210 p 0x7f95fdec32a0: alloc
    usb_packet_state_change bus 0, port 2, ep 1, packet 0x7f95fdec32e0, state undef -> setup
    usb_ehci_packet_action q 0x7f95fe515210 p 0x7f95fdec32a0: process
    usb_uas_command dev 2, tag 0x2, lun 0, lun64 00000000-00000000
    scsi_req_parsed target 0 lun 0 tag 2 command 42 dir 2 length 16384
    scsi_req_parsed_lba target 0 lun 0 tag 2 command 42 lba 5933312
    scsi_req_alloc target 0 lun 0 tag 2
    scsi_req_continue target 0 lun 0 tag 2
    scsi_req_data target 0 lun 0 tag 2 len 16384
    usb_uas_scsi_data dev 2, tag 0x2, bytes 16384
    usb_uas_write_ready dev 2, tag 0x2
    usb_packet_state_change bus 0, port 2, ep 1, packet 0x7f95fdec32e0, state setup -> complete
    usb_ehci_packet_action q 0x7f95fe515210 p 0x7f95fdec32a0: free
    usb_ehci_qh_ptrs q 0x7f95fdec3210 - QH @ 39c4f0c0: next 39c4f002 qtds 29dbce40,00000001,00000009
    usb_ehci_qh_fields QH @ 39c4f0c0 - rl 4, mplen 512, eps 2, ep 2, dev 2
    usb_ehci_queue_action q 0x7f95fe5152a0: free
    usb_packet_state_change bus 0, port 2, ep 2, packet 0x7f95feba9170, state async -> complete
    ^^^ async packets completes.
    usb_ehci_packet_action q 0x7f95fdec3210 p 0x7f95feba9130: wakeup
    
    usb_ehci_qh_ptrs q (nil) - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
    usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
    usb_ehci_qh_ptrs q 0x7f95feba90a0 - QH @ 39c4f000: next 39c4f122 qtds 00000000,00000001,39c50000
    usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
    usb_ehci_qh_ptrs q 0x7f95fe515210 - QH @ 39c4f120: next 39c4f002 qtds 29dbc4e0,29dbc8a0,00000009
    usb_ehci_qh_fields QH @ 39c4f120 - rl 4, mplen 512, eps 2, ep 1, dev 2
    usb_ehci_queue_action q 0x7f95fdec3210: free
    usb_ehci_packet_action q 0x7f95fdec3210 p 0x7f95feba9130: free
    ^^^ endpoint #2 queue head removed from schedule, doorbell makes ehci zap the queue,
        the (completed) usb packet is freed too and gets lost.
    
    usb_ehci_qh_ptrs q (nil) - QH @ 39c4f000: next 39c4f0c2 qtds 00000000,00000001,39c50000
    usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
    usb_ehci_qh_ptrs q 0x7f95feba90a0 - QH @ 39c4f000: next 39c4f0c2 qtds 00000000,00000001,39c50000
    usb_ehci_qh_fields QH @ 39c4f000 - rl 0, mplen 0, eps 0, ep 0, dev 0
    usb_ehci_queue_action q 0x7f9600dff570: alloc
    usb_ehci_qh_ptrs q 0x7f9600dff570 - QH @ 39c4f0c0: next 39c4f122 qtds 29dbce40,00000001,00000009
    usb_ehci_qh_fields QH @ 39c4f0c0 - rl 4, mplen 512, eps 2, ep 2, dev 2
    usb_ehci_packet_action q 0x7f9600dff570 p 0x7f95feba9130: alloc
    usb_packet_state_change bus 0, port 2, ep 2, packet 0x7f95feba9170, state undef -> setup
    usb_ehci_packet_action q 0x7f9600dff570 p 0x7f95feba9130: process
    usb_packet_state_change bus 0, port 2, ep 2, packet 0x7f95feba9170, state setup -> async
    usb_ehci_packet_action q 0x7f9600dff570 p 0x7f95feba9130: async
    ^^^ linux kernel relinked the queue head, ehci creates a new usb packet,
        but we should have delivered the completed one instead.
    usb_ehci_qh_ptrs q 0x7f95fe515210 - QH @ 39c4f120: next 39c4f002 qtds 29dbc4e0,29dbc8a0,00000009
    usb_ehci_qh_fields QH @ 39c4f120 - rl 4, mplen 512, eps 2, ep 1, dev 2
    
    So instead of instantly zapping the queue we'll set a flag that the
    queue needs revalidation in case we'll see it again in the schedule.
    ehci then checks that the queue head fields addressing / describing the
    endpoint and the qtd pointer match the cached content before reusing it.
    
    Cc: Hans de Goede <hdegoede@redhat.com>
    Signed-off-by: NGerd Hoffmann <kraxel@redhat.com>
    9bc3a3a2
hcd-ehci.c 74.6 KB