From patchwork Thu Feb 22 14:22:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herve Codina X-Patchwork-Id: 204796 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7300:aa16:b0:108:e6aa:91d0 with SMTP id by22csp285814dyb; Thu, 22 Feb 2024 06:24:19 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCWMnxTSe7+mW9aOI69roVDw0WK6uxxU55q/QElOAbJghGkSQQeEu/x3pbSI8l4Vzh4ZvOurkhNSmvY8/CxJ5vZAT4gzLQ== X-Google-Smtp-Source: AGHT+IFMEeOjENHvKnuZxC9pFFhYyv4CUUW4yWSJWiMW/W94/A9RpGmdEIrBpgkQDuJc3x1IB13z X-Received: by 2002:ac8:5756:0:b0:42e:2b69:e2b0 with SMTP id 22-20020ac85756000000b0042e2b69e2b0mr8748158qtx.65.1708611859043; Thu, 22 Feb 2024 06:24:19 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1708611859; cv=pass; d=google.com; s=arc-20160816; b=gO3kfT86m0pnop3CEe/aQK+awwrA1PmRgmBuKK6AY4Qt7/k4mfRFajNTd4qfuGz/Y4 T8QIBgpt4uPrAkwtyfheiprRkWacyvCDZ+ddIs/ZFrdDusmWx+bsr7UxYO9tYNYTVBty WZcmpeXDJRS30Pb3K2HmDuLzSxLONSARsLE5a8JCiNY+d8/JnkdGEi8NYkvQZP2WrXB8 sNvkLrcrkg0wUJoOr7tcDeBzP4aDtqNe90fI/7sWxqKZTkX4MTz+JAbYkMV3LvOIroju /tTvv7K+X0BsC2deMFKIdcDJ1XhAh5LfUy8nfC7s3mD7jnyNxQbZghHm6j2scpQs2Yoz uP5A== 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=GArzHpU6kmO8xUdzlOh0QC5GjmLwbH8840y9bNwiO9I=; fh=S1JXykGn8s83VQzPRjkanrg93kX6oJVbyHnK1JmVqsw=; b=F2XeodPlbACU/s+92BccLal7cFM+tauw55TBXCKy9R9n/UC5eW9uDnSCLMSUGb2aT9 vxhgm2YcGfFkc1qKD5L9IOohTRPkTxnH4dGZ1BxMSLH1/+zKw2y8sVkzaWbzmD22SjQu BAZYl03m/A21/9eM45C57DGrt0/8ngBg0DvJjCwT/06lerUi+iDM1cfH9TcdEl74H9Tr TJf5jtk3Osfh3Dsc0qJL1Ftfyi3xa0vDbZSwiFbuGzMldAZ9M+ZvY7aaPSc/ldil9oRf zntcQunrhtV19lMsoTZX4rf8o/XdPajowGSkD9a91TRq8dtehD7mrDN873vWu+zZ3SwB aNtg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=A7MOPXUS; arc=pass (i=1 spf=pass spfdomain=bootlin.com dkim=pass dkdomain=bootlin.com dmarc=pass fromdomain=bootlin.com); spf=pass (google.com: domain of linux-kernel+bounces-76695-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-76695-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id c19-20020ac85a93000000b0042df364fbd7si13208698qtc.546.2024.02.22.06.24.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Feb 2024 06:24:19 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-76695-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=A7MOPXUS; arc=pass (i=1 spf=pass spfdomain=bootlin.com dkim=pass dkdomain=bootlin.com dmarc=pass fromdomain=bootlin.com); spf=pass (google.com: domain of linux-kernel+bounces-76695-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-76695-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.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 ny.mirrors.kernel.org (Postfix) with ESMTPS id C13DE1C23A6D for ; Thu, 22 Feb 2024 14:24:18 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8D95014E2FF; Thu, 22 Feb 2024 14:22:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="A7MOPXUS" Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) (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 E4C2114901A; Thu, 22 Feb 2024 14:22:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708611759; cv=none; b=jUdvvbjwZ23rX3QNw2HDkyfBNXnWfOuvBKcNBMY/ReLz+cdX1VmSQyWtqJt4CaT5FVUlbh4uQx3jZzP4LPfs6FAuWdzUgoaq808vo7M6CAG7pmUaOPviLvd8wLwp8uB9/s0WX/AzU5o5fM71fXtPR30iYFbyZIpLMAsGXfVZF9g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708611759; c=relaxed/simple; bh=ZOfSb8voG2S87QmQwgJSc6cHyxq2OyEeER2ITJhL8rE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aSLfnmJf2hvGPbiBLYYjrwtGssIjRI0qTJ2FIBbjff6bsJ6TY+vjnIDCPp5VqqBxpEpvNjn4Fm0n3zjdQbFdMM54jlZonI7SgkC3g9O1O8Yq6iARpwrkj+pG3ZILDRF2vXPhjFQSp8+pWDOFRKERMZBWaWEwq6mtNCj5qI9YoRQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=A7MOPXUS; arc=none smtp.client-ip=217.70.183.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Received: by mail.gandi.net (Postfix) with ESMTPA id 831E11BF20C; Thu, 22 Feb 2024 14:22:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1708611755; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GArzHpU6kmO8xUdzlOh0QC5GjmLwbH8840y9bNwiO9I=; b=A7MOPXUSUVPjb9gT448o9Cf55h9mzR7vXS8fm/Js8jywHuuGxtFgP5KOHVPOZqDXNW+QNN Lf4BdD4iysqoDkyzPPqDEud2aB9fay95F5PxoEQhHmAGrqHTYFvgkb+G93X+CM1k0X7984 3GFz9LoBVRm2e7hbv66ogxHjxwSnyzf5mUPycA1aNqLue6P0CcrJsu7XA+u6L/XygVnngP pCQdfpRInj6rU8yOpY/bgj9o3pm614AIgFZl+9NXmdq5LViwumEjmAKsl3ez+pH7/fN1yJ cJUsiKFudbD52R0JNzpoUPAiC/IfzpOYTcweGUtcaqONRtYsS1SGlbuNEeYQwg== From: Herve Codina To: Vadim Fedorenko , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Herve Codina , Yury Norov , Andy Shevchenko , Rasmus Villemoes Cc: linux-kernel@vger.kernel.org, netdev@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, Andrew Lunn , Mark Brown , Christophe Leroy , Thomas Petazzoni Subject: [PATCH v4 4/5] net: wan: fsl_qmc_hdlc: Add runtime timeslots changes support Date: Thu, 22 Feb 2024 15:22:17 +0100 Message-ID: <20240222142219.441767-5-herve.codina@bootlin.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240222142219.441767-1-herve.codina@bootlin.com> References: <20240222142219.441767-1-herve.codina@bootlin.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-GND-Sasl: herve.codina@bootlin.com X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1791609388656346680 X-GMAIL-MSGID: 1791609388656346680 QMC channels support runtime timeslots changes but nothing is done at the QMC HDLC driver to handle these changes. Use existing IFACE ioctl in order to configure the timeslots to use. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Acked-by: Jakub Kicinski --- drivers/net/wan/fsl_qmc_hdlc.c | 152 ++++++++++++++++++++++++++++++++- 1 file changed, 151 insertions(+), 1 deletion(-) diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c index ec08ab217a72..1b7f1d5af273 100644 --- a/drivers/net/wan/fsl_qmc_hdlc.c +++ b/drivers/net/wan/fsl_qmc_hdlc.c @@ -7,6 +7,7 @@ * Author: Herve Codina */ +#include #include #include #include @@ -32,6 +33,7 @@ struct qmc_hdlc { struct qmc_hdlc_desc tx_descs[8]; unsigned int tx_out; struct qmc_hdlc_desc rx_descs[4]; + u32 slot_map; }; static struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device *netdev) @@ -206,6 +208,144 @@ static netdev_tx_t qmc_hdlc_xmit(struct sk_buff *skb, struct net_device *netdev) return ret; } +static int qmc_hdlc_xlate_slot_map(struct qmc_hdlc *qmc_hdlc, + u32 slot_map, struct qmc_chan_ts_info *ts_info) +{ + DECLARE_BITMAP(ts_mask_avail, 64); + DECLARE_BITMAP(ts_mask, 64); + DECLARE_BITMAP(map, 64); + + /* Tx and Rx available masks must be identical */ + if (ts_info->rx_ts_mask_avail != ts_info->tx_ts_mask_avail) { + dev_err(qmc_hdlc->dev, "tx and rx available timeslots mismatch (0x%llx, 0x%llx)\n", + ts_info->rx_ts_mask_avail, ts_info->tx_ts_mask_avail); + return -EINVAL; + } + + bitmap_from_u64(ts_mask_avail, ts_info->rx_ts_mask_avail); + bitmap_from_u64(map, slot_map); + bitmap_scatter(ts_mask, map, ts_mask_avail, 64); + + if (bitmap_weight(ts_mask, 64) != bitmap_weight(map, 64)) { + dev_err(qmc_hdlc->dev, "Cannot translate timeslots %*pb -> (%*pb, %*pb)\n", + 64, map, 64, ts_mask_avail, 64, ts_mask); + return -EINVAL; + } + + bitmap_to_arr64(&ts_info->tx_ts_mask, ts_mask, 64); + ts_info->rx_ts_mask = ts_info->tx_ts_mask; + return 0; +} + +static int qmc_hdlc_xlate_ts_info(struct qmc_hdlc *qmc_hdlc, + const struct qmc_chan_ts_info *ts_info, u32 *slot_map) +{ + DECLARE_BITMAP(ts_mask_avail, 64); + DECLARE_BITMAP(ts_mask, 64); + DECLARE_BITMAP(map, 64); + u32 array32[2]; + + /* Tx and Rx masks and available masks must be identical */ + if (ts_info->rx_ts_mask_avail != ts_info->tx_ts_mask_avail) { + dev_err(qmc_hdlc->dev, "tx and rx available timeslots mismatch (0x%llx, 0x%llx)\n", + ts_info->rx_ts_mask_avail, ts_info->tx_ts_mask_avail); + return -EINVAL; + } + if (ts_info->rx_ts_mask != ts_info->tx_ts_mask) { + dev_err(qmc_hdlc->dev, "tx and rx timeslots mismatch (0x%llx, 0x%llx)\n", + ts_info->rx_ts_mask, ts_info->tx_ts_mask); + return -EINVAL; + } + + bitmap_from_u64(ts_mask_avail, ts_info->rx_ts_mask_avail); + bitmap_from_u64(ts_mask, ts_info->rx_ts_mask); + bitmap_gather(map, ts_mask, ts_mask_avail, 64); + + if (bitmap_weight(ts_mask, 64) != bitmap_weight(map, 64)) { + dev_err(qmc_hdlc->dev, "Cannot translate timeslots (%*pb, %*pb) -> %*pb\n", + 64, ts_mask_avail, 64, ts_mask, 64, map); + return -EINVAL; + } + + bitmap_to_arr32(array32, map, 64); + if (array32[1]) { + dev_err(qmc_hdlc->dev, "Slot map out of 32bit (%*pb, %*pb) -> %*pb\n", + 64, ts_mask_avail, 64, ts_mask, 64, map); + return -EINVAL; + } + + *slot_map = array32[0]; + return 0; +} + +static int qmc_hdlc_set_iface(struct qmc_hdlc *qmc_hdlc, int if_iface, const te1_settings *te1) +{ + struct qmc_chan_ts_info ts_info; + int ret; + + ret = qmc_chan_get_ts_info(qmc_hdlc->qmc_chan, &ts_info); + if (ret) { + dev_err(qmc_hdlc->dev, "get QMC channel ts info failed %d\n", ret); + return ret; + } + ret = qmc_hdlc_xlate_slot_map(qmc_hdlc, te1->slot_map, &ts_info); + if (ret) + return ret; + + ret = qmc_chan_set_ts_info(qmc_hdlc->qmc_chan, &ts_info); + if (ret) { + dev_err(qmc_hdlc->dev, "set QMC channel ts info failed %d\n", ret); + return ret; + } + + qmc_hdlc->slot_map = te1->slot_map; + + return 0; +} + +static int qmc_hdlc_ioctl(struct net_device *netdev, struct if_settings *ifs) +{ + struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev); + te1_settings te1; + + switch (ifs->type) { + case IF_GET_IFACE: + ifs->type = IF_IFACE_E1; + if (ifs->size < sizeof(te1)) { + if (!ifs->size) + return 0; /* only type requested */ + + ifs->size = sizeof(te1); /* data size wanted */ + return -ENOBUFS; + } + + memset(&te1, 0, sizeof(te1)); + + /* Update slot_map */ + te1.slot_map = qmc_hdlc->slot_map; + + if (copy_to_user(ifs->ifs_ifsu.te1, &te1, sizeof(te1))) + return -EFAULT; + return 0; + + case IF_IFACE_E1: + case IF_IFACE_T1: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (netdev->flags & IFF_UP) + return -EBUSY; + + if (copy_from_user(&te1, ifs->ifs_ifsu.te1, sizeof(te1))) + return -EFAULT; + + return qmc_hdlc_set_iface(qmc_hdlc, ifs->type, &te1); + + default: + return hdlc_ioctl(netdev, ifs); + } +} + static int qmc_hdlc_open(struct net_device *netdev) { struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev); @@ -332,13 +472,14 @@ static const struct net_device_ops qmc_hdlc_netdev_ops = { .ndo_open = qmc_hdlc_open, .ndo_stop = qmc_hdlc_close, .ndo_start_xmit = hdlc_start_xmit, - .ndo_siocwandev = hdlc_ioctl, + .ndo_siocwandev = qmc_hdlc_ioctl, }; static int qmc_hdlc_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct qmc_hdlc *qmc_hdlc; + struct qmc_chan_ts_info ts_info; struct qmc_chan_info info; hdlc_device *hdlc; int ret; @@ -368,6 +509,15 @@ static int qmc_hdlc_probe(struct platform_device *pdev) return -EINVAL; } + ret = qmc_chan_get_ts_info(qmc_hdlc->qmc_chan, &ts_info); + if (ret) { + dev_err(qmc_hdlc->dev, "get QMC channel ts info failed %d\n", ret); + return ret; + } + ret = qmc_hdlc_xlate_ts_info(qmc_hdlc, &ts_info, &qmc_hdlc->slot_map); + if (ret) + return ret; + qmc_hdlc->netdev = alloc_hdlcdev(qmc_hdlc); if (!qmc_hdlc->netdev) { dev_err(qmc_hdlc->dev, "failed to alloc hdlc dev\n");