Re: [PATCH v4 20/28] wan: qmc_hdlc: Add runtime timeslots changes support

2023-08-24 Thread Herve Codina
Hi Christophe,

On Mon, 21 Aug 2023 07:40:26 +0200
Christophe JAILLET  wrote:

> Le 18/08/2023 à 18:39, Christophe Leroy a écrit :
> > From: Herve Codina 
> > 
> > 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 
> > Signed-off-by: Christophe Leroy 
> > ---  
> 
> Hi,
> 
> a few nits below, should there be a v5.
> 
> >   drivers/net/wan/fsl_qmc_hdlc.c | 169 -
> >   1 file changed, 168 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c
> > index 4f84ac5fc63e..4b8cb5761fd1 100644
> > --- a/drivers/net/wan/fsl_qmc_hdlc.c
> > +++ b/drivers/net/wan/fsl_qmc_hdlc.c
> > @@ -32,6 +32,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 inline struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device 
> > *netdev)
> > @@ -202,6 +203,162 @@ 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)
> > +{
> > +   u64 ts_mask_avail;
> > +   unsigned int bit;
> > +   unsigned int i;
> > +   u64 ts_mask;
> > +   u64 map = 0;  
> 
> This init looks useless.

Will be removed in the next iteration.

> 
> > +
> > +   /* Tx and Rx 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;
> > +   }
> > +
> > +   ts_mask_avail = ts_info->rx_ts_mask_avail;
> > +   ts_mask = 0;
> > +   map = slot_map;
> > +   bit = 0;
> > +   for (i = 0; i < 64; i++) {
> > +   if (ts_mask_avail & BIT_ULL(i)) {
> > +   if (map & BIT_ULL(bit))
> > +   ts_mask |= BIT_ULL(i);
> > +   bit++;
> > +   }
> > +   }
> > +
> > +   if (hweight64(ts_mask) != hweight64(map)) {
> > +   dev_err(qmc_hdlc->dev, "Cannot translate timeslots 0x%llx -> 
> > (0x%llx,0x%llx)\n",
> > +   map, ts_mask_avail, ts_mask);
> > +   return -EINVAL;
> > +   }
> > +
> > +   ts_info->tx_ts_mask = ts_mask;
> > +   ts_info->rx_ts_mask = 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)
> > +{
> > +   u64 ts_mask_avail;
> > +   unsigned int bit;
> > +   unsigned int i;
> > +   u64 ts_mask;
> > +   u64 map = 0;  
> 
> This init looks useless.

Will be remove in the next iteration.

> 
> > +
> > +   /* Tx and Rx 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;
> > +   }
> > +
> > +   ts_mask_avail = ts_info->rx_ts_mask_avail;
> > +   ts_mask = ts_info->rx_ts_mask;
> > +   map = 0;
> > +   bit = 0;
> > +   for (i = 0; i < 64; i++) {
> > +   if (ts_mask_avail & BIT_ULL(i)) {
> > +   if (ts_mask & BIT_ULL(i))
> > +   map |= BIT_ULL(bit);
> > +   bit++;
> > +   }
> > +   }
> > +
> > +   if (hweight64(ts_mask) != hweight64(map)) {
> > +   dev_err(qmc_hdlc->dev, "Cannot translate timeslots 
> > (0x%llx,0x%llx) -> 0x%llx\n",
> > +   ts_mask_avail, ts_mask, map);
> > +   return -EINVAL;
> > +   }
> > +
> > +   if (map >= BIT_ULL(32)) {
> > +   dev_err(qmc_hdlc->dev, "Slot map out of 32bit (0x%llx,0x%llx) 
> > -> 0x%llx\n",
> > +   ts_mask_avail, ts_mask, map);
> > +   return -EINVAL;
> > +   }
> > +
> > +   *slot_map = 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 < 

Re: [PATCH v4 20/28] wan: qmc_hdlc: Add runtime timeslots changes support

2023-08-21 Thread Christophe JAILLET

Le 18/08/2023 à 18:39, Christophe Leroy a écrit :

From: Herve Codina 

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 
Signed-off-by: Christophe Leroy 
---


Hi,

a few nits below, should there be a v5.


  drivers/net/wan/fsl_qmc_hdlc.c | 169 -
  1 file changed, 168 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c
index 4f84ac5fc63e..4b8cb5761fd1 100644
--- a/drivers/net/wan/fsl_qmc_hdlc.c
+++ b/drivers/net/wan/fsl_qmc_hdlc.c
@@ -32,6 +32,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 inline struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device *netdev)

@@ -202,6 +203,162 @@ 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)
+{
+   u64 ts_mask_avail;
+   unsigned int bit;
+   unsigned int i;
+   u64 ts_mask;
+   u64 map = 0;


This init looks useless.


+
+   /* Tx and Rx 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;
+   }
+
+   ts_mask_avail = ts_info->rx_ts_mask_avail;
+   ts_mask = 0;
+   map = slot_map;
+   bit = 0;
+   for (i = 0; i < 64; i++) {
+   if (ts_mask_avail & BIT_ULL(i)) {
+   if (map & BIT_ULL(bit))
+   ts_mask |= BIT_ULL(i);
+   bit++;
+   }
+   }
+
+   if (hweight64(ts_mask) != hweight64(map)) {
+   dev_err(qmc_hdlc->dev, "Cannot translate timeslots 0x%llx -> 
(0x%llx,0x%llx)\n",
+   map, ts_mask_avail, ts_mask);
+   return -EINVAL;
+   }
+
+   ts_info->tx_ts_mask = ts_mask;
+   ts_info->rx_ts_mask = 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)
+{
+   u64 ts_mask_avail;
+   unsigned int bit;
+   unsigned int i;
+   u64 ts_mask;
+   u64 map = 0;


This init looks useless.


+
+   /* Tx and Rx 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;
+   }
+
+   ts_mask_avail = ts_info->rx_ts_mask_avail;
+   ts_mask = ts_info->rx_ts_mask;
+   map = 0;
+   bit = 0;
+   for (i = 0; i < 64; i++) {
+   if (ts_mask_avail & BIT_ULL(i)) {
+   if (ts_mask & BIT_ULL(i))
+   map |= BIT_ULL(bit);
+   bit++;
+   }
+   }
+
+   if (hweight64(ts_mask) != hweight64(map)) {
+   dev_err(qmc_hdlc->dev, "Cannot translate timeslots (0x%llx,0x%llx) 
-> 0x%llx\n",
+   ts_mask_avail, ts_mask, map);
+   return -EINVAL;
+   }
+
+   if (map >= BIT_ULL(32)) {
+   dev_err(qmc_hdlc->dev, "Slot map out of 32bit (0x%llx,0x%llx) -> 
0x%llx\n",
+   ts_mask_avail, ts_mask, map);
+   return -EINVAL;
+   }
+
+   *slot_map = 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(, 0, sizeof(te1));
+
+   /* Update slot_map */
+   te1.slot_map = qmc_hdlc->slot_map;
+
+   if 

[PATCH v4 20/28] wan: qmc_hdlc: Add runtime timeslots changes support

2023-08-18 Thread Christophe Leroy
From: Herve Codina 

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 
Signed-off-by: Christophe Leroy 
---
 drivers/net/wan/fsl_qmc_hdlc.c | 169 -
 1 file changed, 168 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c
index 4f84ac5fc63e..4b8cb5761fd1 100644
--- a/drivers/net/wan/fsl_qmc_hdlc.c
+++ b/drivers/net/wan/fsl_qmc_hdlc.c
@@ -32,6 +32,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 inline struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device *netdev)
@@ -202,6 +203,162 @@ 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)
+{
+   u64 ts_mask_avail;
+   unsigned int bit;
+   unsigned int i;
+   u64 ts_mask;
+   u64 map = 0;
+
+   /* Tx and Rx 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;
+   }
+
+   ts_mask_avail = ts_info->rx_ts_mask_avail;
+   ts_mask = 0;
+   map = slot_map;
+   bit = 0;
+   for (i = 0; i < 64; i++) {
+   if (ts_mask_avail & BIT_ULL(i)) {
+   if (map & BIT_ULL(bit))
+   ts_mask |= BIT_ULL(i);
+   bit++;
+   }
+   }
+
+   if (hweight64(ts_mask) != hweight64(map)) {
+   dev_err(qmc_hdlc->dev, "Cannot translate timeslots 0x%llx -> 
(0x%llx,0x%llx)\n",
+   map, ts_mask_avail, ts_mask);
+   return -EINVAL;
+   }
+
+   ts_info->tx_ts_mask = ts_mask;
+   ts_info->rx_ts_mask = 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)
+{
+   u64 ts_mask_avail;
+   unsigned int bit;
+   unsigned int i;
+   u64 ts_mask;
+   u64 map = 0;
+
+   /* Tx and Rx 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;
+   }
+
+   ts_mask_avail = ts_info->rx_ts_mask_avail;
+   ts_mask = ts_info->rx_ts_mask;
+   map = 0;
+   bit = 0;
+   for (i = 0; i < 64; i++) {
+   if (ts_mask_avail & BIT_ULL(i)) {
+   if (ts_mask & BIT_ULL(i))
+   map |= BIT_ULL(bit);
+   bit++;
+   }
+   }
+
+   if (hweight64(ts_mask) != hweight64(map)) {
+   dev_err(qmc_hdlc->dev, "Cannot translate timeslots 
(0x%llx,0x%llx) -> 0x%llx\n",
+   ts_mask_avail, ts_mask, map);
+   return -EINVAL;
+   }
+
+   if (map >= BIT_ULL(32)) {
+   dev_err(qmc_hdlc->dev, "Slot map out of 32bit (0x%llx,0x%llx) 
-> 0x%llx\n",
+   ts_mask_avail, ts_mask, map);
+   return -EINVAL;
+   }
+
+   *slot_map = map;
+   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, _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, _info);
+   if (ret)
+   return ret;
+
+   ret = qmc_chan_set_ts_info(qmc_hdlc->qmc_chan, _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 =