Received: by 2002:a89:2c3:0:b0:1ed:23cc:44d1 with SMTP id d3csp918702lqs; Wed, 6 Mar 2024 00:09:12 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCXG7HMaKM84acwEWWTcmPfDFtVtQJWo1wxege8rPMvmDzV4lmWxx8o3hles9cEL0LnshtCRiqmZuIckg/aJ+/V/IGfmpDtuxu4zv8apRA== X-Google-Smtp-Source: AGHT+IHKIZcvEdUZyzx5W9Fr419aKnjGbB2zvpxQrNrYXvOm0hV+1Ldaq3k6W7sdFeZDGidlFRNY X-Received: by 2002:a0c:eda3:0:b0:68f:ab60:785d with SMTP id h3-20020a0ceda3000000b0068fab60785dmr4061819qvr.11.1709712552572; Wed, 06 Mar 2024 00:09:12 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1709712552; cv=pass; d=google.com; s=arc-20160816; b=Ywy+h/c6unsRrQr9vHMdi988qGt6RV+lUBgMEhIxN2jxDB1rRJfjX6e7FpZ1GKom2v AfIyjEimOLPCPNVBCILqDcF+2Aer+1z3qtS+32qAW+HkcmoTw7UF/c9k/fpIV9d6BvoK oZeXaXbWfm5i+/MLQVIIR2P9Vp2WpqCRNuFAQnGbdVqHK+TErkM0zOFCrhh75UBHVyzb Q2iBnYOBLgPFyIP9m405+fCpScMlVS6Lko6OduwaIGSCezwRE75+gpmbuR06SMOz5LQe 1QLp1ekrFK4uFdaGt90z8h1Jin9R4dcXEIkCzUgW71U0pAJUPcSRPLEHrgMynKWEv8T6 +0Mg== 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=JlJArA5cQiNgjEdKQ2Kr090MdFvf677PpXjac5t1UGw=; fh=S1JXykGn8s83VQzPRjkanrg93kX6oJVbyHnK1JmVqsw=; b=0uUNfXh+WgN4y3tG4S8Nnb3P2rJf4wPxz5DZO7a2nI+SgiVca6aFOm9PCqLBfFRlcK P0HRKyjo1Z4BDYS2RfWQEcwVvYRIvesPR9LbW+Tm9OoddaXBDi5ZavAVfylNsQB7RczM WcWlI/j2aQ43R/sf5oxQ2Jolnet4O2QQpHUeMXsdkSfjctlay0AR/6irOZDziOYGpfce G0yPv9KIgi2PzF+KIqZ/qcPupmXknBWD9nP+x+/4pRv3Ed/Uz8lCAlELDLq2aYgKEhpr QszcwsXGsAPA5023pgVKD+e84hc6qnWeYVyvGDl7z4Fh8XyNgtJpI9GuAYGXxfWJaB2K bNWw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@bootlin.com header.s=gm1 header.b=RiUUfRMa; 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-93468-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-93468-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=bootlin.com Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id r2-20020a0562140c4200b0068fac99707fsi13876067qvj.546.2024.03.06.00.09.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 Mar 2024 00:09:12 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-93468-linux.lists.archive=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=RiUUfRMa; 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-93468-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-93468-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 ny.mirrors.kernel.org (Postfix) with ESMTPS id 3ECDC1C22A59 for ; Wed, 6 Mar 2024 08:09:12 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id DE94C5DF30; Wed, 6 Mar 2024 08:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="RiUUfRMa" Received: from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net [217.70.183.200]) (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 8B0E35D496; Wed, 6 Mar 2024 08:07:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.70.183.200 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709712479; cv=none; b=K3wZ8cWeF88mqkBQM2eh5ucOx2LFJNcwLHDz9YOZIGZdxbvzAQACmON7cl3QAvzzTl1udekl9PniS48o8NCQkXLLK0xku8s+hiDwNPdeACMJRCO2DxEOgbwqegyKvkSRWdBreB9pNYxqY/oBGtDu7EOstpZ+oODWGIRK9bpVOgs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1709712479; c=relaxed/simple; bh=WHSwcM+jNjYXm4IPr4lf44OoJhYR8+yIX+QMYxbgWGM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ejJh14t9Pnm8pztZN+I4RnueAaHyKopqjULc6QKuGhz6wl7DQ+sVSZtdCFVOXXiPYJAkhlh0q9+ocwL4opVxONWAJ9BaTldu7qZVYmlaeswkc91d7NOaBgc+T78p22rUkKW8YhWoNcfyAgG9AgjEU0pfWGKWNkLznZLEns8d/bE= 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=RiUUfRMa; arc=none smtp.client-ip=217.70.183.200 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 B567220018; Wed, 6 Mar 2024 08:07:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709712470; 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=JlJArA5cQiNgjEdKQ2Kr090MdFvf677PpXjac5t1UGw=; b=RiUUfRMaAFXlPZcpYDARCwyWT2BhbbVbqY6pmcELmQRjXFiEkVqGaexVzw9MOotKKIsSYh vTYgSfDNw2Ury7r6u4iQMmMd1/0zAC8Z01asLtX63RzLGvoRUVkgM0hFfL2VhomgiD/9gz 0xKj3S8+u7IfPo0P5UXemt/XVyo4rQ0Cm9COpgtVJZMG46EXN6zygCuEX11eB2YFA4sWaj k8xkL2oBRb42Wy3x92qwYWGRL4oj/duppbGBvm0uba9C0vVaF2ZNcEEf26mfkbEC6rdRtH ce82cw8HJ+4UfByNDlB0K0ZFaus3BOZYTcAR9x66IB1ZDV8qUuPrxEbPBgbI5Q== 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 v6 4/5] net: wan: fsl_qmc_hdlc: Add runtime timeslots changes support Date: Wed, 6 Mar 2024 09:07:20 +0100 Message-ID: <20240306080726.167338-5-herve.codina@bootlin.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240306080726.167338-1-herve.codina@bootlin.com> References: <20240306080726.167338-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 90063a92209e..31c0f32474a3 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) @@ -203,6 +205,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 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 (%64pb, %64pb) -> %64pb\n", + ts_mask_avail, ts_mask, map); + return -EINVAL; + } + + bitmap_to_arr32(array32, map, 64); + if (array32[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 = 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); @@ -326,12 +466,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; @@ -357,6 +498,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