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

Commit 14d39648 authored by Mintz, Yuval's avatar Mintz, Yuval Committed by David S. Miller
Browse files

qed*: Add support for WoL

parent 7a4b21b7
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -195,6 +195,11 @@ enum qed_dev_cap {
	QED_DEV_CAP_ROCE,
};

enum qed_wol_support {
	QED_WOL_SUPPORT_NONE,
	QED_WOL_SUPPORT_PME,
};

struct qed_hw_info {
	/* PCI personality */
	enum qed_pci_personality	personality;
@@ -227,6 +232,8 @@ struct qed_hw_info {
	u32				hw_mode;
	unsigned long		device_capabilities;
	u16				mtu;

	enum qed_wol_support b_wol_support;
};

struct qed_hw_cid_data {
@@ -539,7 +546,9 @@ struct qed_dev {
	u8				mcp_rev;
	u8				boot_mode;

	u8				wol;
	/* WoL related configurations */
	u8 wol_config;
	u8 wol_mac[ETH_ALEN];

	u32				int_mode;
	enum qed_coalescing_mode	int_coalescing_mode;
+17 −2
Original line number Diff line number Diff line
@@ -1364,8 +1364,24 @@ int qed_hw_reset(struct qed_dev *cdev)
{
	int rc = 0;
	u32 unload_resp, unload_param;
	u32 wol_param;
	int i;

	switch (cdev->wol_config) {
	case QED_OV_WOL_DISABLED:
		wol_param = DRV_MB_PARAM_UNLOAD_WOL_DISABLED;
		break;
	case QED_OV_WOL_ENABLED:
		wol_param = DRV_MB_PARAM_UNLOAD_WOL_ENABLED;
		break;
	default:
		DP_NOTICE(cdev,
			  "Unknown WoL configuration %02x\n", cdev->wol_config);
		/* Fallthrough */
	case QED_OV_WOL_DEFAULT:
		wol_param = DRV_MB_PARAM_UNLOAD_WOL_MCP;
	}

	for_each_hwfn(cdev, i) {
		struct qed_hwfn *p_hwfn = &cdev->hwfns[i];

@@ -1394,8 +1410,7 @@ int qed_hw_reset(struct qed_dev *cdev)

		/* Send unload command to MCP */
		rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
				 DRV_MSG_CODE_UNLOAD_REQ,
				 DRV_MB_PARAM_UNLOAD_WOL_MCP,
				 DRV_MSG_CODE_UNLOAD_REQ, wol_param,
				 &unload_resp, &unload_param);
		if (rc) {
			DP_NOTICE(p_hwfn, "qed_hw_reset: UNLOAD_REQ failed\n");
+4 −0
Original line number Diff line number Diff line
@@ -8601,6 +8601,7 @@ struct public_drv_mb {

#define DRV_MSG_CODE_BIST_TEST			0x001e0000
#define DRV_MSG_CODE_SET_LED_MODE		0x00200000
#define DRV_MSG_CODE_OS_WOL			0x002e0000

#define DRV_MSG_SEQ_NUMBER_MASK			0x0000ffff

@@ -8697,6 +8698,9 @@ struct public_drv_mb {
#define FW_MSG_CODE_NVM_OK			0x00010000
#define FW_MSG_CODE_OK				0x00160000

#define FW_MSG_CODE_OS_WOL_SUPPORTED            0x00800000
#define FW_MSG_CODE_OS_WOL_NOT_SUPPORTED        0x00810000

#define FW_MSG_SEQ_NUMBER_MASK			0x0000ffff

	u32 fw_mb_param;
+29 −0
Original line number Diff line number Diff line
@@ -221,6 +221,10 @@ int qed_fill_dev_info(struct qed_dev *cdev,
		dev_info->fw_eng = FW_ENGINEERING_VERSION;
		dev_info->mf_mode = cdev->mf_mode;
		dev_info->tx_switching = true;

		if (QED_LEADING_HWFN(cdev)->hw_info.b_wol_support ==
		    QED_WOL_SUPPORT_PME)
			dev_info->wol_support = true;
	} else {
		qed_vf_get_fw_version(&cdev->hwfns[0], &dev_info->fw_major,
				      &dev_info->fw_minor, &dev_info->fw_rev,
@@ -1433,6 +1437,30 @@ static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode)
	return status;
}

static int qed_update_wol(struct qed_dev *cdev, bool enabled)
{
	struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
	struct qed_ptt *ptt;
	int rc = 0;

	if (IS_VF(cdev))
		return 0;

	ptt = qed_ptt_acquire(hwfn);
	if (!ptt)
		return -EAGAIN;

	rc = qed_mcp_ov_update_wol(hwfn, ptt, enabled ? QED_OV_WOL_ENABLED
				   : QED_OV_WOL_DISABLED);
	if (rc)
		goto out;
	rc = qed_mcp_ov_update_current_config(hwfn, ptt, QED_OV_CLIENT_DRV);

out:
	qed_ptt_release(hwfn, ptt);
	return rc;
}

static int qed_update_drv_state(struct qed_dev *cdev, bool active)
{
	struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
@@ -1541,6 +1569,7 @@ const struct qed_common_ops qed_common_ops_pass = {
	.update_drv_state = &qed_update_drv_state,
	.update_mac = &qed_update_mac,
	.update_mtu = &qed_update_mtu,
	.update_wol = &qed_update_wol,
};

void qed_get_protocol_stats(struct qed_dev *cdev,
+54 −2
Original line number Diff line number Diff line
@@ -330,6 +330,7 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
				 struct qed_mcp_mb_params *p_mb_params)
{
	u32 union_data_addr;

	int rc;

	/* MCP not initialized */
@@ -375,11 +376,32 @@ int qed_mcp_cmd(struct qed_hwfn *p_hwfn,
		u32 *o_mcp_param)
{
	struct qed_mcp_mb_params mb_params;
	union drv_union_data data_src;
	int rc;

	memset(&mb_params, 0, sizeof(mb_params));
	memset(&data_src, 0, sizeof(data_src));
	mb_params.cmd = cmd;
	mb_params.param = param;

	/* In case of UNLOAD_DONE, set the primary MAC */
	if ((cmd == DRV_MSG_CODE_UNLOAD_DONE) &&
	    (p_hwfn->cdev->wol_config == QED_OV_WOL_ENABLED)) {
		u8 *p_mac = p_hwfn->cdev->wol_mac;

		data_src.wol_mac.mac_upper = p_mac[0] << 8 | p_mac[1];
		data_src.wol_mac.mac_lower = p_mac[2] << 24 | p_mac[3] << 16 |
					     p_mac[4] << 8 | p_mac[5];

		DP_VERBOSE(p_hwfn,
			   (QED_MSG_SP | NETIF_MSG_IFDOWN),
			   "Setting WoL MAC: %pM --> [%08x,%08x]\n",
			   p_mac, data_src.wol_mac.mac_upper,
			   data_src.wol_mac.mac_lower);

		mb_params.p_data_src = &data_src;
	}

	rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
	if (rc)
		return rc;
@@ -1058,6 +1080,9 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn,
		info->mac[3] = (u8)(shmem_info.mac_lower >> 16);
		info->mac[4] = (u8)(shmem_info.mac_lower >> 8);
		info->mac[5] = (u8)(shmem_info.mac_lower);

		/* Store primary MAC for later possible WoL */
		memcpy(&p_hwfn->cdev->wol_mac, info->mac, ETH_ALEN);
	} else {
		DP_NOTICE(p_hwfn, "MAC is 0 in shmem\n");
	}
@@ -1071,13 +1096,28 @@ int qed_mcp_fill_shmem_func_info(struct qed_hwfn *p_hwfn,

	info->mtu = (u16)shmem_info.mtu_size;

	p_hwfn->hw_info.b_wol_support = QED_WOL_SUPPORT_NONE;
	p_hwfn->cdev->wol_config = (u8)QED_OV_WOL_DEFAULT;
	if (qed_mcp_is_init(p_hwfn)) {
		u32 resp = 0, param = 0;
		int rc;

		rc = qed_mcp_cmd(p_hwfn, p_ptt,
				 DRV_MSG_CODE_OS_WOL, 0, &resp, &param);
		if (rc)
			return rc;
		if (resp == FW_MSG_CODE_OS_WOL_SUPPORTED)
			p_hwfn->hw_info.b_wol_support = QED_WOL_SUPPORT_PME;
	}

	DP_VERBOSE(p_hwfn, (QED_MSG_SP | NETIF_MSG_IFUP),
		   "Read configuration from shmem: pause_on_host %02x protocol %02x BW [%02x - %02x] MAC %02x:%02x:%02x:%02x:%02x:%02x wwn port %llx node %llx ovlan %04x\n",
		   "Read configuration from shmem: pause_on_host %02x protocol %02x BW [%02x - %02x] MAC %02x:%02x:%02x:%02x:%02x:%02x wwn port %llx node %llx ovlan %04x wol %02x\n",
		info->pause_on_host, info->protocol,
		info->bandwidth_min, info->bandwidth_max,
		info->mac[0], info->mac[1], info->mac[2],
		info->mac[3], info->mac[4], info->mac[5],
		info->wwn_port, info->wwn_node, info->ovlan);
		info->wwn_port, info->wwn_node,
		info->ovlan, (u8)p_hwfn->hw_info.b_wol_support);

	return 0;
}
@@ -1322,6 +1362,9 @@ int qed_mcp_ov_update_mac(struct qed_hwfn *p_hwfn,
	if (rc)
		DP_ERR(p_hwfn, "Failed to send mac address, rc = %d\n", rc);

	/* Store primary MAC for later possible WoL */
	memcpy(p_hwfn->cdev->wol_mac, mac, ETH_ALEN);

	return rc;
}

@@ -1332,6 +1375,12 @@ int qed_mcp_ov_update_wol(struct qed_hwfn *p_hwfn,
	u32 drv_mb_param;
	int rc;

	if (p_hwfn->hw_info.b_wol_support == QED_WOL_SUPPORT_NONE) {
		DP_VERBOSE(p_hwfn, QED_MSG_SP,
			   "Can't change WoL configuration when WoL isn't supported\n");
		return -EINVAL;
	}

	switch (wol) {
	case QED_OV_WOL_DEFAULT:
		drv_mb_param = DRV_MB_PARAM_WOL_DEFAULT;
@@ -1352,6 +1401,9 @@ int qed_mcp_ov_update_wol(struct qed_hwfn *p_hwfn,
	if (rc)
		DP_ERR(p_hwfn, "Failed to send wol mode, rc = %d\n", rc);

	/* Store the WoL update for a future unload */
	p_hwfn->cdev->wol_config = (u8)wol;

	return rc;
}

Loading