6868
6969#define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03
7070#define PCI_DEVICE_ID_LOONGSON_GNET 0x7a13
71- #define DWMAC_CORE_LS_MULTICHAN 0x10 /* Loongson custom ID */
72- #define CHANNEL_NUM 8
71+ #define DWMAC_CORE_MULTICHAN_V1 0x10 /* Loongson custom ID 0x10 */
72+ #define DWMAC_CORE_MULTICHAN_V2 0x12 /* Loongson custom ID 0x12 */
7373
7474struct loongson_data {
75+ u32 multichan ;
7576 u32 loongson_id ;
7677 struct device * dev ;
7778};
@@ -119,18 +120,29 @@ static void loongson_default_data(struct pci_dev *pdev,
119120 plat -> dma_cfg -> pbl = 32 ;
120121 plat -> dma_cfg -> pblx8 = true;
121122
122- if (ld -> loongson_id == DWMAC_CORE_LS_MULTICHAN ) {
123- plat -> rx_queues_to_use = CHANNEL_NUM ;
124- plat -> tx_queues_to_use = CHANNEL_NUM ;
123+ switch (ld -> loongson_id ) {
124+ case DWMAC_CORE_MULTICHAN_V1 :
125+ ld -> multichan = 1 ;
126+ plat -> rx_queues_to_use = 8 ;
127+ plat -> tx_queues_to_use = 8 ;
125128
126129 /* Only channel 0 supports checksum,
127130 * so turn off checksum to enable multiple channels.
128131 */
129- for (int i = 1 ; i < CHANNEL_NUM ; i ++ )
132+ for (int i = 1 ; i < 8 ; i ++ )
130133 plat -> tx_queues_cfg [i ].coe_unsupported = 1 ;
131- } else {
134+
135+ break ;
136+ case DWMAC_CORE_MULTICHAN_V2 :
137+ ld -> multichan = 1 ;
138+ plat -> rx_queues_to_use = 4 ;
139+ plat -> tx_queues_to_use = 4 ;
140+ break ;
141+ default :
142+ ld -> multichan = 0 ;
132143 plat -> tx_queues_to_use = 1 ;
133144 plat -> rx_queues_to_use = 1 ;
145+ break ;
134146 }
135147}
136148
@@ -328,14 +340,14 @@ static struct mac_device_info *loongson_dwmac_setup(void *apriv)
328340 return NULL ;
329341
330342 /* The Loongson GMAC and GNET devices are based on the DW GMAC
331- * v3.50a and v3.73a IP-cores. But the HW designers have changed the
332- * GMAC_VERSION.SNPSVER field to the custom 0x10 value on the
333- * network controllers with the multi-channels feature
343+ * v3.50a and v3.73a IP-cores. But the HW designers have changed
344+ * the GMAC_VERSION.SNPSVER field to the custom 0x10/0x12 value
345+ * on the network controllers with the multi-channels feature
334346 * available to emphasize the differences: multiple DMA-channels,
335347 * AV feature and GMAC_INT_STATUS CSR flags layout. Get back the
336348 * original value so the correct HW-interface would be selected.
337349 */
338- if (ld -> loongson_id == DWMAC_CORE_LS_MULTICHAN ) {
350+ if (ld -> multichan ) {
339351 priv -> synopsys_id = DWMAC_CORE_3_70 ;
340352 * dma = dwmac1000_dma_ops ;
341353 dma -> init_chan = loongson_dwmac_dma_init_channel ;
@@ -356,13 +368,13 @@ static struct mac_device_info *loongson_dwmac_setup(void *apriv)
356368 if (mac -> multicast_filter_bins )
357369 mac -> mcast_bits_log2 = ilog2 (mac -> multicast_filter_bins );
358370
359- /* Loongson GMAC doesn't support the flow control. LS2K2000
360- * GNET doesn't support the half-duplex link mode.
371+ /* Loongson GMAC doesn't support the flow control. Loongson GNET
372+ * without multi-channel doesn't support the half-duplex link mode.
361373 */
362374 if (pdev -> device == PCI_DEVICE_ID_LOONGSON_GMAC ) {
363375 mac -> link .caps = MAC_10 | MAC_100 | MAC_1000 ;
364376 } else {
365- if (ld -> loongson_id == DWMAC_CORE_LS_MULTICHAN )
377+ if (ld -> multichan )
366378 mac -> link .caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
367379 MAC_10 | MAC_100 | MAC_1000 ;
368380 else
@@ -391,9 +403,11 @@ static int loongson_dwmac_msi_config(struct pci_dev *pdev,
391403 struct plat_stmmacenet_data * plat ,
392404 struct stmmac_resources * res )
393405{
394- int i , ret , vecs ;
406+ int i , ch_num , ret , vecs ;
407+
408+ ch_num = min (plat -> tx_queues_to_use , plat -> rx_queues_to_use );
395409
396- vecs = roundup_pow_of_two (CHANNEL_NUM * 2 + 1 );
410+ vecs = roundup_pow_of_two (ch_num * 2 + 1 );
397411 ret = pci_alloc_irq_vectors (pdev , vecs , vecs , PCI_IRQ_MSI );
398412 if (ret < 0 ) {
399413 dev_warn (& pdev -> dev , "Failed to allocate MSI IRQs\n" );
@@ -402,14 +416,12 @@ static int loongson_dwmac_msi_config(struct pci_dev *pdev,
402416
403417 res -> irq = pci_irq_vector (pdev , 0 );
404418
405- for (i = 0 ; i < plat -> rx_queues_to_use ; i ++ ) {
406- res -> rx_irq [CHANNEL_NUM - 1 - i ] =
407- pci_irq_vector (pdev , 1 + i * 2 );
419+ for (i = 0 ; i < ch_num ; i ++ ) {
420+ res -> rx_irq [ch_num - 1 - i ] = pci_irq_vector (pdev , 1 + i * 2 );
408421 }
409422
410- for (i = 0 ; i < plat -> tx_queues_to_use ; i ++ ) {
411- res -> tx_irq [CHANNEL_NUM - 1 - i ] =
412- pci_irq_vector (pdev , 2 + i * 2 );
423+ for (i = 0 ; i < ch_num ; i ++ ) {
424+ res -> tx_irq [ch_num - 1 - i ] = pci_irq_vector (pdev , 2 + i * 2 );
413425 }
414426
415427 plat -> flags |= STMMAC_FLAG_MULTI_MSI_EN ;
@@ -571,7 +583,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
571583 goto err_disable_device ;
572584
573585 /* Use the common MAC IRQ if per-channel MSIs allocation failed */
574- if (ld -> loongson_id == DWMAC_CORE_LS_MULTICHAN )
586+ if (ld -> multichan )
575587 loongson_dwmac_msi_config (pdev , plat , & res );
576588
577589 ret = stmmac_dvr_probe (& pdev -> dev , plat , & res );
@@ -583,7 +595,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
583595err_plat_clear :
584596 if (dev_of_node (& pdev -> dev ))
585597 loongson_dwmac_dt_clear (pdev , plat );
586- if (ld -> loongson_id == DWMAC_CORE_LS_MULTICHAN )
598+ if (ld -> multichan )
587599 loongson_dwmac_msi_clear (pdev );
588600err_disable_device :
589601 pci_disable_device (pdev );
@@ -602,7 +614,7 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)
602614 if (dev_of_node (& pdev -> dev ))
603615 loongson_dwmac_dt_clear (pdev , priv -> plat );
604616
605- if (ld -> loongson_id == DWMAC_CORE_LS_MULTICHAN )
617+ if (ld -> multichan )
606618 loongson_dwmac_msi_clear (pdev );
607619
608620 pci_disable_device (pdev );
0 commit comments