From patchwork Mon Jul 27 11:57:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Edward Cree X-Patchwork-Id: 1336900 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=solarflare.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by ozlabs.org (Postfix) with ESMTP id 4BFdbD0St6z9sRR for ; Mon, 27 Jul 2020 21:57:28 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728276AbgG0L50 (ORCPT ); Mon, 27 Jul 2020 07:57:26 -0400 Received: from dispatch1-us1.ppe-hosted.com ([148.163.129.52]:46876 "EHLO dispatch1-us1.ppe-hosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726890AbgG0L50 (ORCPT ); Mon, 27 Jul 2020 07:57:26 -0400 Received: from mx1-us1.ppe-hosted.com (unknown [10.7.65.61]) by dispatch1-us1.ppe-hosted.com (PPE Hosted ESMTP Server) with ESMTP id 7250C600B0; Mon, 27 Jul 2020 11:57:25 +0000 (UTC) Received: from us4-mdac16-17.ut7.mdlocal (unknown [10.7.65.241]) by mx1-us1.ppe-hosted.com (PPE Hosted ESMTP Server) with ESMTP id 62D098011F; Mon, 27 Jul 2020 11:57:24 +0000 (UTC) X-Virus-Scanned: Proofpoint Essentials engine Received: from mx1-us1.ppe-hosted.com (unknown [10.7.66.30]) by mx1-us1.ppe-hosted.com (PPE Hosted ESMTP Server) with ESMTPS id 62B7B8005D; Mon, 27 Jul 2020 11:57:20 +0000 (UTC) Received: from webmail.solarflare.com (uk.solarflare.com [193.34.186.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mx1-us1.ppe-hosted.com (PPE Hosted ESMTP Server) with ESMTPS id 90F071000A1; Mon, 27 Jul 2020 11:57:19 +0000 (UTC) Received: from [10.17.20.203] (10.17.20.203) by ukex01.SolarFlarecom.com (10.17.10.4) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 27 Jul 2020 12:57:14 +0100 From: Edward Cree Subject: [PATCH v5 net-next 08/16] sfc_ef100: implement MCDI transport To: , CC: References: <72cc6ef1-4f7f-bf22-5bec-942beb6353ed@solarflare.com> Message-ID: <38524487-7cd2-a25e-f460-d1c2b0fbd623@solarflare.com> Date: Mon, 27 Jul 2020 12:57:09 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.2.2 MIME-Version: 1.0 In-Reply-To: <72cc6ef1-4f7f-bf22-5bec-942beb6353ed@solarflare.com> Content-Language: en-GB X-Originating-IP: [10.17.20.203] X-ClientProxiedBy: ocex03.SolarFlarecom.com (10.20.40.36) To ukex01.SolarFlarecom.com (10.17.10.4) X-TM-AS-Product-Ver: SMEX-12.5.0.1300-8.6.1012-25566.005 X-TM-AS-Result: No-11.319900-8.000000-10 X-TMASE-MatchedRID: YNw1G8ZMFRKh9oPbMj7PPPCoOvLLtsMhP6Tki+9nU38HZBaLwEXlKCzy bVqWyY2NQpbnr2qRsUlc8y3w14AFDNvWh31RtNY81bFtmBqqFLTcVi8qZmJWc4+Ixb7djOSCSb8 Woy4yLo4IAEZnJGXRA/tnnh8+7vvDb7QFkjVAWhaqDSBu0tUhr+ZM8S4DYUopR2YNIFh+clETJ7 4q/iXJiipu7calyAo9bTV/KYdB9WCt7MyBjLt7zjn/wcdfjLjCVCGp3g4/hjuRjx4hNpIk+NkbV xyiYfRTt2M/b0y5tZwhoTAGY824W/KSiKFBFYghPja3w1ExF8RcaNB/u5yQq/a7agslQWYYRyqM LIj/WA3gYsxc0Oenakj4YJn2mzfPUYdYa4LfLrGfG8+bi+/3vIv8yhR3Ab/7bDD7i2QfyEcnDf+ 57mBigX4+xG7OCBs/MSPjUMycTXefO8RAj0nqTsmR5yDJkPg4hnpDm0ThsHRUjspoiX02F7FmLU uqedKxPE7FMRuDJPKRk6XtYogiau9c69BWUTGwC24oEZ6SpSkj80Za3RRg8K+JpMvWhNHbA3mYy Okat2Qs0g/gwyNOib5kRQcoTNRmEze1V/T0TyU= X-TM-AS-User-Approved-Sender: Yes X-TM-AS-User-Blocked-Sender: No X-TMASE-Result: 10--11.319900-8.000000 X-TMASE-Version: SMEX-12.5.0.1300-8.6.1012-25566.005 X-MDID: 1595851044-SP5GYPbeBX1l Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Signed-off-by: Edward Cree --- 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; };