Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* r8169_firmware.c: RealTek 8169/8168/8101 ethernet driver.
  3 *
  4 * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
  5 * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
  6 * Copyright (c) a lot of people too. Please respect their work.
  7 *
  8 * See MAINTAINERS file for support contact information.
  9 */
 10
 11#include <linux/delay.h>
 12#include <linux/firmware.h>
 13
 14#include "r8169_firmware.h"
 15
 16enum rtl_fw_opcode {
 17	PHY_READ		= 0x0,
 18	PHY_DATA_OR		= 0x1,
 19	PHY_DATA_AND		= 0x2,
 20	PHY_BJMPN		= 0x3,
 21	PHY_MDIO_CHG		= 0x4,
 22	PHY_CLEAR_READCOUNT	= 0x7,
 23	PHY_WRITE		= 0x8,
 24	PHY_READCOUNT_EQ_SKIP	= 0x9,
 25	PHY_COMP_EQ_SKIPN	= 0xa,
 26	PHY_COMP_NEQ_SKIPN	= 0xb,
 27	PHY_WRITE_PREVIOUS	= 0xc,
 28	PHY_SKIPN		= 0xd,
 29	PHY_DELAY_MS		= 0xe,
 30};
 31
 32struct fw_info {
 33	u32	magic;
 34	char	version[RTL_VER_SIZE];
 35	__le32	fw_start;
 36	__le32	fw_len;
 37	u8	chksum;
 38} __packed;
 39
 40#define FW_OPCODE_SIZE sizeof_field(struct rtl_fw_phy_action, code[0])
 41
 42static bool rtl_fw_format_ok(struct rtl_fw *rtl_fw)
 43{
 44	const struct firmware *fw = rtl_fw->fw;
 45	struct fw_info *fw_info = (struct fw_info *)fw->data;
 46	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
 47
 48	if (fw->size < FW_OPCODE_SIZE)
 49		return false;
 50
 51	if (!fw_info->magic) {
 52		size_t i, size, start;
 53		u8 checksum = 0;
 54
 55		if (fw->size < sizeof(*fw_info))
 56			return false;
 57
 58		for (i = 0; i < fw->size; i++)
 59			checksum += fw->data[i];
 60		if (checksum != 0)
 61			return false;
 62
 63		start = le32_to_cpu(fw_info->fw_start);
 64		if (start > fw->size)
 65			return false;
 66
 67		size = le32_to_cpu(fw_info->fw_len);
 68		if (size > (fw->size - start) / FW_OPCODE_SIZE)
 69			return false;
 70
 71		strscpy(rtl_fw->version, fw_info->version, RTL_VER_SIZE);
 72
 73		pa->code = (__le32 *)(fw->data + start);
 74		pa->size = size;
 75	} else {
 76		if (fw->size % FW_OPCODE_SIZE)
 77			return false;
 78
 79		strscpy(rtl_fw->version, rtl_fw->fw_name, RTL_VER_SIZE);
 80
 81		pa->code = (__le32 *)fw->data;
 82		pa->size = fw->size / FW_OPCODE_SIZE;
 83	}
 84
 85	return true;
 86}
 87
 88static bool rtl_fw_data_ok(struct rtl_fw *rtl_fw)
 89{
 90	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
 91	size_t index;
 92
 93	for (index = 0; index < pa->size; index++) {
 94		u32 action = le32_to_cpu(pa->code[index]);
 95		u32 val = action & 0x0000ffff;
 96		u32 regno = (action & 0x0fff0000) >> 16;
 97
 98		switch (action >> 28) {
 99		case PHY_READ:
100		case PHY_DATA_OR:
101		case PHY_DATA_AND:
102		case PHY_CLEAR_READCOUNT:
103		case PHY_WRITE:
104		case PHY_WRITE_PREVIOUS:
105		case PHY_DELAY_MS:
106			break;
107
108		case PHY_MDIO_CHG:
109			if (val > 1)
110				goto out;
111			break;
112
113		case PHY_BJMPN:
114			if (regno > index)
115				goto out;
116			break;
117		case PHY_READCOUNT_EQ_SKIP:
118			if (index + 2 >= pa->size)
119				goto out;
120			break;
121		case PHY_COMP_EQ_SKIPN:
122		case PHY_COMP_NEQ_SKIPN:
123		case PHY_SKIPN:
124			if (index + 1 + regno >= pa->size)
125				goto out;
126			break;
127
128		default:
129			dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action);
130			return false;
131		}
132	}
133
134	return true;
135out:
136	dev_err(rtl_fw->dev, "Out of range of firmware\n");
137	return false;
138}
139
140void rtl_fw_write_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
141{
142	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
143	rtl_fw_write_t fw_write = rtl_fw->phy_write;
144	rtl_fw_read_t fw_read = rtl_fw->phy_read;
145	int predata = 0, count = 0;
146	size_t index;
147
148	for (index = 0; index < pa->size; index++) {
149		u32 action = le32_to_cpu(pa->code[index]);
150		u32 data = action & 0x0000ffff;
151		u32 regno = (action & 0x0fff0000) >> 16;
152		enum rtl_fw_opcode opcode = action >> 28;
153
 
 
 
154		switch (opcode) {
155		case PHY_READ:
156			predata = fw_read(tp, regno);
157			count++;
158			break;
159		case PHY_DATA_OR:
160			predata |= data;
161			break;
162		case PHY_DATA_AND:
163			predata &= data;
164			break;
165		case PHY_BJMPN:
166			index -= (regno + 1);
167			break;
168		case PHY_MDIO_CHG:
169			if (data) {
170				fw_write = rtl_fw->mac_mcu_write;
171				fw_read = rtl_fw->mac_mcu_read;
172			} else {
173				fw_write = rtl_fw->phy_write;
174				fw_read = rtl_fw->phy_read;
175			}
176
177			break;
178		case PHY_CLEAR_READCOUNT:
179			count = 0;
180			break;
181		case PHY_WRITE:
182			fw_write(tp, regno, data);
183			break;
184		case PHY_READCOUNT_EQ_SKIP:
185			if (count == data)
186				index++;
187			break;
188		case PHY_COMP_EQ_SKIPN:
189			if (predata == data)
190				index += regno;
191			break;
192		case PHY_COMP_NEQ_SKIPN:
193			if (predata != data)
194				index += regno;
195			break;
196		case PHY_WRITE_PREVIOUS:
197			fw_write(tp, regno, predata);
198			break;
199		case PHY_SKIPN:
200			index += regno;
201			break;
202		case PHY_DELAY_MS:
203			msleep(data);
204			break;
205		}
206	}
207}
208
209void rtl_fw_release_firmware(struct rtl_fw *rtl_fw)
210{
211	release_firmware(rtl_fw->fw);
212}
213
214int rtl_fw_request_firmware(struct rtl_fw *rtl_fw)
215{
216	int rc;
217
218	rc = firmware_request_nowarn(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
219	if (rc < 0)
220		goto out;
221
222	if (!rtl_fw_format_ok(rtl_fw) || !rtl_fw_data_ok(rtl_fw)) {
223		release_firmware(rtl_fw->fw);
224		rc = -EINVAL;
225		goto out;
226	}
227
228	return 0;
229out:
230	dev_warn(rtl_fw->dev, "Unable to load firmware %s (%d)\n",
231		 rtl_fw->fw_name, rc);
232	return rc;
233}
v6.2
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* r8169_firmware.c: RealTek 8169/8168/8101 ethernet driver.
  3 *
  4 * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
  5 * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
  6 * Copyright (c) a lot of people too. Please respect their work.
  7 *
  8 * See MAINTAINERS file for support contact information.
  9 */
 10
 11#include <linux/delay.h>
 12#include <linux/firmware.h>
 13
 14#include "r8169_firmware.h"
 15
 16enum rtl_fw_opcode {
 17	PHY_READ		= 0x0,
 18	PHY_DATA_OR		= 0x1,
 19	PHY_DATA_AND		= 0x2,
 20	PHY_BJMPN		= 0x3,
 21	PHY_MDIO_CHG		= 0x4,
 22	PHY_CLEAR_READCOUNT	= 0x7,
 23	PHY_WRITE		= 0x8,
 24	PHY_READCOUNT_EQ_SKIP	= 0x9,
 25	PHY_COMP_EQ_SKIPN	= 0xa,
 26	PHY_COMP_NEQ_SKIPN	= 0xb,
 27	PHY_WRITE_PREVIOUS	= 0xc,
 28	PHY_SKIPN		= 0xd,
 29	PHY_DELAY_MS		= 0xe,
 30};
 31
 32struct fw_info {
 33	u32	magic;
 34	char	version[RTL_VER_SIZE];
 35	__le32	fw_start;
 36	__le32	fw_len;
 37	u8	chksum;
 38} __packed;
 39
 40#define FW_OPCODE_SIZE sizeof_field(struct rtl_fw_phy_action, code[0])
 41
 42static bool rtl_fw_format_ok(struct rtl_fw *rtl_fw)
 43{
 44	const struct firmware *fw = rtl_fw->fw;
 45	struct fw_info *fw_info = (struct fw_info *)fw->data;
 46	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
 47
 48	if (fw->size < FW_OPCODE_SIZE)
 49		return false;
 50
 51	if (!fw_info->magic) {
 52		size_t i, size, start;
 53		u8 checksum = 0;
 54
 55		if (fw->size < sizeof(*fw_info))
 56			return false;
 57
 58		for (i = 0; i < fw->size; i++)
 59			checksum += fw->data[i];
 60		if (checksum != 0)
 61			return false;
 62
 63		start = le32_to_cpu(fw_info->fw_start);
 64		if (start > fw->size)
 65			return false;
 66
 67		size = le32_to_cpu(fw_info->fw_len);
 68		if (size > (fw->size - start) / FW_OPCODE_SIZE)
 69			return false;
 70
 71		strscpy(rtl_fw->version, fw_info->version, RTL_VER_SIZE);
 72
 73		pa->code = (__le32 *)(fw->data + start);
 74		pa->size = size;
 75	} else {
 76		if (fw->size % FW_OPCODE_SIZE)
 77			return false;
 78
 79		strscpy(rtl_fw->version, rtl_fw->fw_name, RTL_VER_SIZE);
 80
 81		pa->code = (__le32 *)fw->data;
 82		pa->size = fw->size / FW_OPCODE_SIZE;
 83	}
 84
 85	return true;
 86}
 87
 88static bool rtl_fw_data_ok(struct rtl_fw *rtl_fw)
 89{
 90	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
 91	size_t index;
 92
 93	for (index = 0; index < pa->size; index++) {
 94		u32 action = le32_to_cpu(pa->code[index]);
 95		u32 val = action & 0x0000ffff;
 96		u32 regno = (action & 0x0fff0000) >> 16;
 97
 98		switch (action >> 28) {
 99		case PHY_READ:
100		case PHY_DATA_OR:
101		case PHY_DATA_AND:
102		case PHY_CLEAR_READCOUNT:
103		case PHY_WRITE:
104		case PHY_WRITE_PREVIOUS:
105		case PHY_DELAY_MS:
106			break;
107
108		case PHY_MDIO_CHG:
109			if (val > 1)
110				goto out;
111			break;
112
113		case PHY_BJMPN:
114			if (regno > index)
115				goto out;
116			break;
117		case PHY_READCOUNT_EQ_SKIP:
118			if (index + 2 >= pa->size)
119				goto out;
120			break;
121		case PHY_COMP_EQ_SKIPN:
122		case PHY_COMP_NEQ_SKIPN:
123		case PHY_SKIPN:
124			if (index + 1 + regno >= pa->size)
125				goto out;
126			break;
127
128		default:
129			dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action);
130			return false;
131		}
132	}
133
134	return true;
135out:
136	dev_err(rtl_fw->dev, "Out of range of firmware\n");
137	return false;
138}
139
140void rtl_fw_write_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
141{
142	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
143	rtl_fw_write_t fw_write = rtl_fw->phy_write;
144	rtl_fw_read_t fw_read = rtl_fw->phy_read;
145	int predata = 0, count = 0;
146	size_t index;
147
148	for (index = 0; index < pa->size; index++) {
149		u32 action = le32_to_cpu(pa->code[index]);
150		u32 data = action & 0x0000ffff;
151		u32 regno = (action & 0x0fff0000) >> 16;
152		enum rtl_fw_opcode opcode = action >> 28;
153
154		if (!action)
155			break;
156
157		switch (opcode) {
158		case PHY_READ:
159			predata = fw_read(tp, regno);
160			count++;
161			break;
162		case PHY_DATA_OR:
163			predata |= data;
164			break;
165		case PHY_DATA_AND:
166			predata &= data;
167			break;
168		case PHY_BJMPN:
169			index -= (regno + 1);
170			break;
171		case PHY_MDIO_CHG:
172			if (data) {
173				fw_write = rtl_fw->mac_mcu_write;
174				fw_read = rtl_fw->mac_mcu_read;
175			} else {
176				fw_write = rtl_fw->phy_write;
177				fw_read = rtl_fw->phy_read;
178			}
179
180			break;
181		case PHY_CLEAR_READCOUNT:
182			count = 0;
183			break;
184		case PHY_WRITE:
185			fw_write(tp, regno, data);
186			break;
187		case PHY_READCOUNT_EQ_SKIP:
188			if (count == data)
189				index++;
190			break;
191		case PHY_COMP_EQ_SKIPN:
192			if (predata == data)
193				index += regno;
194			break;
195		case PHY_COMP_NEQ_SKIPN:
196			if (predata != data)
197				index += regno;
198			break;
199		case PHY_WRITE_PREVIOUS:
200			fw_write(tp, regno, predata);
201			break;
202		case PHY_SKIPN:
203			index += regno;
204			break;
205		case PHY_DELAY_MS:
206			msleep(data);
207			break;
208		}
209	}
210}
211
212void rtl_fw_release_firmware(struct rtl_fw *rtl_fw)
213{
214	release_firmware(rtl_fw->fw);
215}
216
217int rtl_fw_request_firmware(struct rtl_fw *rtl_fw)
218{
219	int rc;
220
221	rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
222	if (rc < 0)
223		goto out;
224
225	if (!rtl_fw_format_ok(rtl_fw) || !rtl_fw_data_ok(rtl_fw)) {
226		release_firmware(rtl_fw->fw);
227		rc = -EINVAL;
228		goto out;
229	}
230
231	return 0;
232out:
233	dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n",
234		rtl_fw->fw_name, rc);
235	return rc;
236}