diff options
author | Ram Amrani <Ram.Amrani@caviumnetworks.com> | 2016-10-01 15:00:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-10-03 23:22:47 -0400 |
commit | abd49676c70793ee0a251bc3d8fe1604f9303210 (patch) | |
tree | e5a5e271c1020d6b07c29bdd35475c4d901c39fb /drivers/net | |
parent | ee8eaea30b1368680f4d2f873bc14e1d7b57d021 (diff) |
qed: Add RoCE ll2 & GSI support
Add the RoCE-specific LL2 logic [as well as GSI support] over
the 'generic' LL2 interface.
Signed-off-by: Ram Amrani <Ram.Amrani@caviumnetworks.com>
Signed-off-by: Yuval Mintz <Yuval.Mintz@caviumnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_hsi.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_ll2.c | 115 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_ll2.h | 29 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_roce.c | 307 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_roce.h | 1 |
6 files changed, 444 insertions, 12 deletions
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index c5a098a2ca2c..653bb5735f0c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h | |||
@@ -437,6 +437,7 @@ struct qed_hwfn { | |||
437 | #endif | 437 | #endif |
438 | 438 | ||
439 | struct z_stream_s *stream; | 439 | struct z_stream_s *stream; |
440 | struct qed_roce_ll2_info *ll2; | ||
440 | }; | 441 | }; |
441 | 442 | ||
442 | struct pci_params { | 443 | struct pci_params { |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 2777d5bb4380..72eee29c677f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h | |||
@@ -727,6 +727,9 @@ struct core_tx_bd_flags { | |||
727 | #define CORE_TX_BD_FLAGS_L4_PROTOCOL_SHIFT 6 | 727 | #define CORE_TX_BD_FLAGS_L4_PROTOCOL_SHIFT 6 |
728 | #define CORE_TX_BD_FLAGS_L4_PSEUDO_CSUM_MODE_MASK 0x1 | 728 | #define CORE_TX_BD_FLAGS_L4_PSEUDO_CSUM_MODE_MASK 0x1 |
729 | #define CORE_TX_BD_FLAGS_L4_PSEUDO_CSUM_MODE_SHIFT 7 | 729 | #define CORE_TX_BD_FLAGS_L4_PSEUDO_CSUM_MODE_SHIFT 7 |
730 | #define CORE_TX_BD_FLAGS_ROCE_FLAV_MASK 0x1 | ||
731 | #define CORE_TX_BD_FLAGS_ROCE_FLAV_SHIFT 12 | ||
732 | |||
730 | }; | 733 | }; |
731 | 734 | ||
732 | struct core_tx_bd { | 735 | struct core_tx_bd { |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c index e0ec8ed2f92c..a6db10717d5c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c | |||
@@ -278,6 +278,7 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle) | |||
278 | struct qed_ll2_tx_packet *p_pkt = NULL; | 278 | struct qed_ll2_tx_packet *p_pkt = NULL; |
279 | struct qed_ll2_info *p_ll2_conn; | 279 | struct qed_ll2_info *p_ll2_conn; |
280 | struct qed_ll2_tx_queue *p_tx; | 280 | struct qed_ll2_tx_queue *p_tx; |
281 | dma_addr_t tx_frag; | ||
281 | 282 | ||
282 | p_ll2_conn = qed_ll2_handle_sanity_inactive(p_hwfn, connection_handle); | 283 | p_ll2_conn = qed_ll2_handle_sanity_inactive(p_hwfn, connection_handle); |
283 | if (!p_ll2_conn) | 284 | if (!p_ll2_conn) |
@@ -297,11 +298,22 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle) | |||
297 | p_tx->cur_completing_packet = *p_pkt; | 298 | p_tx->cur_completing_packet = *p_pkt; |
298 | p_tx->cur_completing_bd_idx = 1; | 299 | p_tx->cur_completing_bd_idx = 1; |
299 | b_last_frag = p_tx->cur_completing_bd_idx == p_pkt->bd_used; | 300 | b_last_frag = p_tx->cur_completing_bd_idx == p_pkt->bd_used; |
301 | tx_frag = p_pkt->bds_set[0].tx_frag; | ||
302 | if (p_ll2_conn->gsi_enable) | ||
303 | qed_ll2b_release_tx_gsi_packet(p_hwfn, | ||
304 | p_ll2_conn->my_id, | ||
305 | p_pkt->cookie, | ||
306 | tx_frag, | ||
307 | b_last_frag, | ||
308 | b_last_packet); | ||
309 | else | ||
310 | qed_ll2b_complete_tx_packet(p_hwfn, | ||
311 | p_ll2_conn->my_id, | ||
312 | p_pkt->cookie, | ||
313 | tx_frag, | ||
314 | b_last_frag, | ||
315 | b_last_packet); | ||
300 | 316 | ||
301 | qed_ll2b_complete_tx_packet(p_hwfn, p_ll2_conn->my_id, | ||
302 | p_pkt->cookie, | ||
303 | p_pkt->bds_set[0].tx_frag, | ||
304 | b_last_frag, b_last_packet); | ||
305 | } | 317 | } |
306 | } | 318 | } |
307 | 319 | ||
@@ -313,6 +325,7 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie) | |||
313 | struct qed_ll2_tx_packet *p_pkt; | 325 | struct qed_ll2_tx_packet *p_pkt; |
314 | bool b_last_frag = false; | 326 | bool b_last_frag = false; |
315 | unsigned long flags; | 327 | unsigned long flags; |
328 | dma_addr_t tx_frag; | ||
316 | int rc = -EINVAL; | 329 | int rc = -EINVAL; |
317 | 330 | ||
318 | spin_lock_irqsave(&p_tx->lock, flags); | 331 | spin_lock_irqsave(&p_tx->lock, flags); |
@@ -353,11 +366,19 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie) | |||
353 | list_add_tail(&p_pkt->list_entry, &p_tx->free_descq); | 366 | list_add_tail(&p_pkt->list_entry, &p_tx->free_descq); |
354 | 367 | ||
355 | spin_unlock_irqrestore(&p_tx->lock, flags); | 368 | spin_unlock_irqrestore(&p_tx->lock, flags); |
356 | qed_ll2b_complete_tx_packet(p_hwfn, | 369 | tx_frag = p_pkt->bds_set[0].tx_frag; |
357 | p_ll2_conn->my_id, | 370 | if (p_ll2_conn->gsi_enable) |
358 | p_pkt->cookie, | 371 | qed_ll2b_complete_tx_gsi_packet(p_hwfn, |
359 | p_pkt->bds_set[0].tx_frag, | 372 | p_ll2_conn->my_id, |
360 | b_last_frag, !num_bds); | 373 | p_pkt->cookie, |
374 | tx_frag, | ||
375 | b_last_frag, !num_bds); | ||
376 | else | ||
377 | qed_ll2b_complete_tx_packet(p_hwfn, | ||
378 | p_ll2_conn->my_id, | ||
379 | p_pkt->cookie, | ||
380 | tx_frag, | ||
381 | b_last_frag, !num_bds); | ||
361 | spin_lock_irqsave(&p_tx->lock, flags); | 382 | spin_lock_irqsave(&p_tx->lock, flags); |
362 | } | 383 | } |
363 | 384 | ||
@@ -368,6 +389,54 @@ out: | |||
368 | return rc; | 389 | return rc; |
369 | } | 390 | } |
370 | 391 | ||
392 | static int | ||
393 | qed_ll2_rxq_completion_gsi(struct qed_hwfn *p_hwfn, | ||
394 | struct qed_ll2_info *p_ll2_info, | ||
395 | union core_rx_cqe_union *p_cqe, | ||
396 | unsigned long lock_flags, bool b_last_cqe) | ||
397 | { | ||
398 | struct qed_ll2_rx_queue *p_rx = &p_ll2_info->rx_queue; | ||
399 | struct qed_ll2_rx_packet *p_pkt = NULL; | ||
400 | u16 packet_length, parse_flags, vlan; | ||
401 | u32 src_mac_addrhi; | ||
402 | u16 src_mac_addrlo; | ||
403 | |||
404 | if (!list_empty(&p_rx->active_descq)) | ||
405 | p_pkt = list_first_entry(&p_rx->active_descq, | ||
406 | struct qed_ll2_rx_packet, list_entry); | ||
407 | if (!p_pkt) { | ||
408 | DP_NOTICE(p_hwfn, | ||
409 | "GSI Rx completion but active_descq is empty\n"); | ||
410 | return -EIO; | ||
411 | } | ||
412 | |||
413 | list_del(&p_pkt->list_entry); | ||
414 | parse_flags = le16_to_cpu(p_cqe->rx_cqe_gsi.parse_flags.flags); | ||
415 | packet_length = le16_to_cpu(p_cqe->rx_cqe_gsi.data_length); | ||
416 | vlan = le16_to_cpu(p_cqe->rx_cqe_gsi.vlan); | ||
417 | src_mac_addrhi = le32_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrhi); | ||
418 | src_mac_addrlo = le16_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrlo); | ||
419 | if (qed_chain_consume(&p_rx->rxq_chain) != p_pkt->rxq_bd) | ||
420 | DP_NOTICE(p_hwfn, | ||
421 | "Mismatch between active_descq and the LL2 Rx chain\n"); | ||
422 | list_add_tail(&p_pkt->list_entry, &p_rx->free_descq); | ||
423 | |||
424 | spin_unlock_irqrestore(&p_rx->lock, lock_flags); | ||
425 | qed_ll2b_complete_rx_gsi_packet(p_hwfn, | ||
426 | p_ll2_info->my_id, | ||
427 | p_pkt->cookie, | ||
428 | p_pkt->rx_buf_addr, | ||
429 | packet_length, | ||
430 | p_cqe->rx_cqe_gsi.data_length_error, | ||
431 | parse_flags, | ||
432 | vlan, | ||
433 | src_mac_addrhi, | ||
434 | src_mac_addrlo, b_last_cqe); | ||
435 | spin_lock_irqsave(&p_rx->lock, lock_flags); | ||
436 | |||
437 | return 0; | ||
438 | } | ||
439 | |||
371 | static int qed_ll2_rxq_completion_reg(struct qed_hwfn *p_hwfn, | 440 | static int qed_ll2_rxq_completion_reg(struct qed_hwfn *p_hwfn, |
372 | struct qed_ll2_info *p_ll2_conn, | 441 | struct qed_ll2_info *p_ll2_conn, |
373 | union core_rx_cqe_union *p_cqe, | 442 | union core_rx_cqe_union *p_cqe, |
@@ -429,6 +498,10 @@ static int qed_ll2_rxq_completion(struct qed_hwfn *p_hwfn, void *cookie) | |||
429 | DP_NOTICE(p_hwfn, "LL2 - unexpected Rx CQE slowpath\n"); | 498 | DP_NOTICE(p_hwfn, "LL2 - unexpected Rx CQE slowpath\n"); |
430 | rc = -EINVAL; | 499 | rc = -EINVAL; |
431 | break; | 500 | break; |
501 | case CORE_RX_CQE_TYPE_GSI_OFFLOAD: | ||
502 | rc = qed_ll2_rxq_completion_gsi(p_hwfn, p_ll2_conn, | ||
503 | cqe, flags, b_last_cqe); | ||
504 | break; | ||
432 | case CORE_RX_CQE_TYPE_REGULAR: | 505 | case CORE_RX_CQE_TYPE_REGULAR: |
433 | rc = qed_ll2_rxq_completion_reg(p_hwfn, p_ll2_conn, | 506 | rc = qed_ll2_rxq_completion_reg(p_hwfn, p_ll2_conn, |
434 | cqe, flags, b_last_cqe); | 507 | cqe, flags, b_last_cqe); |
@@ -527,6 +600,7 @@ static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn, | |||
527 | } | 600 | } |
528 | 601 | ||
529 | p_ramrod->action_on_error.error_type = action_on_error; | 602 | p_ramrod->action_on_error.error_type = action_on_error; |
603 | p_ramrod->gsi_offload_flag = p_ll2_conn->gsi_enable; | ||
530 | return qed_spq_post(p_hwfn, p_ent, NULL); | 604 | return qed_spq_post(p_hwfn, p_ent, NULL); |
531 | } | 605 | } |
532 | 606 | ||
@@ -589,6 +663,7 @@ static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn, | |||
589 | DP_NOTICE(p_hwfn, "Unknown connection type: %d\n", conn_type); | 663 | DP_NOTICE(p_hwfn, "Unknown connection type: %d\n", conn_type); |
590 | } | 664 | } |
591 | 665 | ||
666 | p_ramrod->gsi_offload_flag = p_ll2_conn->gsi_enable; | ||
592 | return qed_spq_post(p_hwfn, p_ent, NULL); | 667 | return qed_spq_post(p_hwfn, p_ent, NULL); |
593 | } | 668 | } |
594 | 669 | ||
@@ -775,6 +850,7 @@ int qed_ll2_acquire_connection(struct qed_hwfn *p_hwfn, | |||
775 | p_ll2_info->tx_dest = p_params->tx_dest; | 850 | p_ll2_info->tx_dest = p_params->tx_dest; |
776 | p_ll2_info->ai_err_packet_too_big = p_params->ai_err_packet_too_big; | 851 | p_ll2_info->ai_err_packet_too_big = p_params->ai_err_packet_too_big; |
777 | p_ll2_info->ai_err_no_buf = p_params->ai_err_no_buf; | 852 | p_ll2_info->ai_err_no_buf = p_params->ai_err_no_buf; |
853 | p_ll2_info->gsi_enable = p_params->gsi_enable; | ||
778 | 854 | ||
779 | rc = qed_ll2_acquire_connection_rx(p_hwfn, p_ll2_info, rx_num_desc); | 855 | rc = qed_ll2_acquire_connection_rx(p_hwfn, p_ll2_info, rx_num_desc); |
780 | if (rc) | 856 | if (rc) |
@@ -1026,6 +1102,7 @@ static void qed_ll2_prepare_tx_packet_set_bd(struct qed_hwfn *p_hwfn, | |||
1026 | u16 vlan, | 1102 | u16 vlan, |
1027 | u8 bd_flags, | 1103 | u8 bd_flags, |
1028 | u16 l4_hdr_offset_w, | 1104 | u16 l4_hdr_offset_w, |
1105 | enum core_roce_flavor_type type, | ||
1029 | dma_addr_t first_frag, | 1106 | dma_addr_t first_frag, |
1030 | u16 first_frag_len) | 1107 | u16 first_frag_len) |
1031 | { | 1108 | { |
@@ -1046,6 +1123,9 @@ static void qed_ll2_prepare_tx_packet_set_bd(struct qed_hwfn *p_hwfn, | |||
1046 | DMA_REGPAIR_LE(start_bd->addr, first_frag); | 1123 | DMA_REGPAIR_LE(start_bd->addr, first_frag); |
1047 | start_bd->nbytes = cpu_to_le16(first_frag_len); | 1124 | start_bd->nbytes = cpu_to_le16(first_frag_len); |
1048 | 1125 | ||
1126 | SET_FIELD(start_bd->bd_flags.as_bitfield, CORE_TX_BD_FLAGS_ROCE_FLAV, | ||
1127 | type); | ||
1128 | |||
1049 | DP_VERBOSE(p_hwfn, | 1129 | DP_VERBOSE(p_hwfn, |
1050 | (NETIF_MSG_TX_QUEUED | QED_MSG_LL2), | 1130 | (NETIF_MSG_TX_QUEUED | QED_MSG_LL2), |
1051 | "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Tx Producer at [0x%04x] - set with a %04x bytes %02x BDs buffer at %08x:%08x\n", | 1131 | "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Tx Producer at [0x%04x] - set with a %04x bytes %02x BDs buffer at %08x:%08x\n", |
@@ -1137,11 +1217,13 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn, | |||
1137 | u16 vlan, | 1217 | u16 vlan, |
1138 | u8 bd_flags, | 1218 | u8 bd_flags, |
1139 | u16 l4_hdr_offset_w, | 1219 | u16 l4_hdr_offset_w, |
1220 | enum qed_ll2_roce_flavor_type qed_roce_flavor, | ||
1140 | dma_addr_t first_frag, | 1221 | dma_addr_t first_frag, |
1141 | u16 first_frag_len, void *cookie, u8 notify_fw) | 1222 | u16 first_frag_len, void *cookie, u8 notify_fw) |
1142 | { | 1223 | { |
1143 | struct qed_ll2_tx_packet *p_curp = NULL; | 1224 | struct qed_ll2_tx_packet *p_curp = NULL; |
1144 | struct qed_ll2_info *p_ll2_conn = NULL; | 1225 | struct qed_ll2_info *p_ll2_conn = NULL; |
1226 | enum core_roce_flavor_type roce_flavor; | ||
1145 | struct qed_ll2_tx_queue *p_tx; | 1227 | struct qed_ll2_tx_queue *p_tx; |
1146 | struct qed_chain *p_tx_chain; | 1228 | struct qed_chain *p_tx_chain; |
1147 | unsigned long flags; | 1229 | unsigned long flags; |
@@ -1174,6 +1256,15 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn, | |||
1174 | goto out; | 1256 | goto out; |
1175 | } | 1257 | } |
1176 | 1258 | ||
1259 | if (qed_roce_flavor == QED_LL2_ROCE) { | ||
1260 | roce_flavor = CORE_ROCE; | ||
1261 | } else if (qed_roce_flavor == QED_LL2_RROCE) { | ||
1262 | roce_flavor = CORE_RROCE; | ||
1263 | } else { | ||
1264 | rc = -EINVAL; | ||
1265 | goto out; | ||
1266 | } | ||
1267 | |||
1177 | /* Prepare packet and BD, and perhaps send a doorbell to FW */ | 1268 | /* Prepare packet and BD, and perhaps send a doorbell to FW */ |
1178 | qed_ll2_prepare_tx_packet_set(p_hwfn, p_tx, p_curp, | 1269 | qed_ll2_prepare_tx_packet_set(p_hwfn, p_tx, p_curp, |
1179 | num_of_bds, first_frag, | 1270 | num_of_bds, first_frag, |
@@ -1181,6 +1272,7 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn, | |||
1181 | qed_ll2_prepare_tx_packet_set_bd(p_hwfn, p_ll2_conn, p_curp, | 1272 | qed_ll2_prepare_tx_packet_set_bd(p_hwfn, p_ll2_conn, p_curp, |
1182 | num_of_bds, CORE_TX_DEST_NW, | 1273 | num_of_bds, CORE_TX_DEST_NW, |
1183 | vlan, bd_flags, l4_hdr_offset_w, | 1274 | vlan, bd_flags, l4_hdr_offset_w, |
1275 | roce_flavor, | ||
1184 | first_frag, first_frag_len); | 1276 | first_frag, first_frag_len); |
1185 | 1277 | ||
1186 | qed_ll2_tx_packet_notify(p_hwfn, p_ll2_conn); | 1278 | qed_ll2_tx_packet_notify(p_hwfn, p_ll2_conn); |
@@ -1476,6 +1568,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params) | |||
1476 | ll2_info.rx_vlan_removal_en = params->rx_vlan_stripping; | 1568 | ll2_info.rx_vlan_removal_en = params->rx_vlan_stripping; |
1477 | ll2_info.tx_tc = 0; | 1569 | ll2_info.tx_tc = 0; |
1478 | ll2_info.tx_dest = CORE_TX_DEST_NW; | 1570 | ll2_info.tx_dest = CORE_TX_DEST_NW; |
1571 | ll2_info.gsi_enable = 1; | ||
1479 | 1572 | ||
1480 | rc = qed_ll2_acquire_connection(QED_LEADING_HWFN(cdev), &ll2_info, | 1573 | rc = qed_ll2_acquire_connection(QED_LEADING_HWFN(cdev), &ll2_info, |
1481 | QED_LL2_RX_SIZE, QED_LL2_TX_SIZE, | 1574 | QED_LL2_RX_SIZE, QED_LL2_TX_SIZE, |
@@ -1625,8 +1718,8 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb) | |||
1625 | rc = qed_ll2_prepare_tx_packet(QED_LEADING_HWFN(cdev), | 1718 | rc = qed_ll2_prepare_tx_packet(QED_LEADING_HWFN(cdev), |
1626 | cdev->ll2->handle, | 1719 | cdev->ll2->handle, |
1627 | 1 + skb_shinfo(skb)->nr_frags, | 1720 | 1 + skb_shinfo(skb)->nr_frags, |
1628 | vlan, flags, 0, mapping, | 1721 | vlan, flags, 0, 0 /* RoCE FLAVOR */, |
1629 | skb->len, skb, 1); | 1722 | mapping, skb->len, skb, 1); |
1630 | if (rc) | 1723 | if (rc) |
1631 | goto err; | 1724 | goto err; |
1632 | 1725 | ||
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.h b/drivers/net/ethernet/qlogic/qed/qed_ll2.h index a037c4845928..80a5dc2d652d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_ll2.h +++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.h | |||
@@ -24,6 +24,12 @@ | |||
24 | 24 | ||
25 | #define QED_MAX_NUM_OF_LL2_CONNECTIONS (4) | 25 | #define QED_MAX_NUM_OF_LL2_CONNECTIONS (4) |
26 | 26 | ||
27 | enum qed_ll2_roce_flavor_type { | ||
28 | QED_LL2_ROCE, | ||
29 | QED_LL2_RROCE, | ||
30 | MAX_QED_LL2_ROCE_FLAVOR_TYPE | ||
31 | }; | ||
32 | |||
27 | enum qed_ll2_conn_type { | 33 | enum qed_ll2_conn_type { |
28 | QED_LL2_TYPE_RESERVED, | 34 | QED_LL2_TYPE_RESERVED, |
29 | QED_LL2_TYPE_ISCSI, | 35 | QED_LL2_TYPE_ISCSI, |
@@ -119,6 +125,7 @@ struct qed_ll2_info { | |||
119 | u8 tx_stats_en; | 125 | u8 tx_stats_en; |
120 | struct qed_ll2_rx_queue rx_queue; | 126 | struct qed_ll2_rx_queue rx_queue; |
121 | struct qed_ll2_tx_queue tx_queue; | 127 | struct qed_ll2_tx_queue tx_queue; |
128 | u8 gsi_enable; | ||
122 | }; | 129 | }; |
123 | 130 | ||
124 | /** | 131 | /** |
@@ -199,6 +206,7 @@ int qed_ll2_prepare_tx_packet(struct qed_hwfn *p_hwfn, | |||
199 | u16 vlan, | 206 | u16 vlan, |
200 | u8 bd_flags, | 207 | u8 bd_flags, |
201 | u16 l4_hdr_offset_w, | 208 | u16 l4_hdr_offset_w, |
209 | enum qed_ll2_roce_flavor_type qed_roce_flavor, | ||
202 | dma_addr_t first_frag, | 210 | dma_addr_t first_frag, |
203 | u16 first_frag_len, void *cookie, u8 notify_fw); | 211 | u16 first_frag_len, void *cookie, u8 notify_fw); |
204 | 212 | ||
@@ -285,5 +293,24 @@ void qed_ll2_setup(struct qed_hwfn *p_hwfn, | |||
285 | */ | 293 | */ |
286 | void qed_ll2_free(struct qed_hwfn *p_hwfn, | 294 | void qed_ll2_free(struct qed_hwfn *p_hwfn, |
287 | struct qed_ll2_info *p_ll2_connections); | 295 | struct qed_ll2_info *p_ll2_connections); |
288 | 296 | void qed_ll2b_complete_rx_gsi_packet(struct qed_hwfn *p_hwfn, | |
297 | u8 connection_handle, | ||
298 | void *cookie, | ||
299 | dma_addr_t rx_buf_addr, | ||
300 | u16 data_length, | ||
301 | u8 data_length_error, | ||
302 | u16 parse_flags, | ||
303 | u16 vlan, | ||
304 | u32 src_mac_addr_hi, | ||
305 | u16 src_mac_addr_lo, bool b_last_packet); | ||
306 | void qed_ll2b_complete_tx_gsi_packet(struct qed_hwfn *p_hwfn, | ||
307 | u8 connection_handle, | ||
308 | void *cookie, | ||
309 | dma_addr_t first_frag_addr, | ||
310 | bool b_last_fragment, bool b_last_packet); | ||
311 | void qed_ll2b_release_tx_gsi_packet(struct qed_hwfn *p_hwfn, | ||
312 | u8 connection_handle, | ||
313 | void *cookie, | ||
314 | dma_addr_t first_frag_addr, | ||
315 | bool b_last_fragment, bool b_last_packet); | ||
289 | #endif | 316 | #endif |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c index 8b4854d3b395..23430059471c 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_roce.c +++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include "qed_reg_addr.h" | 64 | #include "qed_reg_addr.h" |
65 | #include "qed_sp.h" | 65 | #include "qed_sp.h" |
66 | #include "qed_roce.h" | 66 | #include "qed_roce.h" |
67 | #include "qed_ll2.h" | ||
67 | 68 | ||
68 | void qed_async_roce_event(struct qed_hwfn *p_hwfn, | 69 | void qed_async_roce_event(struct qed_hwfn *p_hwfn, |
69 | struct event_ring_entry *p_eqe) | 70 | struct event_ring_entry *p_eqe) |
@@ -2611,6 +2612,306 @@ void qed_rdma_remove_user(void *rdma_cxt, u16 dpi) | |||
2611 | spin_unlock_bh(&p_hwfn->p_rdma_info->lock); | 2612 | spin_unlock_bh(&p_hwfn->p_rdma_info->lock); |
2612 | } | 2613 | } |
2613 | 2614 | ||
2615 | void qed_ll2b_complete_tx_gsi_packet(struct qed_hwfn *p_hwfn, | ||
2616 | u8 connection_handle, | ||
2617 | void *cookie, | ||
2618 | dma_addr_t first_frag_addr, | ||
2619 | bool b_last_fragment, bool b_last_packet) | ||
2620 | { | ||
2621 | struct qed_roce_ll2_packet *packet = cookie; | ||
2622 | struct qed_roce_ll2_info *roce_ll2 = p_hwfn->ll2; | ||
2623 | |||
2624 | roce_ll2->cbs.tx_cb(roce_ll2->cb_cookie, packet); | ||
2625 | } | ||
2626 | |||
2627 | void qed_ll2b_release_tx_gsi_packet(struct qed_hwfn *p_hwfn, | ||
2628 | u8 connection_handle, | ||
2629 | void *cookie, | ||
2630 | dma_addr_t first_frag_addr, | ||
2631 | bool b_last_fragment, bool b_last_packet) | ||
2632 | { | ||
2633 | qed_ll2b_complete_tx_gsi_packet(p_hwfn, connection_handle, | ||
2634 | cookie, first_frag_addr, | ||
2635 | b_last_fragment, b_last_packet); | ||
2636 | } | ||
2637 | |||
2638 | void qed_ll2b_complete_rx_gsi_packet(struct qed_hwfn *p_hwfn, | ||
2639 | u8 connection_handle, | ||
2640 | void *cookie, | ||
2641 | dma_addr_t rx_buf_addr, | ||
2642 | u16 data_length, | ||
2643 | u8 data_length_error, | ||
2644 | u16 parse_flags, | ||
2645 | u16 vlan, | ||
2646 | u32 src_mac_addr_hi, | ||
2647 | u16 src_mac_addr_lo, bool b_last_packet) | ||
2648 | { | ||
2649 | struct qed_roce_ll2_info *roce_ll2 = p_hwfn->ll2; | ||
2650 | struct qed_roce_ll2_rx_params params; | ||
2651 | struct qed_dev *cdev = p_hwfn->cdev; | ||
2652 | struct qed_roce_ll2_packet pkt; | ||
2653 | |||
2654 | DP_VERBOSE(cdev, | ||
2655 | QED_MSG_LL2, | ||
2656 | "roce ll2 rx complete: bus_addr=%p, len=%d, data_len_err=%d\n", | ||
2657 | (void *)(uintptr_t)rx_buf_addr, | ||
2658 | data_length, data_length_error); | ||
2659 | |||
2660 | memset(&pkt, 0, sizeof(pkt)); | ||
2661 | pkt.n_seg = 1; | ||
2662 | pkt.payload[0].baddr = rx_buf_addr; | ||
2663 | pkt.payload[0].len = data_length; | ||
2664 | |||
2665 | memset(¶ms, 0, sizeof(params)); | ||
2666 | params.vlan_id = vlan; | ||
2667 | *((u32 *)¶ms.smac[0]) = ntohl(src_mac_addr_hi); | ||
2668 | *((u16 *)¶ms.smac[4]) = ntohs(src_mac_addr_lo); | ||
2669 | |||
2670 | if (data_length_error) { | ||
2671 | DP_ERR(cdev, | ||
2672 | "roce ll2 rx complete: data length error %d, length=%d\n", | ||
2673 | data_length_error, data_length); | ||
2674 | params.rc = -EINVAL; | ||
2675 | } | ||
2676 | |||
2677 | roce_ll2->cbs.rx_cb(roce_ll2->cb_cookie, &pkt, ¶ms); | ||
2678 | } | ||
2679 | |||
2680 | static int qed_roce_ll2_set_mac_filter(struct qed_dev *cdev, | ||
2681 | u8 *old_mac_address, | ||
2682 | u8 *new_mac_address) | ||
2683 | { | ||
2684 | struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); | ||
2685 | struct qed_ptt *p_ptt; | ||
2686 | int rc = 0; | ||
2687 | |||
2688 | if (!hwfn->ll2 || hwfn->ll2->handle == QED_LL2_UNUSED_HANDLE) { | ||
2689 | DP_ERR(cdev, | ||
2690 | "qed roce mac filter failed - roce_info/ll2 NULL\n"); | ||
2691 | return -EINVAL; | ||
2692 | } | ||
2693 | |||
2694 | p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); | ||
2695 | if (!p_ptt) { | ||
2696 | DP_ERR(cdev, | ||
2697 | "qed roce ll2 mac filter set: failed to acquire PTT\n"); | ||
2698 | return -EINVAL; | ||
2699 | } | ||
2700 | |||
2701 | mutex_lock(&hwfn->ll2->lock); | ||
2702 | if (old_mac_address) | ||
2703 | qed_llh_remove_mac_filter(QED_LEADING_HWFN(cdev), p_ptt, | ||
2704 | old_mac_address); | ||
2705 | if (new_mac_address) | ||
2706 | rc = qed_llh_add_mac_filter(QED_LEADING_HWFN(cdev), p_ptt, | ||
2707 | new_mac_address); | ||
2708 | mutex_unlock(&hwfn->ll2->lock); | ||
2709 | |||
2710 | qed_ptt_release(QED_LEADING_HWFN(cdev), p_ptt); | ||
2711 | |||
2712 | if (rc) | ||
2713 | DP_ERR(cdev, | ||
2714 | "qed roce ll2 mac filter set: failed to add mac filter\n"); | ||
2715 | |||
2716 | return rc; | ||
2717 | } | ||
2718 | |||
2719 | static int qed_roce_ll2_start(struct qed_dev *cdev, | ||
2720 | struct qed_roce_ll2_params *params) | ||
2721 | { | ||
2722 | struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); | ||
2723 | struct qed_roce_ll2_info *roce_ll2; | ||
2724 | struct qed_ll2_info ll2_params; | ||
2725 | int rc; | ||
2726 | |||
2727 | if (!params) { | ||
2728 | DP_ERR(cdev, "qed roce ll2 start: failed due to NULL params\n"); | ||
2729 | return -EINVAL; | ||
2730 | } | ||
2731 | if (!params->cbs.tx_cb || !params->cbs.rx_cb) { | ||
2732 | DP_ERR(cdev, | ||
2733 | "qed roce ll2 start: failed due to NULL tx/rx. tx_cb=%p, rx_cb=%p\n", | ||
2734 | params->cbs.tx_cb, params->cbs.rx_cb); | ||
2735 | return -EINVAL; | ||
2736 | } | ||
2737 | if (!is_valid_ether_addr(params->mac_address)) { | ||
2738 | DP_ERR(cdev, | ||
2739 | "qed roce ll2 start: failed due to invalid Ethernet address %pM\n", | ||
2740 | params->mac_address); | ||
2741 | return -EINVAL; | ||
2742 | } | ||
2743 | |||
2744 | /* Initialize */ | ||
2745 | roce_ll2 = kzalloc(sizeof(*roce_ll2), GFP_ATOMIC); | ||
2746 | if (!roce_ll2) { | ||
2747 | DP_ERR(cdev, "qed roce ll2 start: failed memory allocation\n"); | ||
2748 | return -ENOMEM; | ||
2749 | } | ||
2750 | memset(roce_ll2, 0, sizeof(*roce_ll2)); | ||
2751 | roce_ll2->handle = QED_LL2_UNUSED_HANDLE; | ||
2752 | roce_ll2->cbs = params->cbs; | ||
2753 | roce_ll2->cb_cookie = params->cb_cookie; | ||
2754 | mutex_init(&roce_ll2->lock); | ||
2755 | |||
2756 | memset(&ll2_params, 0, sizeof(ll2_params)); | ||
2757 | ll2_params.conn_type = QED_LL2_TYPE_ROCE; | ||
2758 | ll2_params.mtu = params->mtu; | ||
2759 | ll2_params.rx_drop_ttl0_flg = true; | ||
2760 | ll2_params.rx_vlan_removal_en = false; | ||
2761 | ll2_params.tx_dest = CORE_TX_DEST_NW; | ||
2762 | ll2_params.ai_err_packet_too_big = LL2_DROP_PACKET; | ||
2763 | ll2_params.ai_err_no_buf = LL2_DROP_PACKET; | ||
2764 | ll2_params.gsi_enable = true; | ||
2765 | |||
2766 | rc = qed_ll2_acquire_connection(QED_LEADING_HWFN(cdev), &ll2_params, | ||
2767 | params->max_rx_buffers, | ||
2768 | params->max_tx_buffers, | ||
2769 | &roce_ll2->handle); | ||
2770 | if (rc) { | ||
2771 | DP_ERR(cdev, | ||
2772 | "qed roce ll2 start: failed to acquire LL2 connection (rc=%d)\n", | ||
2773 | rc); | ||
2774 | goto err; | ||
2775 | } | ||
2776 | |||
2777 | rc = qed_ll2_establish_connection(QED_LEADING_HWFN(cdev), | ||
2778 | roce_ll2->handle); | ||
2779 | if (rc) { | ||
2780 | DP_ERR(cdev, | ||
2781 | "qed roce ll2 start: failed to establish LL2 connection (rc=%d)\n", | ||
2782 | rc); | ||
2783 | goto err1; | ||
2784 | } | ||
2785 | |||
2786 | hwfn->ll2 = roce_ll2; | ||
2787 | |||
2788 | rc = qed_roce_ll2_set_mac_filter(cdev, NULL, params->mac_address); | ||
2789 | if (rc) { | ||
2790 | hwfn->ll2 = NULL; | ||
2791 | goto err2; | ||
2792 | } | ||
2793 | ether_addr_copy(roce_ll2->mac_address, params->mac_address); | ||
2794 | |||
2795 | return 0; | ||
2796 | |||
2797 | err2: | ||
2798 | qed_ll2_terminate_connection(QED_LEADING_HWFN(cdev), roce_ll2->handle); | ||
2799 | err1: | ||
2800 | qed_ll2_release_connection(QED_LEADING_HWFN(cdev), roce_ll2->handle); | ||
2801 | err: | ||
2802 | kfree(roce_ll2); | ||
2803 | return rc; | ||
2804 | } | ||
2805 | |||
2806 | static int qed_roce_ll2_stop(struct qed_dev *cdev) | ||
2807 | { | ||
2808 | struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); | ||
2809 | struct qed_roce_ll2_info *roce_ll2 = hwfn->ll2; | ||
2810 | int rc; | ||
2811 | |||
2812 | if (!cdev) { | ||
2813 | DP_ERR(cdev, "qed roce ll2 stop: invalid cdev\n"); | ||
2814 | return -EINVAL; | ||
2815 | } | ||
2816 | |||
2817 | if (roce_ll2->handle == QED_LL2_UNUSED_HANDLE) { | ||
2818 | DP_ERR(cdev, "qed roce ll2 stop: cannot stop an unused LL2\n"); | ||
2819 | return -EINVAL; | ||
2820 | } | ||
2821 | |||
2822 | /* remove LL2 MAC address filter */ | ||
2823 | rc = qed_roce_ll2_set_mac_filter(cdev, roce_ll2->mac_address, NULL); | ||
2824 | eth_zero_addr(roce_ll2->mac_address); | ||
2825 | |||
2826 | rc = qed_ll2_terminate_connection(QED_LEADING_HWFN(cdev), | ||
2827 | roce_ll2->handle); | ||
2828 | if (rc) | ||
2829 | DP_ERR(cdev, | ||
2830 | "qed roce ll2 stop: failed to terminate LL2 connection (rc=%d)\n", | ||
2831 | rc); | ||
2832 | |||
2833 | qed_ll2_release_connection(QED_LEADING_HWFN(cdev), roce_ll2->handle); | ||
2834 | |||
2835 | roce_ll2->handle = QED_LL2_UNUSED_HANDLE; | ||
2836 | |||
2837 | kfree(roce_ll2); | ||
2838 | |||
2839 | return rc; | ||
2840 | } | ||
2841 | |||
2842 | static int qed_roce_ll2_tx(struct qed_dev *cdev, | ||
2843 | struct qed_roce_ll2_packet *pkt, | ||
2844 | struct qed_roce_ll2_tx_params *params) | ||
2845 | { | ||
2846 | struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); | ||
2847 | struct qed_roce_ll2_info *roce_ll2 = hwfn->ll2; | ||
2848 | enum qed_ll2_roce_flavor_type qed_roce_flavor; | ||
2849 | u8 flags = 0; | ||
2850 | int rc; | ||
2851 | int i; | ||
2852 | |||
2853 | if (!cdev || !pkt || !params) { | ||
2854 | DP_ERR(cdev, | ||
2855 | "roce ll2 tx: failed tx because one of the following is NULL - drv=%p, pkt=%p, params=%p\n", | ||
2856 | cdev, pkt, params); | ||
2857 | return -EINVAL; | ||
2858 | } | ||
2859 | |||
2860 | qed_roce_flavor = (pkt->roce_mode == ROCE_V1) ? QED_LL2_ROCE | ||
2861 | : QED_LL2_RROCE; | ||
2862 | |||
2863 | if (pkt->roce_mode == ROCE_V2_IPV4) | ||
2864 | flags |= BIT(CORE_TX_BD_FLAGS_IP_CSUM_SHIFT); | ||
2865 | |||
2866 | /* Tx header */ | ||
2867 | rc = qed_ll2_prepare_tx_packet(QED_LEADING_HWFN(cdev), roce_ll2->handle, | ||
2868 | 1 + pkt->n_seg, 0, flags, 0, | ||
2869 | qed_roce_flavor, pkt->header.baddr, | ||
2870 | pkt->header.len, pkt, 1); | ||
2871 | if (rc) { | ||
2872 | DP_ERR(cdev, "roce ll2 tx: header failed (rc=%d)\n", rc); | ||
2873 | return QED_ROCE_TX_HEAD_FAILURE; | ||
2874 | } | ||
2875 | |||
2876 | /* Tx payload */ | ||
2877 | for (i = 0; i < pkt->n_seg; i++) { | ||
2878 | rc = qed_ll2_set_fragment_of_tx_packet(QED_LEADING_HWFN(cdev), | ||
2879 | roce_ll2->handle, | ||
2880 | pkt->payload[i].baddr, | ||
2881 | pkt->payload[i].len); | ||
2882 | if (rc) { | ||
2883 | /* If failed not much to do here, partial packet has | ||
2884 | * been posted * we can't free memory, will need to wait | ||
2885 | * for completion | ||
2886 | */ | ||
2887 | DP_ERR(cdev, | ||
2888 | "roce ll2 tx: payload failed (rc=%d)\n", rc); | ||
2889 | return QED_ROCE_TX_FRAG_FAILURE; | ||
2890 | } | ||
2891 | } | ||
2892 | |||
2893 | return 0; | ||
2894 | } | ||
2895 | |||
2896 | static int qed_roce_ll2_post_rx_buffer(struct qed_dev *cdev, | ||
2897 | struct qed_roce_ll2_buffer *buf, | ||
2898 | u64 cookie, u8 notify_fw) | ||
2899 | { | ||
2900 | return qed_ll2_post_rx_buffer(QED_LEADING_HWFN(cdev), | ||
2901 | QED_LEADING_HWFN(cdev)->ll2->handle, | ||
2902 | buf->baddr, buf->len, | ||
2903 | (void *)(uintptr_t)cookie, notify_fw); | ||
2904 | } | ||
2905 | |||
2906 | static int qed_roce_ll2_stats(struct qed_dev *cdev, struct qed_ll2_stats *stats) | ||
2907 | { | ||
2908 | struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); | ||
2909 | struct qed_roce_ll2_info *roce_ll2 = hwfn->ll2; | ||
2910 | |||
2911 | return qed_ll2_get_stats(QED_LEADING_HWFN(cdev), | ||
2912 | roce_ll2->handle, stats); | ||
2913 | } | ||
2914 | |||
2614 | static const struct qed_rdma_ops qed_rdma_ops_pass = { | 2915 | static const struct qed_rdma_ops qed_rdma_ops_pass = { |
2615 | .common = &qed_common_ops_pass, | 2916 | .common = &qed_common_ops_pass, |
2616 | .fill_dev_info = &qed_fill_rdma_dev_info, | 2917 | .fill_dev_info = &qed_fill_rdma_dev_info, |
@@ -2638,6 +2939,12 @@ static const struct qed_rdma_ops qed_rdma_ops_pass = { | |||
2638 | .rdma_free_tid = &qed_rdma_free_tid, | 2939 | .rdma_free_tid = &qed_rdma_free_tid, |
2639 | .rdma_register_tid = &qed_rdma_register_tid, | 2940 | .rdma_register_tid = &qed_rdma_register_tid, |
2640 | .rdma_deregister_tid = &qed_rdma_deregister_tid, | 2941 | .rdma_deregister_tid = &qed_rdma_deregister_tid, |
2942 | .roce_ll2_start = &qed_roce_ll2_start, | ||
2943 | .roce_ll2_stop = &qed_roce_ll2_stop, | ||
2944 | .roce_ll2_tx = &qed_roce_ll2_tx, | ||
2945 | .roce_ll2_post_rx_buffer = &qed_roce_ll2_post_rx_buffer, | ||
2946 | .roce_ll2_set_mac_filter = &qed_roce_ll2_set_mac_filter, | ||
2947 | .roce_ll2_stats = &qed_roce_ll2_stats, | ||
2641 | }; | 2948 | }; |
2642 | 2949 | ||
2643 | const struct qed_rdma_ops *qed_get_rdma_ops() | 2950 | const struct qed_rdma_ops *qed_get_rdma_ops() |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.h b/drivers/net/ethernet/qlogic/qed/qed_roce.h index b8ddda456101..2f091e8a0f40 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_roce.h +++ b/drivers/net/ethernet/qlogic/qed/qed_roce.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "qed.h" | 42 | #include "qed.h" |
43 | #include "qed_dev_api.h" | 43 | #include "qed_dev_api.h" |
44 | #include "qed_hsi.h" | 44 | #include "qed_hsi.h" |
45 | #include "qed_ll2.h" | ||
45 | 46 | ||
46 | #define QED_RDMA_MAX_FMR (RDMA_MAX_TIDS) | 47 | #define QED_RDMA_MAX_FMR (RDMA_MAX_TIDS) |
47 | #define QED_RDMA_MAX_P_KEY (1) | 48 | #define QED_RDMA_MAX_P_KEY (1) |