From ff4c2f9a3fa6f20b95ef88e172bf355b367434dc Mon Sep 17 00:00:00 2001 From: Rick Gaiser Date: Sun, 1 Nov 2026 23:51:04 +0100 Subject: [PATCH] ps2link: Send each fileio write as one request with one reply pko_write_file split every write into PKO_MAX_WRITE_SEGMENT (1448 byte) pieces and waited for a PKO_WRITE_RLY after each one, so writes to host: cost a network round trip per 1448 bytes. ps2client already reads a write request's nbytes from the socket whatever their size, so send one request header for the whole length, the data straight from the caller's buffer, and wait for one reply (checked as before). On a PS2 (ps2link over Ethernet to ps2client on Linux), one fileio WRITE call of 32 KiB from the EE goes from 40.7 ms to 22.5 ms, and the sustained write rate from 0.80 MB/s to 1.46 MB/s at every size from 16 KiB to 256 KiB. Reads are unchanged (2.1 MB/s). The ZEROCOPY option only chose between copying each segment into the packet buffer or sending it in place; the data is now always sent in place, so the option is gone. Co-Authored-By: Claude Opus 5.5 --- Makefile | 5 +-- iop/Makefile | 4 --- iop/net_fio.c | 98 +++++++++++++++++++-------------------------------- 3 files changed, 38 insertions(+), 69 deletions(-) diff --git a/Makefile b/Makefile index 7cd8800..903d89d 100644 --- a/Makefile +++ b/Makefile @@ -6,9 +6,6 @@ DEBUG ?= 0 # Set this to 1 to build a highloading version, 0 for normal low version LOADHIGH ?= 0 -# Set this to 1 to enable zero-copy on fileio writes. -ZEROCOPY ?= 0 - # Set this to 1 to power off the ps2 when the reset button is tapped # otherwise it will try and reset ps2link PWOFFONRESET ?= 0 @@ -29,7 +26,7 @@ $(EE_BIN): ee $(EE_BIN_PKD): $(EE_BIN) ps2-packer $< $@ > /dev/null -export DEBUG LOADHIGH ZEROCOPY PWOFFONRESET +export DEBUG LOADHIGH PWOFFONRESET ee: iop $(MAKE) -C ee diff --git a/iop/Makefile b/iop/Makefile index c5564f1..e4ac81a 100644 --- a/iop/Makefile +++ b/iop/Makefile @@ -14,10 +14,6 @@ IOP_LIBS += IOP_LDFLAGS += IOP_CFLAGS += -Werror -# Enable zero-copy on fileio writes. -ifeq ($(ZEROCOPY),1) -IOP_CFLAGS += -DZEROCOPY -endif # Enable debug mode ifeq ($(DEBUG),1) diff --git a/iop/net_fio.c b/iop/net_fio.c index b7ed26a..d14cd46 100644 --- a/iop/net_fio.c +++ b/iop/net_fio.c @@ -265,21 +265,26 @@ int pko_lseek_file(int fd, unsigned int offset, int whence) //---------------------------------------------------------------------- -// +// Write: one request for the whole length, the data after it as one +// stream, then one reply. ps2client takes the request's nbytes from the +// socket whatever their size, so the data need not be split into +// PKO_MAX_WRITE_SEGMENT pieces with a reply each (a round trip per 1448 +// bytes, which held writes to about 0.8 MB/s). int pko_write_file(int fd, char *buf, int length) { pko_pkt_write_req *writecmd; pko_pkt_file_rly *writerly; int hlen; - int writtenbytes; - int nbytes; int retval; if (pko_fileio_sock < 0 || length < 0) { return -1; } + if (length == 0) { + return 0; + } - dbgprintf("pko_file: file write req (fd: %d)\n", fd); + dbgprintf("pko_file: file write req (fd: %d, %d bytes)\n", fd, length); writecmd = (pko_pkt_write_req *)&send_packet[0]; writerly = (pko_pkt_file_rly *)&recv_packet[0]; @@ -288,69 +293,40 @@ int pko_write_file(int fd, char *buf, int length) writecmd->cmd = htonl(PKO_WRITE_CMD); writecmd->len = htons(hlen); writecmd->fd = htonl(fd); + writecmd->nbytes = htonl(length); - // Divide the write request - writtenbytes = 0; - while (writtenbytes < length) { - - if ((length - writtenbytes) > PKO_MAX_WRITE_SEGMENT) { - // Need to split in several read reqs - nbytes = PKO_MAX_WRITE_SEGMENT; - } else { - nbytes = length - writtenbytes; - } - - writecmd->nbytes = htonl(nbytes); -#ifdef ZEROCOPY - /* Send the packet header. */ - if (pko_lwip_send(pko_fileio_sock, writecmd, hlen, 0) < 0) - return -1; - /* Send the write() data. */ - if (pko_lwip_send(pko_fileio_sock, &buf[writtenbytes], nbytes, 0) < 0) - return -1; -#else - // Copy data to the acutal packet - memcpy(&send_packet[sizeof(pko_pkt_write_req)], &buf[writtenbytes], - nbytes); - - if (pko_lwip_send(pko_fileio_sock, writecmd, hlen + nbytes, 0) < 0) - return -1; -#endif - - - // Get reply - if (!pko_accept_pkt(pko_fileio_sock, (char *)writerly, - sizeof(pko_pkt_file_rly), PKO_WRITE_RLY)) { - dbgprintf("pko_file: pko_write_file: " - "did not receive PKO_WRITE_RLY\n"); - return -1; - } - retval = ntohl(writerly->retval); + /* The packet header, then the write() data straight from buf. */ + if (pko_lwip_send(pko_fileio_sock, writecmd, hlen, 0) < 0) + return -1; + if (pko_lwip_send(pko_fileio_sock, buf, length, 0) < 0) + return -1; - dbgprintf("pko_file: wrote %d bytes (asked for %d)\n", - retval, nbytes); + // Get reply + if (!pko_accept_pkt(pko_fileio_sock, (char *)writerly, + sizeof(pko_pkt_file_rly), PKO_WRITE_RLY)) { + dbgprintf("pko_file: pko_write_file: " + "did not receive PKO_WRITE_RLY\n"); + return -1; + } + retval = ntohl(writerly->retval); - if (retval < 0) { - // Error - dbgprintf("pko_file: pko_write_file: received error on write req (%d)\n", - retval); - return retval; - } + dbgprintf("pko_file: wrote %d bytes (asked for %d)\n", retval, length); - if (!pko_fileio_write_progress_valid(retval, nbytes)) { - dbgprintf("pko_file: invalid write reply %d (requested %d)\n", - retval, nbytes); - pko_close_socket(); - return -1; - } + if (retval < 0) { + // Error + dbgprintf("pko_file: pko_write_file: received error on write req (%d)\n", + retval); + return retval; + } - writtenbytes += retval; - if (retval < nbytes) { - // EOF? - break; - } + if (!pko_fileio_write_progress_valid(retval, length)) { + dbgprintf("pko_file: invalid write reply %d (requested %d)\n", + retval, length); + pko_close_socket(); + return -1; } - return writtenbytes; + + return retval; } //----------------------------------------------------------------------