diff options
author | David S. Miller <davem@davemloft.net> | 2014-09-19 17:30:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-19 17:30:16 -0400 |
commit | 58310b3fc6aaa4f896ad3cbcd88851e7ad0908f6 (patch) | |
tree | bb24828b191225b2af2e5f25ebbcc90c08469faa /drivers/net | |
parent | 54003f119c26573d3bb86a5efc64f3e5fd43b8c6 (diff) | |
parent | b1b6b4da7867d220f0da5f6686b869b304c5459b (diff) |
Merge branch 'mlx4-next'
Or Gerlitz says:
====================
mlx4: CQE/EQE stride support
This series from Ido Shamay is intended for archs having
cache line larger then 64 bytes.
Since our CQE/EQEs are generally 64B in those systems, HW will write
twice to the same cache line consecutively, causing pipe locks due to
he hazard prevention mechanism. For elements in a cyclic buffer, writes
are consecutive, so entries smaller than a cache line should be
avoided, especially if they are written at a high rate.
Reduce consecutive writes to same cache line in CQs/EQs, by allowing the
driver to increase the distance between entries so that each will reside
in a different cache line.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_rx.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/en_tx.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/eq.c | 30 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.c | 38 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/fw.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/main.c | 61 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 6 |
9 files changed, 130 insertions, 19 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index abddcf8c40aa..f3032fec8fce 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
@@ -2459,6 +2459,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, | |||
2459 | } | 2459 | } |
2460 | priv->rx_ring_num = prof->rx_ring_num; | 2460 | priv->rx_ring_num = prof->rx_ring_num; |
2461 | priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0; | 2461 | priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0; |
2462 | priv->cqe_size = mdev->dev->caps.cqe_size; | ||
2462 | priv->mac_index = -1; | 2463 | priv->mac_index = -1; |
2463 | priv->msg_enable = MLX4_EN_MSG_LEVEL; | 2464 | priv->msg_enable = MLX4_EN_MSG_LEVEL; |
2464 | spin_lock_init(&priv->stats_lock); | 2465 | spin_lock_init(&priv->stats_lock); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c index 14686b6f4bc5..a33048ee9621 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c | |||
@@ -671,7 +671,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud | |||
671 | * descriptor offset can be deduced from the CQE index instead of | 671 | * descriptor offset can be deduced from the CQE index instead of |
672 | * reading 'cqe->index' */ | 672 | * reading 'cqe->index' */ |
673 | index = cq->mcq.cons_index & ring->size_mask; | 673 | index = cq->mcq.cons_index & ring->size_mask; |
674 | cqe = &cq->buf[(index << factor) + factor]; | 674 | cqe = mlx4_en_get_cqe(cq->buf, index, priv->cqe_size) + factor; |
675 | 675 | ||
676 | /* Process all completed CQEs */ | 676 | /* Process all completed CQEs */ |
677 | while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK, | 677 | while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK, |
@@ -858,7 +858,7 @@ next: | |||
858 | 858 | ||
859 | ++cq->mcq.cons_index; | 859 | ++cq->mcq.cons_index; |
860 | index = (cq->mcq.cons_index) & ring->size_mask; | 860 | index = (cq->mcq.cons_index) & ring->size_mask; |
861 | cqe = &cq->buf[(index << factor) + factor]; | 861 | cqe = mlx4_en_get_cqe(cq->buf, index, priv->cqe_size) + factor; |
862 | if (++polled == budget) | 862 | if (++polled == budget) |
863 | goto out; | 863 | goto out; |
864 | } | 864 | } |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index bc8f51c77d80..c44f4237b9be 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c | |||
@@ -382,7 +382,7 @@ static bool mlx4_en_process_tx_cq(struct net_device *dev, | |||
382 | return true; | 382 | return true; |
383 | 383 | ||
384 | index = cons_index & size_mask; | 384 | index = cons_index & size_mask; |
385 | cqe = &buf[(index << factor) + factor]; | 385 | cqe = mlx4_en_get_cqe(buf, index, priv->cqe_size) + factor; |
386 | ring_index = ring->cons & size_mask; | 386 | ring_index = ring->cons & size_mask; |
387 | stamp_index = ring_index; | 387 | stamp_index = ring_index; |
388 | 388 | ||
@@ -430,7 +430,7 @@ static bool mlx4_en_process_tx_cq(struct net_device *dev, | |||
430 | 430 | ||
431 | ++cons_index; | 431 | ++cons_index; |
432 | index = cons_index & size_mask; | 432 | index = cons_index & size_mask; |
433 | cqe = &buf[(index << factor) + factor]; | 433 | cqe = mlx4_en_get_cqe(buf, index, priv->cqe_size) + factor; |
434 | } | 434 | } |
435 | 435 | ||
436 | 436 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 2a004b347e1d..a49c9d11d8a5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c | |||
@@ -101,21 +101,24 @@ static void eq_set_ci(struct mlx4_eq *eq, int req_not) | |||
101 | mb(); | 101 | mb(); |
102 | } | 102 | } |
103 | 103 | ||
104 | static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry, u8 eqe_factor) | 104 | static struct mlx4_eqe *get_eqe(struct mlx4_eq *eq, u32 entry, u8 eqe_factor, |
105 | u8 eqe_size) | ||
105 | { | 106 | { |
106 | /* (entry & (eq->nent - 1)) gives us a cyclic array */ | 107 | /* (entry & (eq->nent - 1)) gives us a cyclic array */ |
107 | unsigned long offset = (entry & (eq->nent - 1)) * (MLX4_EQ_ENTRY_SIZE << eqe_factor); | 108 | unsigned long offset = (entry & (eq->nent - 1)) * eqe_size; |
108 | /* CX3 is capable of extending the EQE from 32 to 64 bytes. | 109 | /* CX3 is capable of extending the EQE from 32 to 64 bytes with |
109 | * When this feature is enabled, the first (in the lower addresses) | 110 | * strides of 64B,128B and 256B. |
111 | * When 64B EQE is used, the first (in the lower addresses) | ||
110 | * 32 bytes in the 64 byte EQE are reserved and the next 32 bytes | 112 | * 32 bytes in the 64 byte EQE are reserved and the next 32 bytes |
111 | * contain the legacy EQE information. | 113 | * contain the legacy EQE information. |
114 | * In all other cases, the first 32B contains the legacy EQE info. | ||
112 | */ | 115 | */ |
113 | return eq->page_list[offset / PAGE_SIZE].buf + (offset + (eqe_factor ? MLX4_EQ_ENTRY_SIZE : 0)) % PAGE_SIZE; | 116 | return eq->page_list[offset / PAGE_SIZE].buf + (offset + (eqe_factor ? MLX4_EQ_ENTRY_SIZE : 0)) % PAGE_SIZE; |
114 | } | 117 | } |
115 | 118 | ||
116 | static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq, u8 eqe_factor) | 119 | static struct mlx4_eqe *next_eqe_sw(struct mlx4_eq *eq, u8 eqe_factor, u8 size) |
117 | { | 120 | { |
118 | struct mlx4_eqe *eqe = get_eqe(eq, eq->cons_index, eqe_factor); | 121 | struct mlx4_eqe *eqe = get_eqe(eq, eq->cons_index, eqe_factor, size); |
119 | return !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? NULL : eqe; | 122 | return !!(eqe->owner & 0x80) ^ !!(eq->cons_index & eq->nent) ? NULL : eqe; |
120 | } | 123 | } |
121 | 124 | ||
@@ -459,8 +462,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) | |||
459 | enum slave_port_gen_event gen_event; | 462 | enum slave_port_gen_event gen_event; |
460 | unsigned long flags; | 463 | unsigned long flags; |
461 | struct mlx4_vport_state *s_info; | 464 | struct mlx4_vport_state *s_info; |
465 | int eqe_size = dev->caps.eqe_size; | ||
462 | 466 | ||
463 | while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor))) { | 467 | while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor, eqe_size))) { |
464 | /* | 468 | /* |
465 | * Make sure we read EQ entry contents after we've | 469 | * Make sure we read EQ entry contents after we've |
466 | * checked the ownership bit. | 470 | * checked the ownership bit. |
@@ -894,8 +898,10 @@ static int mlx4_create_eq(struct mlx4_dev *dev, int nent, | |||
894 | 898 | ||
895 | eq->dev = dev; | 899 | eq->dev = dev; |
896 | eq->nent = roundup_pow_of_two(max(nent, 2)); | 900 | eq->nent = roundup_pow_of_two(max(nent, 2)); |
897 | /* CX3 is capable of extending the CQE/EQE from 32 to 64 bytes */ | 901 | /* CX3 is capable of extending the CQE/EQE from 32 to 64 bytes, with |
898 | npages = PAGE_ALIGN(eq->nent * (MLX4_EQ_ENTRY_SIZE << dev->caps.eqe_factor)) / PAGE_SIZE; | 902 | * strides of 64B,128B and 256B. |
903 | */ | ||
904 | npages = PAGE_ALIGN(eq->nent * dev->caps.eqe_size) / PAGE_SIZE; | ||
899 | 905 | ||
900 | eq->page_list = kmalloc(npages * sizeof *eq->page_list, | 906 | eq->page_list = kmalloc(npages * sizeof *eq->page_list, |
901 | GFP_KERNEL); | 907 | GFP_KERNEL); |
@@ -997,8 +1003,10 @@ static void mlx4_free_eq(struct mlx4_dev *dev, | |||
997 | struct mlx4_cmd_mailbox *mailbox; | 1003 | struct mlx4_cmd_mailbox *mailbox; |
998 | int err; | 1004 | int err; |
999 | int i; | 1005 | int i; |
1000 | /* CX3 is capable of extending the CQE/EQE from 32 to 64 bytes */ | 1006 | /* CX3 is capable of extending the CQE/EQE from 32 to 64 bytes, with |
1001 | int npages = PAGE_ALIGN((MLX4_EQ_ENTRY_SIZE << dev->caps.eqe_factor) * eq->nent) / PAGE_SIZE; | 1007 | * strides of 64B,128B and 256B |
1008 | */ | ||
1009 | int npages = PAGE_ALIGN(dev->caps.eqe_size * eq->nent) / PAGE_SIZE; | ||
1002 | 1010 | ||
1003 | mailbox = mlx4_alloc_cmd_mailbox(dev); | 1011 | mailbox = mlx4_alloc_cmd_mailbox(dev); |
1004 | if (IS_ERR(mailbox)) | 1012 | if (IS_ERR(mailbox)) |
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 494753e44ae3..13b2e4a51ef4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c | |||
@@ -137,7 +137,9 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags) | |||
137 | [8] = "Dynamic QP updates support", | 137 | [8] = "Dynamic QP updates support", |
138 | [9] = "Device managed flow steering IPoIB support", | 138 | [9] = "Device managed flow steering IPoIB support", |
139 | [10] = "TCP/IP offloads/flow-steering for VXLAN support", | 139 | [10] = "TCP/IP offloads/flow-steering for VXLAN support", |
140 | [11] = "MAD DEMUX (Secure-Host) support" | 140 | [11] = "MAD DEMUX (Secure-Host) support", |
141 | [12] = "Large cache line (>64B) CQE stride support", | ||
142 | [13] = "Large cache line (>64B) EQE stride support" | ||
141 | }; | 143 | }; |
142 | int i; | 144 | int i; |
143 | 145 | ||
@@ -557,6 +559,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
557 | #define QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET 0x74 | 559 | #define QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET 0x74 |
558 | #define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76 | 560 | #define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76 |
559 | #define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77 | 561 | #define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77 |
562 | #define QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE 0x7a | ||
560 | #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80 | 563 | #define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80 |
561 | #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82 | 564 | #define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82 |
562 | #define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84 | 565 | #define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET 0x84 |
@@ -733,6 +736,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
733 | dev_cap->max_rq_sg = field; | 736 | dev_cap->max_rq_sg = field; |
734 | MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET); | 737 | MLX4_GET(size, outbox, QUERY_DEV_CAP_MAX_DESC_SZ_RQ_OFFSET); |
735 | dev_cap->max_rq_desc_sz = size; | 738 | dev_cap->max_rq_desc_sz = size; |
739 | MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE); | ||
740 | if (field & (1 << 6)) | ||
741 | dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_CQE_STRIDE; | ||
742 | if (field & (1 << 7)) | ||
743 | dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_EQE_STRIDE; | ||
736 | 744 | ||
737 | MLX4_GET(dev_cap->bmme_flags, outbox, | 745 | MLX4_GET(dev_cap->bmme_flags, outbox, |
738 | QUERY_DEV_CAP_BMME_FLAGS_OFFSET); | 746 | QUERY_DEV_CAP_BMME_FLAGS_OFFSET); |
@@ -1376,6 +1384,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) | |||
1376 | #define INIT_HCA_CQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x30) | 1384 | #define INIT_HCA_CQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x30) |
1377 | #define INIT_HCA_LOG_CQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x37) | 1385 | #define INIT_HCA_LOG_CQ_OFFSET (INIT_HCA_QPC_OFFSET + 0x37) |
1378 | #define INIT_HCA_EQE_CQE_OFFSETS (INIT_HCA_QPC_OFFSET + 0x38) | 1386 | #define INIT_HCA_EQE_CQE_OFFSETS (INIT_HCA_QPC_OFFSET + 0x38) |
1387 | #define INIT_HCA_EQE_CQE_STRIDE_OFFSET (INIT_HCA_QPC_OFFSET + 0x3b) | ||
1379 | #define INIT_HCA_ALTC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x40) | 1388 | #define INIT_HCA_ALTC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x40) |
1380 | #define INIT_HCA_AUXC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x50) | 1389 | #define INIT_HCA_AUXC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x50) |
1381 | #define INIT_HCA_EQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x60) | 1390 | #define INIT_HCA_EQC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x60) |
@@ -1452,11 +1461,25 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) | |||
1452 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_CQE) { | 1461 | if (dev->caps.flags & MLX4_DEV_CAP_FLAG_64B_CQE) { |
1453 | *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 30); | 1462 | *(inbox + INIT_HCA_EQE_CQE_OFFSETS / 4) |= cpu_to_be32(1 << 30); |
1454 | dev->caps.cqe_size = 64; | 1463 | dev->caps.cqe_size = 64; |
1455 | dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_64B_CQE; | 1464 | dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE; |
1456 | } else { | 1465 | } else { |
1457 | dev->caps.cqe_size = 32; | 1466 | dev->caps.cqe_size = 32; |
1458 | } | 1467 | } |
1459 | 1468 | ||
1469 | /* CX3 is capable of extending CQEs\EQEs to strides larger than 64B */ | ||
1470 | if ((dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_EQE_STRIDE) && | ||
1471 | (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_CQE_STRIDE)) { | ||
1472 | dev->caps.eqe_size = cache_line_size(); | ||
1473 | dev->caps.cqe_size = cache_line_size(); | ||
1474 | dev->caps.eqe_factor = 0; | ||
1475 | MLX4_PUT(inbox, (u8)((ilog2(dev->caps.eqe_size) - 5) << 4 | | ||
1476 | (ilog2(dev->caps.eqe_size) - 5)), | ||
1477 | INIT_HCA_EQE_CQE_STRIDE_OFFSET); | ||
1478 | |||
1479 | /* User still need to know to support CQE > 32B */ | ||
1480 | dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE; | ||
1481 | } | ||
1482 | |||
1460 | /* QPC/EEC/CQC/EQC/RDMARC attributes */ | 1483 | /* QPC/EEC/CQC/EQC/RDMARC attributes */ |
1461 | 1484 | ||
1462 | MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET); | 1485 | MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET); |
@@ -1616,6 +1639,17 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, | |||
1616 | if (byte_field & 0x40) /* 64-bytes cqe enabled */ | 1639 | if (byte_field & 0x40) /* 64-bytes cqe enabled */ |
1617 | param->dev_cap_enabled |= MLX4_DEV_CAP_64B_CQE_ENABLED; | 1640 | param->dev_cap_enabled |= MLX4_DEV_CAP_64B_CQE_ENABLED; |
1618 | 1641 | ||
1642 | /* CX3 is capable of extending CQEs\EQEs to strides larger than 64B */ | ||
1643 | MLX4_GET(byte_field, outbox, INIT_HCA_EQE_CQE_STRIDE_OFFSET); | ||
1644 | if (byte_field) { | ||
1645 | param->dev_cap_enabled |= MLX4_DEV_CAP_64B_EQE_ENABLED; | ||
1646 | param->dev_cap_enabled |= MLX4_DEV_CAP_64B_CQE_ENABLED; | ||
1647 | param->cqe_size = 1 << ((byte_field & | ||
1648 | MLX4_CQE_SIZE_MASK_STRIDE) + 5); | ||
1649 | param->eqe_size = 1 << (((byte_field & | ||
1650 | MLX4_EQE_SIZE_MASK_STRIDE) >> 4) + 5); | ||
1651 | } | ||
1652 | |||
1619 | /* TPT attributes */ | 1653 | /* TPT attributes */ |
1620 | 1654 | ||
1621 | MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET); | 1655 | MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h index 1fce03ebe5c4..9b835aecac96 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/drivers/net/ethernet/mellanox/mlx4/fw.h | |||
@@ -178,6 +178,8 @@ struct mlx4_init_hca_param { | |||
178 | u8 uar_page_sz; /* log pg sz in 4k chunks */ | 178 | u8 uar_page_sz; /* log pg sz in 4k chunks */ |
179 | u8 steering_mode; /* for QUERY_HCA */ | 179 | u8 steering_mode; /* for QUERY_HCA */ |
180 | u64 dev_cap_enabled; | 180 | u64 dev_cap_enabled; |
181 | u16 cqe_size; /* For use only when CQE stride feature enabled */ | ||
182 | u16 eqe_size; /* For use only when EQE stride feature enabled */ | ||
181 | }; | 183 | }; |
182 | 184 | ||
183 | struct mlx4_init_ib_param { | 185 | struct mlx4_init_ib_param { |
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 7e2d5d57c598..1f10023af1db 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -104,7 +104,8 @@ module_param(enable_64b_cqe_eqe, bool, 0444); | |||
104 | MODULE_PARM_DESC(enable_64b_cqe_eqe, | 104 | MODULE_PARM_DESC(enable_64b_cqe_eqe, |
105 | "Enable 64 byte CQEs/EQEs when the FW supports this (default: True)"); | 105 | "Enable 64 byte CQEs/EQEs when the FW supports this (default: True)"); |
106 | 106 | ||
107 | #define PF_CONTEXT_BEHAVIOUR_MASK MLX4_FUNC_CAP_64B_EQE_CQE | 107 | #define PF_CONTEXT_BEHAVIOUR_MASK (MLX4_FUNC_CAP_64B_EQE_CQE | \ |
108 | MLX4_FUNC_CAP_EQE_CQE_STRIDE) | ||
108 | 109 | ||
109 | static char mlx4_version[] = | 110 | static char mlx4_version[] = |
110 | DRV_NAME ": Mellanox ConnectX core driver v" | 111 | DRV_NAME ": Mellanox ConnectX core driver v" |
@@ -196,6 +197,40 @@ static void mlx4_set_port_mask(struct mlx4_dev *dev) | |||
196 | dev->caps.port_mask[i] = dev->caps.port_type[i]; | 197 | dev->caps.port_mask[i] = dev->caps.port_type[i]; |
197 | } | 198 | } |
198 | 199 | ||
200 | static void mlx4_enable_cqe_eqe_stride(struct mlx4_dev *dev) | ||
201 | { | ||
202 | struct mlx4_caps *dev_cap = &dev->caps; | ||
203 | |||
204 | /* FW not supporting or cancelled by user */ | ||
205 | if (!(dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_EQE_STRIDE) || | ||
206 | !(dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_CQE_STRIDE)) | ||
207 | return; | ||
208 | |||
209 | /* Must have 64B CQE_EQE enabled by FW to use bigger stride | ||
210 | * When FW has NCSI it may decide not to report 64B CQE/EQEs | ||
211 | */ | ||
212 | if (!(dev_cap->flags & MLX4_DEV_CAP_FLAG_64B_EQE) || | ||
213 | !(dev_cap->flags & MLX4_DEV_CAP_FLAG_64B_CQE)) { | ||
214 | dev_cap->flags2 &= ~MLX4_DEV_CAP_FLAG2_CQE_STRIDE; | ||
215 | dev_cap->flags2 &= ~MLX4_DEV_CAP_FLAG2_EQE_STRIDE; | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | if (cache_line_size() == 128 || cache_line_size() == 256) { | ||
220 | mlx4_dbg(dev, "Enabling CQE stride cacheLine supported\n"); | ||
221 | /* Changing the real data inside CQE size to 32B */ | ||
222 | dev_cap->flags &= ~MLX4_DEV_CAP_FLAG_64B_CQE; | ||
223 | dev_cap->flags &= ~MLX4_DEV_CAP_FLAG_64B_EQE; | ||
224 | |||
225 | if (mlx4_is_master(dev)) | ||
226 | dev_cap->function_caps |= MLX4_FUNC_CAP_EQE_CQE_STRIDE; | ||
227 | } else { | ||
228 | mlx4_dbg(dev, "Disabling CQE stride cacheLine unsupported\n"); | ||
229 | dev_cap->flags2 &= ~MLX4_DEV_CAP_FLAG2_CQE_STRIDE; | ||
230 | dev_cap->flags2 &= ~MLX4_DEV_CAP_FLAG2_EQE_STRIDE; | ||
231 | } | ||
232 | } | ||
233 | |||
199 | static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | 234 | static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) |
200 | { | 235 | { |
201 | int err; | 236 | int err; |
@@ -390,6 +425,14 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
390 | dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_CQE; | 425 | dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_CQE; |
391 | dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_EQE; | 426 | dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_64B_EQE; |
392 | } | 427 | } |
428 | |||
429 | if (dev_cap->flags2 & | ||
430 | (MLX4_DEV_CAP_FLAG2_CQE_STRIDE | | ||
431 | MLX4_DEV_CAP_FLAG2_EQE_STRIDE)) { | ||
432 | mlx4_warn(dev, "Disabling EQE/CQE stride per user request\n"); | ||
433 | dev_cap->flags2 &= ~MLX4_DEV_CAP_FLAG2_CQE_STRIDE; | ||
434 | dev_cap->flags2 &= ~MLX4_DEV_CAP_FLAG2_EQE_STRIDE; | ||
435 | } | ||
393 | } | 436 | } |
394 | 437 | ||
395 | if ((dev->caps.flags & | 438 | if ((dev->caps.flags & |
@@ -397,6 +440,9 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
397 | mlx4_is_master(dev)) | 440 | mlx4_is_master(dev)) |
398 | dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE; | 441 | dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE; |
399 | 442 | ||
443 | if (!mlx4_is_slave(dev)) | ||
444 | mlx4_enable_cqe_eqe_stride(dev); | ||
445 | |||
400 | return 0; | 446 | return 0; |
401 | } | 447 | } |
402 | 448 | ||
@@ -724,11 +770,22 @@ static int mlx4_slave_cap(struct mlx4_dev *dev) | |||
724 | 770 | ||
725 | if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_CQE_ENABLED) { | 771 | if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_64B_CQE_ENABLED) { |
726 | dev->caps.cqe_size = 64; | 772 | dev->caps.cqe_size = 64; |
727 | dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_64B_CQE; | 773 | dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE; |
728 | } else { | 774 | } else { |
729 | dev->caps.cqe_size = 32; | 775 | dev->caps.cqe_size = 32; |
730 | } | 776 | } |
731 | 777 | ||
778 | if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_EQE_STRIDE_ENABLED) { | ||
779 | dev->caps.eqe_size = hca_param.eqe_size; | ||
780 | dev->caps.eqe_factor = 0; | ||
781 | } | ||
782 | |||
783 | if (hca_param.dev_cap_enabled & MLX4_DEV_CAP_CQE_STRIDE_ENABLED) { | ||
784 | dev->caps.cqe_size = hca_param.cqe_size; | ||
785 | /* User still need to know when CQE > 32B */ | ||
786 | dev->caps.userspace_caps |= MLX4_USER_DEV_CAP_LARGE_CQE; | ||
787 | } | ||
788 | |||
732 | dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS; | 789 | dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS; |
733 | mlx4_warn(dev, "Timestamping is not supported in slave mode\n"); | 790 | mlx4_warn(dev, "Timestamping is not supported in slave mode\n"); |
734 | 791 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index b508c7887ef8..de10dbb2e6ed 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -285,6 +285,9 @@ struct mlx4_icm_table { | |||
285 | #define MLX4_MPT_STATUS_SW 0xF0 | 285 | #define MLX4_MPT_STATUS_SW 0xF0 |
286 | #define MLX4_MPT_STATUS_HW 0x00 | 286 | #define MLX4_MPT_STATUS_HW 0x00 |
287 | 287 | ||
288 | #define MLX4_CQE_SIZE_MASK_STRIDE 0x3 | ||
289 | #define MLX4_EQE_SIZE_MASK_STRIDE 0x30 | ||
290 | |||
288 | /* | 291 | /* |
289 | * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits. | 292 | * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits. |
290 | */ | 293 | */ |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 3de41be49425..e3d71c386da7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | |||
@@ -542,6 +542,7 @@ struct mlx4_en_priv { | |||
542 | unsigned max_mtu; | 542 | unsigned max_mtu; |
543 | int base_qpn; | 543 | int base_qpn; |
544 | int cqe_factor; | 544 | int cqe_factor; |
545 | int cqe_size; | ||
545 | 546 | ||
546 | struct mlx4_en_rss_map rss_map; | 547 | struct mlx4_en_rss_map rss_map; |
547 | __be32 ctrl_flags; | 548 | __be32 ctrl_flags; |
@@ -612,6 +613,11 @@ struct mlx4_mac_entry { | |||
612 | struct rcu_head rcu; | 613 | struct rcu_head rcu; |
613 | }; | 614 | }; |
614 | 615 | ||
616 | static inline struct mlx4_cqe *mlx4_en_get_cqe(void *buf, int idx, int cqe_sz) | ||
617 | { | ||
618 | return buf + idx * cqe_sz; | ||
619 | } | ||
620 | |||
615 | #ifdef CONFIG_NET_RX_BUSY_POLL | 621 | #ifdef CONFIG_NET_RX_BUSY_POLL |
616 | static inline void mlx4_en_cq_init_lock(struct mlx4_en_cq *cq) | 622 | static inline void mlx4_en_cq_init_lock(struct mlx4_en_cq *cq) |
617 | { | 623 | { |