Commit fd112f2e authored by Francois Romieu's avatar Francois Romieu
Browse files

r8169: check firmware content sooner.



Firmware checking is only performed when the firmware is loaded
instead of each time the driver inits the phy.

Signed-off-by: default avatarFrancois Romieu <romieu@fr.zoreil.com>
parent 960aee6c
Loading
Loading
Loading
Loading
+44 −19
Original line number Diff line number Diff line
@@ -1815,18 +1815,12 @@ out:
	return rc;
}

static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev,
			   struct rtl_fw_phy_action *pa)
{
	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
	struct net_device *dev = tp->dev;
	u32 predata, count;
	bool rc = false;
	size_t index;

	if (!rtl_fw_format_ok(tp, rtl_fw)) {
		netif_err(tp, probe, dev, "invalid firwmare\n");
		return;
	}

	for (index = 0; index < pa->size; index++) {
		u32 action = le32_to_cpu(pa->code[index]);
		u32 regno = (action & 0x0fff0000) >> 16;
@@ -1844,25 +1838,25 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)

		case PHY_BJMPN:
			if (regno > index) {
				netif_err(tp, probe, tp->dev,
				netif_err(tp, ifup, tp->dev,
					  "Out of range of firmware\n");
				return;
				goto out;
			}
			break;
		case PHY_READCOUNT_EQ_SKIP:
			if (index + 2 >= pa->size) {
				netif_err(tp, probe, tp->dev,
				netif_err(tp, ifup, tp->dev,
					  "Out of range of firmware\n");
				return;
				goto out;
			}
			break;
		case PHY_COMP_EQ_SKIPN:
		case PHY_COMP_NEQ_SKIPN:
		case PHY_SKIPN:
			if (index + 1 + regno >= pa->size) {
				netif_err(tp, probe, tp->dev,
				netif_err(tp, ifup, tp->dev,
					  "Out of range of firmware\n");
				return;
				goto out;
			}
			break;

@@ -1870,14 +1864,39 @@ static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
		case PHY_WRITE_MAC_BYTE:
		case PHY_WRITE_ERI_WORD:
		default:
			netif_err(tp, probe, tp->dev,
			netif_err(tp, ifup, tp->dev,
				  "Invalid action 0x%08x\n", action);
			return;
			goto out;
		}
	}
	rc = true;
out:
	return rc;
}

	predata = 0;
	count = 0;
static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
{
	struct net_device *dev = tp->dev;
	int rc = -EINVAL;

	if (!rtl_fw_format_ok(tp, rtl_fw)) {
		netif_err(tp, ifup, dev, "invalid firwmare\n");
		goto out;
	}

	if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action))
		rc = 0;
out:
	return rc;
}

static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
{
	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
	u32 predata, count;
	size_t index;

	predata = count = 0;

	for (index = 0; index < pa->size; ) {
		u32 action = le32_to_cpu(pa->code[index]);
@@ -3605,10 +3624,16 @@ static void rtl_request_uncached_firmware(struct rtl8169_private *tp)
	if (rc < 0)
		goto err_free;

	rc = rtl_check_firmware(tp, rtl_fw);
	if (rc < 0)
		goto err_release_firmware;

	tp->rtl_fw = rtl_fw;
out:
	return;

err_release_firmware:
	release_firmware(rtl_fw->fw);
err_free:
	kfree(rtl_fw);
err_warn: