Received: by 2002:ab2:788f:0:b0:1ee:8f2e:70ae with SMTP id b15csp500522lqi; Thu, 7 Mar 2024 03:48:20 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUmOHhXOPwRD4H49E3A+OSySSq/Y21JOHBBZrgUvaRtS4T6Vh75xeiUYVcELdUAe8Odq/3T0eMWHB0FPLEp3A484r/6aalUX1UZqQ6FvQ== X-Google-Smtp-Source: AGHT+IFOBvVTG3ROOSEWbDTUgUaj5AjmP5c0EeMTfWjWm50MoDpql+i2pDCnlsGZDHqwp0N1fxlJ X-Received: by 2002:a05:6a21:8ccc:b0:1a1:4191:3cf9 with SMTP id ta12-20020a056a218ccc00b001a141913cf9mr9028574pzb.45.1709812100413; Thu, 07 Mar 2024 03:48:20 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1709812100; cv=pass; d=google.com; s=arc-20160816; b=xnBqU8QWcz5+H9AJBeurnn2rWCEoQwq6asbiO/tEYHOmYdQi1He8Vvwrw/ZLqD7qRi CJu57+p4YkZeaLzVtNj0ZMKnRD/9tTv3DhA9eyMD2NB1yU1T7mxuI2WvrXG79FCwTYgw 4vQIABlZGrBjJl7dlCgDey1Lhpyat3YzdEAcJxNxpnhHO6/49eeRPFVV3yWcDnxljVr9 W3Rj+XcEOehY7yciVikAeMPTaL+F4u3Zb9KnAUHvKri4WP6aWIjG24Mw1xJM+CV/OaxF YzLC9/I2tta0MSnTutVUcsPJGPjYy2aw7ZLQh9Y+7hPONfHKQPmRsUWfvQR2mcbWk0J2 N52g== 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=YcO76rLHbysLzSM0U7sP4jYJS1mQqZZkE1T/YxLFMFc=; fh=Hyv4vHvDikDbr11SH1c2q6Zo+bmmwkam3RVpRE4EFJU=; b=IC5INcQqFHHvEhFp6oxEn3A+VS7/iGU0eyXJo5a5nDRxjHjjCMaILcphA2mQ7J5E5D S02jK8xsflFIGT0TbaZzabpvSBRe5Ajav26G5c2whMJhbLvR2SnL4DERlUzO1g9rKbf1 ykhlVl2PcHe1jBs+T9kX66V9/vkqA2k4aBChZy5zskKRSt5WIYjyBMcXknEOFASKLofK zma6IZSL3zGRVLPlm2o+U+6STikr9LtCNzOOY3atFD0EOgr/sNfb1jCd3TM4VYu1ZhHY VMeZ0DaL0CfgJFTtLIyF+7PGkTjUIYfi/je4Y2mYr1q/ZHrZB+jFSWTn2dwR0mfwUuyc 6Fdg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=Roz+eI5m; 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-95446-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-95446-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id nv5-20020a17090b1b4500b0029939864617si1592809pjb.145.2024.03.07.03.48.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 07 Mar 2024 03:48:20 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-95446-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=Roz+eI5m; 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-95446-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-95446-linux.lists.archive=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 sy.mirrors.kernel.org (Postfix) with ESMTPS id F32C2B231D7 for ; Thu, 7 Mar 2024 11:41:34 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CF19712C534; Thu, 7 Mar 2024 11:39:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="Roz+eI5m" Received: from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net [217.70.183.198]) (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 6F2AC1292F1; Thu, 7 Mar 2024 11:39:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.198 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709811586; cv=none; b=MlD+rn2qAV1zT4aAplgAH2H063gVq6sFUziLfJSSofcZnFng9uCoZ16bBVpHC0k/GO1XwMbWCDzU7IK2ZinjQdkEirO6VV1Bc7baG7lEKWQ8jU5fpW3klHGfbargvdMW0Yo5HFCF3Oi+VlxxHdYfM/cqiyeRZbGUWBW4idmUrew= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709811586; c=relaxed/simple; bh=OYGgVM6Gop5yShpxVtewg+UTsjEKqxPyvyRwVkCKhto=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=L17AZsGfK5ChKzKoziKts1h4bVKRLL4vHubaPsHtNgDbZGNZAIGgQ5ZvWnD607RIEN+BrXhAb7guge4+oxSL9P9j99JkTmm3cf2Q70CM2DfFQHMkJxUUNzj81IbSkD5idTaah4irVcKy7+8yFwXpdi9lGllre1rZ52Myzn5LxMI= 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=Roz+eI5m; arc=none smtp.client-ip=217.70.183.198 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 0F371C0008; Thu, 7 Mar 2024 11:39:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709811580; 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=YcO76rLHbysLzSM0U7sP4jYJS1mQqZZkE1T/YxLFMFc=; b=Roz+eI5mt9yYvFoQEr3CVCU6sKcqXOXRVoRhQ6z7ztNuLjcMn/63pD47jRqO4TyzloTmhC CWrbJbXtUycQIU6df7apS8wYl0mK6IodP4ssuyNcgw7FM9Xw+/JrCPaixxzzR2GbTa5hY3 sPvyY1bwaP2hHdg+5NHI9IqWhjM2YjEUwEdA8epPVoxdZK3zdnO21OXSG0Gh+EyCL0QzTf os8QF/Za8mz9I93+G1mq3hbqDwwO7nH6LI3i7gr+8D5UWaTxsv4fPmBKPso6bzDP/Ua4Hm AufkCXUiJneW2AzZTpRGM8BY0X4LJ8iXRk0GC0SNGkcQmvgjpfyg0PvTu7AxCA== 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 , Ratheesh Kannoth , Christophe Leroy , Thomas Petazzoni Subject: [PATCH v7 4/5] net: wan: fsl_qmc_hdlc: Add runtime timeslots changes support Date: Thu, 7 Mar 2024 12:39:07 +0100 Message-ID: <20240307113909.227375-5-herve.codina@bootlin.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240307113909.227375-1-herve.codina@bootlin.com> References: <20240307113909.227375-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 Content-Transfer-Encoding: 8bit X-GND-Sasl: herve.codina@bootlin.com 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 Reviewed-by: Andy Shevchenko --- drivers/net/wan/fsl_qmc_hdlc.c | 151 ++++++++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 1 deletion(-) diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c index 5fd7ed325f5b..57935b48a848 100644 --- a/drivers/net/wan/fsl_qmc_hdlc.c +++ b/drivers/net/wan/fsl_qmc_hdlc.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,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) @@ -209,6 +211,144 @@ static netdev_tx_t qmc_hdlc_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } +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 %64pb -> (%64pb, %64pb)\n", + map, ts_mask_avail, 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 slot_array[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 (%64pb, %64pb) -> %64pb\n", + ts_mask_avail, ts_mask, map); + return -EINVAL; + } + + bitmap_to_arr32(slot_array, map, 64); + if (slot_array[1]) { + dev_err(qmc_hdlc->dev, "Slot map out of 32bit (%64pb, %64pb) -> %64pb\n", + ts_mask_avail, ts_mask, map); + return -EINVAL; + } + + *slot_map = slot_array[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,12 +472,13 @@ 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 *dev = &pdev->dev; + struct qmc_chan_ts_info ts_info; struct qmc_hdlc *qmc_hdlc; struct qmc_chan_info info; hdlc_device *hdlc; @@ -363,6 +504,14 @@ static int qmc_hdlc_probe(struct platform_device *pdev) return dev_err_probe(dev, -EINVAL, "QMC chan mode %d is not QMC_HDLC\n", info.mode); + ret = qmc_chan_get_ts_info(qmc_hdlc->qmc_chan, &ts_info); + if (ret) + return dev_err_probe(dev, ret, "get QMC channel ts info failed\n"); + + 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) return -ENOMEM; -- 2.43.0