* [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes
@ 2013-12-17 1:39 Peter Crosthwaite
2013-12-17 1:40 ` [Qemu-devel] [PATCH v1 01/11] char/cadence_uart: Mark struct fields as public/private Peter Crosthwaite
` (10 more replies)
0 siblings, 11 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:39 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
When using QEMU in some terminal environments, char back-ends for serial
devices can return EAGAIN for non trivial periods. This coupled with use
of qemu_chr_fe_write_all() is a leading cause of:
main-loop: WARNING: I/O thread spun for 1000 iterations
This series fixes this for cadence_uart by replacing the open loop
tx-write logic with a proper closed-loop that is responsive to the
back-end short return.
Various trivial cleanups are at the front of the series. Last patch is
the main event.
There is also a major performance increase with removal of the tx timer
logic (P7).
As a test, I've been using QEMU in a terminal over trans-pacific SSH.
Before this series:
$ time ./qemu-build/arm-softmmu/qemu-system-arm -M xilinx-zynq-a9 ...
main-loop: WARNING: I/O thread spun for 1000 iterations
Booting Linux on physical CPU 0x0
...
PetaLinux v2013.04 (Yocto 1.3) zynq ttyPS0
zynq login: QEMU: Terminated
real 2m26.908s
user 1m41.430s
sys 1m7.116s
And after:
$ time ./qemu-build/arm-softmmu/qemu-system-arm -M xilinx-zynq-a9 ...
Booting Linux on physical CPU 0x0
...
PetaLinux v2013.04 (Yocto 1.3) zynq ttyPS0
zynq login: QEMU: Terminated
real 0m16.149s
user 0m10.357s
sys 0m0.164s
Peter Crosthwaite (11):
char/cadence_uart: Mark struct fields as public/private
char/cadence_uart: Add missing uart_update_state
char/cadence_uart: Fix reset.
char/cadence_uart: s/r_fifo/rx_fifo
char/cadence_uart: Simplify status generation
char/cadence_uart: Define Missing SR/ISR fields
char/cadence_uart: Remove TX timer & add TX FIFO state
char/cadence_uart: Fix can_receive logic
char/cadence_uart: Use the TX fifo for transmission
char/cadence_uart: Delete redundant rx rst logic
char/cadence_uart: Implement Tx flow control
hw/char/cadence_uart.c | 153 ++++++++++++++++++++++++++++---------------------
1 file changed, 87 insertions(+), 66 deletions(-)
--
1.8.5.1
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v1 01/11] char/cadence_uart: Mark struct fields as public/private
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
@ 2013-12-17 1:40 ` Peter Crosthwaite
2013-12-18 23:15 ` Andreas Färber
2013-12-17 1:40 ` [Qemu-devel] [PATCH v1 02/11] char/cadence_uart: Add missing uart_update_state Peter Crosthwaite
` (9 subsequent siblings)
10 siblings, 1 reply; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:40 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
As per current QOM conventions.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/char/cadence_uart.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index f18db53..2f19a53 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -110,7 +110,9 @@
#define CADENCE_UART(obj) OBJECT_CHECK(UartState, (obj), TYPE_CADENCE_UART)
typedef struct {
+ /* <private> */
SysBusDevice parent_obj;
+ /* <public> */
MemoryRegion iomem;
uint32_t r[R_MAX];
--
1.8.5.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v1 02/11] char/cadence_uart: Add missing uart_update_state
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
2013-12-17 1:40 ` [Qemu-devel] [PATCH v1 01/11] char/cadence_uart: Mark struct fields as public/private Peter Crosthwaite
@ 2013-12-17 1:40 ` Peter Crosthwaite
2013-12-17 1:41 ` [Qemu-devel] [PATCH v1 03/11] char/cadence_uart: Fix reset Peter Crosthwaite
` (8 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:40 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
This should be rechecked on bus write accesses as such accesses may
change the underlying state that generates the interrupt. Particular
relevant for when the guest touches the interrupt status or mask.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/char/cadence_uart.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 2f19a53..a43f92c 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -403,6 +403,7 @@ static void uart_write(void *opaque, hwaddr offset,
uart_parameters_setup(s);
break;
}
+ uart_update_status(s);
}
static uint64_t uart_read(void *opaque, hwaddr offset,
--
1.8.5.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v1 03/11] char/cadence_uart: Fix reset.
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
2013-12-17 1:40 ` [Qemu-devel] [PATCH v1 01/11] char/cadence_uart: Mark struct fields as public/private Peter Crosthwaite
2013-12-17 1:40 ` [Qemu-devel] [PATCH v1 02/11] char/cadence_uart: Add missing uart_update_state Peter Crosthwaite
@ 2013-12-17 1:41 ` Peter Crosthwaite
2013-12-17 1:42 ` [Qemu-devel] [PATCH v1 04/11] char/cadence_uart: s/r_fifo/rx_fifo Peter Crosthwaite
` (7 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:41 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
Don't reset the uart as an init step. Register the reset function as a
proper reset fn instead.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/char/cadence_uart.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index a43f92c..263d31e 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -431,8 +431,10 @@ static const MemoryRegionOps uart_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void cadence_uart_reset(UartState *s)
+static void cadence_uart_reset(DeviceState *dev)
{
+ UartState *s = CADENCE_UART(dev);
+
s->r[R_CR] = 0x00000128;
s->r[R_IMR] = 0;
s->r[R_CISR] = 0;
@@ -465,8 +467,6 @@ static int cadence_uart_init(SysBusDevice *dev)
s->chr = qemu_char_get_next_serial();
- cadence_uart_reset(s);
-
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
uart_event, s);
@@ -508,6 +508,7 @@ static void cadence_uart_class_init(ObjectClass *klass, void *data)
sdc->init = cadence_uart_init;
dc->vmsd = &vmstate_cadence_uart;
+ dc->reset = cadence_uart_reset;
}
static const TypeInfo cadence_uart_info = {
--
1.8.5.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v1 04/11] char/cadence_uart: s/r_fifo/rx_fifo
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
` (2 preceding siblings ...)
2013-12-17 1:41 ` [Qemu-devel] [PATCH v1 03/11] char/cadence_uart: Fix reset Peter Crosthwaite
@ 2013-12-17 1:42 ` Peter Crosthwaite
2013-12-17 1:42 ` [Qemu-devel] [PATCH v1 05/11] char/cadence_uart: Simplify status generation Peter Crosthwaite
` (6 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:42 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
Rename this field to match the many other uses of "rx". Xilinx
docmentation (UG585) also refers to this as "RxFIFO".
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/char/cadence_uart.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 263d31e..e12d50e 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -116,7 +116,7 @@ typedef struct {
MemoryRegion iomem;
uint32_t r[R_MAX];
- uint8_t r_fifo[RX_FIFO_SIZE];
+ uint8_t rx_fifo[RX_FIFO_SIZE];
uint32_t rx_wpos;
uint32_t rx_count;
uint64_t char_tx_time;
@@ -280,7 +280,7 @@ static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
s->r[R_CISR] |= UART_INTR_ROVR;
} else {
for (i = 0; i < size; i++) {
- s->r_fifo[s->rx_wpos] = buf[i];
+ s->rx_fifo[s->rx_wpos] = buf[i];
s->rx_wpos = (s->rx_wpos + 1) % RX_FIFO_SIZE;
s->rx_count++;
@@ -344,7 +344,7 @@ static void uart_read_rx_fifo(UartState *s, uint32_t *c)
if (s->rx_count) {
uint32_t rx_rpos =
(RX_FIFO_SIZE + s->rx_wpos - s->rx_count) % RX_FIFO_SIZE;
- *c = s->r_fifo[rx_rpos];
+ *c = s->rx_fifo[rx_rpos];
s->rx_count--;
if (!s->rx_count) {
@@ -492,7 +492,7 @@ static const VMStateDescription vmstate_cadence_uart = {
.post_load = cadence_uart_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(r, UartState, R_MAX),
- VMSTATE_UINT8_ARRAY(r_fifo, UartState, RX_FIFO_SIZE),
+ VMSTATE_UINT8_ARRAY(rx_fifo, UartState, RX_FIFO_SIZE),
VMSTATE_UINT32(rx_count, UartState),
VMSTATE_UINT32(rx_wpos, UartState),
VMSTATE_TIMER(fifo_trigger_handle, UartState),
--
1.8.5.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v1 05/11] char/cadence_uart: Simplify status generation
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
` (3 preceding siblings ...)
2013-12-17 1:42 ` [Qemu-devel] [PATCH v1 04/11] char/cadence_uart: s/r_fifo/rx_fifo Peter Crosthwaite
@ 2013-12-17 1:42 ` Peter Crosthwaite
2013-12-17 1:43 ` [Qemu-devel] [PATCH v1 06/11] char/cadence_uart: Define Missing SR/ISR fields Peter Crosthwaite
` (5 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:42 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
The status register bits are always pure functions of other device
state. Move the generation of these bits to the update_status()
function to simplify. Makes developing much easier as theres now no need
to recheck status bits on all the changes to rx/tx fifo state.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/char/cadence_uart.c | 33 ++++++++-------------------------
1 file changed, 8 insertions(+), 25 deletions(-)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index e12d50e..1d006c5 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -128,6 +128,13 @@ typedef struct {
static void uart_update_status(UartState *s)
{
+ s->r[R_SR] = 0;
+
+ s->r[R_SR] |= s->rx_count == RX_FIFO_SIZE ? UART_SR_INTR_RFUL : 0;
+ s->r[R_SR] |= !s->rx_count ? UART_SR_INTR_REMPTY : 0;
+ s->r[R_SR] |= s->rx_count >= s->r[R_RTRIG] ? UART_SR_INTR_RTRIG : 0;
+
+ s->r[R_SR] |= UART_SR_INTR_TEMPTY;
s->r[R_CISR] |= s->r[R_SR] & UART_SR_TO_CISR_MASK;
qemu_set_irq(s->irq, !!(s->r[R_IMR] & s->r[R_CISR]));
}
@@ -166,15 +173,10 @@ static void uart_rx_reset(UartState *s)
if (s->chr) {
qemu_chr_accept_input(s->chr);
}
-
- s->r[R_SR] |= UART_SR_INTR_REMPTY;
- s->r[R_SR] &= ~UART_SR_INTR_RFUL;
}
static void uart_tx_reset(UartState *s)
{
- s->r[R_SR] |= UART_SR_INTR_TEMPTY;
- s->r[R_SR] &= ~UART_SR_INTR_TFUL;
}
static void uart_send_breaks(UartState *s)
@@ -274,8 +276,6 @@ static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
return;
}
- s->r[R_SR] &= ~UART_SR_INTR_REMPTY;
-
if (s->rx_count == RX_FIFO_SIZE) {
s->r[R_CISR] |= UART_INTR_ROVR;
} else {
@@ -283,15 +283,6 @@ static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
s->rx_fifo[s->rx_wpos] = buf[i];
s->rx_wpos = (s->rx_wpos + 1) % RX_FIFO_SIZE;
s->rx_count++;
-
- if (s->rx_count == RX_FIFO_SIZE) {
- s->r[R_SR] |= UART_SR_INTR_RFUL;
- break;
- }
-
- if (s->rx_count >= s->r[R_RTRIG]) {
- s->r[R_SR] |= UART_SR_INTR_RTRIG;
- }
}
timer_mod(s->fifo_trigger_handle, new_rx_time +
(s->char_tx_time * 4));
@@ -339,26 +330,17 @@ static void uart_read_rx_fifo(UartState *s, uint32_t *c)
return;
}
- s->r[R_SR] &= ~UART_SR_INTR_RFUL;
-
if (s->rx_count) {
uint32_t rx_rpos =
(RX_FIFO_SIZE + s->rx_wpos - s->rx_count) % RX_FIFO_SIZE;
*c = s->rx_fifo[rx_rpos];
s->rx_count--;
- if (!s->rx_count) {
- s->r[R_SR] |= UART_SR_INTR_REMPTY;
- }
qemu_chr_accept_input(s->chr);
} else {
*c = 0;
- s->r[R_SR] |= UART_SR_INTR_REMPTY;
}
- if (s->rx_count < s->r[R_RTRIG]) {
- s->r[R_SR] &= ~UART_SR_INTR_RTRIG;
- }
uart_update_status(s);
}
@@ -447,6 +429,7 @@ static void cadence_uart_reset(DeviceState *dev)
s->rx_count = 0;
s->rx_wpos = 0;
+ uart_update_status(s);
}
static int cadence_uart_init(SysBusDevice *dev)
--
1.8.5.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v1 06/11] char/cadence_uart: Define Missing SR/ISR fields
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
` (4 preceding siblings ...)
2013-12-17 1:42 ` [Qemu-devel] [PATCH v1 05/11] char/cadence_uart: Simplify status generation Peter Crosthwaite
@ 2013-12-17 1:43 ` Peter Crosthwaite
2013-12-17 1:43 ` [Qemu-devel] [PATCH v1 07/11] char/cadence_uart: Remove TX timer & add TX FIFO state Peter Crosthwaite
` (4 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:43 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
Some (interrupt) status register bits relating to the TxFIFO path were
not defined. Define them. This prepares support for proper Tx data path
flow control.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/char/cadence_uart.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 1d006c5..a9700f7 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -34,6 +34,9 @@
#define UART_SR_INTR_RFUL 0x00000004
#define UART_SR_INTR_TEMPTY 0x00000008
#define UART_SR_INTR_TFUL 0x00000010
+/* somewhat awkwardly, TTRIG is misaligned between SR and ISR */
+#define UART_SR_TTRIG 0x00002000
+#define UART_INTR_TTRIG 0x00000400
/* bits fields in CSR that correlate to CISR. If any of these bits are set in
* SR, then the same bit in CISR is set high too */
#define UART_SR_TO_CISR_MASK 0x0000001F
@@ -43,6 +46,7 @@
#define UART_INTR_PARE 0x00000080
#define UART_INTR_TIMEOUT 0x00000100
#define UART_INTR_DMSI 0x00000200
+#define UART_INTR_TOVR 0x00001000
#define UART_SR_RACTIVE 0x00000400
#define UART_SR_TACTIVE 0x00000800
--
1.8.5.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v1 07/11] char/cadence_uart: Remove TX timer & add TX FIFO state
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
` (5 preceding siblings ...)
2013-12-17 1:43 ` [Qemu-devel] [PATCH v1 06/11] char/cadence_uart: Define Missing SR/ISR fields Peter Crosthwaite
@ 2013-12-17 1:43 ` Peter Crosthwaite
2013-12-17 1:44 ` [Qemu-devel] [PATCH v1 08/11] char/cadence_uart: Fix can_receive logic Peter Crosthwaite
` (3 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:43 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
This tx timer implementation is flawed. Despite the controller
attempting to time the guest visable assertion of the TX-empty status
bit (and corresponding interrupt) the controller is still transmitting
characters instantaneously. There is also no sense of multiple character
delay.
The only side effect of this timer is assertion of tx-empty status. So
just remove the timer completely and hold tx-empty as permanently
asserted (its reset status). This matches the actual behaviour of
instantaneous transmission.
While we are VMSD version bumping, add the tx_fifo as device state to
prepare for upcomming TxFIFO flow control. Implement the interrupt
generation logic for the TxFIFO occupancy.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/char/cadence_uart.c | 44 +++++++++++++-------------------------------
1 file changed, 13 insertions(+), 31 deletions(-)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index a9700f7..f28e503 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -121,13 +121,14 @@ typedef struct {
MemoryRegion iomem;
uint32_t r[R_MAX];
uint8_t rx_fifo[RX_FIFO_SIZE];
+ uint8_t tx_fifo[TX_FIFO_SIZE];
uint32_t rx_wpos;
uint32_t rx_count;
+ uint32_t tx_count;
uint64_t char_tx_time;
CharDriverState *chr;
qemu_irq irq;
QEMUTimer *fifo_trigger_handle;
- QEMUTimer *tx_time_handle;
} UartState;
static void uart_update_status(UartState *s)
@@ -138,8 +139,12 @@ static void uart_update_status(UartState *s)
s->r[R_SR] |= !s->rx_count ? UART_SR_INTR_REMPTY : 0;
s->r[R_SR] |= s->rx_count >= s->r[R_RTRIG] ? UART_SR_INTR_RTRIG : 0;
- s->r[R_SR] |= UART_SR_INTR_TEMPTY;
+ s->r[R_SR] |= s->tx_count == TX_FIFO_SIZE ? UART_SR_INTR_TFUL : 0;
+ s->r[R_SR] |= !s->tx_count ? UART_SR_INTR_TEMPTY : 0;
+ s->r[R_SR] |= s->tx_count >= s->r[R_TTRIG] ? UART_SR_TTRIG : 0;
+
s->r[R_CISR] |= s->r[R_SR] & UART_SR_TO_CISR_MASK;
+ s->r[R_CISR] |= s->r[R_SR] & UART_SR_TTRIG ? UART_INTR_TTRIG : 0;
qemu_set_irq(s->irq, !!(s->r[R_IMR] & s->r[R_CISR]));
}
@@ -152,24 +157,6 @@ static void fifo_trigger_update(void *opaque)
uart_update_status(s);
}
-static void uart_tx_redo(UartState *s)
-{
- uint64_t new_tx_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-
- timer_mod(s->tx_time_handle, new_tx_time + s->char_tx_time);
-
- s->r[R_SR] |= UART_SR_INTR_TEMPTY;
-
- uart_update_status(s);
-}
-
-static void uart_tx_write(void *opaque)
-{
- UartState *s = (UartState *)opaque;
-
- uart_tx_redo(s);
-}
-
static void uart_rx_reset(UartState *s)
{
s->rx_wpos = 0;
@@ -181,6 +168,7 @@ static void uart_rx_reset(UartState *s)
static void uart_tx_reset(UartState *s)
{
+ s->tx_count = 0;
}
static void uart_send_breaks(UartState *s)
@@ -261,10 +249,6 @@ static void uart_ctrl_update(UartState *s)
s->r[R_CR] &= ~(UART_CR_TXRST | UART_CR_RXRST);
- if ((s->r[R_CR] & UART_CR_TX_EN) && !(s->r[R_CR] & UART_CR_TX_DIS)) {
- uart_tx_redo(s);
- }
-
if (s->r[R_CR] & UART_CR_STARTBRK && !(s->r[R_CR] & UART_CR_STOPBRK)) {
uart_send_breaks(s);
}
@@ -447,9 +431,6 @@ static int cadence_uart_init(SysBusDevice *dev)
s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
(QEMUTimerCB *)fifo_trigger_update, s);
- s->tx_time_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
- (QEMUTimerCB *)uart_tx_write, s);
-
s->char_tx_time = (get_ticks_per_sec() / 9600) * 10;
s->chr = qemu_char_get_next_serial();
@@ -473,17 +454,18 @@ static int cadence_uart_post_load(void *opaque, int version_id)
static const VMStateDescription vmstate_cadence_uart = {
.name = "cadence_uart",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
+ .version_id = 2,
+ .minimum_version_id = 2,
+ .minimum_version_id_old = 2,
.post_load = cadence_uart_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(r, UartState, R_MAX),
VMSTATE_UINT8_ARRAY(rx_fifo, UartState, RX_FIFO_SIZE),
+ VMSTATE_UINT8_ARRAY(tx_fifo, UartState, RX_FIFO_SIZE),
VMSTATE_UINT32(rx_count, UartState),
+ VMSTATE_UINT32(tx_count, UartState),
VMSTATE_UINT32(rx_wpos, UartState),
VMSTATE_TIMER(fifo_trigger_handle, UartState),
- VMSTATE_TIMER(tx_time_handle, UartState),
VMSTATE_END_OF_LIST()
}
};
--
1.8.5.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v1 08/11] char/cadence_uart: Fix can_receive logic
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
` (6 preceding siblings ...)
2013-12-17 1:43 ` [Qemu-devel] [PATCH v1 07/11] char/cadence_uart: Remove TX timer & add TX FIFO state Peter Crosthwaite
@ 2013-12-17 1:44 ` Peter Crosthwaite
2013-12-17 1:45 ` [Qemu-devel] [PATCH v1 09/11] char/cadence_uart: Use the TX fifo for transmission Peter Crosthwaite
` (2 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:44 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
The can_receive logic was only taking into account the RxFIFO
occupancy. RxFIFO population is only used for the echo and normal modes
however. Improve the logic to correctly return the true number of
receivable characters based on the current mode:
Normal mode: RxFIFO vacancy.
Remote loopback: TxFIFO vacancy.
Echo mode: The min of the TxFIFO and RxFIFO vacancies.
Local Loopback: Return non-zero (to implement droppage)
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/char/cadence_uart.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index f28e503..85e9a00 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -233,8 +233,16 @@ static void uart_parameters_setup(UartState *s)
static int uart_can_receive(void *opaque)
{
UartState *s = (UartState *)opaque;
+ int ret = MAX(RX_FIFO_SIZE, TX_FIFO_SIZE);
+ uint32_t ch_mode = s->r[R_MR] & UART_MR_CHMODE;
- return RX_FIFO_SIZE - s->rx_count;
+ if (ch_mode == NORMAL_MODE || ch_mode == ECHO_MODE) {
+ ret = MIN(ret, RX_FIFO_SIZE - s->rx_count);
+ }
+ if (ch_mode == REMOTE_LOOPBACK || ch_mode == ECHO_MODE) {
+ ret = MIN(ret, TX_FIFO_SIZE - s->tx_count);
+ }
+ return ret;
}
static void uart_ctrl_update(UartState *s)
--
1.8.5.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v1 09/11] char/cadence_uart: Use the TX fifo for transmission
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
` (7 preceding siblings ...)
2013-12-17 1:44 ` [Qemu-devel] [PATCH v1 08/11] char/cadence_uart: Fix can_receive logic Peter Crosthwaite
@ 2013-12-17 1:45 ` Peter Crosthwaite
2013-12-17 1:45 ` [Qemu-devel] [PATCH v1 10/11] char/cadence_uart: Delete redundant rx rst logic Peter Crosthwaite
2013-12-17 1:46 ` [Qemu-devel] [PATCH v1 11/11] char/cadence_uart: Implement Tx flow control Peter Crosthwaite
10 siblings, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:45 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
Populate the TxFIFO with the Tx data before sending. Prepares
support for proper Tx flow control implementation.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/char/cadence_uart.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 85e9a00..cffb4c3 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -292,7 +292,22 @@ static void uart_write_tx_fifo(UartState *s, const uint8_t *buf, int size)
return;
}
- qemu_chr_fe_write_all(s->chr, buf, size);
+ if (size > TX_FIFO_SIZE - s->tx_count) {
+ size = TX_FIFO_SIZE - s->tx_count;
+ /*
+ * This can only be a guest error via a bad tx fifo register push,
+ * as can_receive() should stop remote loop and echo modes ever getting
+ * us to here.
+ */
+ qemu_log_mask(LOG_GUEST_ERROR, "cadence_uart: TxFIFO overflow");
+ s->r[R_CISR] |= UART_INTR_ROVR;
+ }
+
+ memcpy(s->tx_fifo + s->tx_count, buf, size);
+ s->tx_count += size;
+
+ qemu_chr_fe_write_all(s->chr, s->tx_fifo, s->tx_count);
+ s->tx_count = 0;
}
static void uart_receive(void *opaque, const uint8_t *buf, int size)
--
1.8.5.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v1 10/11] char/cadence_uart: Delete redundant rx rst logic
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
` (8 preceding siblings ...)
2013-12-17 1:45 ` [Qemu-devel] [PATCH v1 09/11] char/cadence_uart: Use the TX fifo for transmission Peter Crosthwaite
@ 2013-12-17 1:45 ` Peter Crosthwaite
2013-12-17 1:46 ` [Qemu-devel] [PATCH v1 11/11] char/cadence_uart: Implement Tx flow control Peter Crosthwaite
10 siblings, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:45 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
uart_rx_reset() called immediately above already does this. Remove.
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/char/cadence_uart.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index cffb4c3..3be110c 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -438,8 +438,6 @@ static void cadence_uart_reset(DeviceState *dev)
uart_rx_reset(s);
uart_tx_reset(s);
- s->rx_count = 0;
- s->rx_wpos = 0;
uart_update_status(s);
}
--
1.8.5.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Qemu-devel] [PATCH v1 11/11] char/cadence_uart: Implement Tx flow control
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
` (9 preceding siblings ...)
2013-12-17 1:45 ` [Qemu-devel] [PATCH v1 10/11] char/cadence_uart: Delete redundant rx rst logic Peter Crosthwaite
@ 2013-12-17 1:46 ` Peter Crosthwaite
10 siblings, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-17 1:46 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, antonynpavlov
If the UART back-end blocks, buffer in the Tx FIFO to try again later.
This stops the IO-thread busy waiting on char back-ends (which causes
all sorts of performance problems).
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
---
hw/char/cadence_uart.c | 31 +++++++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index 3be110c..6516a3e 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -286,6 +286,34 @@ static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
uart_update_status(s);
}
+static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
+ void *opaque)
+{
+ UartState *s = opaque;
+ int ret;
+
+ /* instant drain the fifo when there's no back-end */
+ if (!s->chr) {
+ s->tx_count = 0;
+ }
+
+ if (!s->tx_count) {
+ return FALSE;
+ }
+
+ ret = qemu_chr_fe_write(s->chr, s->tx_fifo, s->tx_count);
+ s->tx_count -= ret;
+ memmove(s->tx_fifo, s->tx_fifo + ret, s->tx_count);
+
+ if (s->tx_count) {
+ int r = qemu_chr_fe_add_watch(s->chr, G_IO_OUT, cadence_uart_xmit, s);
+ assert(r);
+ }
+
+ uart_update_status(s);
+ return FALSE;
+}
+
static void uart_write_tx_fifo(UartState *s, const uint8_t *buf, int size)
{
if ((s->r[R_CR] & UART_CR_TX_DIS) || !(s->r[R_CR] & UART_CR_TX_EN)) {
@@ -306,8 +334,7 @@ static void uart_write_tx_fifo(UartState *s, const uint8_t *buf, int size)
memcpy(s->tx_fifo + s->tx_count, buf, size);
s->tx_count += size;
- qemu_chr_fe_write_all(s->chr, s->tx_fifo, s->tx_count);
- s->tx_count = 0;
+ cadence_uart_xmit(NULL, G_IO_OUT, s);
}
static void uart_receive(void *opaque, const uint8_t *buf, int size)
--
1.8.5.1
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v1 01/11] char/cadence_uart: Mark struct fields as public/private
2013-12-17 1:40 ` [Qemu-devel] [PATCH v1 01/11] char/cadence_uart: Mark struct fields as public/private Peter Crosthwaite
@ 2013-12-18 23:15 ` Andreas Färber
2013-12-18 23:21 ` Peter Crosthwaite
0 siblings, 1 reply; 14+ messages in thread
From: Andreas Färber @ 2013-12-18 23:15 UTC (permalink / raw)
To: Peter Crosthwaite, qemu-devel; +Cc: peter.maydell, antonynpavlov
Am 17.12.2013 02:40, schrieb Peter Crosthwaite:
> As per current QOM conventions.
>
> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
>
> hw/char/cadence_uart.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
> index f18db53..2f19a53 100644
> --- a/hw/char/cadence_uart.c
> +++ b/hw/char/cadence_uart.c
> @@ -110,7 +110,9 @@
> #define CADENCE_UART(obj) OBJECT_CHECK(UartState, (obj), TYPE_CADENCE_UART)
>
> typedef struct {
> + /* <private> */
> SysBusDevice parent_obj;
> + /* <public> */
Note that it's /*< ... >*/ if I'm not mistaken.
However since this is outside include/ it won't get parsed by the
patches flying around. This being Cadence IP that is likely to be reused
on other SoCs, I do guess we'll end up with an
include/hw/char/cadence_uart.h at some point.
Cheers,
Andreas
>
> MemoryRegion iomem;
> uint32_t r[R_MAX];
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Qemu-devel] [PATCH v1 01/11] char/cadence_uart: Mark struct fields as public/private
2013-12-18 23:15 ` Andreas Färber
@ 2013-12-18 23:21 ` Peter Crosthwaite
0 siblings, 0 replies; 14+ messages in thread
From: Peter Crosthwaite @ 2013-12-18 23:21 UTC (permalink / raw)
To: Andreas Färber
Cc: Peter Maydell, qemu-devel@nongnu.org Developers, Antony Pavlov
On Thu, Dec 19, 2013 at 9:15 AM, Andreas Färber <afaerber@suse.de> wrote:
> Am 17.12.2013 02:40, schrieb Peter Crosthwaite:
>> As per current QOM conventions.
>>
>> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
>> ---
>>
>> hw/char/cadence_uart.c | 2 ++
>> 1 file changed, 2 insertions(+)
>>
>> diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
>> index f18db53..2f19a53 100644
>> --- a/hw/char/cadence_uart.c
>> +++ b/hw/char/cadence_uart.c
>> @@ -110,7 +110,9 @@
>> #define CADENCE_UART(obj) OBJECT_CHECK(UartState, (obj), TYPE_CADENCE_UART)
>>
>> typedef struct {
>> + /* <private> */
>> SysBusDevice parent_obj;
>> + /* <public> */
>
> Note that it's /*< ... >*/ if I'm not mistaken.
Thanks, will fix v2.
>
> However since this is outside include/ it won't get parsed by the
> patches flying around. This being Cadence IP that is likely to be reused
> on other SoCs, I do guess we'll end up with an
> include/hw/char/cadence_uart.h at some point.
>
Well ideally all peripherals are headerified for the sake of
consistency. I dont think we should be making judgement calls on
coding style based on target usages.
I'm patching old style files as I notice issue just in general
browsing/developing hopefully to one day bring them into line.
Regards,
Peter
> Cheers,
> Andreas
>
>>
>> MemoryRegion iomem;
>> uint32_t r[R_MAX];
>
> --
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
>
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2013-12-18 23:21 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-17 1:39 [Qemu-devel] [PATCH v1 00/11] Cadence UART cleanups and Tx path fixes Peter Crosthwaite
2013-12-17 1:40 ` [Qemu-devel] [PATCH v1 01/11] char/cadence_uart: Mark struct fields as public/private Peter Crosthwaite
2013-12-18 23:15 ` Andreas Färber
2013-12-18 23:21 ` Peter Crosthwaite
2013-12-17 1:40 ` [Qemu-devel] [PATCH v1 02/11] char/cadence_uart: Add missing uart_update_state Peter Crosthwaite
2013-12-17 1:41 ` [Qemu-devel] [PATCH v1 03/11] char/cadence_uart: Fix reset Peter Crosthwaite
2013-12-17 1:42 ` [Qemu-devel] [PATCH v1 04/11] char/cadence_uart: s/r_fifo/rx_fifo Peter Crosthwaite
2013-12-17 1:42 ` [Qemu-devel] [PATCH v1 05/11] char/cadence_uart: Simplify status generation Peter Crosthwaite
2013-12-17 1:43 ` [Qemu-devel] [PATCH v1 06/11] char/cadence_uart: Define Missing SR/ISR fields Peter Crosthwaite
2013-12-17 1:43 ` [Qemu-devel] [PATCH v1 07/11] char/cadence_uart: Remove TX timer & add TX FIFO state Peter Crosthwaite
2013-12-17 1:44 ` [Qemu-devel] [PATCH v1 08/11] char/cadence_uart: Fix can_receive logic Peter Crosthwaite
2013-12-17 1:45 ` [Qemu-devel] [PATCH v1 09/11] char/cadence_uart: Use the TX fifo for transmission Peter Crosthwaite
2013-12-17 1:45 ` [Qemu-devel] [PATCH v1 10/11] char/cadence_uart: Delete redundant rx rst logic Peter Crosthwaite
2013-12-17 1:46 ` [Qemu-devel] [PATCH v1 11/11] char/cadence_uart: Implement Tx flow control Peter Crosthwaite
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).