core: Reuse buffers for tx, allow message pools
Use new m_msg_alloc/m_msg_free operations for whole-message
MCTP buffers. m_realloc is no longer used, instead the maximum
sized buffer is allocated for each reassembly.
This allows applications to keep a pool of MCTP message buffers.
Don't create a queue of packets to transmit, instead reuse a single
binding-provided tx_storage buffer for each transmitted packet, which
can be static for bindings that have a known maximum packet size.
Asynchronous users/bindings can no longer rely on the core for queueing
TX packets, instead they should test mctp_is_tx_ready() prior to calling
mctp_message_tx(). The stack will return -EBUSY from mctp_message_tx()
if there is already a message pending to send.
Bindings must be updated to add the tx_storage member, and the core will
no longer free packets passed to mctp_bus_rx().
Change-Id: I2598bb91026ccef01b268c52b06c0f8e20bebb1e
Signed-off-by: Matt Johnston <matt@codeconstruct.com.au>
diff --git a/astlpc.c b/astlpc.c
index d322b7c..0acc39b 100644
--- a/astlpc.c
+++ b/astlpc.c
@@ -870,6 +870,26 @@
return rc == -EBUSY ? 0 : rc;
}
+/* Update binding pkt_size and reallocate tx_storage */
+static int mctp_astlpc_set_pkt_size(struct mctp_binding_astlpc *astlpc,
+ size_t pkt_size)
+{
+ size_t body = MCTP_BODY_SIZE(pkt_size);
+ body += astlpc->binding.pkt_header + astlpc->binding.pkt_trailer;
+ size_t pktbuf_size = MCTP_PKTBUF_SIZE(body);
+ /* Reallocate TX storage */
+ if (astlpc->binding.tx_storage) {
+ __mctp_free(astlpc->binding.tx_storage);
+ }
+ astlpc->binding.tx_storage = __mctp_alloc(pktbuf_size);
+ if (!astlpc->binding.tx_storage) {
+ return -ENOMEM;
+ }
+
+ astlpc->binding.pkt_size = pkt_size;
+ return 0;
+}
+
static uint32_t mctp_astlpc_calculate_mtu(struct mctp_binding_astlpc *astlpc,
struct mctp_astlpc_layout *layout)
{
@@ -940,8 +960,13 @@
return -EINVAL;
}
- if (astlpc->proto->version >= 2)
- astlpc->binding.pkt_size = MCTP_PACKET_SIZE(mtu);
+ if (astlpc->proto->version >= 2) {
+ rc = mctp_astlpc_set_pkt_size(astlpc, MCTP_PACKET_SIZE(mtu));
+ if (rc) {
+ astlpc_prwarn(astlpc, "Allocation error");
+ return rc;
+ }
+ }
return 0;
}
@@ -1056,9 +1081,9 @@
mctp_bus_rx(&astlpc->binding, pkt);
} else {
/* TODO: Drop any associated assembly */
- mctp_pktbuf_free(pkt);
astlpc_prdebug(astlpc, "Dropped corrupt packet");
}
+ mctp_pktbuf_free(pkt);
}
static void mctp_astlpc_tx_complete(struct mctp_binding_astlpc *astlpc)
@@ -1266,8 +1291,6 @@
astlpc->requested_mtu = mtu;
astlpc->binding.name = "astlpc";
astlpc->binding.version = 1;
- astlpc->binding.pkt_size =
- MCTP_PACKET_SIZE(mtu > MCTP_BTU ? mtu : MCTP_BTU);
astlpc->binding.pkt_header = 4;
astlpc->binding.pkt_trailer = 4;
astlpc->binding.tx = mctp_binding_astlpc_tx;
@@ -1281,6 +1304,14 @@
return NULL;
}
+ if (mctp_astlpc_set_pkt_size(
+ astlpc,
+ MCTP_PACKET_SIZE(mtu > MCTP_BTU ? mtu : MCTP_BTU)) != 0) {
+ astlpc_prerr(astlpc, "%s: Allocation error", __func__);
+ __mctp_free(astlpc);
+ return NULL;
+ }
+
return astlpc;
}
@@ -1326,6 +1357,7 @@
/* Clear channel-active and bmc-ready */
if (astlpc->mode == MCTP_BINDING_ASTLPC_MODE_BMC)
mctp_astlpc_kcs_set_status(astlpc, 0);
+ __mctp_free(astlpc->binding.tx_storage);
__mctp_free(astlpc);
}