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

Commit 1b0b807d authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'r8169-fw'



Heiner Kallweit says:

====================
r8169: decouple firmware handling code from actual driver code

These two patches are a step towards eventually factoring out firmware
handling code to a separate source file.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 25e94115 ce8843ab
Loading
Loading
Loading
Loading
+37 −34
Original line number Diff line number Diff line
@@ -626,6 +626,10 @@ struct rtl8169_stats {
	struct u64_stats_sync	syncp;
};

struct rtl8169_private;
typedef void (*rtl_fw_write_t)(struct rtl8169_private *tp, int reg, int val);
typedef int (*rtl_fw_read_t)(struct rtl8169_private *tp, int reg);

struct rtl8169_private {
	void __iomem *mmio_addr;	/* memory map physical address */
	struct pci_dev *pci_dev;
@@ -679,6 +683,10 @@ struct rtl8169_private {

	const char *fw_name;
	struct rtl_fw {
		rtl_fw_write_t phy_write;
		rtl_fw_read_t phy_read;
		rtl_fw_write_t mac_mcu_write;
		rtl_fw_read_t mac_mcu_read;
		const struct firmware *fw;

#define RTL_VER_SIZE		32
@@ -1009,7 +1017,7 @@ static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
	return value;
}

static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val)
static void rtl_writephy(struct rtl8169_private *tp, int location, int val)
{
	tp->mdio_ops.write(tp, location, val);
}
@@ -2314,50 +2322,45 @@ static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
	const struct firmware *fw = rtl_fw->fw;
	struct fw_info *fw_info = (struct fw_info *)fw->data;
	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
	char *version = rtl_fw->version;
	bool rc = false;

	if (fw->size < FW_OPCODE_SIZE)
		goto out;
		return false;

	if (!fw_info->magic) {
		size_t i, size, start;
		u8 checksum = 0;

		if (fw->size < sizeof(*fw_info))
			goto out;
			return false;

		for (i = 0; i < fw->size; i++)
			checksum += fw->data[i];
		if (checksum != 0)
			goto out;
			return false;

		start = le32_to_cpu(fw_info->fw_start);
		if (start > fw->size)
			goto out;
			return false;

		size = le32_to_cpu(fw_info->fw_len);
		if (size > (fw->size - start) / FW_OPCODE_SIZE)
			goto out;
			return false;

		memcpy(version, fw_info->version, RTL_VER_SIZE);
		strscpy(rtl_fw->version, fw_info->version, RTL_VER_SIZE);

		pa->code = (__le32 *)(fw->data + start);
		pa->size = size;
	} else {
		if (fw->size % FW_OPCODE_SIZE)
			goto out;
			return false;

		strlcpy(version, tp->fw_name, RTL_VER_SIZE);
		strscpy(rtl_fw->version, tp->fw_name, RTL_VER_SIZE);

		pa->code = (__le32 *)fw->data;
		pa->size = fw->size / FW_OPCODE_SIZE;
	}
	version[RTL_VER_SIZE - 1] = 0;

	rc = true;
out:
	return rc;
	return true;
}

static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
@@ -2432,17 +2435,15 @@ static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
	return rc;
}

static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
static void rtl_fw_write_firmware(struct rtl8169_private *tp,
				  struct rtl_fw *rtl_fw)
{
	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
	struct mdio_ops org, *ops = &tp->mdio_ops;
	u32 predata, count;
	rtl_fw_write_t fw_write = rtl_fw->phy_write;
	rtl_fw_read_t fw_read = rtl_fw->phy_read;
	int predata = 0, count = 0;
	size_t index;

	predata = count = 0;
	org.write = ops->write;
	org.read = ops->read;

	for (index = 0; index < pa->size; ) {
		u32 action = le32_to_cpu(pa->code[index]);
		u32 data = action & 0x0000ffff;
@@ -2453,7 +2454,7 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)

		switch(action & 0xf0000000) {
		case PHY_READ:
			predata = rtl_readphy(tp, regno);
			predata = fw_read(tp, regno);
			count++;
			index++;
			break;
@@ -2470,11 +2471,11 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
			break;
		case PHY_MDIO_CHG:
			if (data == 0) {
				ops->write = org.write;
				ops->read = org.read;
				fw_write = rtl_fw->phy_write;
				fw_read = rtl_fw->phy_read;
			} else if (data == 1) {
				ops->write = mac_mcu_write;
				ops->read = mac_mcu_read;
				fw_write = rtl_fw->mac_mcu_write;
				fw_read = rtl_fw->mac_mcu_read;
			}

			index++;
@@ -2484,7 +2485,7 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
			index++;
			break;
		case PHY_WRITE:
			rtl_writephy(tp, regno, data);
			fw_write(tp, regno, data);
			index++;
			break;
		case PHY_READCOUNT_EQ_SKIP:
@@ -2501,7 +2502,7 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
			index++;
			break;
		case PHY_WRITE_PREVIOUS:
			rtl_writephy(tp, regno, predata);
			fw_write(tp, regno, predata);
			index++;
			break;
		case PHY_SKIPN:
@@ -2516,9 +2517,6 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
			BUG();
		}
	}

	ops->write = org.write;
	ops->read = org.read;
}

static void rtl_release_firmware(struct rtl8169_private *tp)
@@ -2532,9 +2530,9 @@ static void rtl_release_firmware(struct rtl8169_private *tp)

static void rtl_apply_firmware(struct rtl8169_private *tp)
{
	/* TODO: release firmware once rtl_phy_write_fw signals failures. */
	/* TODO: release firmware if rtl_fw_write_firmware signals failure. */
	if (tp->rtl_fw)
		rtl_phy_write_fw(tp, tp->rtl_fw);
		rtl_fw_write_firmware(tp, tp->rtl_fw);
}

static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
@@ -4364,6 +4362,11 @@ static void rtl_request_firmware(struct rtl8169_private *tp)
	if (!rtl_fw)
		goto err_warn;

	rtl_fw->phy_write = rtl_writephy;
	rtl_fw->phy_read = rtl_readphy;
	rtl_fw->mac_mcu_write = mac_mcu_write;
	rtl_fw->mac_mcu_read = mac_mcu_read;

	rc = request_firmware(&rtl_fw->fw, tp->fw_name, tp_to_dev(tp));
	if (rc < 0)
		goto err_free;