diff --git a/chardev/baum.c b/chardev/baum.c
index 78b0c87625..5367d82f53 100644
--- a/chardev/baum.c
+++ b/chardev/baum.c
@@ -479,7 +479,7 @@ static int baum_eat_packet(BaumChardev *baum, const uint8_t *buf, int len)
 }
 
 /* The other end is writing some data.  Store it and try to interpret */
-static int baum_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t baum_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     BaumChardev *baum = BAUM_CHARDEV(chr);
     int tocopy, cur, eaten, orig_len = len;
diff --git a/chardev/char-fd.c b/chardev/char-fd.c
index 2421d8e216..bb426fa4b1 100644
--- a/chardev/char-fd.c
+++ b/chardev/char-fd.c
@@ -32,7 +32,7 @@
 #include "chardev/char-io.h"
 
 /* Called with chr_write_lock held.  */
-static int fd_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t fd_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     FDChardev *s = FD_CHARDEV(chr);
 
diff --git a/chardev/char-mux.c b/chardev/char-mux.c
index 6055e76293..3ca732d3a8 100644
--- a/chardev/char-mux.c
+++ b/chardev/char-mux.c
@@ -33,7 +33,7 @@
 /* MUX driver for serial I/O splitting */
 
 /* Called with chr_write_lock held.  */
-static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t mux_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     MuxChardev *d = MUX_CHARDEV(chr);
     int ret;
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index 626ca30cb3..a2b78b44d8 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -125,7 +125,7 @@ static void pty_chr_update_read_handler(Chardev *chr)
 }
 
 /* Called with chr_write_lock held.  */
-static int char_pty_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t char_pty_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     PtyChardev *s = PTY_CHARDEV(chr);
 
diff --git a/chardev/char-ringbuf.c b/chardev/char-ringbuf.c
index 87832e2792..b805a585e3 100644
--- a/chardev/char-ringbuf.c
+++ b/chardev/char-ringbuf.c
@@ -49,12 +49,12 @@ static size_t ringbuf_count(const Chardev *chr)
     return d->prod - d->cons;
 }
 
-static int ringbuf_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t ringbuf_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     RingBufChardev *d = RINGBUF_CHARDEV(chr);
     int i;
 
-    if (!buf || (len < 0)) {
+    if (!buf) {
         return -1;
     }
 
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index 7e627b243e..7c7fb06d48 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -124,7 +124,7 @@ static gboolean tcp_chr_read_poll(void *opaque);
 static void tcp_chr_disconnect(Chardev *chr);
 
 /* Called with chr_write_lock held.  */
-static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t tcp_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     SocketChardev *s = SOCKET_CHARDEV(chr);
 
diff --git a/chardev/char-udp.c b/chardev/char-udp.c
index b6e399e983..577d049d78 100644
--- a/chardev/char-udp.c
+++ b/chardev/char-udp.c
@@ -45,7 +45,7 @@ typedef struct {
 #define UDP_CHARDEV(obj) OBJECT_CHECK(UdpChardev, (obj), TYPE_CHARDEV_UDP)
 
 /* Called with chr_write_lock held.  */
-static int udp_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t udp_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     UdpChardev *s = UDP_CHARDEV(chr);
 
diff --git a/chardev/char.c b/chardev/char.c
index 952f9c9bcc..608c2569f4 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -245,7 +245,7 @@ static void char_init(Object *obj)
     qemu_mutex_init(&chr->chr_write_lock);
 }
 
-static int null_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t null_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     return len;
 }
diff --git a/chardev/msmouse.c b/chardev/msmouse.c
index 0ffd137ce8..0aad738cae 100644
--- a/chardev/msmouse.c
+++ b/chardev/msmouse.c
@@ -133,7 +133,7 @@ static void msmouse_input_sync(DeviceState *dev)
     msmouse_chr_accept_input(chr);
 }
 
-static int msmouse_chr_write(struct Chardev *s, const uint8_t *buf, int len)
+static size_t msmouse_chr_write(struct Chardev *s, const uint8_t *buf, size_t len)
 {
     /* Ignore writes to mouse port */
     return len;
diff --git a/chardev/spice.c b/chardev/spice.c
index e66e3ad568..a9e7b4e374 100644
--- a/chardev/spice.c
+++ b/chardev/spice.c
@@ -193,7 +193,7 @@ static GSource *spice_chr_add_watch(Chardev *chr, GIOCondition cond)
     return (GSource *)src;
 }
 
-static int spice_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t spice_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     SpiceChardev *s = SPICE_CHARDEV(chr);
     int read_bytes;
diff --git a/chardev/testdev.c b/chardev/testdev.c
index 031e9a23e8..6ebaf5fdaf 100644
--- a/chardev/testdev.c
+++ b/chardev/testdev.c
@@ -82,7 +82,7 @@ static int testdev_eat_packet(TestdevChardev *testdev)
 }
 
 /* The other end is writing some data.  Store it and try to interpret */
-static int testdev_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t testdev_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     TestdevChardev *testdev = TESTDEV_CHARDEV(chr);
     int tocopy, eaten, orig_len = len;
diff --git a/chardev/wctablet.c b/chardev/wctablet.c
index 969d014574..52acbdb609 100644
--- a/chardev/wctablet.c
+++ b/chardev/wctablet.c
@@ -203,8 +203,8 @@ static void wctablet_chr_accept_input(Chardev *chr)
     }
 }
 
-static int wctablet_chr_write(struct Chardev *chr,
-                              const uint8_t *buf, int len)
+static size_t wctablet_chr_write(struct Chardev *chr,
+                              const uint8_t *buf, size_t len)
 {
     TabletChardev *tablet = WCTABLET_CHARDEV(chr);
     unsigned int i, clen;
diff --git a/gdbstub.c b/gdbstub.c
index c8478de8f5..bbbb1cfcc1 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1955,7 +1955,7 @@ static void gdb_monitor_output(GDBState *s, const char *msg, int len)
     put_packet(s, buf);
 }
 
-static int gdb_monitor_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t gdb_monitor_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     const char *p = (const char *)buf;
     int max_sz;
diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c
index 0341ded50c..21ac388675 100644
--- a/hw/bt/hci-csr.c
+++ b/hw/bt/hci-csr.c
@@ -314,8 +314,8 @@ static void csrhci_ready_for_next_inpkt(struct csrhci_s *s)
     s->in_hdr = INT_MAX;
 }
 
-static int csrhci_write(struct Chardev *chr,
-                const uint8_t *buf, int len)
+static size_t csrhci_write(struct Chardev *chr,
+                const uint8_t *buf, size_t len)
 {
     struct csrhci_s *s = (struct csrhci_s *)chr;
     int total = 0;
diff --git a/include/chardev/char.h b/include/chardev/char.h
index ef4509bfa3..091a514022 100644
--- a/include/chardev/char.h
+++ b/include/chardev/char.h
@@ -250,7 +250,7 @@ typedef struct ChardevClass {
     void (*open)(Chardev *chr, ChardevBackend *backend,
                  bool *be_opened, Error **errp);
 
-    int (*chr_write)(Chardev *s, const uint8_t *buf, int len);
+    size_t (*chr_write)(Chardev *s, const uint8_t *buf, size_t len);
     size_t (*chr_sync_read)(Chardev *s, const uint8_t *buf, size_t len);
     GSource *(*chr_add_watch)(Chardev *s, GIOCondition cond);
     void (*chr_update_read_handler)(Chardev *s);
diff --git a/ui/console.c b/ui/console.c
index 3a285bae00..5fed0504f4 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1080,7 +1080,7 @@ typedef struct VCChardev {
 #define TYPE_CHARDEV_VC "chardev-vc"
 #define VC_CHARDEV(obj) OBJECT_CHECK(VCChardev, (obj), TYPE_CHARDEV_VC)
 
-static int vc_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t vc_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     VCChardev *drv = VC_CHARDEV(chr);
     QemuConsole *s = drv->console;
diff --git a/ui/gtk.c b/ui/gtk.c
index 3ddb5fe162..7990b58833 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1842,7 +1842,7 @@ static void gd_vc_adjustment_changed(GtkAdjustment *adjustment, void *opaque)
     }
 }
 
-static int gd_vc_chr_write(Chardev *chr, const uint8_t *buf, int len)
+static size_t gd_vc_chr_write(Chardev *chr, const uint8_t *buf, size_t len)
 {
     VCChardev *vcd = VC_CHARDEV(chr);
     VirtualConsole *vc = vcd->console;
