Driver imeplementation for packing the data from the Host Driver to the Device firmware in the eXtended Type-Length-Value (XTLV) Format. Signed-off-by: Gokul Sivakumar --- drivers/net/wireless/infineon/inffmac/xtlv.c | 106 +++++++++++++++++++ drivers/net/wireless/infineon/inffmac/xtlv.h | 37 +++++++ 2 files changed, 143 insertions(+) create mode 100644 drivers/net/wireless/infineon/inffmac/xtlv.c create mode 100644 drivers/net/wireless/infineon/inffmac/xtlv.h diff --git a/drivers/net/wireless/infineon/inffmac/xtlv.c b/drivers/net/wireless/infineon/inffmac/xtlv.c new file mode 100644 index 000000000000..05983783d453 --- /dev/null +++ b/drivers/net/wireless/infineon/inffmac/xtlv.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (c) 2019 Broadcom + * + * Copyright (c) 2025, Infineon Technologies AG, or an affiliate of Infineon Technologies AG. + * All rights reserved. + */ + +#include + +#include +#include +#include + +#include "xtlv.h" + +static int inff_xtlv_header_size(u16 opts) +{ + int len = (int)offsetof(struct inff_xtlv, data); + + if (opts & INFF_XTLV_OPTION_IDU8) + --len; + if (opts & INFF_XTLV_OPTION_LENU8) + --len; + + return len; +} + +int inff_xtlv_data_size(int dlen, u16 opts) +{ + int hsz; + + hsz = inff_xtlv_header_size(opts); + if (opts & INFF_XTLV_OPTION_ALIGN32) + return roundup(dlen + hsz, 4); + + return dlen + hsz; +} + +void inff_xtlv_pack_header(struct inff_xtlv *xtlv, u16 id, u16 len, + const u8 *data, u16 opts) +{ + u8 *data_buf; + u16 mask = INFF_XTLV_OPTION_IDU8 | INFF_XTLV_OPTION_LENU8; + + if (!(opts & mask)) { + u8 *idp = (u8 *)xtlv; + u8 *lenp = idp + sizeof(xtlv->id); + + put_unaligned_le16(id, idp); + put_unaligned_le16(len, lenp); + data_buf = lenp + sizeof(u16); + } else if ((opts & mask) == mask) { /* u8 id and u8 len */ + u8 *idp = (u8 *)xtlv; + u8 *lenp = idp + 1; + + *idp = (u8)id; + *lenp = (u8)len; + data_buf = lenp + sizeof(u8); + } else if (opts & INFF_XTLV_OPTION_IDU8) { /* u8 id, u16 len */ + u8 *idp = (u8 *)xtlv; + u8 *lenp = idp + 1; + + *idp = (u8)id; + put_unaligned_le16(len, lenp); + data_buf = lenp + sizeof(u16); + } else if (opts & INFF_XTLV_OPTION_LENU8) { /* u16 id, u8 len */ + u8 *idp = (u8 *)xtlv; + u8 *lenp = idp + sizeof(u16); + + put_unaligned_le16(id, idp); + *lenp = (u8)len; + data_buf = lenp + sizeof(u8); + } else { + WARN(true, "Unexpected xtlv option"); + return; + } + + if (opts & INFF_XTLV_OPTION_LENU8) { + WARN_ON(len > 0x00ff); + len &= 0xff; + } + + if (data) + memcpy(data_buf, data, len); +} + +u32 inff_pack_xtlv(u16 id, char *data, u32 len, + char **buf, u16 *buflen) +{ + u32 iolen; + + iolen = inff_xtlv_data_size(len, INFF_XTLV_OPTION_ALIGN32); + + if (iolen > *buflen) { + WARN(true, "xtlv buffer is too short"); + return 0; + } + + inff_xtlv_pack_header((void *)*buf, id, len, data, + INFF_XTLV_OPTION_ALIGN32); + + *buf = *buf + iolen; + *buflen -= iolen; + return iolen; +} diff --git a/drivers/net/wireless/infineon/inffmac/xtlv.h b/drivers/net/wireless/infineon/inffmac/xtlv.h new file mode 100644 index 000000000000..eb7564f608ed --- /dev/null +++ b/drivers/net/wireless/infineon/inffmac/xtlv.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: ISC */ +/* + * Copyright (c) 2019 Broadcom + * + * Copyright (c) 2025, Infineon Technologies AG, or an affiliate of Infineon Technologies AG. + * All rights reserved. + */ + +#ifndef INFF_XTLV_H +#define INFF_XTLV_H + +#include +#include + +/* inf type(id), length, value with w/16 bit id/len. The structure below + * is nominal, and is used to support variable length id and type. See + * xtlv options below. + */ +struct inff_xtlv { + u16 id; + u16 len; + u8 data[]; +}; + +enum inff_xtlv_option { + INFF_XTLV_OPTION_ALIGN32 = BIT(0), + INFF_XTLV_OPTION_IDU8 = BIT(1), + INFF_XTLV_OPTION_LENU8 = BIT(2), +}; + +int inff_xtlv_data_size(int dlen, u16 opts); +void inff_xtlv_pack_header(struct inff_xtlv *xtlv, u16 id, u16 len, + const u8 *data, u16 opts); +u32 inff_pack_xtlv(u16 id, char *data, u32 len, + char **buf, u16 *buflen); + +#endif /* INFF_XTLV_H */ -- 2.25.1