From patchwork Wed Feb 7 06:52:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shinas Rasheed X-Patchwork-Id: 197769 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:168b:b0:106:860b:bbdd with SMTP id ma11csp2045564dyb; Tue, 6 Feb 2024 22:54:11 -0800 (PST) X-Google-Smtp-Source: AGHT+IEe0OW2jBEI7clso8g98SKzAuAAhUpNssW2AIUAidgvAAfKy73Dwd4A44Yn0RNJEAQCspHb X-Received: by 2002:a17:906:235b:b0:a38:8766:c7ab with SMTP id m27-20020a170906235b00b00a388766c7abmr195445eja.55.1707288850829; Tue, 06 Feb 2024 22:54:10 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707288850; cv=pass; d=google.com; s=arc-20160816; b=DYuYtPAk9YYC0g2Zc7/x/nCERiZcqMpWIckqbklInZRL0XtSG7u+gAGntv7aSfGObq z2mapTWNiWmN/Y1PsY8lbZjHM0efjrSKpK5kRKcKbjhvU4OlM/UEylMZO2PanRcsS1dv rFBIo7bkGY0lEj6mI/EpNTUUM8tx4RN6EB8/+QC3bmOk9AAuUbsj9qPr8zTXEFQa0qkN kSsav5J3CPxSVzS+mf3Or2OM2SVKMwRdutEAk7dujfHR8EqwXZbChcyt0g1cfU9AJn+X p15AHJXarT3XGwAKzpb5FqpuifJYr+zGDn+Ru1UzF8MXgRcsYCIoURbPmvNxnpy8cfpE my1Q== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=j/hcTQHD7qIiJWBLQ/sDGe9iFT9lJaad5q2J2paGKF0=; fh=owerP0yxuPTfONLKfS+H9tK9PX6zFuLF4XldKeTPLgQ=; b=mnk298nXHLqW9l1vPCuT/4fqSKin4G8frfsgkSw3yfqk3TXGHRKvkwsGAIG+Ca0q7f 8b7EXDzakPs07YnjnfaiKHDKXDJmzEt9Txl+9oGGIdiiNtqR95mC3c2Fa59u/fvdO+yk 1rn5s+ChuEJHw4d9h51p1/fmzTXUDCuTB2Md0F7dV6NlpM+f3Sr7DkupbuMdfeJXNHZQ zHPlZY0yP3ZxtTIc9X83yjPJlxbllSPRMZ8AIkAVDv8XmBCAdtqH6YC0jktWH2BHSlbC l/WRxfvAdQxyioDMuW0PAZCKM/qJHo0IpliGw9hrzttnFKTle8C7UJ2cnfkV3WWl7tkZ Vw7w==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=II4nMVdt; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-56036-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56036-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com X-Forwarded-Encrypted: i=2; AJvYcCWC1i/hSqKzIM8v4eYiWcbDCR5fAaib24ah8RfbzFWOfw7sqTnfKb+jYiqlB8C09qU0loydYpK/pL+TXvkgDNM20ohZaw== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id rh2-20020a17090720e200b00a3842f4dfb3si533538ejb.66.2024.02.06.22.54.10 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 06 Feb 2024 22:54:10 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-56036-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=II4nMVdt; arc=pass (i=1 spf=pass spfdomain=marvell.com dkim=pass dkdomain=marvell.com dmarc=pass fromdomain=marvell.com); spf=pass (google.com: domain of linux-kernel+bounces-56036-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-56036-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id 09CC01F27283 for ; Wed, 7 Feb 2024 06:54:10 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 37EC5208A3; Wed, 7 Feb 2024 06:52:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="II4nMVdt" Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F10581CF8C; Wed, 7 Feb 2024 06:52:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=67.231.156.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707288772; cv=none; b=Nnf+dkj8QHsYyXo5GgcjBS8XNvNmt1qgwj0CaDTjZkW3c3ou8pYGexd9oB0R4D9tiOgotIUxWADRca4V/NcsbY26Y0qqEdgExm+P4ajA9QeyGcUX11lauBfZ1SD9w+gBeKGxN1sDr0+u0Qt5NKJ/FJ+a8S8UjUy2WR1lZ/02rZM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707288772; c=relaxed/simple; bh=gT+fl+LISvMmY2D8T+YmrGetYdbPU43ze9W2S+9TWe8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=hXf6Wt7pD75Pu9QdWxrB9dh8S6IPaBDpohdcmH0omL7M1yYxd6J7CLKskrqpOWOE4jLnlE+5RPacea/XKEq34+jD3BXhNc74+YIJ4BaJpXM8BX51028PpfT0+TtZeoLqp2vmq60pnFR+61kbGjLxnvwR9ZZcLlLLJIsJh1UNR/c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com; spf=pass smtp.mailfrom=marvell.com; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b=II4nMVdt; arc=none smtp.client-ip=67.231.156.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=marvell.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=marvell.com Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 4170fBAq007435; Tue, 6 Feb 2024 22:52:42 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=j/hcTQHD7qIiJWBLQ/sDGe9iFT9lJaad5q2J2paGKF0=; b=II4 nMVdtEtDXkGBmOuiqD64PD51O0dY7Tp7whPHOCruMoUTSqLQa0XWO7HSbKsI/Q9k 546lYtB1n6UQXNOR62t1vtkQ1q6hnCqOWdxm9mBFrhbwWXUbOOrj5Yak9kgjoYuP ZNYJoskZWTUtG8oZ86Y1O7WKT+/XZ9jqSz/4+CwfizzIkVv8E11rNxnHZRCMvRN4 c8A1FBWCuqqH40MTQ/77kmrcog7WPSi4C2REE/cFunrf7PRYJc7NhWJlpStdMRJE 5gZVjo7P2rG60D5dbz5LqNsGfKAX7ci5lLKelw/1KCtJ/jPxXB5NQ647uGT6IFFB c82DgIAsh2DpWqBap2g== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3w38u85xxd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Tue, 06 Feb 2024 22:52:41 -0800 (PST) Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Tue, 6 Feb 2024 22:52:39 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Tue, 6 Feb 2024 22:52:39 -0800 Received: from ubuntu-PowerEdge-T110-II.sclab.marvell.com (unknown [10.106.27.86]) by maili.marvell.com (Postfix) with ESMTP id 1D4D33F7082; Tue, 6 Feb 2024 22:52:39 -0800 (PST) From: Shinas Rasheed To: , CC: , , , , , , , , , , , , Veerasenareddy Burru , Satananda Burla , "David S. Miller" , Eric Dumazet Subject: [PATCH net-next v6 3/8] octeon_ep_vf: add VF-PF mailbox communication. Date: Tue, 6 Feb 2024 22:52:02 -0800 Message-ID: <20240207065207.3092004-4-srasheed@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20240207065207.3092004-1-srasheed@marvell.com> References: <20240207065207.3092004-1-srasheed@marvell.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: bm8fxH5qq7Wvnkg92ESnFXTjLrRBu3k7 X-Proofpoint-GUID: bm8fxH5qq7Wvnkg92ESnFXTjLrRBu3k7 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-02-06_16,2024-01-31_01,2023-05-22_02 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1790222113925272324 X-GMAIL-MSGID: 1790222113925272324 Implement VF-PF mailbox to send all control commands from VF to PF and receive responses and notifications from PF to VF. Signed-off-by: Shinas Rasheed --- V6: - Changed error label of octep_get_fw_info in probe function to have action-specific name V5: https://lore.kernel.org/all/20240129050254.3047778-4-srasheed@marvell.com/ - No changes V4: https://lore.kernel.org/all/20240108124213.2966536-4-srasheed@marvell.com/ - No changes V3: https://lore.kernel.org/all/20240105203823.2953604-4-srasheed@marvell.com/ - No changes V2: https://lore.kernel.org/all/20231223134000.2906144-4-srasheed@marvell.com/ - No changes V1: https://lore.kernel.org/all/20231221092844.2885872-4-srasheed@marvell.com/ .../marvell/octeon_ep_vf/octep_vf_main.c | 103 ++++++ .../marvell/octeon_ep_vf/octep_vf_main.h | 1 + .../marvell/octeon_ep_vf/octep_vf_mbox.c | 336 +++++++++++++++++- .../marvell/octeon_ep_vf/octep_vf_mbox.h | 143 +++++++- 4 files changed, 581 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c index 2ade88698f65..562beed9af6a 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.c @@ -186,6 +186,19 @@ static netdev_tx_t octep_vf_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } +int octep_vf_get_link_info(struct octep_vf_device *oct) +{ + int ret, size; + + ret = octep_vf_mbox_bulk_read(oct, OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO, + (u8 *)&oct->link_info, &size); + if (ret) { + dev_err(&oct->pdev->dev, "Get VF link info failed via VF Mbox\n"); + return ret; + } + return 0; +} + /** * octep_vf_tx_timeout_task - work queue task to Handle Tx queue timeout. * @@ -226,11 +239,84 @@ static void octep_vf_tx_timeout(struct net_device *netdev, unsigned int txqueue) schedule_work(&oct->tx_timeout_task); } +static int octep_vf_set_mac(struct net_device *netdev, void *p) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + struct sockaddr *addr = (struct sockaddr *)p; + int err; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + err = octep_vf_mbox_set_mac_addr(oct, addr->sa_data); + if (err) + return err; + + memcpy(oct->mac_addr, addr->sa_data, ETH_ALEN); + eth_hw_addr_set(netdev, addr->sa_data); + + return 0; +} + +static int octep_vf_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + struct octep_vf_iface_link_info *link_info; + int err; + + link_info = &oct->link_info; + if (link_info->mtu == new_mtu) + return 0; + + err = octep_vf_mbox_set_mtu(oct, new_mtu); + if (!err) { + oct->link_info.mtu = new_mtu; + netdev->mtu = new_mtu; + } + return err; +} + +static int octep_vf_set_features(struct net_device *netdev, + netdev_features_t features) +{ + struct octep_vf_device *oct = netdev_priv(netdev); + u16 rx_offloads = 0, tx_offloads = 0; + int err; + + /* We only support features received from firmware */ + if ((features & netdev->hw_features) != features) + return -EINVAL; + + if (features & NETIF_F_TSO) + tx_offloads |= OCTEP_VF_TX_OFFLOAD_TSO; + + if (features & NETIF_F_TSO6) + tx_offloads |= OCTEP_VF_TX_OFFLOAD_TSO; + + if (features & NETIF_F_IP_CSUM) + tx_offloads |= OCTEP_VF_TX_OFFLOAD_CKSUM; + + if (features & NETIF_F_IPV6_CSUM) + tx_offloads |= OCTEP_VF_TX_OFFLOAD_CKSUM; + + if (features & NETIF_F_RXCSUM) + rx_offloads |= OCTEP_VF_RX_OFFLOAD_CKSUM; + + err = octep_vf_mbox_set_offloads(oct, tx_offloads, rx_offloads); + if (!err) + netdev->features = features; + + return err; +} + static const struct net_device_ops octep_vf_netdev_ops = { .ndo_open = octep_vf_open, .ndo_stop = octep_vf_stop, .ndo_start_xmit = octep_vf_start_xmit, .ndo_tx_timeout = octep_vf_tx_timeout, + .ndo_set_mac_address = octep_vf_set_mac, + .ndo_change_mtu = octep_vf_change_mtu, + .ndo_set_features = octep_vf_set_features, }; static const char *octep_vf_devid_to_str(struct octep_vf_device *oct) @@ -412,11 +498,28 @@ static int octep_vf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto delete_mbox; } + if (octep_vf_mbox_get_fw_info(octep_vf_dev)) { + dev_err(&pdev->dev, "unable to get fw info\n"); + err = -EINVAL; + goto delete_mbox; + } + netdev->hw_features = NETIF_F_SG; + if (OCTEP_VF_TX_IP_CSUM(octep_vf_dev->fw_info.tx_ol_flags)) + netdev->hw_features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); + + if (OCTEP_VF_RX_IP_CSUM(octep_vf_dev->fw_info.rx_ol_flags)) + netdev->hw_features |= NETIF_F_RXCSUM; + netdev->min_mtu = OCTEP_VF_MIN_MTU; netdev->max_mtu = OCTEP_VF_MAX_MTU; netdev->mtu = OCTEP_VF_DEFAULT_MTU; + if (OCTEP_VF_TX_TSO(octep_vf_dev->fw_info.tx_ol_flags)) { + netdev->hw_features |= NETIF_F_TSO; + netif_set_tso_max_size(netdev, netdev->max_mtu); + } + netdev->features |= netdev->hw_features; octep_vf_get_mac_addr(octep_vf_dev, octep_vf_dev->mac_addr); eth_hw_addr_set(netdev, octep_vf_dev->mac_addr); diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h index e22e393c6ee2..5a3b545ad590 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_main.h @@ -327,6 +327,7 @@ void octep_vf_device_setup_cn93(struct octep_vf_device *oct); void octep_vf_device_setup_cnxk(struct octep_vf_device *oct); int octep_vf_iq_process_completions(struct octep_vf_iq *iq, u16 budget); int octep_vf_oq_process_rx(struct octep_vf_oq *oq, int budget); +int octep_vf_get_link_info(struct octep_vf_device *oct); int octep_vf_get_if_stats(struct octep_vf_device *oct); void octep_vf_mbox_work(struct work_struct *work); #endif /* _OCTEP_VF_MAIN_H_ */ diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c index 1c1fe293fc50..2eab21e43048 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.c @@ -10,6 +10,15 @@ #include "octep_vf_config.h" #include "octep_vf_main.h" +/* When a new command is implemented, the below table should be updated + * with new command and it's version info. + */ +static u32 pfvf_cmd_versions[OCTEP_PFVF_MBOX_CMD_MAX] = { + [0 ... OCTEP_PFVF_MBOX_CMD_DEV_REMOVE] = OCTEP_PFVF_MBOX_VERSION_V1, + [OCTEP_PFVF_MBOX_CMD_GET_FW_INFO ... OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS] = + OCTEP_PFVF_MBOX_VERSION_V2 +}; + int octep_vf_setup_mbox(struct octep_vf_device *oct) { int ring = 0; @@ -23,6 +32,7 @@ int octep_vf_setup_mbox(struct octep_vf_device *oct) oct->hw_ops.setup_mbox_regs(oct, ring); INIT_WORK(&oct->mbox->wk.work, octep_vf_mbox_work); oct->mbox->wk.ctxptr = oct; + oct->mbox_neg_ver = OCTEP_PFVF_MBOX_VERSION_CURRENT; dev_info(&oct->pdev->dev, "setup vf mbox successfully\n"); return 0; } @@ -42,55 +52,379 @@ void octep_vf_delete_mbox(struct octep_vf_device *oct) int octep_vf_mbox_version_check(struct octep_vf_device *oct) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_version.opcode = OCTEP_PFVF_MBOX_CMD_VERSION; + cmd.s_version.version = OCTEP_PFVF_MBOX_VERSION_CURRENT; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret == OCTEP_PFVF_MBOX_CMD_STATUS_NACK) { + dev_err(&oct->pdev->dev, + "VF Mbox version is incompatible with PF\n"); + return -EINVAL; + } + oct->mbox_neg_ver = (u32)rsp.s_version.version; + dev_dbg(&oct->pdev->dev, + "VF Mbox version:%u Negotiated VF version with PF:%u\n", + (u32)cmd.s_version.version, + (u32)rsp.s_version.version); return 0; } void octep_vf_mbox_work(struct work_struct *work) { + struct octep_vf_mbox_wk *wk = container_of(work, struct octep_vf_mbox_wk, work); + struct octep_vf_iface_link_info *link_info; + struct octep_vf_device *oct = NULL; + struct octep_vf_mbox *mbox = NULL; + union octep_pfvf_mbox_word *notif; + u64 pf_vf_data; + + oct = (struct octep_vf_device *)wk->ctxptr; + link_info = &oct->link_info; + mbox = oct->mbox; + pf_vf_data = readq(mbox->mbox_read_reg); + + notif = (union octep_pfvf_mbox_word *)&pf_vf_data; + + switch (notif->s.opcode) { + case OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS: + if (notif->s_link_status.status) { + link_info->oper_up = OCTEP_PFVF_LINK_STATUS_UP; + netif_carrier_on(oct->netdev); + dev_info(&oct->pdev->dev, "netif_carrier_on\n"); + } else { + link_info->oper_up = OCTEP_PFVF_LINK_STATUS_DOWN; + netif_carrier_off(oct->netdev); + dev_info(&oct->pdev->dev, "netif_carrier_off\n"); + } + break; + default: + dev_err(&oct->pdev->dev, + "Received unsupported notif %d\n", notif->s.opcode); + break; + } +} + +static int __octep_vf_mbox_send_cmd(struct octep_vf_device *oct, + union octep_pfvf_mbox_word cmd, + union octep_pfvf_mbox_word *rsp) +{ + struct octep_vf_mbox *mbox = oct->mbox; + u64 reg_val = 0ull; + int count; + + if (!mbox) + return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP; + + cmd.s.type = OCTEP_PFVF_MBOX_TYPE_CMD; + writeq(cmd.u64, mbox->mbox_write_reg); + + /* No response for notification messages */ + if (!rsp) + return 0; + + for (count = 0; count < OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT; count++) { + usleep_range(1000, 1500); + reg_val = readq(mbox->mbox_write_reg); + if (reg_val != cmd.u64) { + rsp->u64 = reg_val; + break; + } + } + if (count == OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT) { + dev_err(&oct->pdev->dev, "mbox send command timed out\n"); + return OCTEP_PFVF_MBOX_CMD_STATUS_TIMEDOUT; + } + if (rsp->s.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "mbox_send: Received NACK\n"); + return OCTEP_PFVF_MBOX_CMD_STATUS_NACK; + } + rsp->u64 = reg_val; + return 0; +} + +int octep_vf_mbox_send_cmd(struct octep_vf_device *oct, union octep_pfvf_mbox_word cmd, + union octep_pfvf_mbox_word *rsp) +{ + struct octep_vf_mbox *mbox = oct->mbox; + int ret; + + if (!mbox) + return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP; + mutex_lock(&mbox->lock); + if (pfvf_cmd_versions[cmd.s.opcode] > oct->mbox_neg_ver) { + dev_dbg(&oct->pdev->dev, "CMD:%d not supported in Version:%d\n", + cmd.s.opcode, oct->mbox_neg_ver); + mutex_unlock(&mbox->lock); + return -EOPNOTSUPP; + } + ret = __octep_vf_mbox_send_cmd(oct, cmd, rsp); + mutex_unlock(&mbox->lock); + return ret; +} + +int octep_vf_mbox_bulk_read(struct octep_vf_device *oct, enum octep_pfvf_mbox_opcode opcode, + u8 *data, int *size) +{ + struct octep_vf_mbox *mbox = oct->mbox; + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int data_len = 0, tmp_len = 0; + int read_cnt, i = 0, ret; + + if (!mbox) + return OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP; + + mutex_lock(&mbox->lock); + cmd.u64 = 0; + cmd.s_data.opcode = opcode; + cmd.s_data.frag = 0; + /* Send cmd to read data from PF */ + ret = __octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "send mbox cmd fail for data request\n"); + mutex_unlock(&mbox->lock); + return ret; + } + /* PF sends the data length of requested CMD + * in ACK + */ + data_len = *((int32_t *)rsp.s_data.data); + tmp_len = data_len; + cmd.u64 = 0; + rsp.u64 = 0; + cmd.s_data.opcode = opcode; + cmd.s_data.frag = 1; + while (data_len) { + ret = __octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "send mbox cmd fail for data request\n"); + mutex_unlock(&mbox->lock); + mbox->mbox_data.data_index = 0; + memset(mbox->mbox_data.recv_data, 0, OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE); + return ret; + } + if (data_len > OCTEP_PFVF_MBOX_MAX_DATA_SIZE) { + data_len -= OCTEP_PFVF_MBOX_MAX_DATA_SIZE; + read_cnt = OCTEP_PFVF_MBOX_MAX_DATA_SIZE; + } else { + read_cnt = data_len; + data_len = 0; + } + for (i = 0; i < read_cnt; i++) { + mbox->mbox_data.recv_data[mbox->mbox_data.data_index] = + rsp.s_data.data[i]; + mbox->mbox_data.data_index++; + } + cmd.u64 = 0; + rsp.u64 = 0; + cmd.s_data.opcode = opcode; + cmd.s_data.frag = 1; + } + memcpy(data, mbox->mbox_data.recv_data, tmp_len); + *size = tmp_len; + mbox->mbox_data.data_index = 0; + memset(mbox->mbox_data.recv_data, 0, OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE); + mutex_unlock(&mbox->lock); + return 0; } int octep_vf_mbox_set_mtu(struct octep_vf_device *oct, int mtu) { + int frame_size = mtu + ETH_HLEN + ETH_FCS_LEN; + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret = 0; + + if (mtu < ETH_MIN_MTU || frame_size > ETH_MAX_MTU) { + dev_err(&oct->pdev->dev, + "Failed to set MTU to %d MIN MTU:%d MAX MTU:%d\n", + mtu, ETH_MIN_MTU, ETH_MAX_MTU); + return -EINVAL; + } + + cmd.u64 = 0; + cmd.s_set_mtu.opcode = OCTEP_PFVF_MBOX_CMD_SET_MTU; + cmd.s_set_mtu.mtu = mtu; + + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Mbox send failed; err=%d\n", ret); + return ret; + } + if (rsp.s_set_mtu.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Received Mbox NACK from PF for MTU:%d\n", mtu); + return -EINVAL; + } + return 0; } int octep_vf_mbox_set_mac_addr(struct octep_vf_device *oct, char *mac_addr) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int i, ret; + + cmd.u64 = 0; + cmd.s_set_mac.opcode = OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR; + for (i = 0; i < ETH_ALEN; i++) + cmd.s_set_mac.mac_addr[i] = mac_addr[i]; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Mbox send failed; err = %d\n", ret); + return ret; + } + if (rsp.s_set_mac.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "received NACK\n"); + return -EINVAL; + } return 0; } int octep_vf_mbox_get_mac_addr(struct octep_vf_device *oct, char *mac_addr) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int i, ret; + + cmd.u64 = 0; + cmd.s_set_mac.opcode = OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "get_mac: mbox send failed; err = %d\n", ret); + return ret; + } + if (rsp.s_set_mac.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "get_mac: received NACK\n"); + return -EINVAL; + } + for (i = 0; i < ETH_ALEN; i++) + mac_addr[i] = rsp.s_set_mac.mac_addr[i]; return 0; } int octep_vf_mbox_set_rx_state(struct octep_vf_device *oct, bool state) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_link_state.opcode = OCTEP_PFVF_MBOX_CMD_SET_RX_STATE; + cmd.s_link_state.state = state; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Set Rx state via VF Mbox send failed\n"); + return ret; + } + if (rsp.s_link_state.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Set Rx state received NACK\n"); + return -EINVAL; + } return 0; } int octep_vf_mbox_set_link_status(struct octep_vf_device *oct, bool status) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_link_status.opcode = OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS; + cmd.s_link_status.status = status; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Set link status via VF Mbox send failed\n"); + return ret; + } + if (rsp.s_link_status.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Set link status received NACK\n"); + return -EINVAL; + } return 0; } int octep_vf_mbox_get_link_status(struct octep_vf_device *oct, u8 *oper_up) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_link_status.opcode = OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Get link status via VF Mbox send failed\n"); + return ret; + } + if (rsp.s_link_status.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Get link status received NACK\n"); + return -EINVAL; + } + *oper_up = rsp.s_link_status.status; return 0; } int octep_vf_mbox_dev_remove(struct octep_vf_device *oct) { - return 0; + union octep_pfvf_mbox_word cmd; + int ret; + + cmd.u64 = 0; + cmd.s.opcode = OCTEP_PFVF_MBOX_CMD_DEV_REMOVE; + ret = octep_vf_mbox_send_cmd(oct, cmd, NULL); + return ret; } int octep_vf_mbox_get_fw_info(struct octep_vf_device *oct) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_fw_info.opcode = OCTEP_PFVF_MBOX_CMD_GET_FW_INFO; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Get link status via VF Mbox send failed\n"); + return ret; + } + if (rsp.s_fw_info.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Get link status received NACK\n"); + return -EINVAL; + } + oct->fw_info.pkind = rsp.s_fw_info.pkind; + oct->fw_info.fsz = rsp.s_fw_info.fsz; + oct->fw_info.rx_ol_flags = rsp.s_fw_info.rx_ol_flags; + oct->fw_info.tx_ol_flags = rsp.s_fw_info.tx_ol_flags; + return 0; } int octep_vf_mbox_set_offloads(struct octep_vf_device *oct, u16 tx_offloads, u16 rx_offloads) { + union octep_pfvf_mbox_word cmd; + union octep_pfvf_mbox_word rsp; + int ret; + + cmd.u64 = 0; + cmd.s_offloads.opcode = OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS; + cmd.s_offloads.rx_ol_flags = rx_offloads; + cmd.s_offloads.tx_ol_flags = tx_offloads; + ret = octep_vf_mbox_send_cmd(oct, cmd, &rsp); + if (ret) { + dev_err(&oct->pdev->dev, "Set offloads via VF Mbox send failed\n"); + return ret; + } + if (rsp.s_link_state.type != OCTEP_PFVF_MBOX_TYPE_RSP_ACK) { + dev_err(&oct->pdev->dev, "Set offloads received NACK\n"); + return -EINVAL; + } return 0; } diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h index 14f4fb19445b..9b5efad37eab 100644 --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_mbox.h @@ -7,10 +7,151 @@ #ifndef _OCTEP_VF_MBOX_H_ #define _OCTEP_VF_MBOX_H_ -#define OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE 256 +/* When a new command is implemented, VF Mbox version should be bumped. + */ +enum octep_pfvf_mbox_version { + OCTEP_PFVF_MBOX_VERSION_V0, + OCTEP_PFVF_MBOX_VERSION_V1, + OCTEP_PFVF_MBOX_VERSION_V2 +}; + +#define OCTEP_PFVF_MBOX_VERSION_CURRENT OCTEP_PFVF_MBOX_VERSION_V2 + +enum octep_pfvf_mbox_opcode { + OCTEP_PFVF_MBOX_CMD_VERSION, + OCTEP_PFVF_MBOX_CMD_SET_MTU, + OCTEP_PFVF_MBOX_CMD_SET_MAC_ADDR, + OCTEP_PFVF_MBOX_CMD_GET_MAC_ADDR, + OCTEP_PFVF_MBOX_CMD_GET_LINK_INFO, + OCTEP_PFVF_MBOX_CMD_GET_STATS, + OCTEP_PFVF_MBOX_CMD_SET_RX_STATE, + OCTEP_PFVF_MBOX_CMD_SET_LINK_STATUS, + OCTEP_PFVF_MBOX_CMD_GET_LINK_STATUS, + OCTEP_PFVF_MBOX_CMD_GET_MTU, + OCTEP_PFVF_MBOX_CMD_DEV_REMOVE, + OCTEP_PFVF_MBOX_CMD_GET_FW_INFO, + OCTEP_PFVF_MBOX_CMD_SET_OFFLOADS, + OCTEP_PFVF_MBOX_NOTIF_LINK_STATUS, + OCTEP_PFVF_MBOX_CMD_MAX, +}; + +enum octep_pfvf_mbox_word_type { + OCTEP_PFVF_MBOX_TYPE_CMD, + OCTEP_PFVF_MBOX_TYPE_RSP_ACK, + OCTEP_PFVF_MBOX_TYPE_RSP_NACK, +}; + +enum octep_pfvf_mbox_cmd_status { + OCTEP_PFVF_MBOX_CMD_STATUS_NOT_SETUP = 1, + OCTEP_PFVF_MBOX_CMD_STATUS_TIMEDOUT = 2, + OCTEP_PFVF_MBOX_CMD_STATUS_NACK = 3, + OCTEP_PFVF_MBOX_CMD_STATUS_BUSY = 4, + OCTEP_PFVF_MBOX_CMD_STATUS_ERR = 5 +}; + +enum octep_pfvf_link_status { + OCTEP_PFVF_LINK_STATUS_DOWN, + OCTEP_PFVF_LINK_STATUS_UP, +}; + +enum octep_pfvf_link_speed { + OCTEP_PFVF_LINK_SPEED_NONE, + OCTEP_PFVF_LINK_SPEED_1000, + OCTEP_PFVF_LINK_SPEED_10000, + OCTEP_PFVF_LINK_SPEED_25000, + OCTEP_PFVF_LINK_SPEED_40000, + OCTEP_PFVF_LINK_SPEED_50000, + OCTEP_PFVF_LINK_SPEED_100000, + OCTEP_PFVF_LINK_SPEED_LAST, +}; + +enum octep_pfvf_link_duplex { + OCTEP_PFVF_LINK_HALF_DUPLEX, + OCTEP_PFVF_LINK_FULL_DUPLEX, +}; + +enum octep_pfvf_link_autoneg { + OCTEP_PFVF_LINK_AUTONEG, + OCTEP_PFVF_LINK_FIXED, +}; + +#define OCTEP_PFVF_MBOX_TIMEOUT_WAIT_COUNT 8000 +#define OCTEP_PFVF_MBOX_TIMEOUT_WAIT_UDELAY 1000 +#define OCTEP_PFVF_MBOX_MAX_RETRIES 2 +#define OCTEP_PFVF_MBOX_VERSION 0 +#define OCTEP_PFVF_MBOX_MAX_DATA_SIZE 6 +#define OCTEP_PFVF_MBOX_MAX_DATA_BUF_SIZE 320 +#define OCTEP_PFVF_MBOX_MORE_FRAG_FLAG 1 + +union octep_pfvf_mbox_word { + u64 u64; + struct { + u64 opcode:8; + u64 type:2; + u64 rsvd:6; + u64 data:48; + } s; + struct { + u64 opcode:8; + u64 type:2; + u64 frag:1; + u64 rsvd:5; + u8 data[6]; + } s_data; + struct { + u64 opcode:8; + u64 type:2; + u64 rsvd:6; + u64 version:48; + } s_version; + struct { + u64 opcode:8; + u64 type:2; + u64 rsvd:6; + u8 mac_addr[6]; + } s_set_mac; + struct { + u64 opcode:8; + u64 type:2; + u64 rsvd:6; + u64 mtu:48; + } s_set_mtu; + struct { + u64 opcode:8; + u64 type:2; + u64 state:1; + u64 rsvd:53; + } s_link_state; + struct { + u64 opcode:8; + u64 type:2; + u64 status:1; + u64 rsvd:53; + } s_link_status; + struct { + u64 opcode:8; + u64 type:2; + u64 pkind:8; + u64 fsz:8; + u64 rx_ol_flags:16; + u64 tx_ol_flags:16; + u64 rsvd:6; + } s_fw_info; + struct { + u64 opcode:8; + u64 type:2; + u64 rsvd:22; + u64 rx_ol_flags:16; + u64 tx_ol_flags:16; + } s_offloads; +} __packed; int octep_vf_setup_mbox(struct octep_vf_device *oct); void octep_vf_delete_mbox(struct octep_vf_device *oct); +int octep_vf_mbox_send_cmd(struct octep_vf_device *oct, union octep_pfvf_mbox_word cmd, + union octep_pfvf_mbox_word *rsp); +int octep_vf_mbox_bulk_read(struct octep_vf_device *oct, enum octep_pfvf_mbox_opcode opcode, + u8 *data, int *size); int octep_vf_mbox_set_mtu(struct octep_vf_device *oct, int mtu); int octep_vf_mbox_set_mac_addr(struct octep_vf_device *oct, char *mac_addr); int octep_vf_mbox_get_mac_addr(struct octep_vf_device *oct, char *mac_addr);