All of lore.kernel.org
 help / color / mirror / Atom feed
From: Edward Cree <ecree@solarflare.com>
To: <linux-net-drivers@solarflare.com>, <davem@davemloft.net>
Cc: <netdev@vger.kernel.org>
Subject: [PATCH v4 net-next 08/16] sfc_ef100: implement MCDI transport
Date: Fri, 24 Jul 2020 16:58:57 +0100	[thread overview]
Message-ID: <0ae88dee-9872-bc20-87ed-fec4458d6162@solarflare.com> (raw)
In-Reply-To: <d224dbb2-ef20-dca9-d50b-7f583b45d859@solarflare.com>

Signed-off-by: Edward Cree <ecree@solarflare.com>
---
 drivers/net/ethernet/sfc/ef100_nic.c | 106 +++++++++++++++++++++++++++
 drivers/net/ethernet/sfc/ef100_nic.h |   1 +
 2 files changed, 107 insertions(+)

diff --git a/drivers/net/ethernet/sfc/ef100_nic.c b/drivers/net/ethernet/sfc/ef100_nic.c
index 802ab0ce00fe..189a8a706c0e 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.c
+++ b/drivers/net/ethernet/sfc/ef100_nic.c
@@ -25,11 +25,23 @@
 #include "ef100_netdev.h"
 
 #define EF100_MAX_VIS 4096
+#define EF100_NUM_MCDI_BUFFERS	1
+#define MCDI_BUF_LEN (8 + MCDI_CTL_SDU_LEN_MAX)
 
 #define EF100_RESET_PORT ((ETH_RESET_MAC | ETH_RESET_PHY) << ETH_RESET_SHARED_SHIFT)
 
 /*	MCDI
  */
+static u8 *ef100_mcdi_buf(struct efx_nic *efx, u8 bufid, dma_addr_t *dma_addr)
+{
+	struct ef100_nic_data *nic_data = efx->nic_data;
+
+	if (dma_addr)
+		*dma_addr = nic_data->mcdi_buf.dma_addr +
+			    bufid * ALIGN(MCDI_BUF_LEN, 256);
+	return nic_data->mcdi_buf.addr + bufid * ALIGN(MCDI_BUF_LEN, 256);
+}
+
 static int ef100_get_warm_boot_count(struct efx_nic *efx)
 {
 	efx_dword_t reg;
@@ -46,6 +58,72 @@ static int ef100_get_warm_boot_count(struct efx_nic *efx)
 	}
 }
 
+static void ef100_mcdi_request(struct efx_nic *efx,
+			       const efx_dword_t *hdr, size_t hdr_len,
+			       const efx_dword_t *sdu, size_t sdu_len)
+{
+	dma_addr_t dma_addr;
+	u8 *pdu = ef100_mcdi_buf(efx, 0, &dma_addr);
+
+	memcpy(pdu, hdr, hdr_len);
+	memcpy(pdu + hdr_len, sdu, sdu_len);
+	wmb();
+
+	/* The hardware provides 'low' and 'high' (doorbell) registers
+	 * for passing the 64-bit address of an MCDI request to
+	 * firmware.  However the dwords are swapped by firmware.  The
+	 * least significant bits of the doorbell are then 0 for all
+	 * MCDI requests due to alignment.
+	 */
+	_efx_writed(efx, cpu_to_le32((u64)dma_addr >> 32),  efx_reg(efx, ER_GZ_MC_DB_LWRD));
+	_efx_writed(efx, cpu_to_le32((u32)dma_addr),  efx_reg(efx, ER_GZ_MC_DB_HWRD));
+}
+
+static bool ef100_mcdi_poll_response(struct efx_nic *efx)
+{
+	const efx_dword_t hdr =
+		*(const efx_dword_t *)(ef100_mcdi_buf(efx, 0, NULL));
+
+	rmb();
+	return EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE);
+}
+
+static void ef100_mcdi_read_response(struct efx_nic *efx,
+				     efx_dword_t *outbuf, size_t offset,
+				     size_t outlen)
+{
+	const u8 *pdu = ef100_mcdi_buf(efx, 0, NULL);
+
+	memcpy(outbuf, pdu + offset, outlen);
+}
+
+static int ef100_mcdi_poll_reboot(struct efx_nic *efx)
+{
+	struct ef100_nic_data *nic_data = efx->nic_data;
+	int rc;
+
+	rc = ef100_get_warm_boot_count(efx);
+	if (rc < 0) {
+		/* The firmware is presumably in the process of
+		 * rebooting.  However, we are supposed to report each
+		 * reboot just once, so we must only do that once we
+		 * can read and store the updated warm boot count.
+		 */
+		return 0;
+	}
+
+	if (rc == nic_data->warm_boot_count)
+		return 0;
+
+	nic_data->warm_boot_count = rc;
+
+	return -EIO;
+}
+
+static void ef100_mcdi_reboot_detected(struct efx_nic *efx)
+{
+}
+
 /*	Event handling
  */
 static int ef100_ev_probe(struct efx_channel *channel)
@@ -139,6 +217,11 @@ const struct efx_nic_type ef100_pf_nic_type = {
 	.is_vf = false,
 	.probe = ef100_probe_pf,
 	.mcdi_max_ver = 2,
+	.mcdi_request = ef100_mcdi_request,
+	.mcdi_poll_response = ef100_mcdi_poll_response,
+	.mcdi_read_response = ef100_mcdi_read_response,
+	.mcdi_poll_reboot = ef100_mcdi_poll_reboot,
+	.mcdi_reboot_detected = ef100_mcdi_reboot_detected,
 	.irq_enable_master = efx_port_dummy_op_void,
 	.irq_disable_non_ev = efx_port_dummy_op_void,
 	.push_irq_moderation = efx_channel_dummy_op_void,
@@ -178,6 +261,15 @@ static int ef100_probe_main(struct efx_nic *efx)
 	net_dev->features |= efx->type->offload_features;
 	net_dev->hw_features |= efx->type->offload_features;
 
+	/* we assume later that we can copy from this buffer in dwords */
+	BUILD_BUG_ON(MCDI_CTL_SDU_LEN_MAX_V2 % 4);
+
+	/* MCDI buffers must be 256 byte aligned. */
+	rc = efx_nic_alloc_buffer(efx, &nic_data->mcdi_buf, MCDI_BUF_LEN,
+				  GFP_KERNEL);
+	if (rc)
+		goto fail;
+
 	/* Get the MC's warm boot count.  In case it's rebooting right
 	 * now, be prepared to retry.
 	 */
@@ -201,6 +293,16 @@ static int ef100_probe_main(struct efx_nic *efx)
 
 	/* Post-IO section. */
 
+	rc = efx_mcdi_init(efx);
+	if (!rc && efx->mcdi->fn_flags &
+		   (1 << MC_CMD_DRV_ATTACH_EXT_OUT_FLAG_NO_ACTIVE_PORT)) {
+		netif_info(efx, probe, efx->net_dev,
+			   "No network port on this PCI function");
+		rc = -ENODEV;
+	}
+	if (rc)
+		goto fail;
+
 	efx->max_vis = EF100_MAX_VIS;
 
 	rc = ef100_phy_probe(efx);
@@ -233,6 +335,10 @@ void ef100_remove(struct efx_nic *efx)
 	efx_fini_channels(efx);
 	kfree(efx->phy_data);
 	efx->phy_data = NULL;
+	efx_mcdi_detach(efx);
+	efx_mcdi_fini(efx);
+	if (nic_data)
+		efx_nic_free_buffer(efx, &nic_data->mcdi_buf);
 	kfree(nic_data);
 	efx->nic_data = NULL;
 }
diff --git a/drivers/net/ethernet/sfc/ef100_nic.h b/drivers/net/ethernet/sfc/ef100_nic.h
index 643111aebba5..a4290d183879 100644
--- a/drivers/net/ethernet/sfc/ef100_nic.h
+++ b/drivers/net/ethernet/sfc/ef100_nic.h
@@ -19,6 +19,7 @@ void ef100_remove(struct efx_nic *efx);
 
 struct ef100_nic_data {
 	struct efx_nic *efx;
+	struct efx_buffer mcdi_buf;
 	u16 warm_boot_count;
 };
 


  parent reply	other threads:[~2020-07-24 15:59 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-24 15:56 [PATCH v4 net-next 00/16] sfc: driver for EF100 family NICs, part 1 Edward Cree
2020-07-24 15:57 ` [PATCH v4 net-next 01/16] sfc: remove efx_ethtool_nway_reset() Edward Cree
2020-07-24 15:57 ` [PATCH v4 net-next 02/16] sfc_ef100: add EF100 register definitions Edward Cree
2020-07-24 15:57 ` [PATCH v4 net-next 03/16] sfc_ef100: register accesses on EF100 Edward Cree
2020-07-24 15:57 ` [PATCH v4 net-next 04/16] sfc: skeleton EF100 PF driver Edward Cree
2020-07-24 20:32   ` kernel test robot
2020-07-24 20:32     ` kernel test robot
2020-07-27 10:41     ` Edward Cree
2020-07-27 10:41       ` Edward Cree
2020-07-24 21:44   ` kernel test robot
2020-07-24 21:44     ` kernel test robot
2020-07-24 15:58 ` [PATCH v4 net-next 05/16] sfc_ef100: reset-handling stub Edward Cree
2020-07-24 15:58 ` [PATCH v4 net-next 06/16] sfc_ef100: PHY probe stub Edward Cree
2020-07-24 15:58 ` [PATCH v4 net-next 07/16] sfc_ef100: don't call efx_reset_down()/up() on EF100 Edward Cree
2020-07-24 15:58 ` Edward Cree [this message]
2020-07-24 15:59 ` [PATCH v4 net-next 09/16] sfc_ef100: implement ndo_open/close and EVQ probing Edward Cree
2020-07-24 21:54   ` kernel test robot
2020-07-24 21:54     ` kernel test robot
2020-07-24 15:59 ` [PATCH v4 net-next 10/16] sfc_ef100: process events for MCDI completions Edward Cree
2020-07-24 15:59 ` [PATCH v4 net-next 11/16] sfc_ef100: read datapath caps, implement check_caps Edward Cree
2020-07-24 16:00 ` [PATCH v4 net-next 12/16] sfc_ef100: extend ef100_check_caps to cover datapath_caps3 Edward Cree
2020-07-24 16:00 ` [PATCH v4 net-next 13/16] sfc_ef100: actually perform resets Edward Cree
2020-07-24 16:00 ` [PATCH v4 net-next 14/16] sfc_ef100: probe the PHY and configure the MAC Edward Cree
2020-07-24 16:01 ` [PATCH v4 net-next 15/16] sfc_ef100: read device MAC address at probe time Edward Cree
2020-07-24 16:01 ` [PATCH v4 net-next 16/16] sfc_ef100: implement ndo_get_phys_port_{id,name} Edward Cree

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0ae88dee-9872-bc20-87ed-fec4458d6162@solarflare.com \
    --to=ecree@solarflare.com \
    --cc=davem@davemloft.net \
    --cc=linux-net-drivers@solarflare.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.