Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 403f15c8 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "wil6210: add support for multiple sections in brd file"

parents 17c39488 e6bbc756
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014,2016 Qualcomm Atheros, Inc.
 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
@@ -109,12 +109,17 @@ struct wil_fw_record_concurrency { /* type == wil_fw_type_comment */

/* brd file info encoded inside a comment record */
#define WIL_BRD_FILE_MAGIC (0xabcddcbb)

struct brd_info {
	__le32 base_addr;
	__le32 max_size_bytes;
} __packed;

struct wil_fw_record_brd_file { /* type == wil_fw_type_comment */
	/* identifies brd file record */
	struct wil_fw_record_comment_hdr hdr;
	__le32 version;
	__le32 base_addr;
	__le32 max_size_bytes;
	struct brd_info brd_info[0];
} __packed;

/* perform action
+109 −39
Original line number Diff line number Diff line
@@ -156,17 +156,52 @@ fw_handle_brd_file(struct wil6210_priv *wil, const void *data,
		   size_t size)
{
	const struct wil_fw_record_brd_file *rec = data;
	u32 max_num_ent, i, ent_size;

	if (size < sizeof(*rec)) {
		wil_err_fw(wil, "brd_file record too short: %zu\n", size);
		return 0;
	if (size <= offsetof(struct wil_fw_record_brd_file, brd_info)) {
		wil_err(wil, "board record too short, size %zu\n", size);
		return -EINVAL;
	}

	ent_size = size - offsetof(struct wil_fw_record_brd_file, brd_info);
	max_num_ent = ent_size / sizeof(struct brd_info);

	if (!max_num_ent) {
		wil_err(wil, "brd info entries are missing\n");
		return -EINVAL;
	}

	wil->brd_info = kcalloc(max_num_ent, sizeof(struct wil_brd_info),
				GFP_KERNEL);
	if (!wil->brd_info)
		return -ENOMEM;

	for (i = 0; i < max_num_ent; i++) {
		wil->brd_info[i].file_addr =
			le32_to_cpu(rec->brd_info[i].base_addr);
		wil->brd_info[i].file_max_size =
			le32_to_cpu(rec->brd_info[i].max_size_bytes);

		if (!wil->brd_info[i].file_addr)
			break;

		wil_dbg_fw(wil,
			   "brd info %d: file_addr 0x%x, file_max_size %d\n",
			   i, wil->brd_info[i].file_addr,
			   wil->brd_info[i].file_max_size);
	}

	wil->brd_file_addr = le32_to_cpu(rec->base_addr);
	wil->brd_file_max_size = le32_to_cpu(rec->max_size_bytes);
	wil->num_of_brd_entries = i;
	if (wil->num_of_brd_entries == 0) {
		kfree(wil->brd_info);
		wil->brd_info = NULL;
		wil_dbg_fw(wil,
			   "no valid brd info entries, using brd file addr\n");

	wil_dbg_fw(wil, "brd_file_addr 0x%x, brd_file_max_size %d\n",
		   wil->brd_file_addr, wil->brd_file_max_size);
	} else {
		wil_dbg_fw(wil, "num of brd info entries %d\n",
			   wil->num_of_brd_entries);
	}

	return 0;
}
@@ -634,6 +669,11 @@ int wil_request_firmware(struct wil6210_priv *wil, const char *name,
	}
	wil_dbg_fw(wil, "Loading <%s>, %zu bytes\n", name, fw->size);

	/* re-initialize board info params */
	wil->num_of_brd_entries = 0;
	kfree(wil->brd_info);
	wil->brd_info = NULL;

	for (sz = fw->size, d = fw->data; sz; sz -= rc1, d += rc1) {
		rc1 = wil_fw_verify(wil, d, sz);
		if (rc1 < 0) {
@@ -662,11 +702,13 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data,
{
	int rc = 0;
	const struct wil_fw_record_head *hdr = data;
	size_t s, hdr_sz;
	size_t s, hdr_sz = 0;
	u16 type;
	int i = 0;

	/* Assuming the board file includes only one header record and one data
	 * record. Each record starts with wil_fw_record_head.
	/* Assuming the board file includes only one file header
	 * and one or several data records.
	 * Each record starts with wil_fw_record_head.
	 */
	if (size < sizeof(*hdr))
		return -EINVAL;
@@ -674,14 +716,24 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data,
	if (s > size)
		return -EINVAL;

	/* Skip the header record and handle the data record */
	hdr = (const void *)hdr + s;
	/* Skip the header record and handle the data records */
	size -= s;

	for (hdr = data + s;; hdr = (const void *)hdr + s, size -= s, i++) {
		if (size < sizeof(*hdr))
		return -EINVAL;
	hdr_sz = le32_to_cpu(hdr->size);
			break;

	if (wil->brd_file_max_size && hdr_sz > wil->brd_file_max_size)
		if (i >= wil->num_of_brd_entries) {
			wil_err_fw(wil,
				   "Too many brd records: %d, num of expected entries %d\n",
				   i, wil->num_of_brd_entries);
			break;
		}

		hdr_sz = le32_to_cpu(hdr->size);
		s = sizeof(*hdr) + hdr_sz;
		if (wil->brd_info[i].file_max_size &&
		    hdr_sz > wil->brd_info[i].file_max_size)
			return -EINVAL;
		if (sizeof(*hdr) + hdr_sz > size)
			return -EINVAL;
@@ -692,7 +744,8 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data,
		}
		type = le16_to_cpu(hdr->type);
		if (type != wil_fw_type_data) {
		wil_err_fw(wil, "invalid record type for board file: %d\n",
			wil_err_fw(wil,
				   "invalid record type for board file: %d\n",
				   type);
			return -EINVAL;
		}
@@ -701,15 +754,31 @@ static int wil_brd_process(struct wil6210_priv *wil, const void *data,
			return -EINVAL;
		}

	wil_dbg_fw(wil, "using addr from fw file: [0x%08x]\n",
		   wil->brd_file_addr);
		wil_dbg_fw(wil,
			   "using info from fw file for record %d: addr[0x%08x], max size %d\n",
			   i, wil->brd_info[i].file_addr,
			   wil->brd_info[i].file_max_size);

		rc = __fw_handle_data(wil, &hdr[1], hdr_sz,
			      cpu_to_le32(wil->brd_file_addr));

				      cpu_to_le32(wil->brd_info[i].file_addr));
		if (rc)
			return rc;
	}

	if (size) {
		wil_err_fw(wil, "unprocessed bytes: %zu\n", size);
		if (size >= sizeof(*hdr)) {
			wil_err_fw(wil,
				   "Stop at offset %ld record type %d [%zd bytes]\n",
				   (long)((const void *)hdr - data),
				   le16_to_cpu(hdr->type), hdr_sz);
		}
		return -EINVAL;
	}

	return 0;
}

/**
 * wil_request_board - Request board file
 *
@@ -738,7 +807,8 @@ int wil_request_board(struct wil6210_priv *wil, const char *name)
		rc = dlen;
		goto out;
	}
	/* Process the data record */

	/* Process the data records */
	rc = wil_brd_process(wil, brd->data, dlen);

out:
+2 −1
Original line number Diff line number Diff line
@@ -860,6 +860,7 @@ void wil_priv_deinit(struct wil6210_priv *wil)
	destroy_workqueue(wil->wq_service);
	destroy_workqueue(wil->wmi_wq);
	kfree(wil->board_file);
	kfree(wil->brd_info);
}

static void wil_shutdown_bl(struct wil6210_priv *wil)
@@ -1760,7 +1761,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
		rc = wil_request_firmware(wil, wil->wil_fw_name, true);
		if (rc)
			goto out;
		if (wil->brd_file_addr)
		if (wil->num_of_brd_entries)
			rc = wil_request_board(wil, board_file);
		else
			rc = wil_request_firmware(wil, board_file, true);
+2 −0
Original line number Diff line number Diff line
@@ -135,6 +135,8 @@ int wil_set_capabilities(struct wil6210_priv *wil)
		       min(sizeof(wil->platform_capa), sizeof(platform_capa)));
	}

	wil_info(wil, "platform_capa 0x%lx\n", *wil->platform_capa);

	/* extract FW capabilities from file without loading the FW */
	wil_request_firmware(wil, wil->wil_fw_name, false);
	wil_refresh_fw_capabilities(wil);
+3 −0
Original line number Diff line number Diff line
@@ -1782,6 +1782,9 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif,
		}
	}

	if (!_desc)
		goto mem_error;

	/* first descriptor may also be the last.
	 * in this case d pointer is invalid
	 */
Loading