uart_alloc_xmit_buf() allocates the transmit buffer of a serial port. The
buffer only backs the port's kfifo, the data being sent is copied in and
out of it.

This buffer can be allocated with kmalloc() as there's nothing special
about it to go directly to the page allocator.

kmalloc() provides a better API that does not require ugly casts and
kfree() does not need to know the size of the freed object.

Performance difference between kmalloc() and __get_free_pages() is not
measurable as both allocators take an object/page from a per-CPU list for
fast path allocations.

For the slow path the performance is anyway determined by the amount of
reclaim involved rather than by what allocator is used.

While on it, make the local variable holding the buffer a pointer to get
rid of the casts.

Replace use of get_zeroed_page() with kzalloc() and free_page() with
kfree().

Link: 
https://lore.kernel.org/all/[email protected]
Assisted-by: copilot:claude-opus
Signed-off-by: Mike Rapoport (Microsoft) <[email protected]>
---
 drivers/tty/serial/serial_core.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 95774b0f1484..f12ce7d190fe 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -247,29 +247,29 @@ static int uart_alloc_xmit_buf(struct tty_port *port)
        struct uart_state *state = container_of(port, struct uart_state, port);
        struct uart_port *uport;
        unsigned long flags;
-       unsigned long page;
+       unsigned char *buf;
 
        /*
         * Initialise and allocate the transmit and temporary
         * buffer.
         */
-       page = get_zeroed_page(GFP_KERNEL);
-       if (!page)
+       buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!buf)
                return -ENOMEM;
 
        uport = uart_port_ref_lock(state, &flags);
        if (!state->port.xmit_buf) {
-               state->port.xmit_buf = (unsigned char *)page;
+               state->port.xmit_buf = buf;
                kfifo_init(&state->port.xmit_fifo, state->port.xmit_buf,
                                PAGE_SIZE);
                uart_port_unlock_deref(uport, flags);
        } else {
                uart_port_unlock_deref(uport, flags);
                /*
-                * Do not free() the page under the port lock, see
+                * Do not free() the buffer under the port lock, see
                 * uart_free_xmit_buf().
                 */
-               free_page(page);
+               kfree(buf);
        }
 
        return 0;
@@ -283,7 +283,7 @@ static void uart_free_xmit_buf(struct tty_port *port)
        char *xmit_buf;
 
        /*
-        * Do not free() the transmit buffer page under the port lock since
+        * Do not free() the transmit buffer under the port lock since
         * this can create various circular locking scenarios. For instance,
         * console driver may need to allocate/free a debug object, which
         * can end up in printk() recursion.
@@ -294,7 +294,7 @@ static void uart_free_xmit_buf(struct tty_port *port)
        INIT_KFIFO(port->xmit_fifo);
        uart_port_unlock_deref(uport, flags);
 
-       free_page((unsigned long)xmit_buf);
+       kfree(xmit_buf);
 }
 
 /*

-- 
2.53.0


Reply via email to