Skip to content

Commit

Permalink
wifi: rtw89: introduce infrastructure of firmware elements
Browse files Browse the repository at this point in the history
In order to pack more data into firmware file, we introduce firmware
elements and append BB_MCU firmware first. The first part of new firmware
file is still unchanged firmware of WiFi CPU, so the new firmware format
can be backward compatible to old format. The new elements part consists
of ID and size basically, which can append more elements simply. To avoid
unaligned access in certain platform and be easy to read, headers of all
elements start at 16-byte aligned address.

 +===========================================+
 |             original firmware             |
 |                             +-------------+
 |                             |   padding   |
 +===========================================+
 | elm ID 1 | elm size |  other header data  |
 +----------+----------+                     |
 |                                           |
 +-------------------------------------------+
 | content (variable length)                 |
 |                             +-------------+
 |                             |   padding   |
 +===========================================+
 | elm ID 2 | elm size |  other header data  |
 +----------+----------+                     |
 |                                           |
 +-------------------------------------------+
 | content (variable length)                 |
 |                   +-----------------------+
 |                   | (no padding for the last one)
 +===================+

More detail of element header is shown below. The additional fields
'version' and 'element_priv[]' are meta data of elements, so that we can
know element version easily, and element_priv[] provide specific fields
for certain element, such as RF path index for RF parameter tables.

 +===========================================+
 |  elm ID  | elm size | version  |   rsvd0  |
 +----------+----------+----------+----------+
 |        rsvd1/2      |  element_priv[]     |
 +-------------------------------------------+

Signed-off-by: Ping-Ke Shih <[email protected]>
Signed-off-by: Kalle Valo <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
  • Loading branch information
Ping-Ke Shih authored and lwfinger committed Aug 13, 2023
1 parent 14c08f1 commit 380e420
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 0 deletions.
6 changes: 6 additions & 0 deletions core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3846,6 +3846,12 @@ int rtw89_chip_info_setup(struct rtw89_dev *rtwdev)
return ret;
}

ret = rtw89_fw_recognize_elements(rtwdev);
if (ret) {
rtw89_err(rtwdev, "failed to recognize firmware elements\n");
return ret;
}

ret = rtw89_chip_efuse_info_setup(rtwdev);
if (ret)
return ret;
Expand Down
78 changes: 78 additions & 0 deletions fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,21 @@ int __rtw89_fw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
return 0;
}

static
int __rtw89_fw_recognize_from_elm(struct rtw89_dev *rtwdev,
const struct rtw89_fw_element_hdr *elm,
const void *data)
{
enum rtw89_fw_type type = (enum rtw89_fw_type)data;
struct rtw89_fw_suit *fw_suit;

fw_suit = rtw89_fw_suit_get(rtwdev, type);
fw_suit->data = elm->u.common.contents;
fw_suit->size = le32_to_cpu(elm->size);

return rtw89_fw_update_ver(rtwdev, type, fw_suit);
}

#define __DEF_FW_FEAT_COND(__cond, __op) \
static bool __fw_feat_cond_ ## __cond(u32 suit_ver_code, u32 comp_ver_code) \
{ \
Expand Down Expand Up @@ -376,6 +391,69 @@ int rtw89_fw_recognize(struct rtw89_dev *rtwdev)
return 0;
}

struct rtw89_fw_element_handler {
int (*fn)(struct rtw89_dev *rtwdev,
const struct rtw89_fw_element_hdr *elm, const void *data);
const void *data;
const char *name;
};

static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
[RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm,
(const void *)RTW89_FW_BBMCU0, NULL},
[RTW89_FW_ELEMENT_ID_BBMCU1] = {__rtw89_fw_recognize_from_elm,
(const void *)RTW89_FW_BBMCU1, NULL},
};

int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev)
{
struct rtw89_fw_info *fw_info = &rtwdev->fw;
const struct firmware *firmware = fw_info->req.firmware;
const struct rtw89_fw_element_handler *handler;
const struct rtw89_fw_element_hdr *hdr;
u32 elm_size;
u32 elem_id;
u32 offset;
int ret;

offset = rtw89_mfw_get_size(rtwdev);
offset = ALIGN(offset, RTW89_FW_ELEMENT_ALIGN);
if (offset == 0)
return -EINVAL;

while (offset + sizeof(*hdr) < firmware->size) {
hdr = (const struct rtw89_fw_element_hdr *)(firmware->data + offset);

elm_size = le32_to_cpu(hdr->size);
if (offset + elm_size >= firmware->size) {
rtw89_warn(rtwdev, "firmware element size exceeds\n");
break;
}

elem_id = le32_to_cpu(hdr->id);
if (elem_id >= ARRAY_SIZE(__fw_element_handlers))
goto next;

handler = &__fw_element_handlers[elem_id];
if (!handler->fn)
goto next;

ret = handler->fn(rtwdev, hdr, handler->data);
if (ret)
return ret;

if (handler->name)
rtw89_info(rtwdev, "Firmware element %s version: %4ph\n",
handler->name, hdr->ver);

next:
offset += sizeof(*hdr) + elm_size;
offset = ALIGN(offset, RTW89_FW_ELEMENT_ALIGN);
}

return 0;
}

void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb,
u8 type, u8 cat, u8 class, u8 func,
bool rack, bool dack, u32 len)
Expand Down
31 changes: 31 additions & 0 deletions fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -3426,6 +3426,36 @@ struct rtw89_mfw_hdr {
struct rtw89_mfw_info info[];
} __packed;

#define RTW89_FW_ELEMENT_ALIGN 16

enum rtw89_fw_element_id {
RTW89_FW_ELEMENT_ID_BBMCU0 = 0,
RTW89_FW_ELEMENT_ID_BBMCU1 = 1,
};

struct rtw89_fw_element_hdr {
__le32 id; /* enum rtw89_fw_element_id */
__le32 size; /* exclude header size */
u8 ver[4];
__le32 rsvd0;
__le32 rsvd1;
__le32 rsvd2;
union {
struct {
u8 priv[8];
u8 contents[];
} __packed common;
struct {
u8 idx;
u8 rsvd[7];
struct {
__le32 addr;
__le32 data;
} __packed regs[];
} __packed reg2;
} __packed u;
} __packed;

struct fwcmd_hdr {
__le32 hdr0;
__le32 hdr1;
Expand Down Expand Up @@ -3607,6 +3637,7 @@ struct rtw89_fw_h2c_rf_get_mccch {

int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev);
int rtw89_fw_recognize(struct rtw89_dev *rtwdev);
int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev);
const struct firmware *
rtw89_early_fw_feature_recognize(struct device *device,
const struct rtw89_chip_info *chip,
Expand Down

0 comments on commit 380e420

Please sign in to comment.