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