1 | Hi, | 1 | Hi, |
---|---|---|---|
2 | 2 | ||
3 | This RFC is wide-ranging for such a simple addition of XHCI TR NOOP | 3 | This series adds XHCI "TR NOOP" support, but adding qtests ran into |
4 | command, because adding qtests for it caught up some PCI/MSIX issues. | 4 | issues with PCI and MSIX, and fixing those irritated what looks like |
5 | a bug in the e1000e/igb tests. | ||
5 | 6 | ||
6 | Firstly, the XHCI host shares a BAR between device registers and MSIX | 7 | Firstly, the XHCI NEC PCI host has a shared BAR for device registers |
7 | space, which is not handled by qtest/pci. Keeping track of BAR mappings | 8 | and MSIX space, which is not handled by qtest/pci. Keeping track of BAR |
8 | in qtest and allowing MSIX to use an existing mapping seems to work. | 9 | mappings in qtest and allowing MSIX to use an existing mapping seems to |
10 | work. | ||
9 | 11 | ||
10 | For XHCI qtest, I added a MSIX check to ensure interrupts are working | 12 | For the XHCI qtest, I added a MSIX check to ensure interrupts are working |
11 | correctly. As part of that I need to dequeue masked interrupts which | 13 | correctly, similarly to e1000e it polls the PBA bit with the interrupt |
12 | seems to require PBA writes to clear them, but I could be way off | 14 | masked. Doing this never actually clears the pending msix irq, because |
13 | base here. Adding that does cause e1000e qtest to break, because it | 15 | that is not implemented in the hw/pci code. So a test that waits for an |
14 | doesn't like clear pending via PBA. | 16 | interrupt to be triggered multiple times will fail. |
15 | 17 | ||
16 | The XHCI model change gets AIX's XHCI driver working, so that's another | 18 | Adding the PBA write operations to clear/trigger pending interrupts |
17 | data point beyond the simple qtest for it added here. Unfortunately it | 19 | breaks e1000e/igb tests that wait for multiple triggers, because they |
18 | is not so easy to independently test. | 20 | are actually buggy and only triggering the irq once, but the missing |
21 | MSIX write support was saving them because it made it look like the | ||
22 | irq had triggered. | ||
19 | 23 | ||
20 | Any guidance or input would be welcome. | 24 | My XHCI qtest caught that issue because it has some code which |
25 | asserts that the interrupt is *not* pending. | ||
26 | |||
27 | Since RFC I fixed up some checkpatch issues as Fabiano pointed out, | ||
28 | and also dug into the e1000e/igb test failure a bit more and hopefully | ||
29 | fixed it properly. | ||
21 | 30 | ||
22 | Thanks, | 31 | Thanks, |
23 | Nick | 32 | Nick |
24 | 33 | ||
25 | Nicholas Piggin (5): | 34 | Nicholas Piggin (8): |
26 | qtest/pci: Enforce balanced iomap/unmap | 35 | qtest/pci: Enforce balanced iomap/unmap |
27 | qtest/libqos/pci: Fix msix_enable sharing bar0 | 36 | qtest/libqos/pci: Fix qpci_msix_enable sharing bar0 |
28 | pci/msix: Implement PBA writes | 37 | pci/msix: Implement PBA writes |
38 | tests/qtest/e1000e|igb: Fix e1000e and igb tests to re-trigger | ||
39 | interrupts | ||
40 | hw/usb/xhci: Move HCD constants to a header and add register constants | ||
29 | qtest/xhci: Add controller and device setup and ring tests | 41 | qtest/xhci: Add controller and device setup and ring tests |
30 | hw/usb: Support XHCI TR NOOP commands | 42 | hw/usb/xhci: Support TR NOOP commands |
43 | qtest/xhci: add a test for TR NOOP commands | ||
31 | 44 | ||
45 | hw/usb/hcd-xhci.h | 197 ++++++++++++ | ||
32 | tests/qtest/libqos/ahci.h | 1 + | 46 | tests/qtest/libqos/ahci.h | 1 + |
33 | tests/qtest/libqos/pci.h | 4 + | 47 | tests/qtest/libqos/pci.h | 4 + |
34 | tests/qtest/libqos/virtio-pci.h | 1 + | 48 | tests/qtest/libqos/virtio-pci.h | 1 + |
35 | tests/qtest/usb-hcd-xhci-test.h | 232 ++++++++++++++ | ||
36 | hw/pci/msix.c | 16 + | 49 | hw/pci/msix.c | 16 + |
37 | hw/usb/hcd-xhci.c | 28 +- | 50 | hw/usb/hcd-xhci.c | 318 ++++++------------- |
38 | tests/qtest/ahci-test.c | 2 + | 51 | tests/qtest/ahci-test.c | 2 + |
52 | tests/qtest/e1000e-test.c | 8 +- | ||
53 | tests/qtest/igb-test.c | 8 +- | ||
39 | tests/qtest/libqos/ahci.c | 6 + | 54 | tests/qtest/libqos/ahci.c | 6 + |
40 | tests/qtest/libqos/pci.c | 75 ++++- | 55 | tests/qtest/libqos/e1000e.c | 2 +- |
56 | tests/qtest/libqos/pci.c | 92 +++++- | ||
41 | tests/qtest/libqos/virtio-pci.c | 6 +- | 57 | tests/qtest/libqos/virtio-pci.c | 6 +- |
42 | tests/qtest/usb-hcd-xhci-test.c | 540 +++++++++++++++++++++++++++++++- | 58 | tests/qtest/usb-hcd-xhci-test.c | 535 +++++++++++++++++++++++++++++++- |
43 | 11 files changed, 893 insertions(+), 18 deletions(-) | 59 | 14 files changed, 943 insertions(+), 253 deletions(-) |
44 | create mode 100644 tests/qtest/usb-hcd-xhci-test.h | ||
45 | 60 | ||
46 | -- | 61 | -- |
47 | 2.45.2 | 62 | 2.45.2 | diff view generated by jsdifflib |
1 | Add assertions to ensure a BAR is not mapped twice, and only | 1 | Add assertions to ensure a BAR is not mapped twice, and only |
---|---|---|---|
2 | previously mapped BARs are unmapped. This can help catch some | 2 | previously mapped BARs are unmapped. This can help catch some |
3 | bugs. | 3 | bugs. |
4 | 4 | ||
5 | Cc: Michael S. Tsirkin <mst@redhat.com> | ||
6 | Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> | ||
7 | Reviewed-by: Fabiano Rosas <farosas@suse.de> | ||
5 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> | 8 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> |
6 | --- | 9 | --- |
7 | tests/qtest/libqos/ahci.h | 1 + | 10 | tests/qtest/libqos/ahci.h | 1 + |
8 | tests/qtest/libqos/pci.h | 2 ++ | 11 | tests/qtest/libqos/pci.h | 2 ++ |
9 | tests/qtest/libqos/virtio-pci.h | 1 + | 12 | tests/qtest/libqos/virtio-pci.h | 1 + |
... | ... | diff view generated by jsdifflib |
1 | Devices where the MSI-X addresses are shared with other MMIO on BAR0 | 1 | Devices where the MSI-X addresses are shared with other MMIO on BAR0 |
---|---|---|---|
2 | can not use msi_enable because it unmaps and remaps BAR0, which | 2 | can not use msi_enable because it unmaps and remaps BAR0, which |
3 | interferes with device MMIO mappings. xhci-nec is one such device we | 3 | interferes with device MMIO mappings. xhci-nec is one such device we |
4 | would like to test msix with. | 4 | would like to test msix with. |
5 | 5 | ||
6 | Keep track of each the BAR iomaps for each device and add code in msix | 6 | Use the BAR iomap tracking structure introduced in the previous change |
7 | to use existing iomap if the msix bars are already mapped. | 7 | to have qpci_misx_enable() use existing iomaps if msix bars are |
8 | already mapped. | ||
8 | 9 | ||
10 | Cc: Michael S. Tsirkin <mst@redhat.com> | ||
11 | Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> | ||
12 | Reviewed-by: Fabiano Rosas <farosas@suse.de> | ||
9 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> | 13 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> |
10 | --- | 14 | --- |
11 | tests/qtest/libqos/pci.h | 1 + | 15 | tests/qtest/libqos/pci.h | 1 + |
12 | tests/qtest/libqos/pci.c | 22 ++++++++++++++++------ | 16 | tests/qtest/libqos/pci.c | 40 ++++++++++++++++++++++++++++++++++------ |
13 | 2 files changed, 17 insertions(+), 6 deletions(-) | 17 | 2 files changed, 35 insertions(+), 6 deletions(-) |
14 | 18 | ||
15 | diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h | 19 | diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h |
16 | index XXXXXXX..XXXXXXX 100644 | 20 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/tests/qtest/libqos/pci.h | 21 | --- a/tests/qtest/libqos/pci.h |
18 | +++ b/tests/qtest/libqos/pci.h | 22 | +++ b/tests/qtest/libqos/pci.h |
... | ... | ||
52 | + dev->msix_pba_bar_iomap = true; | 56 | + dev->msix_pba_bar_iomap = true; |
53 | + dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL); | 57 | + dev->msix_pba_bar = qpci_iomap(dev, bir_pba, NULL); |
54 | } | 58 | } |
55 | dev->msix_pba_off = table & ~PCI_MSIX_FLAGS_BIRMASK; | 59 | dev->msix_pba_off = table & ~PCI_MSIX_FLAGS_BIRMASK; |
56 | 60 | ||
61 | @@ -XXX,XX +XXX,XX @@ void qpci_msix_disable(QPCIDevice *dev) | ||
62 | { | ||
63 | uint8_t addr; | ||
64 | uint16_t val; | ||
65 | + uint32_t table; | ||
66 | |||
67 | g_assert(dev->msix_enabled); | ||
68 | addr = qpci_find_capability(dev, PCI_CAP_ID_MSIX, 0); | ||
57 | @@ -XXX,XX +XXX,XX @@ void qpci_msix_disable(QPCIDevice *dev) | 69 | @@ -XXX,XX +XXX,XX @@ void qpci_msix_disable(QPCIDevice *dev) |
58 | qpci_config_writew(dev, addr + PCI_MSIX_FLAGS, | 70 | qpci_config_writew(dev, addr + PCI_MSIX_FLAGS, |
59 | val & ~PCI_MSIX_FLAGS_ENABLE); | 71 | val & ~PCI_MSIX_FLAGS_ENABLE); |
60 | 72 | ||
61 | - if (dev->msix_pba_bar.addr != dev->msix_table_bar.addr) { | 73 | - if (dev->msix_pba_bar.addr != dev->msix_table_bar.addr) { |
62 | + if (dev->msix_pba_bar_iomap) { | 74 | + if (dev->msix_pba_bar_iomap) { |
63 | + dev->msix_pba_bar_iomap = false; | 75 | + dev->msix_pba_bar_iomap = false; |
64 | qpci_iounmap(dev, dev->msix_pba_bar); | 76 | qpci_iounmap(dev, dev->msix_pba_bar); |
65 | } | 77 | + } else { |
66 | - qpci_iounmap(dev, dev->msix_table_bar); | 78 | + /* |
79 | + * If we had reused an existing iomap, ensure it is still mapped | ||
80 | + * otherwise it would be a bug if it were unmapped before msix is | ||
81 | + * disabled. A refcounting iomap implementation could avoid this | ||
82 | + * issue entirely, but let's wait until that's needed. | ||
83 | + */ | ||
84 | + uint8_t bir_pba; | ||
85 | + table = qpci_config_readl(dev, addr + PCI_MSIX_PBA); | ||
86 | + bir_pba = table & PCI_MSIX_FLAGS_BIRMASK; | ||
87 | + g_assert(dev->bars_mapped[bir_pba]); | ||
88 | + } | ||
89 | + | ||
67 | + if (dev->msix_table_bar_iomap) { | 90 | + if (dev->msix_table_bar_iomap) { |
68 | + dev->msix_table_bar_iomap = false; | 91 | + dev->msix_table_bar_iomap = false; |
69 | + qpci_iounmap(dev, dev->msix_table_bar); | 92 | + qpci_iounmap(dev, dev->msix_table_bar); |
70 | + } | 93 | + } else { |
94 | + uint8_t bir_table; | ||
95 | + table = qpci_config_readl(dev, addr + PCI_MSIX_TABLE); | ||
96 | + bir_table = table & PCI_MSIX_FLAGS_BIRMASK; | ||
97 | + g_assert(dev->bars_mapped[bir_table]); | ||
98 | } | ||
99 | - qpci_iounmap(dev, dev->msix_table_bar); | ||
71 | 100 | ||
72 | dev->msix_enabled = 0; | 101 | dev->msix_enabled = 0; |
73 | dev->msix_table_off = 0; | 102 | dev->msix_table_off = 0; |
74 | -- | 103 | -- |
75 | 2.45.2 | 104 | 2.45.2 | diff view generated by jsdifflib |
1 | Implement PBA write 1 to trigger and 0 to clear. This is used by | 1 | Implement MMIO PBA writes, 1 to trigger and 0 to clear. |
---|---|---|---|
2 | qtests which mask the MSI irq and so the bits remain pending and | ||
3 | expect to be cleared with stores. | ||
4 | 2 | ||
5 | Some devices like e1000e seem to have MSIX PBA pending tied to | 3 | This functionality is used by some qtests, which keep the msix irq |
6 | some device state level, as such they call msix_clr_pending() | 4 | masked and test irq pending via the PBA bits, for simplicity. Some |
7 | directly, and clearing pending via a store to PBA causes this | 5 | tests expect to be able to clear the irq with a store, so a side-effect |
8 | to go out of synch. So the qpci_msix_pending() function is | 6 | of this is that qpci_msix_pending() would actually clear the pending |
9 | changed to avoid clearing, and a new test-and-clear function is | 7 | bit where it previously did not. This actually causes some [possibly |
10 | added for tests that would like to clear. | 8 | buggy] tests to fail. So to avoid breakage until tests are re-examined, |
9 | prior behavior of qpci_msix_pending() is kept by changing it to avoid | ||
10 | clearing PBA. | ||
11 | 11 | ||
12 | A new function qpci_msix_test_clear_pending() is added for tests that | ||
13 | do want the PBA clearing, and it will be used by XHCI and e1000e/igb | ||
14 | tests in subsequent changes. | ||
15 | |||
16 | Cc: Michael S. Tsirkin <mst@redhat.com> | ||
17 | Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> | ||
18 | Cc: Dmitry Fleytman <dmitry.fleytman@gmail.com> | ||
19 | Cc: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
20 | Cc: Sriram Yagnaraman <sriram.yagnaraman@ericsson.com> | ||
12 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> | 21 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> |
13 | --- | 22 | --- |
14 | tests/qtest/libqos/pci.h | 1 + | 23 | tests/qtest/libqos/pci.h | 1 + |
15 | hw/pci/msix.c | 16 ++++++++++++++++ | 24 | hw/pci/msix.c | 16 ++++++++++++++++ |
16 | tests/qtest/libqos/pci.c | 21 ++++++++++++++++++--- | 25 | tests/qtest/libqos/pci.c | 20 +++++++++++++++++--- |
17 | 3 files changed, 35 insertions(+), 3 deletions(-) | 26 | 3 files changed, 34 insertions(+), 3 deletions(-) |
18 | 27 | ||
19 | diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h | 28 | diff --git a/tests/qtest/libqos/pci.h b/tests/qtest/libqos/pci.h |
20 | index XXXXXXX..XXXXXXX 100644 | 29 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/tests/qtest/libqos/pci.h | 30 | --- a/tests/qtest/libqos/pci.h |
22 | +++ b/tests/qtest/libqos/pci.h | 31 | +++ b/tests/qtest/libqos/pci.h |
... | ... | ||
64 | g_assert(dev->msix_enabled); | 73 | g_assert(dev->msix_enabled); |
65 | pba_entry = qpci_io_readl(dev, dev->msix_pba_bar, dev->msix_pba_off + off); | 74 | pba_entry = qpci_io_readl(dev, dev->msix_pba_bar, dev->msix_pba_off + off); |
66 | - qpci_io_writel(dev, dev->msix_pba_bar, dev->msix_pba_off + off, | 75 | - qpci_io_writel(dev, dev->msix_pba_bar, dev->msix_pba_off + off, |
67 | - pba_entry & ~(1 << bit_n)); | 76 | - pba_entry & ~(1 << bit_n)); |
68 | - return (pba_entry & (1 << bit_n)) != 0; | 77 | - return (pba_entry & (1 << bit_n)) != 0; |
69 | + return (pba_entry & (1 << bit_n)); | 78 | + return pba_entry & (1 << bit_n); |
70 | } | 79 | +} |
71 | 80 | + | |
72 | +bool qpci_msix_test_clear_pending(QPCIDevice *dev, uint16_t entry) | 81 | +bool qpci_msix_test_clear_pending(QPCIDevice *dev, uint16_t entry) |
73 | +{ | 82 | +{ |
74 | + uint32_t pba_entry; | 83 | + uint32_t pba_entry; |
75 | + uint8_t bit_n = entry % 32; | 84 | + uint8_t bit_n = entry % 32; |
76 | + uint64_t off = (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4; | 85 | + uint64_t off = (entry / 32) * PCI_MSIX_ENTRY_SIZE / 4; |
... | ... | ||
81 | + qpci_io_writel(dev, dev->msix_pba_bar, dev->msix_pba_off + off, | 90 | + qpci_io_writel(dev, dev->msix_pba_bar, dev->msix_pba_off + off, |
82 | + pba_entry & ~(1 << bit_n)); | 91 | + pba_entry & ~(1 << bit_n)); |
83 | + return true; | 92 | + return true; |
84 | + } | 93 | + } |
85 | + return false; | 94 | + return false; |
86 | +} | 95 | } |
87 | + | 96 | |
88 | + | ||
89 | bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry) | 97 | bool qpci_msix_masked(QPCIDevice *dev, uint16_t entry) |
90 | { | ||
91 | uint8_t addr; | ||
92 | -- | 98 | -- |
93 | 2.45.2 | 99 | 2.45.2 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | The e1000e and igb tests don't clear the msix pending bit after waiting | ||
2 | for it sit is masked so the irq doesn't get delivered. Failing to clear | ||
3 | the pending interrupt means all subsequent waits for interrupt after the | ||
4 | first do not actually wait for an interrupt genreated by the device. | ||
1 | 5 | ||
6 | Explicitly clearing the msix pending bit results in the | ||
7 | multiple-transfers test hanging waiting for the second interrupt. This | ||
8 | happens because the e1000e and igb tests do not clear (or set | ||
9 | auto-clear) on queue interrupts, so the cause remains ste in ICR/EICR, | ||
10 | which inhibits triggering of a new interrupt. | ||
11 | |||
12 | Fix both these problems. Clear the msix pending bit explicitly after | ||
13 | waiting for it; and clear the ICR/EICR cause bits after seeing and | ||
14 | interrupt (also verify we saw the correct cause bit). | ||
15 | |||
16 | Cc: Michael S. Tsirkin <mst@redhat.com> | ||
17 | Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> | ||
18 | Cc: Dmitry Fleytman <dmitry.fleytman@gmail.com> | ||
19 | Cc: Akihiko Odaki <akihiko.odaki@daynix.com> | ||
20 | Cc: Sriram Yagnaraman <sriram.yagnaraman@ericsson.com> | ||
21 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> | ||
22 | --- | ||
23 | tests/qtest/e1000e-test.c | 8 ++++++-- | ||
24 | tests/qtest/igb-test.c | 8 ++++++-- | ||
25 | tests/qtest/libqos/e1000e.c | 2 +- | ||
26 | 3 files changed, 13 insertions(+), 5 deletions(-) | ||
27 | |||
28 | diff --git a/tests/qtest/e1000e-test.c b/tests/qtest/e1000e-test.c | ||
29 | index XXXXXXX..XXXXXXX 100644 | ||
30 | --- a/tests/qtest/e1000e-test.c | ||
31 | +++ b/tests/qtest/e1000e-test.c | ||
32 | @@ -XXX,XX +XXX,XX @@ static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *a | ||
33 | /* Put descriptor to the ring */ | ||
34 | e1000e_tx_ring_push(d, &descr); | ||
35 | |||
36 | - /* Wait for TX WB interrupt */ | ||
37 | + /* Wait for TX WB interrupt (this clears the MSIX PBA) */ | ||
38 | e1000e_wait_isr(d, E1000E_TX0_MSG_ID); | ||
39 | + /* Read ICR which clears it ready for next interrupt, assert TXQ0 cause */ | ||
40 | + g_assert(e1000e_macreg_read(d, E1000_ICR) & E1000_ICR_TXQ0); | ||
41 | |||
42 | /* Check DD bit */ | ||
43 | g_assert_cmphex(le32_to_cpu(descr.upper.data) & E1000_TXD_STAT_DD, ==, | ||
44 | @@ -XXX,XX +XXX,XX @@ static void e1000e_receive_verify(QE1000E *d, int *test_sockets, QGuestAllocator | ||
45 | /* Put descriptor to the ring */ | ||
46 | e1000e_rx_ring_push(d, &descr); | ||
47 | |||
48 | - /* Wait for TX WB interrupt */ | ||
49 | + /* Wait for TX WB interrupt (this clears the MSIX PBA) */ | ||
50 | e1000e_wait_isr(d, E1000E_RX0_MSG_ID); | ||
51 | + /* Read ICR which clears it ready for next interrupt, assert RXQ0 cause */ | ||
52 | + g_assert(e1000e_macreg_read(d, E1000_ICR) & E1000_ICR_RXQ0); | ||
53 | |||
54 | /* Check DD bit */ | ||
55 | g_assert_cmphex(le32_to_cpu(descr.wb.upper.status_error) & | ||
56 | diff --git a/tests/qtest/igb-test.c b/tests/qtest/igb-test.c | ||
57 | index XXXXXXX..XXXXXXX 100644 | ||
58 | --- a/tests/qtest/igb-test.c | ||
59 | +++ b/tests/qtest/igb-test.c | ||
60 | @@ -XXX,XX +XXX,XX @@ static void igb_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *allo | ||
61 | /* Put descriptor to the ring */ | ||
62 | e1000e_tx_ring_push(d, &descr); | ||
63 | |||
64 | - /* Wait for TX WB interrupt */ | ||
65 | + /* Wait for TX WB interrupt (this clears the MSIX PBA) */ | ||
66 | e1000e_wait_isr(d, E1000E_TX0_MSG_ID); | ||
67 | + /* Read EICR which clears it ready for next interrupt, assert TXQ0 cause */ | ||
68 | + g_assert(e1000e_macreg_read(d, E1000_EICR) & (1 << E1000E_TX0_MSG_ID)); | ||
69 | |||
70 | /* Check DD bit */ | ||
71 | g_assert_cmphex(le32_to_cpu(descr.wb.status) & E1000_TXD_STAT_DD, ==, | ||
72 | @@ -XXX,XX +XXX,XX @@ static void igb_receive_verify(QE1000E *d, int *test_sockets, QGuestAllocator *a | ||
73 | /* Put descriptor to the ring */ | ||
74 | e1000e_rx_ring_push(d, &descr); | ||
75 | |||
76 | - /* Wait for TX WB interrupt */ | ||
77 | + /* Wait for TX WB interrupt (this clears the MSIX PBA) */ | ||
78 | e1000e_wait_isr(d, E1000E_RX0_MSG_ID); | ||
79 | + /* Read EICR which clears it ready for next interrupt, assert RXQ0 cause */ | ||
80 | + g_assert(e1000e_macreg_read(d, E1000_EICR) & (1 << E1000E_RX0_MSG_ID)); | ||
81 | |||
82 | /* Check DD bit */ | ||
83 | g_assert_cmphex(le32_to_cpu(descr.wb.upper.status_error) & | ||
84 | diff --git a/tests/qtest/libqos/e1000e.c b/tests/qtest/libqos/e1000e.c | ||
85 | index XXXXXXX..XXXXXXX 100644 | ||
86 | --- a/tests/qtest/libqos/e1000e.c | ||
87 | +++ b/tests/qtest/libqos/e1000e.c | ||
88 | @@ -XXX,XX +XXX,XX @@ void e1000e_wait_isr(QE1000E *d, uint16_t msg_id) | ||
89 | guint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; | ||
90 | |||
91 | do { | ||
92 | - if (qpci_msix_pending(&d_pci->pci_dev, msg_id)) { | ||
93 | + if (qpci_msix_test_clear_pending(&d_pci->pci_dev, msg_id)) { | ||
94 | return; | ||
95 | } | ||
96 | qtest_clock_step(d_pci->pci_dev.bus->qts, 10000); | ||
97 | -- | ||
98 | 2.45.2 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | Prepare to use some of these constants in xhci qtest code. | ||
1 | 2 | ||
3 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> | ||
4 | --- | ||
5 | hw/usb/hcd-xhci.h | 190 +++++++++++++++++++++++++++++++ | ||
6 | hw/usb/hcd-xhci.c | 283 ++++++++++------------------------------------ | ||
7 | 2 files changed, 250 insertions(+), 223 deletions(-) | ||
8 | |||
9 | diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h | ||
10 | index XXXXXXX..XXXXXXX 100644 | ||
11 | --- a/hw/usb/hcd-xhci.h | ||
12 | +++ b/hw/usb/hcd-xhci.h | ||
13 | @@ -XXX,XX +XXX,XX @@ typedef enum TRBCCode { | ||
14 | CC_SPLIT_TRANSACTION_ERROR | ||
15 | } TRBCCode; | ||
16 | |||
17 | +/* Register definitions */ | ||
18 | +#define XHCI_HCCAP_CAPLENGTH 0x00 | ||
19 | +#define XHCI_HCCAP_HCIVERSION 0x02 | ||
20 | +#define XHCI_HCCAP_HCSPARAMS1 0x04 | ||
21 | +#define XHCI_HCCAP_HCSPARAMS2 0x08 | ||
22 | +#define XHCI_HCCAP_HCSPARAMS3 0x0C | ||
23 | +#define XHCI_HCCAP_HCCPARAMS1 0x10 | ||
24 | +#define XHCI_HCCAP_DBOFF 0x14 | ||
25 | +#define XHCI_HCCAP_RTSOFF 0x18 | ||
26 | +#define XHCI_HCCAP_HCCPARAMS2 0x1C | ||
27 | +#define XHCI_HCCAP_EXTCAP_START 0x20 /* SW-defined */ | ||
28 | + | ||
29 | +#define XHCI_PORT_PORTSC 0x00 | ||
30 | +#define PORTSC_CCS (1 << 0) | ||
31 | +#define PORTSC_PED (1 << 1) | ||
32 | +#define PORTSC_OCA (1 << 3) | ||
33 | +#define PORTSC_PR (1 << 4) | ||
34 | +#define PORTSC_PLS_SHIFT 5 | ||
35 | +#define PORTSC_PLS_MASK 0xf | ||
36 | +#define PORTSC_PP (1 << 9) | ||
37 | +#define PORTSC_SPEED_SHIFT 10 | ||
38 | +#define PORTSC_SPEED_MASK 0xf | ||
39 | +#define PORTSC_SPEED_FULL (1 << 10) | ||
40 | +#define PORTSC_SPEED_LOW (2 << 10) | ||
41 | +#define PORTSC_SPEED_HIGH (3 << 10) | ||
42 | +#define PORTSC_SPEED_SUPER (4 << 10) | ||
43 | +#define PORTSC_PIC_SHIFT 14 | ||
44 | +#define PORTSC_PIC_MASK 0x3 | ||
45 | +#define PORTSC_LWS (1 << 16) | ||
46 | +#define PORTSC_CSC (1 << 17) | ||
47 | +#define PORTSC_PEC (1 << 18) | ||
48 | +#define PORTSC_WRC (1 << 19) | ||
49 | +#define PORTSC_OCC (1 << 20) | ||
50 | +#define PORTSC_PRC (1 << 21) | ||
51 | +#define PORTSC_PLC (1 << 22) | ||
52 | +#define PORTSC_CEC (1 << 23) | ||
53 | +#define PORTSC_CAS (1 << 24) | ||
54 | +#define PORTSC_WCE (1 << 25) | ||
55 | +#define PORTSC_WDE (1 << 26) | ||
56 | +#define PORTSC_WOE (1 << 27) | ||
57 | +#define PORTSC_DR (1 << 30) | ||
58 | +#define PORTSC_WPR (1 << 31) | ||
59 | +#define XHCI_PORT_PORTPMSC 0x04 | ||
60 | +#define XHCI_PORT_PORTLI 0x08 | ||
61 | +#define XHCI_PORT_PORTHLPMC 0x0C | ||
62 | + | ||
63 | +#define XHCI_OPER_USBCMD 0x00 | ||
64 | +#define USBCMD_RS (1 << 0) | ||
65 | +#define USBCMD_HCRST (1 << 1) | ||
66 | +#define USBCMD_INTE (1 << 2) | ||
67 | +#define USBCMD_HSEE (1 << 3) | ||
68 | +#define USBCMD_LHCRST (1 << 7) | ||
69 | +#define USBCMD_CSS (1 << 8) | ||
70 | +#define USBCMD_CRS (1 << 9) | ||
71 | +#define USBCMD_EWE (1 << 10) | ||
72 | +#define USBCMD_EU3S (1 << 11) | ||
73 | +#define XHCI_OPER_USBSTS 0x04 | ||
74 | +#define USBSTS_HCH (1 << 0) | ||
75 | +#define USBSTS_HSE (1 << 2) | ||
76 | +#define USBSTS_EINT (1 << 3) | ||
77 | +#define USBSTS_PCD (1 << 4) | ||
78 | +#define USBSTS_SSS (1 << 8) | ||
79 | +#define USBSTS_RSS (1 << 9) | ||
80 | +#define USBSTS_SRE (1 << 10) | ||
81 | +#define USBSTS_CNR (1 << 11) | ||
82 | +#define USBSTS_HCE (1 << 12) | ||
83 | +#define XHCI_OPER_PAGESIZE 0x08 | ||
84 | +#define XHCI_OPER_DNCTRL 0x14 | ||
85 | +#define XHCI_OPER_CRCR_LO 0x18 | ||
86 | +#define CRCR_RCS (1 << 0) | ||
87 | +#define CRCR_CS (1 << 1) | ||
88 | +#define CRCR_CA (1 << 2) | ||
89 | +#define CRCR_CRR (1 << 3) | ||
90 | +#define XHCI_OPER_CRCR_HI 0x1C | ||
91 | +#define XHCI_OPER_DCBAAP_LO 0x30 | ||
92 | +#define XHCI_OPER_DCBAAP_HI 0x34 | ||
93 | +#define XHCI_OPER_CONFIG 0x38 | ||
94 | + | ||
95 | +#define XHCI_OPER_MFINDEX 0x00 | ||
96 | +#define XHCI_OPER_IR0 0x20 | ||
97 | +#define XHCI_OPER_IR_SZ 0x20 | ||
98 | + | ||
99 | +#define XHCI_INTR_IMAN 0x00 | ||
100 | +#define IMAN_IP (1 << 0) | ||
101 | +#define IMAN_IE (1 << 1) | ||
102 | +#define XHCI_INTR_IMOD 0x04 | ||
103 | +#define XHCI_INTR_ERSTSZ 0x08 | ||
104 | +#define XHCI_INTR_ERSTBA_LO 0x10 | ||
105 | +#define XHCI_INTR_ERSTBA_HI 0x14 | ||
106 | +#define XHCI_INTR_ERDP_LO 0x18 | ||
107 | +#define ERDP_EHB (1 << 3) | ||
108 | +#define XHCI_INTR_ERDP_HI 0x1C | ||
109 | + | ||
110 | +#define TRB_SIZE 16 | ||
111 | +typedef struct XHCITRB { | ||
112 | + uint64_t parameter; | ||
113 | + uint32_t status; | ||
114 | + uint32_t control; | ||
115 | + dma_addr_t addr; | ||
116 | + bool ccs; | ||
117 | +} XHCITRB; | ||
118 | + | ||
119 | +enum { | ||
120 | + PLS_U0 = 0, | ||
121 | + PLS_U1 = 1, | ||
122 | + PLS_U2 = 2, | ||
123 | + PLS_U3 = 3, | ||
124 | + PLS_DISABLED = 4, | ||
125 | + PLS_RX_DETECT = 5, | ||
126 | + PLS_INACTIVE = 6, | ||
127 | + PLS_POLLING = 7, | ||
128 | + PLS_RECOVERY = 8, | ||
129 | + PLS_HOT_RESET = 9, | ||
130 | + PLS_COMPILANCE_MODE = 10, | ||
131 | + PLS_TEST_MODE = 11, | ||
132 | + PLS_RESUME = 15, | ||
133 | +}; | ||
134 | + | ||
135 | +#define CR_LINK TR_LINK | ||
136 | + | ||
137 | +#define TRB_C (1 << 0) | ||
138 | +#define TRB_TYPE_SHIFT 10 | ||
139 | +#define TRB_TYPE_MASK 0x3f | ||
140 | +#define TRB_TYPE(t) (((t).control >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK) | ||
141 | + | ||
142 | +#define TRB_EV_ED (1 << 2) | ||
143 | + | ||
144 | +#define TRB_TR_ENT (1 << 1) | ||
145 | +#define TRB_TR_ISP (1 << 2) | ||
146 | +#define TRB_TR_NS (1 << 3) | ||
147 | +#define TRB_TR_CH (1 << 4) | ||
148 | +#define TRB_TR_IOC (1 << 5) | ||
149 | +#define TRB_TR_IDT (1 << 6) | ||
150 | +#define TRB_TR_TBC_SHIFT 7 | ||
151 | +#define TRB_TR_TBC_MASK 0x3 | ||
152 | +#define TRB_TR_BEI (1 << 9) | ||
153 | +#define TRB_TR_TLBPC_SHIFT 16 | ||
154 | +#define TRB_TR_TLBPC_MASK 0xf | ||
155 | +#define TRB_TR_FRAMEID_SHIFT 20 | ||
156 | +#define TRB_TR_FRAMEID_MASK 0x7ff | ||
157 | +#define TRB_TR_SIA (1 << 31) | ||
158 | + | ||
159 | +#define TRB_TR_DIR (1 << 16) | ||
160 | + | ||
161 | +#define TRB_CR_SLOTID_SHIFT 24 | ||
162 | +#define TRB_CR_SLOTID_MASK 0xff | ||
163 | +#define TRB_CR_EPID_SHIFT 16 | ||
164 | +#define TRB_CR_EPID_MASK 0x1f | ||
165 | + | ||
166 | +#define TRB_CR_BSR (1 << 9) | ||
167 | +#define TRB_CR_DC (1 << 9) | ||
168 | + | ||
169 | +#define TRB_LK_TC (1 << 1) | ||
170 | + | ||
171 | +#define TRB_INTR_SHIFT 22 | ||
172 | +#define TRB_INTR_MASK 0x3ff | ||
173 | +#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK) | ||
174 | + | ||
175 | +#define EP_TYPE_MASK 0x7 | ||
176 | +#define EP_TYPE_SHIFT 3 | ||
177 | + | ||
178 | +#define EP_STATE_MASK 0x7 | ||
179 | +#define EP_DISABLED (0 << 0) | ||
180 | +#define EP_RUNNING (1 << 0) | ||
181 | +#define EP_HALTED (2 << 0) | ||
182 | +#define EP_STOPPED (3 << 0) | ||
183 | +#define EP_ERROR (4 << 0) | ||
184 | + | ||
185 | +#define SLOT_STATE_MASK 0x1f | ||
186 | +#define SLOT_STATE_SHIFT 27 | ||
187 | +#define SLOT_STATE(s) (((s) >> SLOT_STATE_SHIFT) & SLOT_STATE_MASK) | ||
188 | +#define SLOT_ENABLED 0 | ||
189 | +#define SLOT_DEFAULT 1 | ||
190 | +#define SLOT_ADDRESSED 2 | ||
191 | +#define SLOT_CONFIGURED 3 | ||
192 | + | ||
193 | +#define SLOT_CONTEXT_ENTRIES_MASK 0x1f | ||
194 | +#define SLOT_CONTEXT_ENTRIES_SHIFT 27 | ||
195 | + | ||
196 | +typedef enum EPType { | ||
197 | + ET_INVALID = 0, | ||
198 | + ET_ISO_OUT, | ||
199 | + ET_BULK_OUT, | ||
200 | + ET_INTR_OUT, | ||
201 | + ET_CONTROL, | ||
202 | + ET_ISO_IN, | ||
203 | + ET_BULK_IN, | ||
204 | + ET_INTR_IN, | ||
205 | +} EPType; | ||
206 | + | ||
207 | typedef struct XHCIRing { | ||
208 | dma_addr_t dequeue; | ||
209 | bool ccs; | ||
210 | diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c | ||
211 | index XXXXXXX..XXXXXXX 100644 | ||
212 | --- a/hw/usb/hcd-xhci.c | ||
213 | +++ b/hw/usb/hcd-xhci.c | ||
214 | @@ -XXX,XX +XXX,XX @@ | ||
215 | # error Increase XHCI_LEN_REGS | ||
216 | #endif | ||
217 | |||
218 | -/* bit definitions */ | ||
219 | -#define USBCMD_RS (1<<0) | ||
220 | -#define USBCMD_HCRST (1<<1) | ||
221 | -#define USBCMD_INTE (1<<2) | ||
222 | -#define USBCMD_HSEE (1<<3) | ||
223 | -#define USBCMD_LHCRST (1<<7) | ||
224 | -#define USBCMD_CSS (1<<8) | ||
225 | -#define USBCMD_CRS (1<<9) | ||
226 | -#define USBCMD_EWE (1<<10) | ||
227 | -#define USBCMD_EU3S (1<<11) | ||
228 | - | ||
229 | -#define USBSTS_HCH (1<<0) | ||
230 | -#define USBSTS_HSE (1<<2) | ||
231 | -#define USBSTS_EINT (1<<3) | ||
232 | -#define USBSTS_PCD (1<<4) | ||
233 | -#define USBSTS_SSS (1<<8) | ||
234 | -#define USBSTS_RSS (1<<9) | ||
235 | -#define USBSTS_SRE (1<<10) | ||
236 | -#define USBSTS_CNR (1<<11) | ||
237 | -#define USBSTS_HCE (1<<12) | ||
238 | - | ||
239 | - | ||
240 | -#define PORTSC_CCS (1<<0) | ||
241 | -#define PORTSC_PED (1<<1) | ||
242 | -#define PORTSC_OCA (1<<3) | ||
243 | -#define PORTSC_PR (1<<4) | ||
244 | -#define PORTSC_PLS_SHIFT 5 | ||
245 | -#define PORTSC_PLS_MASK 0xf | ||
246 | -#define PORTSC_PP (1<<9) | ||
247 | -#define PORTSC_SPEED_SHIFT 10 | ||
248 | -#define PORTSC_SPEED_MASK 0xf | ||
249 | -#define PORTSC_SPEED_FULL (1<<10) | ||
250 | -#define PORTSC_SPEED_LOW (2<<10) | ||
251 | -#define PORTSC_SPEED_HIGH (3<<10) | ||
252 | -#define PORTSC_SPEED_SUPER (4<<10) | ||
253 | -#define PORTSC_PIC_SHIFT 14 | ||
254 | -#define PORTSC_PIC_MASK 0x3 | ||
255 | -#define PORTSC_LWS (1<<16) | ||
256 | -#define PORTSC_CSC (1<<17) | ||
257 | -#define PORTSC_PEC (1<<18) | ||
258 | -#define PORTSC_WRC (1<<19) | ||
259 | -#define PORTSC_OCC (1<<20) | ||
260 | -#define PORTSC_PRC (1<<21) | ||
261 | -#define PORTSC_PLC (1<<22) | ||
262 | -#define PORTSC_CEC (1<<23) | ||
263 | -#define PORTSC_CAS (1<<24) | ||
264 | -#define PORTSC_WCE (1<<25) | ||
265 | -#define PORTSC_WDE (1<<26) | ||
266 | -#define PORTSC_WOE (1<<27) | ||
267 | -#define PORTSC_DR (1<<30) | ||
268 | -#define PORTSC_WPR (1<<31) | ||
269 | - | ||
270 | -#define CRCR_RCS (1<<0) | ||
271 | -#define CRCR_CS (1<<1) | ||
272 | -#define CRCR_CA (1<<2) | ||
273 | -#define CRCR_CRR (1<<3) | ||
274 | - | ||
275 | -#define IMAN_IP (1<<0) | ||
276 | -#define IMAN_IE (1<<1) | ||
277 | - | ||
278 | -#define ERDP_EHB (1<<3) | ||
279 | - | ||
280 | -#define TRB_SIZE 16 | ||
281 | -typedef struct XHCITRB { | ||
282 | - uint64_t parameter; | ||
283 | - uint32_t status; | ||
284 | - uint32_t control; | ||
285 | - dma_addr_t addr; | ||
286 | - bool ccs; | ||
287 | -} XHCITRB; | ||
288 | - | ||
289 | -enum { | ||
290 | - PLS_U0 = 0, | ||
291 | - PLS_U1 = 1, | ||
292 | - PLS_U2 = 2, | ||
293 | - PLS_U3 = 3, | ||
294 | - PLS_DISABLED = 4, | ||
295 | - PLS_RX_DETECT = 5, | ||
296 | - PLS_INACTIVE = 6, | ||
297 | - PLS_POLLING = 7, | ||
298 | - PLS_RECOVERY = 8, | ||
299 | - PLS_HOT_RESET = 9, | ||
300 | - PLS_COMPILANCE_MODE = 10, | ||
301 | - PLS_TEST_MODE = 11, | ||
302 | - PLS_RESUME = 15, | ||
303 | -}; | ||
304 | - | ||
305 | -#define CR_LINK TR_LINK | ||
306 | - | ||
307 | -#define TRB_C (1<<0) | ||
308 | -#define TRB_TYPE_SHIFT 10 | ||
309 | -#define TRB_TYPE_MASK 0x3f | ||
310 | -#define TRB_TYPE(t) (((t).control >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK) | ||
311 | - | ||
312 | -#define TRB_EV_ED (1<<2) | ||
313 | - | ||
314 | -#define TRB_TR_ENT (1<<1) | ||
315 | -#define TRB_TR_ISP (1<<2) | ||
316 | -#define TRB_TR_NS (1<<3) | ||
317 | -#define TRB_TR_CH (1<<4) | ||
318 | -#define TRB_TR_IOC (1<<5) | ||
319 | -#define TRB_TR_IDT (1<<6) | ||
320 | -#define TRB_TR_TBC_SHIFT 7 | ||
321 | -#define TRB_TR_TBC_MASK 0x3 | ||
322 | -#define TRB_TR_BEI (1<<9) | ||
323 | -#define TRB_TR_TLBPC_SHIFT 16 | ||
324 | -#define TRB_TR_TLBPC_MASK 0xf | ||
325 | -#define TRB_TR_FRAMEID_SHIFT 20 | ||
326 | -#define TRB_TR_FRAMEID_MASK 0x7ff | ||
327 | -#define TRB_TR_SIA (1<<31) | ||
328 | - | ||
329 | -#define TRB_TR_DIR (1<<16) | ||
330 | - | ||
331 | -#define TRB_CR_SLOTID_SHIFT 24 | ||
332 | -#define TRB_CR_SLOTID_MASK 0xff | ||
333 | -#define TRB_CR_EPID_SHIFT 16 | ||
334 | -#define TRB_CR_EPID_MASK 0x1f | ||
335 | - | ||
336 | -#define TRB_CR_BSR (1<<9) | ||
337 | -#define TRB_CR_DC (1<<9) | ||
338 | - | ||
339 | -#define TRB_LK_TC (1<<1) | ||
340 | - | ||
341 | -#define TRB_INTR_SHIFT 22 | ||
342 | -#define TRB_INTR_MASK 0x3ff | ||
343 | -#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK) | ||
344 | - | ||
345 | -#define EP_TYPE_MASK 0x7 | ||
346 | -#define EP_TYPE_SHIFT 3 | ||
347 | - | ||
348 | -#define EP_STATE_MASK 0x7 | ||
349 | -#define EP_DISABLED (0<<0) | ||
350 | -#define EP_RUNNING (1<<0) | ||
351 | -#define EP_HALTED (2<<0) | ||
352 | -#define EP_STOPPED (3<<0) | ||
353 | -#define EP_ERROR (4<<0) | ||
354 | - | ||
355 | -#define SLOT_STATE_MASK 0x1f | ||
356 | -#define SLOT_STATE_SHIFT 27 | ||
357 | -#define SLOT_STATE(s) (((s)>>SLOT_STATE_SHIFT)&SLOT_STATE_MASK) | ||
358 | -#define SLOT_ENABLED 0 | ||
359 | -#define SLOT_DEFAULT 1 | ||
360 | -#define SLOT_ADDRESSED 2 | ||
361 | -#define SLOT_CONFIGURED 3 | ||
362 | - | ||
363 | -#define SLOT_CONTEXT_ENTRIES_MASK 0x1f | ||
364 | -#define SLOT_CONTEXT_ENTRIES_SHIFT 27 | ||
365 | - | ||
366 | #define get_field(data, field) \ | ||
367 | (((data) >> field##_SHIFT) & field##_MASK) | ||
368 | |||
369 | @@ -XXX,XX +XXX,XX @@ enum { | ||
370 | *data = val_; \ | ||
371 | } while (0) | ||
372 | |||
373 | -typedef enum EPType { | ||
374 | - ET_INVALID = 0, | ||
375 | - ET_ISO_OUT, | ||
376 | - ET_BULK_OUT, | ||
377 | - ET_INTR_OUT, | ||
378 | - ET_CONTROL, | ||
379 | - ET_ISO_IN, | ||
380 | - ET_BULK_IN, | ||
381 | - ET_INTR_IN, | ||
382 | -} EPType; | ||
383 | - | ||
384 | typedef struct XHCITransfer { | ||
385 | XHCIEPContext *epctx; | ||
386 | USBPacket packet; | ||
387 | @@ -XXX,XX +XXX,XX @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) | ||
388 | uint32_t ret; | ||
389 | |||
390 | switch (reg) { | ||
391 | - case 0x00: /* HCIVERSION, CAPLENGTH */ | ||
392 | + case XHCI_HCCAP_CAPLENGTH: /* Covers HCIVERSION and CAPLENGTH */ | ||
393 | ret = 0x01000000 | LEN_CAP; | ||
394 | break; | ||
395 | - case 0x04: /* HCSPARAMS 1 */ | ||
396 | + case XHCI_HCCAP_HCSPARAMS1: | ||
397 | ret = ((xhci->numports_2+xhci->numports_3)<<24) | ||
398 | | (xhci->numintrs<<8) | xhci->numslots; | ||
399 | break; | ||
400 | - case 0x08: /* HCSPARAMS 2 */ | ||
401 | + case XHCI_HCCAP_HCSPARAMS2: | ||
402 | ret = 0x0000000f; | ||
403 | break; | ||
404 | - case 0x0c: /* HCSPARAMS 3 */ | ||
405 | + case XHCI_HCCAP_HCSPARAMS3: | ||
406 | ret = 0x00000000; | ||
407 | break; | ||
408 | - case 0x10: /* HCCPARAMS */ | ||
409 | - if (sizeof(dma_addr_t) == 4) { | ||
410 | - ret = 0x00080000 | (xhci->max_pstreams_mask << 12); | ||
411 | - } else { | ||
412 | - ret = 0x00080001 | (xhci->max_pstreams_mask << 12); | ||
413 | + case XHCI_HCCAP_HCCPARAMS1: | ||
414 | + ret = (XHCI_HCCAP_EXTCAP_START >> 2) | (xhci->max_pstreams_mask << 12); | ||
415 | + if (sizeof(dma_addr_t) == 8) { | ||
416 | + ret |= 0x00000001; /* AC64 */ | ||
417 | } | ||
418 | break; | ||
419 | - case 0x14: /* DBOFF */ | ||
420 | + case XHCI_HCCAP_DBOFF: | ||
421 | ret = OFF_DOORBELL; | ||
422 | break; | ||
423 | - case 0x18: /* RTSOFF */ | ||
424 | + case XHCI_HCCAP_RTSOFF: | ||
425 | ret = OFF_RUNTIME; | ||
426 | break; | ||
427 | |||
428 | /* extended capabilities */ | ||
429 | - case 0x20: /* Supported Protocol:00 */ | ||
430 | + case XHCI_HCCAP_EXTCAP_START + 0x00: /* Supported Protocol:00 */ | ||
431 | ret = 0x02000402; /* USB 2.0 */ | ||
432 | break; | ||
433 | - case 0x24: /* Supported Protocol:04 */ | ||
434 | + case XHCI_HCCAP_EXTCAP_START + 0x04: /* Supported Protocol:04 */ | ||
435 | ret = 0x20425355; /* "USB " */ | ||
436 | break; | ||
437 | - case 0x28: /* Supported Protocol:08 */ | ||
438 | + case XHCI_HCCAP_EXTCAP_START + 0x08: /* Supported Protocol:08 */ | ||
439 | ret = (xhci->numports_2 << 8) | (xhci->numports_3 + 1); | ||
440 | break; | ||
441 | - case 0x2c: /* Supported Protocol:0c */ | ||
442 | + case XHCI_HCCAP_EXTCAP_START + 0x0c: /* Supported Protocol:0c */ | ||
443 | ret = 0x00000000; /* reserved */ | ||
444 | break; | ||
445 | - case 0x30: /* Supported Protocol:00 */ | ||
446 | + case XHCI_HCCAP_EXTCAP_START + 0x10: /* Supported Protocol:00 */ | ||
447 | ret = 0x03000002; /* USB 3.0 */ | ||
448 | break; | ||
449 | - case 0x34: /* Supported Protocol:04 */ | ||
450 | + case XHCI_HCCAP_EXTCAP_START + 0x14: /* Supported Protocol:04 */ | ||
451 | ret = 0x20425355; /* "USB " */ | ||
452 | break; | ||
453 | - case 0x38: /* Supported Protocol:08 */ | ||
454 | + case XHCI_HCCAP_EXTCAP_START + 0x18: /* Supported Protocol:08 */ | ||
455 | ret = (xhci->numports_3 << 8) | 1; | ||
456 | break; | ||
457 | - case 0x3c: /* Supported Protocol:0c */ | ||
458 | + case XHCI_HCCAP_EXTCAP_START + 0x1c: /* Supported Protocol:0c */ | ||
459 | ret = 0x00000000; /* reserved */ | ||
460 | break; | ||
461 | default: | ||
462 | @@ -XXX,XX +XXX,XX @@ static uint64_t xhci_port_read(void *ptr, hwaddr reg, unsigned size) | ||
463 | uint32_t ret; | ||
464 | |||
465 | switch (reg) { | ||
466 | - case 0x00: /* PORTSC */ | ||
467 | + case XHCI_PORT_PORTSC: | ||
468 | ret = port->portsc; | ||
469 | break; | ||
470 | - case 0x04: /* PORTPMSC */ | ||
471 | - case 0x08: /* PORTLI */ | ||
472 | + case XHCI_PORT_PORTPMSC: | ||
473 | + case XHCI_PORT_PORTLI: | ||
474 | ret = 0; | ||
475 | break; | ||
476 | - case 0x0c: /* reserved */ | ||
477 | default: | ||
478 | trace_usb_xhci_unimplemented("port read", reg); | ||
479 | ret = 0; | ||
480 | @@ -XXX,XX +XXX,XX @@ static void xhci_port_write(void *ptr, hwaddr reg, | ||
481 | trace_usb_xhci_port_write(port->portnr, reg, val); | ||
482 | |||
483 | switch (reg) { | ||
484 | - case 0x00: /* PORTSC */ | ||
485 | + case XHCI_PORT_PORTSC: | ||
486 | /* write-1-to-start bits */ | ||
487 | if (val & PORTSC_WPR) { | ||
488 | xhci_port_reset(port, true); | ||
489 | @@ -XXX,XX +XXX,XX @@ static void xhci_port_write(void *ptr, hwaddr reg, | ||
490 | xhci_port_notify(port, notify); | ||
491 | } | ||
492 | break; | ||
493 | - case 0x04: /* PORTPMSC */ | ||
494 | - case 0x08: /* PORTLI */ | ||
495 | default: | ||
496 | trace_usb_xhci_unimplemented("port write", reg); | ||
497 | } | ||
498 | @@ -XXX,XX +XXX,XX @@ static uint64_t xhci_oper_read(void *ptr, hwaddr reg, unsigned size) | ||
499 | uint32_t ret; | ||
500 | |||
501 | switch (reg) { | ||
502 | - case 0x00: /* USBCMD */ | ||
503 | + case XHCI_OPER_USBCMD: | ||
504 | ret = xhci->usbcmd; | ||
505 | break; | ||
506 | - case 0x04: /* USBSTS */ | ||
507 | + case XHCI_OPER_USBSTS: | ||
508 | ret = xhci->usbsts; | ||
509 | break; | ||
510 | - case 0x08: /* PAGESIZE */ | ||
511 | + case XHCI_OPER_PAGESIZE: | ||
512 | ret = 1; /* 4KiB */ | ||
513 | break; | ||
514 | - case 0x14: /* DNCTRL */ | ||
515 | + case XHCI_OPER_DNCTRL: | ||
516 | ret = xhci->dnctrl; | ||
517 | break; | ||
518 | - case 0x18: /* CRCR low */ | ||
519 | + case XHCI_OPER_CRCR_LO: | ||
520 | ret = xhci->crcr_low & ~0xe; | ||
521 | break; | ||
522 | - case 0x1c: /* CRCR high */ | ||
523 | + case XHCI_OPER_CRCR_HI: | ||
524 | ret = xhci->crcr_high; | ||
525 | break; | ||
526 | - case 0x30: /* DCBAAP low */ | ||
527 | + case XHCI_OPER_DCBAAP_LO: | ||
528 | ret = xhci->dcbaap_low; | ||
529 | break; | ||
530 | - case 0x34: /* DCBAAP high */ | ||
531 | + case XHCI_OPER_DCBAAP_HI: | ||
532 | ret = xhci->dcbaap_high; | ||
533 | break; | ||
534 | - case 0x38: /* CONFIG */ | ||
535 | + case XHCI_OPER_CONFIG: | ||
536 | ret = xhci->config; | ||
537 | break; | ||
538 | default: | ||
539 | @@ -XXX,XX +XXX,XX @@ static void xhci_oper_write(void *ptr, hwaddr reg, | ||
540 | trace_usb_xhci_oper_write(reg, val); | ||
541 | |||
542 | switch (reg) { | ||
543 | - case 0x00: /* USBCMD */ | ||
544 | + case XHCI_OPER_USBCMD: | ||
545 | if ((val & USBCMD_RS) && !(xhci->usbcmd & USBCMD_RS)) { | ||
546 | xhci_run(xhci); | ||
547 | } else if (!(val & USBCMD_RS) && (xhci->usbcmd & USBCMD_RS)) { | ||
548 | @@ -XXX,XX +XXX,XX @@ static void xhci_oper_write(void *ptr, hwaddr reg, | ||
549 | xhci_intr_update(xhci, 0); | ||
550 | break; | ||
551 | |||
552 | - case 0x04: /* USBSTS */ | ||
553 | + case XHCI_OPER_USBSTS: | ||
554 | /* these bits are write-1-to-clear */ | ||
555 | xhci->usbsts &= ~(val & (USBSTS_HSE|USBSTS_EINT|USBSTS_PCD|USBSTS_SRE)); | ||
556 | xhci_intr_update(xhci, 0); | ||
557 | break; | ||
558 | |||
559 | - case 0x14: /* DNCTRL */ | ||
560 | + case XHCI_OPER_DNCTRL: | ||
561 | xhci->dnctrl = val & 0xffff; | ||
562 | break; | ||
563 | - case 0x18: /* CRCR low */ | ||
564 | + case XHCI_OPER_CRCR_LO: | ||
565 | xhci->crcr_low = (val & 0xffffffcf) | (xhci->crcr_low & CRCR_CRR); | ||
566 | break; | ||
567 | - case 0x1c: /* CRCR high */ | ||
568 | + case XHCI_OPER_CRCR_HI: | ||
569 | xhci->crcr_high = val; | ||
570 | if (xhci->crcr_low & (CRCR_CA|CRCR_CS) && (xhci->crcr_low & CRCR_CRR)) { | ||
571 | XHCIEvent event = {ER_COMMAND_COMPLETE, CC_COMMAND_RING_STOPPED}; | ||
572 | @@ -XXX,XX +XXX,XX @@ static void xhci_oper_write(void *ptr, hwaddr reg, | ||
573 | } | ||
574 | xhci->crcr_low &= ~(CRCR_CA | CRCR_CS); | ||
575 | break; | ||
576 | - case 0x30: /* DCBAAP low */ | ||
577 | + case XHCI_OPER_DCBAAP_LO: | ||
578 | xhci->dcbaap_low = val & 0xffffffc0; | ||
579 | break; | ||
580 | - case 0x34: /* DCBAAP high */ | ||
581 | + case XHCI_OPER_DCBAAP_HI: | ||
582 | xhci->dcbaap_high = val; | ||
583 | break; | ||
584 | - case 0x38: /* CONFIG */ | ||
585 | + case XHCI_OPER_CONFIG: | ||
586 | xhci->config = val & 0xff; | ||
587 | break; | ||
588 | default: | ||
589 | @@ -XXX,XX +XXX,XX @@ static uint64_t xhci_runtime_read(void *ptr, hwaddr reg, | ||
590 | XHCIState *xhci = ptr; | ||
591 | uint32_t ret = 0; | ||
592 | |||
593 | - if (reg < 0x20) { | ||
594 | + if (reg < XHCI_OPER_IR0) { | ||
595 | switch (reg) { | ||
596 | - case 0x00: /* MFINDEX */ | ||
597 | + case XHCI_OPER_MFINDEX: | ||
598 | ret = xhci_mfindex_get(xhci) & 0x3fff; | ||
599 | break; | ||
600 | default: | ||
601 | @@ -XXX,XX +XXX,XX @@ static uint64_t xhci_runtime_read(void *ptr, hwaddr reg, | ||
602 | break; | ||
603 | } | ||
604 | } else { | ||
605 | - int v = (reg - 0x20) / 0x20; | ||
606 | + int v = (reg - XHCI_OPER_IR0) / XHCI_OPER_IR_SZ; | ||
607 | XHCIInterrupter *intr = &xhci->intr[v]; | ||
608 | - switch (reg & 0x1f) { | ||
609 | - case 0x00: /* IMAN */ | ||
610 | + switch (reg & (XHCI_OPER_IR_SZ - 1)) { | ||
611 | + case XHCI_INTR_IMAN: | ||
612 | ret = intr->iman; | ||
613 | break; | ||
614 | - case 0x04: /* IMOD */ | ||
615 | + case XHCI_INTR_IMOD: | ||
616 | ret = intr->imod; | ||
617 | break; | ||
618 | - case 0x08: /* ERSTSZ */ | ||
619 | + case XHCI_INTR_ERSTSZ: | ||
620 | ret = intr->erstsz; | ||
621 | break; | ||
622 | - case 0x10: /* ERSTBA low */ | ||
623 | + case XHCI_INTR_ERSTBA_LO: | ||
624 | ret = intr->erstba_low; | ||
625 | break; | ||
626 | - case 0x14: /* ERSTBA high */ | ||
627 | + case XHCI_INTR_ERSTBA_HI: | ||
628 | ret = intr->erstba_high; | ||
629 | break; | ||
630 | - case 0x18: /* ERDP low */ | ||
631 | + case XHCI_INTR_ERDP_LO: | ||
632 | ret = intr->erdp_low; | ||
633 | break; | ||
634 | - case 0x1c: /* ERDP high */ | ||
635 | + case XHCI_INTR_ERDP_HI: | ||
636 | ret = intr->erdp_high; | ||
637 | break; | ||
638 | } | ||
639 | @@ -XXX,XX +XXX,XX @@ static void xhci_runtime_write(void *ptr, hwaddr reg, | ||
640 | |||
641 | trace_usb_xhci_runtime_write(reg, val); | ||
642 | |||
643 | - if (reg < 0x20) { | ||
644 | + if (reg < XHCI_OPER_IR0) { | ||
645 | trace_usb_xhci_unimplemented("runtime write", reg); | ||
646 | return; | ||
647 | } | ||
648 | - v = (reg - 0x20) / 0x20; | ||
649 | + v = (reg - XHCI_OPER_IR0) / XHCI_OPER_IR_SZ; | ||
650 | intr = &xhci->intr[v]; | ||
651 | |||
652 | - switch (reg & 0x1f) { | ||
653 | - case 0x00: /* IMAN */ | ||
654 | + switch (reg & (XHCI_OPER_IR_SZ - 1)) { | ||
655 | + case XHCI_INTR_IMAN: | ||
656 | if (val & IMAN_IP) { | ||
657 | intr->iman &= ~IMAN_IP; | ||
658 | } | ||
659 | @@ -XXX,XX +XXX,XX @@ static void xhci_runtime_write(void *ptr, hwaddr reg, | ||
660 | intr->iman |= val & IMAN_IE; | ||
661 | xhci_intr_update(xhci, v); | ||
662 | break; | ||
663 | - case 0x04: /* IMOD */ | ||
664 | + case XHCI_INTR_IMOD: | ||
665 | intr->imod = val; | ||
666 | break; | ||
667 | - case 0x08: /* ERSTSZ */ | ||
668 | + case XHCI_INTR_ERSTSZ: | ||
669 | intr->erstsz = val & 0xffff; | ||
670 | break; | ||
671 | - case 0x10: /* ERSTBA low */ | ||
672 | + case XHCI_INTR_ERSTBA_LO: | ||
673 | if (xhci->nec_quirks) { | ||
674 | /* NEC driver bug: it doesn't align this to 64 bytes */ | ||
675 | intr->erstba_low = val & 0xfffffff0; | ||
676 | @@ -XXX,XX +XXX,XX @@ static void xhci_runtime_write(void *ptr, hwaddr reg, | ||
677 | intr->erstba_low = val & 0xffffffc0; | ||
678 | } | ||
679 | break; | ||
680 | - case 0x14: /* ERSTBA high */ | ||
681 | + case XHCI_INTR_ERSTBA_HI: | ||
682 | intr->erstba_high = val; | ||
683 | xhci_er_reset(xhci, v); | ||
684 | break; | ||
685 | - case 0x18: /* ERDP low */ | ||
686 | + case XHCI_INTR_ERDP_LO: | ||
687 | if (val & ERDP_EHB) { | ||
688 | intr->erdp_low &= ~ERDP_EHB; | ||
689 | } | ||
690 | @@ -XXX,XX +XXX,XX @@ static void xhci_runtime_write(void *ptr, hwaddr reg, | ||
691 | } | ||
692 | } | ||
693 | break; | ||
694 | - case 0x1c: /* ERDP high */ | ||
695 | + case XHCI_INTR_ERDP_HI: | ||
696 | intr->erdp_high = val; | ||
697 | break; | ||
698 | default: | ||
699 | -- | ||
700 | 2.45.2 | diff view generated by jsdifflib |
1 | Add tests which init the host controller registers to the point | 1 | Add tests which init the host controller registers to the point where |
---|---|---|---|
2 | where command and event rings, irqs are operational. Enumerate | 2 | command and event rings, irqs are operational. Enumerate ports and set |
3 | ports and set up an attached device context that enables device | 3 | up an attached device context that enables device transfer ring to be |
4 | transfer ring to be set up and tested. | 4 | set up and tested. |
5 | 5 | ||
6 | This test does a bunch of things at once and is yet well | 6 | This test does a bunch of things at once and is not yet well librified, |
7 | librified, but it allows testing basic mechanisms and gives a | 7 | but it allows testing basic mechanisms and gives a starting point for |
8 | starting point for further work. | 8 | further work. |
9 | 9 | ||
10 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> | 10 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> |
11 | --- | 11 | --- |
12 | tests/qtest/usb-hcd-xhci-test.h | 232 +++++++++++++++ | 12 | hw/usb/hcd-xhci.h | 7 + |
13 | tests/qtest/usb-hcd-xhci-test.c | 506 +++++++++++++++++++++++++++++++- | 13 | hw/usb/hcd-xhci.c | 7 - |
14 | 2 files changed, 732 insertions(+), 6 deletions(-) | 14 | tests/qtest/usb-hcd-xhci-test.c | 498 +++++++++++++++++++++++++++++++- |
15 | create mode 100644 tests/qtest/usb-hcd-xhci-test.h | 15 | 3 files changed, 499 insertions(+), 13 deletions(-) |
16 | 16 | ||
17 | diff --git a/tests/qtest/usb-hcd-xhci-test.h b/tests/qtest/usb-hcd-xhci-test.h | 17 | diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h |
18 | new file mode 100644 | 18 | index XXXXXXX..XXXXXXX 100644 |
19 | index XXXXXXX..XXXXXXX | 19 | --- a/hw/usb/hcd-xhci.h |
20 | --- /dev/null | 20 | +++ b/hw/usb/hcd-xhci.h |
21 | +++ b/tests/qtest/usb-hcd-xhci-test.h | 21 | @@ -XXX,XX +XXX,XX @@ typedef struct XHCIRing { |
22 | @@ -XXX,XX +XXX,XX @@ | 22 | bool ccs; |
23 | +#ifndef TESTS_USB_HCD_XHCI_H | 23 | } XHCIRing; |
24 | +#define TESTS_USB_HCD_XHCI_H | 24 | |
25 | + | 25 | +typedef struct XHCIEvRingSeg { |
26 | +typedef enum TRBType { | 26 | + uint32_t addr_low; |
27 | + TRB_RESERVED = 0, | 27 | + uint32_t addr_high; |
28 | + TR_NORMAL, | 28 | + uint32_t size; |
29 | + TR_SETUP, | 29 | + uint32_t rsvd; |
30 | + TR_DATA, | 30 | +} XHCIEvRingSeg; |
31 | + TR_STATUS, | 31 | + |
32 | + TR_ISOCH, | 32 | typedef struct XHCIPort { |
33 | + TR_LINK, | 33 | XHCIState *xhci; |
34 | + TR_EVDATA, | 34 | uint32_t portsc; |
35 | + TR_NOOP, | 35 | diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c |
36 | + CR_ENABLE_SLOT, | 36 | index XXXXXXX..XXXXXXX 100644 |
37 | + CR_DISABLE_SLOT, | 37 | --- a/hw/usb/hcd-xhci.c |
38 | + CR_ADDRESS_DEVICE, | 38 | +++ b/hw/usb/hcd-xhci.c |
39 | + CR_CONFIGURE_ENDPOINT, | 39 | @@ -XXX,XX +XXX,XX @@ struct XHCIEPContext { |
40 | + CR_EVALUATE_CONTEXT, | 40 | QEMUTimer *kick_timer; |
41 | + CR_RESET_ENDPOINT, | 41 | }; |
42 | + CR_STOP_ENDPOINT, | 42 | |
43 | + CR_SET_TR_DEQUEUE, | 43 | -typedef struct XHCIEvRingSeg { |
44 | + CR_RESET_DEVICE, | 44 | - uint32_t addr_low; |
45 | + CR_FORCE_EVENT, | 45 | - uint32_t addr_high; |
46 | + CR_NEGOTIATE_BW, | 46 | - uint32_t size; |
47 | + CR_SET_LATENCY_TOLERANCE, | 47 | - uint32_t rsvd; |
48 | + CR_GET_PORT_BANDWIDTH, | 48 | -} XHCIEvRingSeg; |
49 | + CR_FORCE_HEADER, | 49 | - |
50 | + CR_NOOP, | 50 | static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, |
51 | + ER_TRANSFER = 32, | 51 | unsigned int epid, unsigned int streamid); |
52 | + ER_COMMAND_COMPLETE, | 52 | static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid); |
53 | + ER_PORT_STATUS_CHANGE, | ||
54 | + ER_BANDWIDTH_REQUEST, | ||
55 | + ER_DOORBELL, | ||
56 | + ER_HOST_CONTROLLER, | ||
57 | + ER_DEVICE_NOTIFICATION, | ||
58 | + ER_MFINDEX_WRAP, | ||
59 | + /* vendor specific bits */ | ||
60 | + CR_VENDOR_NEC_FIRMWARE_REVISION = 49, | ||
61 | + CR_VENDOR_NEC_CHALLENGE_RESPONSE = 50, | ||
62 | +} TRBType; | ||
63 | + | ||
64 | +typedef enum TRBCCode { | ||
65 | + CC_INVALID = 0, | ||
66 | + CC_SUCCESS, | ||
67 | + CC_DATA_BUFFER_ERROR, | ||
68 | + CC_BABBLE_DETECTED, | ||
69 | + CC_USB_TRANSACTION_ERROR, | ||
70 | + CC_TRB_ERROR, | ||
71 | + CC_STALL_ERROR, | ||
72 | + CC_RESOURCE_ERROR, | ||
73 | + CC_BANDWIDTH_ERROR, | ||
74 | + CC_NO_SLOTS_ERROR, | ||
75 | + CC_INVALID_STREAM_TYPE_ERROR, | ||
76 | + CC_SLOT_NOT_ENABLED_ERROR, | ||
77 | + CC_EP_NOT_ENABLED_ERROR, | ||
78 | + CC_SHORT_PACKET, | ||
79 | + CC_RING_UNDERRUN, | ||
80 | + CC_RING_OVERRUN, | ||
81 | + CC_VF_ER_FULL, | ||
82 | + CC_PARAMETER_ERROR, | ||
83 | + CC_BANDWIDTH_OVERRUN, | ||
84 | + CC_CONTEXT_STATE_ERROR, | ||
85 | + CC_NO_PING_RESPONSE_ERROR, | ||
86 | + CC_EVENT_RING_FULL_ERROR, | ||
87 | + CC_INCOMPATIBLE_DEVICE_ERROR, | ||
88 | + CC_MISSED_SERVICE_ERROR, | ||
89 | + CC_COMMAND_RING_STOPPED, | ||
90 | + CC_COMMAND_ABORTED, | ||
91 | + CC_STOPPED, | ||
92 | + CC_STOPPED_LENGTH_INVALID, | ||
93 | + CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29, | ||
94 | + CC_ISOCH_BUFFER_OVERRUN = 31, | ||
95 | + CC_EVENT_LOST_ERROR, | ||
96 | + CC_UNDEFINED_ERROR, | ||
97 | + CC_INVALID_STREAM_ID_ERROR, | ||
98 | + CC_SECONDARY_BANDWIDTH_ERROR, | ||
99 | + CC_SPLIT_TRANSACTION_ERROR | ||
100 | +} TRBCCode; | ||
101 | + | ||
102 | +/* bit definitions */ | ||
103 | +#define USBCMD_RS (1<<0) | ||
104 | +#define USBCMD_HCRST (1<<1) | ||
105 | +#define USBCMD_INTE (1<<2) | ||
106 | +#define USBCMD_HSEE (1<<3) | ||
107 | +#define USBCMD_LHCRST (1<<7) | ||
108 | +#define USBCMD_CSS (1<<8) | ||
109 | +#define USBCMD_CRS (1<<9) | ||
110 | +#define USBCMD_EWE (1<<10) | ||
111 | +#define USBCMD_EU3S (1<<11) | ||
112 | + | ||
113 | +#define USBSTS_HCH (1<<0) | ||
114 | +#define USBSTS_HSE (1<<2) | ||
115 | +#define USBSTS_EINT (1<<3) | ||
116 | +#define USBSTS_PCD (1<<4) | ||
117 | +#define USBSTS_SSS (1<<8) | ||
118 | +#define USBSTS_RSS (1<<9) | ||
119 | +#define USBSTS_SRE (1<<10) | ||
120 | +#define USBSTS_CNR (1<<11) | ||
121 | +#define USBSTS_HCE (1<<12) | ||
122 | + | ||
123 | + | ||
124 | +#define PORTSC_CCS (1<<0) | ||
125 | +#define PORTSC_PED (1<<1) | ||
126 | +#define PORTSC_OCA (1<<3) | ||
127 | +#define PORTSC_PR (1<<4) | ||
128 | +#define PORTSC_PLS_SHIFT 5 | ||
129 | +#define PORTSC_PLS_MASK 0xf | ||
130 | +#define PORTSC_PP (1<<9) | ||
131 | +#define PORTSC_SPEED_SHIFT 10 | ||
132 | +#define PORTSC_SPEED_MASK 0xf | ||
133 | +#define PORTSC_SPEED_FULL (1<<10) | ||
134 | +#define PORTSC_SPEED_LOW (2<<10) | ||
135 | +#define PORTSC_SPEED_HIGH (3<<10) | ||
136 | +#define PORTSC_SPEED_SUPER (4<<10) | ||
137 | +#define PORTSC_PIC_SHIFT 14 | ||
138 | +#define PORTSC_PIC_MASK 0x3 | ||
139 | +#define PORTSC_LWS (1<<16) | ||
140 | +#define PORTSC_CSC (1<<17) | ||
141 | +#define PORTSC_PEC (1<<18) | ||
142 | +#define PORTSC_WRC (1<<19) | ||
143 | +#define PORTSC_OCC (1<<20) | ||
144 | +#define PORTSC_PRC (1<<21) | ||
145 | +#define PORTSC_PLC (1<<22) | ||
146 | +#define PORTSC_CEC (1<<23) | ||
147 | +#define PORTSC_CAS (1<<24) | ||
148 | +#define PORTSC_WCE (1<<25) | ||
149 | +#define PORTSC_WDE (1<<26) | ||
150 | +#define PORTSC_WOE (1<<27) | ||
151 | +#define PORTSC_DR (1<<30) | ||
152 | +#define PORTSC_WPR (1<<31) | ||
153 | + | ||
154 | +#define CRCR_RCS (1<<0) | ||
155 | +#define CRCR_CS (1<<1) | ||
156 | +#define CRCR_CA (1<<2) | ||
157 | +#define CRCR_CRR (1<<3) | ||
158 | + | ||
159 | +#define IMAN_IP (1<<0) | ||
160 | +#define IMAN_IE (1<<1) | ||
161 | + | ||
162 | +#define ERDP_EHB (1<<3) | ||
163 | + | ||
164 | +#define TRB_SIZE 16 | ||
165 | + | ||
166 | +enum { | ||
167 | + PLS_U0 = 0, | ||
168 | + PLS_U1 = 1, | ||
169 | + PLS_U2 = 2, | ||
170 | + PLS_U3 = 3, | ||
171 | + PLS_DISABLED = 4, | ||
172 | + PLS_RX_DETECT = 5, | ||
173 | + PLS_INACTIVE = 6, | ||
174 | + PLS_POLLING = 7, | ||
175 | + PLS_RECOVERY = 8, | ||
176 | + PLS_HOT_RESET = 9, | ||
177 | + PLS_COMPILANCE_MODE = 10, | ||
178 | + PLS_TEST_MODE = 11, | ||
179 | + PLS_RESUME = 15, | ||
180 | +}; | ||
181 | + | ||
182 | +#define CR_LINK TR_LINK | ||
183 | + | ||
184 | +#define TRB_C (1<<0) | ||
185 | +#define TRB_TYPE_SHIFT 10 | ||
186 | +#define TRB_TYPE_MASK 0x3f | ||
187 | +#define TRB_TYPE(t) (((t).control >> TRB_TYPE_SHIFT) & TRB_TYPE_MASK) | ||
188 | + | ||
189 | +#define TRB_EV_ED (1<<2) | ||
190 | + | ||
191 | +#define TRB_TR_ENT (1<<1) | ||
192 | +#define TRB_TR_ISP (1<<2) | ||
193 | +#define TRB_TR_NS (1<<3) | ||
194 | +#define TRB_TR_CH (1<<4) | ||
195 | +#define TRB_TR_IOC (1<<5) | ||
196 | +#define TRB_TR_IDT (1<<6) | ||
197 | +#define TRB_TR_TBC_SHIFT 7 | ||
198 | +#define TRB_TR_TBC_MASK 0x3 | ||
199 | +#define TRB_TR_BEI (1<<9) | ||
200 | +#define TRB_TR_TLBPC_SHIFT 16 | ||
201 | +#define TRB_TR_TLBPC_MASK 0xf | ||
202 | +#define TRB_TR_FRAMEID_SHIFT 20 | ||
203 | +#define TRB_TR_FRAMEID_MASK 0x7ff | ||
204 | +#define TRB_TR_SIA (1<<31) | ||
205 | + | ||
206 | +#define TRB_TR_DIR (1<<16) | ||
207 | + | ||
208 | +#define TRB_CR_SLOTID_SHIFT 24 | ||
209 | +#define TRB_CR_SLOTID_MASK 0xff | ||
210 | +#define TRB_CR_EPID_SHIFT 16 | ||
211 | +#define TRB_CR_EPID_MASK 0x1f | ||
212 | + | ||
213 | +#define TRB_CR_BSR (1<<9) | ||
214 | +#define TRB_CR_DC (1<<9) | ||
215 | + | ||
216 | +#define TRB_LK_TC (1<<1) | ||
217 | + | ||
218 | +#define TRB_INTR_SHIFT 22 | ||
219 | +#define TRB_INTR_MASK 0x3ff | ||
220 | +#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK) | ||
221 | + | ||
222 | +#define EP_TYPE_MASK 0x7 | ||
223 | +#define EP_TYPE_SHIFT 3 | ||
224 | + | ||
225 | +#define EP_STATE_MASK 0x7 | ||
226 | +#define EP_DISABLED (0<<0) | ||
227 | +#define EP_RUNNING (1<<0) | ||
228 | +#define EP_HALTED (2<<0) | ||
229 | +#define EP_STOPPED (3<<0) | ||
230 | +#define EP_ERROR (4<<0) | ||
231 | + | ||
232 | +#define SLOT_STATE_MASK 0x1f | ||
233 | +#define SLOT_STATE_SHIFT 27 | ||
234 | +#define SLOT_STATE(s) (((s)>>SLOT_STATE_SHIFT)&SLOT_STATE_MASK) | ||
235 | +#define SLOT_ENABLED 0 | ||
236 | +#define SLOT_DEFAULT 1 | ||
237 | +#define SLOT_ADDRESSED 2 | ||
238 | +#define SLOT_CONFIGURED 3 | ||
239 | + | ||
240 | +#define SLOT_CONTEXT_ENTRIES_MASK 0x1f | ||
241 | +#define SLOT_CONTEXT_ENTRIES_SHIFT 27 | ||
242 | + | ||
243 | +typedef enum EPType { | ||
244 | + ET_INVALID = 0, | ||
245 | + ET_ISO_OUT, | ||
246 | + ET_BULK_OUT, | ||
247 | + ET_INTR_OUT, | ||
248 | + ET_CONTROL, | ||
249 | + ET_ISO_IN, | ||
250 | + ET_BULK_IN, | ||
251 | + ET_INTR_IN, | ||
252 | +} EPType; | ||
253 | + | ||
254 | +#endif /* TESTS_USB_HCD_XHCI_H */ | ||
255 | diff --git a/tests/qtest/usb-hcd-xhci-test.c b/tests/qtest/usb-hcd-xhci-test.c | 53 | diff --git a/tests/qtest/usb-hcd-xhci-test.c b/tests/qtest/usb-hcd-xhci-test.c |
256 | index XXXXXXX..XXXXXXX 100644 | 54 | index XXXXXXX..XXXXXXX 100644 |
257 | --- a/tests/qtest/usb-hcd-xhci-test.c | 55 | --- a/tests/qtest/usb-hcd-xhci-test.c |
258 | +++ b/tests/qtest/usb-hcd-xhci-test.c | 56 | +++ b/tests/qtest/usb-hcd-xhci-test.c |
259 | @@ -XXX,XX +XXX,XX @@ | 57 | @@ -XXX,XX +XXX,XX @@ |
... | ... | ||
265 | +#include "libqos/libqos-pc.h" | 63 | +#include "libqos/libqos-pc.h" |
266 | #include "libqtest-single.h" | 64 | #include "libqtest-single.h" |
267 | #include "libqos/usb.h" | 65 | #include "libqos/usb.h" |
268 | +#include "hw/pci/pci_ids.h" | 66 | +#include "hw/pci/pci_ids.h" |
269 | +#include "hw/pci/pci_regs.h" | 67 | +#include "hw/pci/pci_regs.h" |
270 | +#include "usb-hcd-xhci-test.h" | 68 | +#include "hw/usb/hcd-xhci.h" |
271 | + | 69 | + |
272 | +/*** Test Setup & Teardown ***/ | 70 | +/*** Test Setup & Teardown ***/ |
273 | +typedef struct XHCIEvRingSeg { | ||
274 | + uint32_t addr_low; | ||
275 | + uint32_t addr_high; | ||
276 | + uint32_t size; | ||
277 | + uint32_t rsvd; | ||
278 | +} XHCIEvRingSeg; | ||
279 | + | ||
280 | +typedef struct XHCITRB { | ||
281 | + uint64_t parameter; | ||
282 | + uint32_t status; | ||
283 | + uint32_t control; | ||
284 | +} XHCITRB; | ||
285 | + | ||
286 | +typedef struct XHCIQSlotState { | 71 | +typedef struct XHCIQSlotState { |
287 | + /* In-memory arrays */ | 72 | + /* In-memory arrays */ |
288 | + uint64_t device_context; | 73 | + uint64_t device_context; |
289 | + uint64_t transfer_ring; | 74 | + uint64_t transfer_ring; |
290 | + | 75 | + |
... | ... | ||
412 | + */ | 197 | + */ |
413 | +static void xhci_shutdown(XHCIQState *xhci) | 198 | +static void xhci_shutdown(XHCIQState *xhci) |
414 | +{ | 199 | +{ |
415 | + QOSState *qs = xhci->parent; | 200 | + QOSState *qs = xhci->parent; |
416 | + | 201 | + |
417 | +// xhci_clean_mem(xhci); | ||
418 | + free_xhci_device(xhci->dev); | 202 | + free_xhci_device(xhci->dev); |
419 | + g_free(xhci); | 203 | + g_free(xhci); |
420 | + qtest_shutdown(qs); | 204 | + qtest_shutdown(qs); |
421 | +} | 205 | +} |
422 | + | 206 | + |
... | ... | ||
514 | +} | 298 | +} |
515 | + | 299 | + |
516 | +static void xhci_rt_writel(XHCIQState *s, uint64_t addr, uint32_t value) | 300 | +static void xhci_rt_writel(XHCIQState *s, uint64_t addr, uint32_t value) |
517 | +{ | 301 | +{ |
518 | + qpci_io_writel(s->dev, s->bar, s->rtoff + addr, value); | 302 | + qpci_io_writel(s->dev, s->bar, s->rtoff + addr, value); |
519 | +} | 303 | } |
520 | + | 304 | |
521 | +static void xhci_db_writel(XHCIQState *s, uint32_t db, uint32_t value) | 305 | +static void xhci_db_writel(XHCIQState *s, uint32_t db, uint32_t value) |
522 | +{ | 306 | +{ |
523 | + qpci_io_writel(s->dev, s->bar, s->dboff + db * 4, value); | 307 | + qpci_io_writel(s->dev, s->bar, s->dboff + db * 4, value); |
524 | +} | 308 | +} |
525 | + | 309 | + |
... | ... | ||
570 | + /* Update ERDP to processed TRB addr and EHB bit, which clears EHB */ | 354 | + /* Update ERDP to processed TRB addr and EHB bit, which clears EHB */ |
571 | + er_addr = s->event_ring + s->er_trb_idx * sizeof(*trb); | 355 | + er_addr = s->event_ring + s->er_trb_idx * sizeof(*trb); |
572 | + xhci_rt_writel(s, 0x38, (er_addr & 0xffffffff) | ERDP_EHB); | 356 | + xhci_rt_writel(s, 0x38, (er_addr & 0xffffffff) | ERDP_EHB); |
573 | +} | 357 | +} |
574 | + | 358 | + |
575 | +static void set_link_trb(XHCIQState *s, uint64_t ring, uint32_t c, uint32_t entries) | 359 | +static void set_link_trb(XHCIQState *s, uint64_t ring, uint32_t c, |
360 | + uint32_t entries) | ||
576 | +{ | 361 | +{ |
577 | + XHCITRB trb; | 362 | + XHCITRB trb; |
578 | + | 363 | + |
579 | + g_assert(entries > 1); | 364 | + g_assert(entries > 1); |
580 | + | 365 | + |
581 | + memset(&trb, 0, sizeof(trb)); | 366 | + memset(&trb, 0, sizeof(trb)); |
582 | + trb.parameter = cpu_to_le64(ring); | 367 | + trb.parameter = cpu_to_le64(ring); |
583 | + trb.control = cpu_to_le32(c | /* C */ | 368 | + trb.control = cpu_to_le32(c | /* C */ |
584 | + (TR_LINK << TRB_TYPE_SHIFT) | | 369 | + (TR_LINK << TRB_TYPE_SHIFT) | |
585 | + TRB_LK_TC); | 370 | + TRB_LK_TC); |
586 | + qtest_memwrite(s->parent->qts, ring + sizeof(trb) * (entries - 1), &trb, sizeof(trb)); | 371 | + qtest_memwrite(s->parent->qts, ring + sizeof(trb) * (entries - 1), |
587 | } | 372 | + &trb, sizeof(trb)); |
588 | 373 | +} | |
374 | + | ||
589 | +static void submit_cr_trb(XHCIQState *s, XHCITRB *trb) | 375 | +static void submit_cr_trb(XHCIQState *s, XHCITRB *trb) |
590 | +{ | 376 | +{ |
591 | + XHCITRB t; | 377 | + XHCITRB t; |
592 | + uint64_t cr_addr = s->command_ring + s->cr_trb_idx * sizeof(*trb); | 378 | + uint64_t cr_addr = s->command_ring + s->cr_trb_idx * sizeof(*trb); |
593 | + | 379 | + |
... | ... | ||
606 | + s->cr_trb_c ^= 1; | 392 | + s->cr_trb_c ^= 1; |
607 | + } | 393 | + } |
608 | + xhci_db_writel(s, 0, 0); /* doorbell 0 */ | 394 | + xhci_db_writel(s, 0, 0); /* doorbell 0 */ |
609 | +} | 395 | +} |
610 | + | 396 | + |
397 | +/* | ||
398 | + * This test brings up an endpoint and runs some noops through its command | ||
399 | + * ring and gets responses back on the event ring. | ||
400 | + * | ||
401 | + * This could be librified in future (like AHCI0 to have a way to bring up | ||
402 | + * an endpoint to test device protocols. | ||
403 | + */ | ||
611 | +static void pci_xhci_stress_rings(void) | 404 | +static void pci_xhci_stress_rings(void) |
612 | +{ | 405 | +{ |
613 | + XHCIQState *s; | 406 | + XHCIQState *s; |
614 | + uint32_t value; | 407 | + uint32_t value; |
615 | + uint64_t input_context; | 408 | + uint64_t input_context; |
616 | + XHCIEvRingSeg ev_seg; | 409 | + XHCIEvRingSeg ev_seg; |
617 | + XHCITRB trb; | 410 | + XHCITRB trb; |
618 | + uint32_t hcsparams1; | 411 | + uint32_t hcsparams1; |
619 | + uint32_t slotid; | 412 | + uint32_t slotid; |
620 | + void *mem; | 413 | + g_autofree void *mem = g_malloc0(0x1000); /* buffer for writing to guest */ |
621 | + int i; | 414 | + int i; |
622 | + | ||
623 | + mem = g_malloc(0x1000); | ||
624 | + memset(mem, 0, 0x1000); | ||
625 | + | 415 | + |
626 | + s = xhci_boot("-M q35 " | 416 | + s = xhci_boot("-M q35 " |
627 | + "-device nec-usb-xhci,id=xhci,bus=pcie.0,addr=1d.0 " | 417 | + "-device nec-usb-xhci,id=xhci,bus=pcie.0,addr=1d.0 " |
628 | + "-device usb-storage,bus=xhci.0,drive=drive0 " | 418 | + "-device usb-storage,bus=xhci.0,drive=drive0 " |
629 | + "-drive id=drive0,if=none,file=null-co://," | 419 | + "-drive id=drive0,if=none,file=null-co://," |
630 | + "file.read-zeroes=on,format=raw " | 420 | + "file.read-zeroes=on,format=raw " |
631 | + ); | 421 | + ); |
632 | +// "-d trace:*xhci*,trace:*usb*,trace:*msi*"); | ||
633 | + | 422 | + |
634 | + hcsparams1 = xhci_cap_readl(s, 0x4); /* HCSPARAMS1 */ | 423 | + hcsparams1 = xhci_cap_readl(s, 0x4); /* HCSPARAMS1 */ |
635 | + s->maxports = (hcsparams1 >> 24) & 0xff; | 424 | + s->maxports = (hcsparams1 >> 24) & 0xff; |
636 | + s->maxintrs = (hcsparams1 >> 8) & 0x3ff; | 425 | + s->maxintrs = (hcsparams1 >> 8) & 0x3ff; |
637 | + s->maxslots = hcsparams1 & 0xff; | 426 | + s->maxslots = hcsparams1 & 0xff; |
... | ... | ||
705 | + | 494 | + |
706 | + /* Only first port should be attached and enabled */ | 495 | + /* Only first port should be attached and enabled */ |
707 | + if (i == 0) { | 496 | + if (i == 0) { |
708 | + g_assert(value & PORTSC_CCS); | 497 | + g_assert(value & PORTSC_CCS); |
709 | + g_assert(value & PORTSC_PED); | 498 | + g_assert(value & PORTSC_PED); |
710 | + /* Port Speed must be identified */ | 499 | + /* Port Speed must be identified (non-zero) */ |
711 | + g_assert(((value >> PORTSC_SPEED_SHIFT) & PORTSC_SPEED_MASK) != 0); | 500 | + g_assert(((value >> PORTSC_SPEED_SHIFT) & PORTSC_SPEED_MASK) != 0); |
712 | + } else { | 501 | + } else { |
713 | + g_assert(!(value & PORTSC_CCS)); | 502 | + g_assert(!(value & PORTSC_CCS)); |
714 | + g_assert(!(value & PORTSC_PED)); | 503 | + g_assert(!(value & PORTSC_PED)); |
715 | + g_assert(((value >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK) == 5); | 504 | + g_assert(((value >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK) == 5); |
716 | + } | 505 | + } |
... | ... | ||
738 | + | 527 | + |
739 | + /* Set endpoint 0 context */ | 528 | + /* Set endpoint 0 context */ |
740 | + ((uint32_t *)mem)[16] = 0; | 529 | + ((uint32_t *)mem)[16] = 0; |
741 | + ((uint32_t *)mem)[17] = cpu_to_le32((ET_CONTROL << EP_TYPE_SHIFT) | | 530 | + ((uint32_t *)mem)[17] = cpu_to_le32((ET_CONTROL << EP_TYPE_SHIFT) | |
742 | + (0x200 << 16)); /* max packet sz XXX? */ | 531 | + (0x200 << 16)); /* max packet sz XXX? */ |
743 | + ((uint32_t *)mem)[18] = cpu_to_le32((s->slots[slotid].transfer_ring & 0xffffffff) | 1); /* DCS=1 */ | 532 | + ((uint32_t *)mem)[18] = cpu_to_le32((s->slots[slotid].transfer_ring & |
533 | + 0xffffffff) | 1); /* DCS=1 */ | ||
744 | + ((uint32_t *)mem)[19] = cpu_to_le32(s->slots[slotid].transfer_ring >> 32); | 534 | + ((uint32_t *)mem)[19] = cpu_to_le32(s->slots[slotid].transfer_ring >> 32); |
745 | + ((uint32_t *)mem)[20] = cpu_to_le32(0x200); /* Average TRB length */ | 535 | + ((uint32_t *)mem)[20] = cpu_to_le32(0x200); /* Average TRB length */ |
746 | + qtest_memwrite(s->parent->qts, input_context, mem, 0x420); | 536 | + qtest_memwrite(s->parent->qts, input_context, mem, 0x420); |
747 | + | 537 | + |
748 | + s->slots[slotid].device_context = xhci_guest_zalloc(s, 0x400); | 538 | + s->slots[slotid].device_context = xhci_guest_zalloc(s, 0x400); |
749 | + | 539 | + |
750 | + ((uint64_t *)mem)[0] = cpu_to_le64(s->slots[slotid].device_context); | 540 | + ((uint64_t *)mem)[0] = cpu_to_le64(s->slots[slotid].device_context); |
751 | + qtest_memwrite(s->parent->qts, s->dc_base_array + 8*slotid, mem, 8); | 541 | + qtest_memwrite(s->parent->qts, s->dc_base_array + 8 * slotid, mem, 8); |
752 | + | 542 | + |
753 | + /* Issue a command ring address device */ | 543 | + /* Issue a command ring address device */ |
754 | + memset(&trb, 0, sizeof(trb)); | 544 | + memset(&trb, 0, sizeof(trb)); |
755 | + trb.parameter = input_context; | 545 | + trb.parameter = input_context; |
756 | + trb.control |= CR_ADDRESS_DEVICE << TRB_TYPE_SHIFT; | 546 | + trb.control |= CR_ADDRESS_DEVICE << TRB_TYPE_SHIFT; |
757 | + trb.control |= slotid << TRB_CR_SLOTID_SHIFT; | 547 | + trb.control |= slotid << TRB_CR_SLOTID_SHIFT; |
758 | + submit_cr_trb(s, &trb); | 548 | + submit_cr_trb(s, &trb); |
759 | + wait_event_trb(s, &trb); | 549 | + wait_event_trb(s, &trb); |
760 | + | 550 | + |
761 | + /* XXX: Check EP state is running? */ | 551 | + /* XXX: Could check EP state is running */ |
762 | + | 552 | + |
763 | + /* Shut it down */ | 553 | + /* Shut it down */ |
764 | + qpci_msix_disable(s->dev); | 554 | + qpci_msix_disable(s->dev); |
765 | + | 555 | + |
766 | + guest_free(&s->parent->alloc, s->slots[slotid].device_context); | 556 | + guest_free(&s->parent->alloc, s->slots[slotid].device_context); |
... | ... | diff view generated by jsdifflib |
1 | Implement TR NOOP commands by setting up then immediately completing | 1 | Implement XHCI TR NOOP commands by setting up then immediately |
---|---|---|---|
2 | the packet. Add a TR NOOP test to the xhci qtest. | 2 | completing the packet. |
3 | 3 | ||
4 | The IBM AIX XHCI driver uses NOOP commands to check driver and | 4 | The IBM AIX XHCI HCD driver uses NOOP commands to check driver and |
5 | hardware health. | 5 | hardware health, which works after this change. |
6 | 6 | ||
7 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> | 7 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> |
8 | --- | 8 | --- |
9 | hw/usb/hcd-xhci.c | 28 ++++++++++++++++++++++++++- | 9 | hw/usb/hcd-xhci.c | 28 +++++++++++++++++++++++++++- |
10 | tests/qtest/usb-hcd-xhci-test.c | 34 +++++++++++++++++++++++++++++++++ | 10 | 1 file changed, 27 insertions(+), 1 deletion(-) |
11 | 2 files changed, 61 insertions(+), 1 deletion(-) | ||
12 | 11 | ||
13 | diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c | 12 | diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c |
14 | index XXXXXXX..XXXXXXX 100644 | 13 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/hw/usb/hcd-xhci.c | 14 | --- a/hw/usb/hcd-xhci.c |
16 | +++ b/hw/usb/hcd-xhci.c | 15 | +++ b/hw/usb/hcd-xhci.c |
... | ... | ||
64 | + xhci_noop_transfer(xhci, xfer); | 63 | + xhci_noop_transfer(xhci, xfer); |
65 | + } else if (epctx->epid == 1) { | 64 | + } else if (epctx->epid == 1) { |
66 | xhci_fire_ctl_transfer(xhci, xfer); | 65 | xhci_fire_ctl_transfer(xhci, xfer); |
67 | } else { | 66 | } else { |
68 | xhci_fire_transfer(xhci, xfer, epctx); | 67 | xhci_fire_transfer(xhci, xfer, epctx); |
69 | diff --git a/tests/qtest/usb-hcd-xhci-test.c b/tests/qtest/usb-hcd-xhci-test.c | ||
70 | index XXXXXXX..XXXXXXX 100644 | ||
71 | --- a/tests/qtest/usb-hcd-xhci-test.c | ||
72 | +++ b/tests/qtest/usb-hcd-xhci-test.c | ||
73 | @@ -XXX,XX +XXX,XX @@ static void submit_cr_trb(XHCIQState *s, XHCITRB *trb) | ||
74 | xhci_db_writel(s, 0, 0); /* doorbell 0 */ | ||
75 | } | ||
76 | |||
77 | +static void submit_tr_trb(XHCIQState *s, int slot, XHCITRB *trb) | ||
78 | +{ | ||
79 | + XHCITRB t; | ||
80 | + uint64_t tr_addr = s->slots[slot].transfer_ring + s->slots[slot].tr_trb_idx * sizeof(*trb); | ||
81 | + | ||
82 | + trb->control |= s->slots[slot].tr_trb_c; /* C */ | ||
83 | + | ||
84 | + t.parameter = cpu_to_le64(trb->parameter); | ||
85 | + t.status = cpu_to_le32(trb->status); | ||
86 | + t.control = cpu_to_le32(trb->control); | ||
87 | + | ||
88 | + qtest_memwrite(s->parent->qts, tr_addr, &t, sizeof(t)); | ||
89 | + s->slots[slot].tr_trb_idx++; | ||
90 | + /* Last entry contains the link, so wrap back */ | ||
91 | + if (s->slots[slot].tr_trb_idx == s->slots[slot].tr_trb_entries - 1) { | ||
92 | + set_link_trb(s, s->slots[slot].transfer_ring, | ||
93 | + s->slots[slot].tr_trb_c, | ||
94 | + s->slots[slot].tr_trb_entries); | ||
95 | + s->slots[slot].tr_trb_idx = 0; | ||
96 | + s->slots[slot].tr_trb_c ^= 1; | ||
97 | + } | ||
98 | + xhci_db_writel(s, slot, 1); /* doorbell slot, EP0 target */ | ||
99 | +} | ||
100 | + | ||
101 | static void pci_xhci_stress_rings(void) | ||
102 | { | ||
103 | XHCIQState *s; | ||
104 | @@ -XXX,XX +XXX,XX @@ static void pci_xhci_stress_rings(void) | ||
105 | |||
106 | /* XXX: Check EP state is running? */ | ||
107 | |||
108 | + /* Wrap the transfer ring a few times */ | ||
109 | + for (i = 0; i < 100; i++) { | ||
110 | + /* Issue a transfer ring slot 0 noop */ | ||
111 | + memset(&trb, 0, sizeof(trb)); | ||
112 | + trb.control |= TR_NOOP << TRB_TYPE_SHIFT; | ||
113 | + trb.control |= TRB_TR_IOC; | ||
114 | + submit_tr_trb(s, slotid, &trb); | ||
115 | + wait_event_trb(s, &trb); | ||
116 | + } | ||
117 | + | ||
118 | /* Shut it down */ | ||
119 | qpci_msix_disable(s->dev); | ||
120 | |||
121 | -- | 68 | -- |
122 | 2.45.2 | 69 | 2.45.2 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | Run some TR NOOP commands through the transfer ring. | ||
1 | 2 | ||
3 | Signed-off-by: Nicholas Piggin <npiggin@gmail.com> | ||
4 | --- | ||
5 | tests/qtest/usb-hcd-xhci-test.c | 41 +++++++++++++++++++++++++++++++-- | ||
6 | 1 file changed, 39 insertions(+), 2 deletions(-) | ||
7 | |||
8 | diff --git a/tests/qtest/usb-hcd-xhci-test.c b/tests/qtest/usb-hcd-xhci-test.c | ||
9 | index XXXXXXX..XXXXXXX 100644 | ||
10 | --- a/tests/qtest/usb-hcd-xhci-test.c | ||
11 | +++ b/tests/qtest/usb-hcd-xhci-test.c | ||
12 | @@ -XXX,XX +XXX,XX @@ static void set_link_trb(XHCIQState *s, uint64_t ring, uint32_t c, | ||
13 | static void submit_cr_trb(XHCIQState *s, XHCITRB *trb) | ||
14 | { | ||
15 | XHCITRB t; | ||
16 | - uint64_t cr_addr = s->command_ring + s->cr_trb_idx * sizeof(*trb); | ||
17 | + uint64_t cr_addr = s->command_ring + | ||
18 | + s->cr_trb_idx * sizeof(*trb); | ||
19 | |||
20 | trb->control |= s->cr_trb_c; /* C */ | ||
21 | |||
22 | @@ -XXX,XX +XXX,XX @@ static void submit_cr_trb(XHCIQState *s, XHCITRB *trb) | ||
23 | xhci_db_writel(s, 0, 0); /* doorbell 0 */ | ||
24 | } | ||
25 | |||
26 | +static void submit_tr_trb(XHCIQState *s, int slot, XHCITRB *trb) | ||
27 | +{ | ||
28 | + XHCITRB t; | ||
29 | + uint64_t tr_addr = s->slots[slot].transfer_ring + | ||
30 | + s->slots[slot].tr_trb_idx * sizeof(*trb); | ||
31 | + | ||
32 | + trb->control |= s->slots[slot].tr_trb_c; /* C */ | ||
33 | + | ||
34 | + t.parameter = cpu_to_le64(trb->parameter); | ||
35 | + t.status = cpu_to_le32(trb->status); | ||
36 | + t.control = cpu_to_le32(trb->control); | ||
37 | + | ||
38 | + qtest_memwrite(s->parent->qts, tr_addr, &t, sizeof(t)); | ||
39 | + s->slots[slot].tr_trb_idx++; | ||
40 | + /* Last entry contains the link, so wrap back */ | ||
41 | + if (s->slots[slot].tr_trb_idx == s->slots[slot].tr_trb_entries - 1) { | ||
42 | + set_link_trb(s, s->slots[slot].transfer_ring, | ||
43 | + s->slots[slot].tr_trb_c, | ||
44 | + s->slots[slot].tr_trb_entries); | ||
45 | + s->slots[slot].tr_trb_idx = 0; | ||
46 | + s->slots[slot].tr_trb_c ^= 1; | ||
47 | + } | ||
48 | + xhci_db_writel(s, slot, 1); /* doorbell slot, EP0 target */ | ||
49 | +} | ||
50 | + | ||
51 | /* | ||
52 | * This test brings up an endpoint and runs some noops through its command | ||
53 | - * ring and gets responses back on the event ring. | ||
54 | + * ring and gets responses back on the event ring, then brings up a device | ||
55 | + * context and runs some noops through its transfer ring. | ||
56 | * | ||
57 | * This could be librified in future (like AHCI0 to have a way to bring up | ||
58 | * an endpoint to test device protocols. | ||
59 | @@ -XXX,XX +XXX,XX @@ static void pci_xhci_stress_rings(void) | ||
60 | |||
61 | /* XXX: Could check EP state is running */ | ||
62 | |||
63 | + /* Wrap the transfer ring a few times */ | ||
64 | + for (i = 0; i < 100; i++) { | ||
65 | + /* Issue a transfer ring slot 0 noop */ | ||
66 | + memset(&trb, 0, sizeof(trb)); | ||
67 | + trb.control |= TR_NOOP << TRB_TYPE_SHIFT; | ||
68 | + trb.control |= TRB_TR_IOC; | ||
69 | + submit_tr_trb(s, slotid, &trb); | ||
70 | + wait_event_trb(s, &trb); | ||
71 | + } | ||
72 | + | ||
73 | /* Shut it down */ | ||
74 | qpci_msix_disable(s->dev); | ||
75 | |||
76 | -- | ||
77 | 2.45.2 | diff view generated by jsdifflib |