From: Fugang Duan <B38611@xxxxxxxxxxxxx> Since i.MX6SX enet-AVB IP support multi queues, so use multi queues interface to allocate and set up an Ethernet device. Signed-off-by: Fugang Duan <B38611@xxxxxxxxxxxxx> Signed-off-by: Frank Li <Frank.Li@xxxxxxxxxxxxx> --- drivers/net/ethernet/freescale/fec.h | 9 ++++++ drivers/net/ethernet/freescale/fec_main.c | 49 ++++++++++++++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 635772b..f77ed6f 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -233,6 +233,13 @@ struct bufdesc_ex { /* This device has up to three irqs on some platforms */ #define FEC_IRQ_NUM 3 +/* Maximum number of queues supported + * ENET with AVB IP can support up to 3 independent tx queues and rx queues. + * User can point the queue number that is less than or equal to 3. + */ +#define FEC_ENET_MAX_TX_QS 3 +#define FEC_ENET_MAX_RX_QS 3 + /* The number of Tx and Rx buffers. These are allocated from the page * pool. The code may assume these are power of two, so it it best * to keep them that size. @@ -278,6 +285,8 @@ struct fec_enet_private { bool ptp_clk_on; struct mutex ptp_clk_mutex; + int num_tx_queues; + int num_rx_queues; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ unsigned char *tx_bounce[TX_RING_SIZE]; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index ee9f04f..00fcadd 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -2573,6 +2573,39 @@ static void fec_reset_phy(struct platform_device *pdev) #endif /* CONFIG_OF */ static int +fec_enet_get_queue_num(struct platform_device *pdev, int *num_tx, int *num_rx) +{ + struct device_node *np = pdev->dev.of_node; + int err; + + if (!np || !of_device_is_available(np)) + return -ENODEV; + + /* parse the num of tx and rx queues */ + err = of_property_read_u32(np, "fsl,num_tx_queues", num_tx); + err |= of_property_read_u32(np, "fsl,num_rx_queues", num_rx); + if (err) { + *num_tx = 1; + *num_rx = 1; + return 0; + } + + if (*num_tx < 1 || *num_tx > FEC_ENET_MAX_TX_QS) { + dev_err(&pdev->dev, "num_tx(=%d) greater than MAX_TX_QS(=%d)\n", + *num_tx, FEC_ENET_MAX_TX_QS); + return -EINVAL; + } + + if (*num_rx < 1 || *num_rx > FEC_ENET_MAX_RX_QS) { + dev_err(&pdev->dev, "num_rx(=%d) greater than MAX_RX_QS(=%d)\n", + *num_rx, FEC_ENET_MAX_RX_QS); + return -EINVAL; + } + + return 0; +} + +static int fec_probe(struct platform_device *pdev) { struct fec_enet_private *fep; @@ -2583,13 +2616,23 @@ fec_probe(struct platform_device *pdev) const struct of_device_id *of_id; static int dev_id; struct device_node *np = pdev->dev.of_node, *phy_node; + int num_tx_qs = 1; + int num_rx_qs = 1; of_id = of_match_device(fec_dt_ids, &pdev->dev); if (of_id) pdev->id_entry = of_id->data; + if (pdev->id_entry && + (pdev->id_entry->driver_data & FEC_QUIRK_HAS_AVB)) { + ret = fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs); + if (ret) + return ret; + } + /* Init network device */ - ndev = alloc_etherdev(sizeof(struct fec_enet_private)); + ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private), + num_tx_qs, num_rx_qs); if (!ndev) return -ENOMEM; @@ -2598,6 +2641,10 @@ fec_probe(struct platform_device *pdev) /* setup board info structure */ fep = netdev_priv(ndev); + fep->num_rx_queues = num_rx_qs; + fep->num_tx_queues = num_tx_qs; + netif_set_real_num_rx_queues(ndev, num_rx_qs); + #if !defined(CONFIG_M5272) /* default enable pause frame auto negotiation */ if (pdev->id_entry && -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html