Re: [PATCH 2/4] net: ethernet: ti: cpsw: add multi queue support

2016-07-19 Thread Ivan Khoronzhuk



On 08.07.16 16:12, Grygorii Strashko wrote:

On 06/30/2016 10:04 PM, Ivan Khoronzhuk wrote:

The cpsw h/w supports up to 8 tx and 8 rx channels.This patch adds
multi-queue support to the driver. An ability to configure h/w
shaper will be added with separate patch. Default shaper mode, as
before, priority mode.

The poll function handles all unprocessed channels, till all of
them are free, beginning from hi priority channel.

The statistic for every channel can be read with:
ethtool -S ethX

Signed-off-by: Ivan Khoronzhuk 
---
   drivers/net/ethernet/ti/cpsw.c  | 334 
+---
   drivers/net/ethernet/ti/davinci_cpdma.c |  12 ++
   drivers/net/ethernet/ti/davinci_cpdma.h |   2 +
   3 files changed, 237 insertions(+), 111 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index a713336..14d53eb 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -140,6 +140,8 @@ do {
\
   #define CPSW_CMINTMAX_INTVL  (1000 / CPSW_CMINTMIN_CNT)
   #define CPSW_CMINTMIN_INTVL  ((1000 / CPSW_CMINTMAX_CNT) + 1)

+#define CPSW_MAX_QUEUES8
+
   #define cpsw_slave_index(priv)   \
((priv->data.dual_emac) ? priv->emac_port :   \
priv->data.active_slave)
@@ -383,7 +385,8 @@ struct cpsw_priv {
u8  mac_addr[ETH_ALEN];
struct cpsw_slave   *slaves;
struct cpdma_ctlr   *dma;
-   struct cpdma_chan   *txch, *rxch;
+   struct cpdma_chan   *txch[CPSW_MAX_QUEUES];
+   struct cpdma_chan   *rxch[CPSW_MAX_QUEUES];
struct cpsw_ale *ale;
boolrx_pause;
booltx_pause;
@@ -395,6 +398,7 @@ struct cpsw_priv {
u32 num_irqs;
struct cpts *cpts;
u32 emac_port;
+   int rx_ch_num, tx_ch_num;
   };



[...]



@@ -989,26 +1024,50 @@ update_return:

   static int cpsw_get_sset_count(struct net_device *ndev, int sset)
   {
+   struct cpsw_priv *priv = netdev_priv(ndev);
+
switch (sset) {
case ETH_SS_STATS:
-   return CPSW_STATS_LEN;
+   return (CPSW_STATS_COMMON_LEN +
+  (priv->rx_ch_num + priv->tx_ch_num) *
+  CPSW_STATS_CH_LEN);
default:
return -EOPNOTSUPP;
}
   }

+static void cpsw_add_ch_strings(u8 **p, int ch_num, int rx_dir)
+{
+   int ch_stats_len;
+   int line;
+   int i;
+
+   ch_stats_len = CPSW_STATS_CH_LEN * ch_num;
+   for (i = 0; i < ch_stats_len; i++) {
+   line = i % CPSW_STATS_CH_LEN;
+   sprintf(*p, "%s DMA chan %d: %s", rx_dir ? "Rx" : "Tx",
+   i / CPSW_STATS_CH_LEN,


snprintf(,ETH_GSTRING_LEN,) ?

It's number of channel.




+   cpsw_gstrings_ch_stats[line].stat_string);
+   *p += ETH_GSTRING_LEN;
+   }
+}
+
   static void cpsw_get_strings(struct net_device *ndev, u32 stringset, u8 
*data)
   {
+   struct cpsw_priv *priv = netdev_priv(ndev);
u8 *p = data;
int i;

switch (stringset) {
case ETH_SS_STATS:
-   for (i = 0; i < CPSW_STATS_LEN; i++) {
+   for (i = 0; i < CPSW_STATS_COMMON_LEN; i++) {
memcpy(p, cpsw_gstrings_stats[i].stat_string,
   ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
+
+   cpsw_add_ch_strings(, priv->rx_ch_num, 1);
+   cpsw_add_ch_strings(, priv->tx_ch_num, 0);
break;
}
   }
@@ -1017,35 +1076,38 @@ static void cpsw_get_ethtool_stats(struct net_device 
*ndev,
struct ethtool_stats *stats, u64 *data)
   {
struct cpsw_priv *priv = netdev_priv(ndev);
-   struct cpdma_chan_stats rx_stats;
-   struct cpdma_chan_stats tx_stats;
-   u32 val;
+   struct cpdma_chan_stats ch_stats;
+   int i, l, ch, ret;
u8 *p;
-   int i;
+
+   ret = pm_runtime_get_sync(>pdev->dev);
+   if (ret < 0) {
+   pm_runtime_put_noidle(>pdev->dev);
+   return;
+   }


You probably need to base you work on top of net-next.git

Yep. Will correct.





/* Collect Davinci CPDMA stats for Rx and Tx Channel */
-   cpdma_chan_get_stats(priv->rxch, _stats);
-   cpdma_chan_get_stats(priv->txch, _stats);
-
-   for (i = 0; i < CPSW_STATS_LEN; i++) {
-   switch (cpsw_gstrings_stats[i].type) {
-   case CPSW_STATS:
-   val = readl(priv->hw_stats +
-   cpsw_gstrings_stats[i].stat_offset);
-   data[i] = val;
-   

Re: [PATCH 2/4] net: ethernet: ti: cpsw: add multi queue support

2016-07-08 Thread Grygorii Strashko
On 06/30/2016 10:04 PM, Ivan Khoronzhuk wrote:
> The cpsw h/w supports up to 8 tx and 8 rx channels.This patch adds
> multi-queue support to the driver. An ability to configure h/w
> shaper will be added with separate patch. Default shaper mode, as
> before, priority mode.
> 
> The poll function handles all unprocessed channels, till all of
> them are free, beginning from hi priority channel.
> 
> The statistic for every channel can be read with:
> ethtool -S ethX
> 
> Signed-off-by: Ivan Khoronzhuk 
> ---
>   drivers/net/ethernet/ti/cpsw.c  | 334 
> +---
>   drivers/net/ethernet/ti/davinci_cpdma.c |  12 ++
>   drivers/net/ethernet/ti/davinci_cpdma.h |   2 +
>   3 files changed, 237 insertions(+), 111 deletions(-)
> 
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index a713336..14d53eb 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
> @@ -140,6 +140,8 @@ do {  
> \
>   #define CPSW_CMINTMAX_INTVL (1000 / CPSW_CMINTMIN_CNT)
>   #define CPSW_CMINTMIN_INTVL ((1000 / CPSW_CMINTMAX_CNT) + 1)
>   
> +#define CPSW_MAX_QUEUES  8
> +
>   #define cpsw_slave_index(priv)  \
>   ((priv->data.dual_emac) ? priv->emac_port : \
>   priv->data.active_slave)
> @@ -383,7 +385,8 @@ struct cpsw_priv {
>   u8  mac_addr[ETH_ALEN];
>   struct cpsw_slave   *slaves;
>   struct cpdma_ctlr   *dma;
> - struct cpdma_chan   *txch, *rxch;
> + struct cpdma_chan   *txch[CPSW_MAX_QUEUES];
> + struct cpdma_chan   *rxch[CPSW_MAX_QUEUES];
>   struct cpsw_ale *ale;
>   boolrx_pause;
>   booltx_pause;
> @@ -395,6 +398,7 @@ struct cpsw_priv {
>   u32 num_irqs;
>   struct cpts *cpts;
>   u32 emac_port;
> + int rx_ch_num, tx_ch_num;
>   };
>   

[...]

>   
> @@ -989,26 +1024,50 @@ update_return:
>   
>   static int cpsw_get_sset_count(struct net_device *ndev, int sset)
>   {
> + struct cpsw_priv *priv = netdev_priv(ndev);
> +
>   switch (sset) {
>   case ETH_SS_STATS:
> - return CPSW_STATS_LEN;
> + return (CPSW_STATS_COMMON_LEN +
> +(priv->rx_ch_num + priv->tx_ch_num) *
> +CPSW_STATS_CH_LEN);
>   default:
>   return -EOPNOTSUPP;
>   }
>   }
>   
> +static void cpsw_add_ch_strings(u8 **p, int ch_num, int rx_dir)
> +{
> + int ch_stats_len;
> + int line;
> + int i;
> +
> + ch_stats_len = CPSW_STATS_CH_LEN * ch_num;
> + for (i = 0; i < ch_stats_len; i++) {
> + line = i % CPSW_STATS_CH_LEN;
> + sprintf(*p, "%s DMA chan %d: %s", rx_dir ? "Rx" : "Tx",
> + i / CPSW_STATS_CH_LEN,

snprintf(,ETH_GSTRING_LEN,) ?

> + cpsw_gstrings_ch_stats[line].stat_string);
> + *p += ETH_GSTRING_LEN;
> + }
> +}
> +
>   static void cpsw_get_strings(struct net_device *ndev, u32 stringset, u8 
> *data)
>   {
> + struct cpsw_priv *priv = netdev_priv(ndev);
>   u8 *p = data;
>   int i;
>   
>   switch (stringset) {
>   case ETH_SS_STATS:
> - for (i = 0; i < CPSW_STATS_LEN; i++) {
> + for (i = 0; i < CPSW_STATS_COMMON_LEN; i++) {
>   memcpy(p, cpsw_gstrings_stats[i].stat_string,
>  ETH_GSTRING_LEN);
>   p += ETH_GSTRING_LEN;
>   }
> +
> + cpsw_add_ch_strings(, priv->rx_ch_num, 1);
> + cpsw_add_ch_strings(, priv->tx_ch_num, 0);
>   break;
>   }
>   }
> @@ -1017,35 +1076,38 @@ static void cpsw_get_ethtool_stats(struct net_device 
> *ndev,
>   struct ethtool_stats *stats, u64 *data)
>   {
>   struct cpsw_priv *priv = netdev_priv(ndev);
> - struct cpdma_chan_stats rx_stats;
> - struct cpdma_chan_stats tx_stats;
> - u32 val;
> + struct cpdma_chan_stats ch_stats;
> + int i, l, ch, ret;
>   u8 *p;
> - int i;
> +
> + ret = pm_runtime_get_sync(>pdev->dev);
> + if (ret < 0) {
> + pm_runtime_put_noidle(>pdev->dev);
> + return;
> + }

You probably need to base you work on top of net-next.git

>   
>   /* Collect Davinci CPDMA stats for Rx and Tx Channel */
> - cpdma_chan_get_stats(priv->rxch, _stats);
> - cpdma_chan_get_stats(priv->txch, _stats);
> -
> - for (i = 0; i < CPSW_STATS_LEN; i++) {
> - switch (cpsw_gstrings_stats[i].type) {
> - case CPSW_STATS:
> - val = readl(priv->hw_stats +
> - cpsw_gstrings_stats[i].stat_offset);
> - data[i] = val;
> -   

[PATCH 2/4] net: ethernet: ti: cpsw: add multi queue support

2016-06-30 Thread Ivan Khoronzhuk
The cpsw h/w supports up to 8 tx and 8 rx channels.This patch adds
multi-queue support to the driver. An ability to configure h/w
shaper will be added with separate patch. Default shaper mode, as
before, priority mode.

The poll function handles all unprocessed channels, till all of
them are free, beginning from hi priority channel.

The statistic for every channel can be read with:
ethtool -S ethX

Signed-off-by: Ivan Khoronzhuk 
---
 drivers/net/ethernet/ti/cpsw.c  | 334 +---
 drivers/net/ethernet/ti/davinci_cpdma.c |  12 ++
 drivers/net/ethernet/ti/davinci_cpdma.h |   2 +
 3 files changed, 237 insertions(+), 111 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index a713336..14d53eb 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -140,6 +140,8 @@ do {
\
 #define CPSW_CMINTMAX_INTVL(1000 / CPSW_CMINTMIN_CNT)
 #define CPSW_CMINTMIN_INTVL((1000 / CPSW_CMINTMAX_CNT) + 1)
 
+#define CPSW_MAX_QUEUES8
+
 #define cpsw_slave_index(priv) \
((priv->data.dual_emac) ? priv->emac_port : \
priv->data.active_slave)
@@ -383,7 +385,8 @@ struct cpsw_priv {
u8  mac_addr[ETH_ALEN];
struct cpsw_slave   *slaves;
struct cpdma_ctlr   *dma;
-   struct cpdma_chan   *txch, *rxch;
+   struct cpdma_chan   *txch[CPSW_MAX_QUEUES];
+   struct cpdma_chan   *rxch[CPSW_MAX_QUEUES];
struct cpsw_ale *ale;
boolrx_pause;
booltx_pause;
@@ -395,6 +398,7 @@ struct cpsw_priv {
u32 num_irqs;
struct cpts *cpts;
u32 emac_port;
+   int rx_ch_num, tx_ch_num;
 };
 
 struct cpsw_stats {
@@ -455,35 +459,26 @@ static const struct cpsw_stats cpsw_gstrings_stats[] = {
{ "Rx Start of Frame Overruns", CPSW_STAT(rxsofoverruns) },
{ "Rx Middle of Frame Overruns", CPSW_STAT(rxmofoverruns) },
{ "Rx DMA Overruns", CPSW_STAT(rxdmaoverruns) },
-   { "Rx DMA chan: head_enqueue", CPDMA_RX_STAT(head_enqueue) },
-   { "Rx DMA chan: tail_enqueue", CPDMA_RX_STAT(tail_enqueue) },
-   { "Rx DMA chan: pad_enqueue", CPDMA_RX_STAT(pad_enqueue) },
-   { "Rx DMA chan: misqueued", CPDMA_RX_STAT(misqueued) },
-   { "Rx DMA chan: desc_alloc_fail", CPDMA_RX_STAT(desc_alloc_fail) },
-   { "Rx DMA chan: pad_alloc_fail", CPDMA_RX_STAT(pad_alloc_fail) },
-   { "Rx DMA chan: runt_receive_buf", CPDMA_RX_STAT(runt_receive_buff) },
-   { "Rx DMA chan: runt_transmit_buf", CPDMA_RX_STAT(runt_transmit_buff) },
-   { "Rx DMA chan: empty_dequeue", CPDMA_RX_STAT(empty_dequeue) },
-   { "Rx DMA chan: busy_dequeue", CPDMA_RX_STAT(busy_dequeue) },
-   { "Rx DMA chan: good_dequeue", CPDMA_RX_STAT(good_dequeue) },
-   { "Rx DMA chan: requeue", CPDMA_RX_STAT(requeue) },
-   { "Rx DMA chan: teardown_dequeue", CPDMA_RX_STAT(teardown_dequeue) },
-   { "Tx DMA chan: head_enqueue", CPDMA_TX_STAT(head_enqueue) },
-   { "Tx DMA chan: tail_enqueue", CPDMA_TX_STAT(tail_enqueue) },
-   { "Tx DMA chan: pad_enqueue", CPDMA_TX_STAT(pad_enqueue) },
-   { "Tx DMA chan: misqueued", CPDMA_TX_STAT(misqueued) },
-   { "Tx DMA chan: desc_alloc_fail", CPDMA_TX_STAT(desc_alloc_fail) },
-   { "Tx DMA chan: pad_alloc_fail", CPDMA_TX_STAT(pad_alloc_fail) },
-   { "Tx DMA chan: runt_receive_buf", CPDMA_TX_STAT(runt_receive_buff) },
-   { "Tx DMA chan: runt_transmit_buf", CPDMA_TX_STAT(runt_transmit_buff) },
-   { "Tx DMA chan: empty_dequeue", CPDMA_TX_STAT(empty_dequeue) },
-   { "Tx DMA chan: busy_dequeue", CPDMA_TX_STAT(busy_dequeue) },
-   { "Tx DMA chan: good_dequeue", CPDMA_TX_STAT(good_dequeue) },
-   { "Tx DMA chan: requeue", CPDMA_TX_STAT(requeue) },
-   { "Tx DMA chan: teardown_dequeue", CPDMA_TX_STAT(teardown_dequeue) },
 };
 
-#define CPSW_STATS_LEN ARRAY_SIZE(cpsw_gstrings_stats)
+static const struct cpsw_stats cpsw_gstrings_ch_stats[] = {
+   { "head_enqueue", CPDMA_RX_STAT(head_enqueue) },
+   { "tail_enqueue", CPDMA_RX_STAT(tail_enqueue) },
+   { "pad_enqueue", CPDMA_RX_STAT(pad_enqueue) },
+   { "misqueued", CPDMA_RX_STAT(misqueued) },
+   { "desc_alloc_fail", CPDMA_RX_STAT(desc_alloc_fail) },
+   { "pad_alloc_fail", CPDMA_RX_STAT(pad_alloc_fail) },
+   { "runt_receive_buf", CPDMA_RX_STAT(runt_receive_buff) },
+   { "runt_transmit_buf", CPDMA_RX_STAT(runt_transmit_buff) },
+   { "empty_dequeue", CPDMA_RX_STAT(empty_dequeue) },
+   { "busy_dequeue", CPDMA_RX_STAT(busy_dequeue) },
+   { "good_dequeue", CPDMA_RX_STAT(good_dequeue) },
+   { "requeue", CPDMA_RX_STAT(requeue) },
+   { "teardown_dequeue",