2823 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)2/* QLogic qed NIC Driver3 * Copyright (c) 2015-2017 QLogic Corporation4 * Copyright (c) 2019-2020 Marvell International Ltd.5 */6 7#include <linux/types.h>8#include <asm/byteorder.h>9#include <linux/dma-mapping.h>10#include <linux/if_vlan.h>11#include <linux/kernel.h>12#include <linux/pci.h>13#include <linux/slab.h>14#include <linux/stddef.h>15#include <linux/workqueue.h>16#include <net/ipv6.h>17#include <linux/bitops.h>18#include <linux/delay.h>19#include <linux/errno.h>20#include <linux/etherdevice.h>21#include <linux/io.h>22#include <linux/list.h>23#include <linux/mutex.h>24#include <linux/spinlock.h>25#include <linux/string.h>26#include <linux/qed/qed_ll2_if.h>27#include "qed.h"28#include "qed_cxt.h"29#include "qed_dev_api.h"30#include "qed_hsi.h"31#include "qed_iro_hsi.h"32#include "qed_hw.h"33#include "qed_int.h"34#include "qed_ll2.h"35#include "qed_mcp.h"36#include "qed_ooo.h"37#include "qed_reg_addr.h"38#include "qed_sp.h"39#include "qed_rdma.h"40 41#define QED_LL2_RX_REGISTERED(ll2) ((ll2)->rx_queue.b_cb_registered)42#define QED_LL2_TX_REGISTERED(ll2) ((ll2)->tx_queue.b_cb_registered)43 44#define QED_LL2_TX_SIZE (256)45#define QED_LL2_RX_SIZE (4096)46 47#define QED_LL2_INVALID_STATS_ID 0xff48 49struct qed_cb_ll2_info {50 int rx_cnt;51 u32 rx_size;52 u8 handle;53 54 /* Lock protecting LL2 buffer lists in sleepless context */55 spinlock_t lock;56 struct list_head list;57 58 const struct qed_ll2_cb_ops *cbs;59 void *cb_cookie;60};61 62struct qed_ll2_buffer {63 struct list_head list;64 void *data;65 dma_addr_t phys_addr;66};67 68static u8 qed_ll2_handle_to_stats_id(struct qed_hwfn *p_hwfn,69 u8 ll2_queue_type, u8 qid)70{71 u8 stats_id;72 73 /* For legacy (RAM based) queues, the stats_id will be set as the74 * queue_id. Otherwise (context based queue), it will be set to75 * the "abs_pf_id" offset from the end of the RAM based queue IDs.76 * If the final value exceeds the total counters amount, return77 * INVALID value to indicate that the stats for this connection should78 * be disabled.79 */80 if (ll2_queue_type == QED_LL2_RX_TYPE_LEGACY)81 stats_id = qid;82 else83 stats_id = MAX_NUM_LL2_RX_RAM_QUEUES + p_hwfn->abs_pf_id;84 85 if (stats_id < MAX_NUM_LL2_TX_STATS_COUNTERS)86 return stats_id;87 else88 return QED_LL2_INVALID_STATS_ID;89}90 91static void qed_ll2b_complete_tx_packet(void *cxt,92 u8 connection_handle,93 void *cookie,94 dma_addr_t first_frag_addr,95 bool b_last_fragment,96 bool b_last_packet)97{98 struct qed_hwfn *p_hwfn = cxt;99 struct qed_dev *cdev = p_hwfn->cdev;100 struct sk_buff *skb = cookie;101 102 /* All we need to do is release the mapping */103 dma_unmap_single(&p_hwfn->cdev->pdev->dev, first_frag_addr,104 skb_headlen(skb), DMA_TO_DEVICE);105 106 if (cdev->ll2->cbs && cdev->ll2->cbs->tx_cb)107 cdev->ll2->cbs->tx_cb(cdev->ll2->cb_cookie, skb,108 b_last_fragment);109 110 dev_kfree_skb_any(skb);111}112 113static int qed_ll2_alloc_buffer(struct qed_dev *cdev,114 u8 **data, dma_addr_t *phys_addr)115{116 size_t size = cdev->ll2->rx_size + NET_SKB_PAD +117 SKB_DATA_ALIGN(sizeof(struct skb_shared_info));118 119 *data = kmalloc(size, GFP_ATOMIC);120 if (!(*data)) {121 DP_INFO(cdev, "Failed to allocate LL2 buffer data\n");122 return -ENOMEM;123 }124 125 *phys_addr = dma_map_single(&cdev->pdev->dev,126 ((*data) + NET_SKB_PAD),127 cdev->ll2->rx_size, DMA_FROM_DEVICE);128 if (dma_mapping_error(&cdev->pdev->dev, *phys_addr)) {129 DP_INFO(cdev, "Failed to map LL2 buffer data\n");130 kfree((*data));131 return -ENOMEM;132 }133 134 return 0;135}136 137static int qed_ll2_dealloc_buffer(struct qed_dev *cdev,138 struct qed_ll2_buffer *buffer)139{140 spin_lock_bh(&cdev->ll2->lock);141 142 dma_unmap_single(&cdev->pdev->dev, buffer->phys_addr,143 cdev->ll2->rx_size, DMA_FROM_DEVICE);144 kfree(buffer->data);145 list_del(&buffer->list);146 147 cdev->ll2->rx_cnt--;148 if (!cdev->ll2->rx_cnt)149 DP_INFO(cdev, "All LL2 entries were removed\n");150 151 spin_unlock_bh(&cdev->ll2->lock);152 153 return 0;154}155 156static void qed_ll2_kill_buffers(struct qed_dev *cdev)157{158 struct qed_ll2_buffer *buffer, *tmp_buffer;159 160 list_for_each_entry_safe(buffer, tmp_buffer, &cdev->ll2->list, list)161 qed_ll2_dealloc_buffer(cdev, buffer);162}163 164static void qed_ll2b_complete_rx_packet(void *cxt,165 struct qed_ll2_comp_rx_data *data)166{167 struct qed_hwfn *p_hwfn = cxt;168 struct qed_ll2_buffer *buffer = data->cookie;169 struct qed_dev *cdev = p_hwfn->cdev;170 dma_addr_t new_phys_addr;171 struct sk_buff *skb;172 bool reuse = false;173 int rc = -EINVAL;174 u8 *new_data;175 176 DP_VERBOSE(p_hwfn,177 (NETIF_MSG_RX_STATUS | QED_MSG_STORAGE | NETIF_MSG_PKTDATA),178 "Got an LL2 Rx completion: [Buffer at phys 0x%llx, offset 0x%02x] Length 0x%04x Parse_flags 0x%04x vlan 0x%04x Opaque data [0x%08x:0x%08x]\n",179 (u64)data->rx_buf_addr,180 data->u.placement_offset,181 data->length.packet_length,182 data->parse_flags,183 data->vlan, data->opaque_data_0, data->opaque_data_1);184 185 if ((cdev->dp_module & NETIF_MSG_PKTDATA) && buffer->data) {186 print_hex_dump(KERN_INFO, "",187 DUMP_PREFIX_OFFSET, 16, 1,188 buffer->data, data->length.packet_length, false);189 }190 191 /* Determine if data is valid */192 if (data->length.packet_length < ETH_HLEN)193 reuse = true;194 195 /* Allocate a replacement for buffer; Reuse upon failure */196 if (!reuse)197 rc = qed_ll2_alloc_buffer(p_hwfn->cdev, &new_data,198 &new_phys_addr);199 200 /* If need to reuse or there's no replacement buffer, repost this */201 if (rc)202 goto out_post;203 dma_unmap_single(&cdev->pdev->dev, buffer->phys_addr,204 cdev->ll2->rx_size, DMA_FROM_DEVICE);205 206 skb = slab_build_skb(buffer->data);207 if (!skb) {208 DP_INFO(cdev, "Failed to build SKB\n");209 kfree(buffer->data);210 goto out_post1;211 }212 213 data->u.placement_offset += NET_SKB_PAD;214 skb_reserve(skb, data->u.placement_offset);215 skb_put(skb, data->length.packet_length);216 skb_checksum_none_assert(skb);217 218 /* Get parital ethernet information instead of eth_type_trans(),219 * Since we don't have an associated net_device.220 */221 skb_reset_mac_header(skb);222 skb->protocol = eth_hdr(skb)->h_proto;223 224 /* Pass SKB onward */225 if (cdev->ll2->cbs && cdev->ll2->cbs->rx_cb) {226 if (data->vlan)227 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),228 data->vlan);229 cdev->ll2->cbs->rx_cb(cdev->ll2->cb_cookie, skb,230 data->opaque_data_0,231 data->opaque_data_1);232 } else {233 DP_VERBOSE(p_hwfn, (NETIF_MSG_RX_STATUS | NETIF_MSG_PKTDATA |234 QED_MSG_LL2 | QED_MSG_STORAGE),235 "Dropping the packet\n");236 kfree(buffer->data);237 }238 239out_post1:240 /* Update Buffer information and update FW producer */241 buffer->data = new_data;242 buffer->phys_addr = new_phys_addr;243 244out_post:245 rc = qed_ll2_post_rx_buffer(p_hwfn, cdev->ll2->handle,246 buffer->phys_addr, 0, buffer, 1);247 if (rc)248 qed_ll2_dealloc_buffer(cdev, buffer);249}250 251static struct qed_ll2_info *__qed_ll2_handle_sanity(struct qed_hwfn *p_hwfn,252 u8 connection_handle,253 bool b_lock,254 bool b_only_active)255{256 struct qed_ll2_info *p_ll2_conn, *p_ret = NULL;257 258 if (connection_handle >= QED_MAX_NUM_OF_LL2_CONNECTIONS)259 return NULL;260 261 if (!p_hwfn->p_ll2_info)262 return NULL;263 264 p_ll2_conn = &p_hwfn->p_ll2_info[connection_handle];265 266 if (b_only_active) {267 if (b_lock)268 mutex_lock(&p_ll2_conn->mutex);269 if (p_ll2_conn->b_active)270 p_ret = p_ll2_conn;271 if (b_lock)272 mutex_unlock(&p_ll2_conn->mutex);273 } else {274 p_ret = p_ll2_conn;275 }276 277 return p_ret;278}279 280static struct qed_ll2_info *qed_ll2_handle_sanity(struct qed_hwfn *p_hwfn,281 u8 connection_handle)282{283 return __qed_ll2_handle_sanity(p_hwfn, connection_handle, false, true);284}285 286static struct qed_ll2_info *qed_ll2_handle_sanity_lock(struct qed_hwfn *p_hwfn,287 u8 connection_handle)288{289 return __qed_ll2_handle_sanity(p_hwfn, connection_handle, true, true);290}291 292static struct qed_ll2_info *qed_ll2_handle_sanity_inactive(struct qed_hwfn293 *p_hwfn,294 u8 connection_handle)295{296 return __qed_ll2_handle_sanity(p_hwfn, connection_handle, false, false);297}298 299static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)300{301 bool b_last_packet = false, b_last_frag = false;302 struct qed_ll2_tx_packet *p_pkt = NULL;303 struct qed_ll2_info *p_ll2_conn;304 struct qed_ll2_tx_queue *p_tx;305 unsigned long flags = 0;306 dma_addr_t tx_frag;307 308 p_ll2_conn = qed_ll2_handle_sanity_inactive(p_hwfn, connection_handle);309 if (!p_ll2_conn)310 return;311 312 p_tx = &p_ll2_conn->tx_queue;313 314 spin_lock_irqsave(&p_tx->lock, flags);315 while (!list_empty(&p_tx->active_descq)) {316 p_pkt = list_first_entry(&p_tx->active_descq,317 struct qed_ll2_tx_packet, list_entry);318 if (!p_pkt)319 break;320 321 list_del(&p_pkt->list_entry);322 b_last_packet = list_empty(&p_tx->active_descq);323 list_add_tail(&p_pkt->list_entry, &p_tx->free_descq);324 spin_unlock_irqrestore(&p_tx->lock, flags);325 if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_OOO) {326 struct qed_ooo_buffer *p_buffer;327 328 p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;329 qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info,330 p_buffer);331 } else {332 p_tx->cur_completing_packet = *p_pkt;333 p_tx->cur_completing_bd_idx = 1;334 b_last_frag =335 p_tx->cur_completing_bd_idx == p_pkt->bd_used;336 tx_frag = p_pkt->bds_set[0].tx_frag;337 p_ll2_conn->cbs.tx_release_cb(p_ll2_conn->cbs.cookie,338 p_ll2_conn->my_id,339 p_pkt->cookie,340 tx_frag,341 b_last_frag,342 b_last_packet);343 }344 spin_lock_irqsave(&p_tx->lock, flags);345 }346 spin_unlock_irqrestore(&p_tx->lock, flags);347}348 349static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)350{351 struct qed_ll2_info *p_ll2_conn = p_cookie;352 struct qed_ll2_tx_queue *p_tx = &p_ll2_conn->tx_queue;353 u16 new_idx = 0, num_bds = 0, num_bds_in_packet = 0;354 struct qed_ll2_tx_packet *p_pkt;355 bool b_last_frag = false;356 unsigned long flags;357 int rc = -EINVAL;358 359 if (!p_ll2_conn)360 return rc;361 362 spin_lock_irqsave(&p_tx->lock, flags);363 if (p_tx->b_completing_packet) {364 rc = -EBUSY;365 goto out;366 }367 368 new_idx = le16_to_cpu(*p_tx->p_fw_cons);369 num_bds = ((s16)new_idx - (s16)p_tx->bds_idx);370 while (num_bds) {371 if (list_empty(&p_tx->active_descq))372 goto out;373 374 p_pkt = list_first_entry(&p_tx->active_descq,375 struct qed_ll2_tx_packet, list_entry);376 if (!p_pkt)377 goto out;378 379 p_tx->b_completing_packet = true;380 p_tx->cur_completing_packet = *p_pkt;381 num_bds_in_packet = p_pkt->bd_used;382 list_del(&p_pkt->list_entry);383 384 if (unlikely(num_bds < num_bds_in_packet)) {385 DP_NOTICE(p_hwfn,386 "Rest of BDs does not cover whole packet\n");387 goto out;388 }389 390 num_bds -= num_bds_in_packet;391 p_tx->bds_idx += num_bds_in_packet;392 while (num_bds_in_packet--)393 qed_chain_consume(&p_tx->txq_chain);394 395 p_tx->cur_completing_bd_idx = 1;396 b_last_frag = p_tx->cur_completing_bd_idx == p_pkt->bd_used;397 list_add_tail(&p_pkt->list_entry, &p_tx->free_descq);398 399 spin_unlock_irqrestore(&p_tx->lock, flags);400 401 p_ll2_conn->cbs.tx_comp_cb(p_ll2_conn->cbs.cookie,402 p_ll2_conn->my_id,403 p_pkt->cookie,404 p_pkt->bds_set[0].tx_frag,405 b_last_frag, !num_bds);406 407 spin_lock_irqsave(&p_tx->lock, flags);408 }409 410 p_tx->b_completing_packet = false;411 rc = 0;412out:413 spin_unlock_irqrestore(&p_tx->lock, flags);414 return rc;415}416 417static void qed_ll2_rxq_parse_gsi(struct qed_hwfn *p_hwfn,418 union core_rx_cqe_union *p_cqe,419 struct qed_ll2_comp_rx_data *data)420{421 data->parse_flags = le16_to_cpu(p_cqe->rx_cqe_gsi.parse_flags.flags);422 data->length.data_length = le16_to_cpu(p_cqe->rx_cqe_gsi.data_length);423 data->vlan = le16_to_cpu(p_cqe->rx_cqe_gsi.vlan);424 data->opaque_data_0 = le32_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrhi);425 data->opaque_data_1 = le16_to_cpu(p_cqe->rx_cqe_gsi.src_mac_addrlo);426 data->u.data_length_error = p_cqe->rx_cqe_gsi.data_length_error;427 data->qp_id = le16_to_cpu(p_cqe->rx_cqe_gsi.qp_id);428 429 data->src_qp = le32_to_cpu(p_cqe->rx_cqe_gsi.src_qp);430}431 432static void qed_ll2_rxq_parse_reg(struct qed_hwfn *p_hwfn,433 union core_rx_cqe_union *p_cqe,434 struct qed_ll2_comp_rx_data *data)435{436 data->parse_flags = le16_to_cpu(p_cqe->rx_cqe_fp.parse_flags.flags);437 data->err_flags = le16_to_cpu(p_cqe->rx_cqe_fp.err_flags.flags);438 data->length.packet_length =439 le16_to_cpu(p_cqe->rx_cqe_fp.packet_length);440 data->vlan = le16_to_cpu(p_cqe->rx_cqe_fp.vlan);441 data->opaque_data_0 = le32_to_cpu(p_cqe->rx_cqe_fp.opaque_data.data[0]);442 data->opaque_data_1 = le32_to_cpu(p_cqe->rx_cqe_fp.opaque_data.data[1]);443 data->u.placement_offset = p_cqe->rx_cqe_fp.placement_offset;444}445 446static int447qed_ll2_handle_slowpath(struct qed_hwfn *p_hwfn,448 struct qed_ll2_info *p_ll2_conn,449 union core_rx_cqe_union *p_cqe,450 unsigned long *p_lock_flags)451{452 struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;453 struct core_rx_slow_path_cqe *sp_cqe;454 455 sp_cqe = &p_cqe->rx_cqe_sp;456 if (sp_cqe->ramrod_cmd_id != CORE_RAMROD_RX_QUEUE_FLUSH) {457 DP_NOTICE(p_hwfn,458 "LL2 - unexpected Rx CQE slowpath ramrod_cmd_id:%d\n",459 sp_cqe->ramrod_cmd_id);460 return -EINVAL;461 }462 463 if (!p_ll2_conn->cbs.slowpath_cb) {464 DP_NOTICE(p_hwfn,465 "LL2 - received RX_QUEUE_FLUSH but no callback was provided\n");466 return -EINVAL;467 }468 469 spin_unlock_irqrestore(&p_rx->lock, *p_lock_flags);470 471 p_ll2_conn->cbs.slowpath_cb(p_ll2_conn->cbs.cookie,472 p_ll2_conn->my_id,473 le32_to_cpu(sp_cqe->opaque_data.data[0]),474 le32_to_cpu(sp_cqe->opaque_data.data[1]));475 476 spin_lock_irqsave(&p_rx->lock, *p_lock_flags);477 478 return 0;479}480 481static int482qed_ll2_rxq_handle_completion(struct qed_hwfn *p_hwfn,483 struct qed_ll2_info *p_ll2_conn,484 union core_rx_cqe_union *p_cqe,485 unsigned long *p_lock_flags, bool b_last_cqe)486{487 struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;488 struct qed_ll2_rx_packet *p_pkt = NULL;489 struct qed_ll2_comp_rx_data data;490 491 if (!list_empty(&p_rx->active_descq))492 p_pkt = list_first_entry(&p_rx->active_descq,493 struct qed_ll2_rx_packet, list_entry);494 if (unlikely(!p_pkt)) {495 DP_NOTICE(p_hwfn,496 "[%d] LL2 Rx completion but active_descq is empty\n",497 p_ll2_conn->input.conn_type);498 499 return -EIO;500 }501 list_del(&p_pkt->list_entry);502 503 if (p_cqe->rx_cqe_sp.type == CORE_RX_CQE_TYPE_REGULAR)504 qed_ll2_rxq_parse_reg(p_hwfn, p_cqe, &data);505 else506 qed_ll2_rxq_parse_gsi(p_hwfn, p_cqe, &data);507 if (unlikely(qed_chain_consume(&p_rx->rxq_chain) != p_pkt->rxq_bd))508 DP_NOTICE(p_hwfn,509 "Mismatch between active_descq and the LL2 Rx chain\n");510 511 list_add_tail(&p_pkt->list_entry, &p_rx->free_descq);512 513 data.connection_handle = p_ll2_conn->my_id;514 data.cookie = p_pkt->cookie;515 data.rx_buf_addr = p_pkt->rx_buf_addr;516 data.b_last_packet = b_last_cqe;517 518 spin_unlock_irqrestore(&p_rx->lock, *p_lock_flags);519 p_ll2_conn->cbs.rx_comp_cb(p_ll2_conn->cbs.cookie, &data);520 521 spin_lock_irqsave(&p_rx->lock, *p_lock_flags);522 523 return 0;524}525 526static int qed_ll2_rxq_completion(struct qed_hwfn *p_hwfn, void *cookie)527{528 struct qed_ll2_info *p_ll2_conn = (struct qed_ll2_info *)cookie;529 struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;530 union core_rx_cqe_union *cqe = NULL;531 u16 cq_new_idx = 0, cq_old_idx = 0;532 unsigned long flags = 0;533 int rc = 0;534 535 if (!p_ll2_conn)536 return rc;537 538 spin_lock_irqsave(&p_rx->lock, flags);539 540 if (!QED_LL2_RX_REGISTERED(p_ll2_conn)) {541 spin_unlock_irqrestore(&p_rx->lock, flags);542 return 0;543 }544 545 cq_new_idx = le16_to_cpu(*p_rx->p_fw_cons);546 cq_old_idx = qed_chain_get_cons_idx(&p_rx->rcq_chain);547 548 while (cq_new_idx != cq_old_idx) {549 bool b_last_cqe = (cq_new_idx == cq_old_idx);550 551 cqe =552 (union core_rx_cqe_union *)553 qed_chain_consume(&p_rx->rcq_chain);554 cq_old_idx = qed_chain_get_cons_idx(&p_rx->rcq_chain);555 556 DP_VERBOSE(p_hwfn,557 QED_MSG_LL2,558 "LL2 [sw. cons %04x, fw. at %04x] - Got Packet of type %02x\n",559 cq_old_idx, cq_new_idx, cqe->rx_cqe_sp.type);560 561 switch (cqe->rx_cqe_sp.type) {562 case CORE_RX_CQE_TYPE_SLOW_PATH:563 rc = qed_ll2_handle_slowpath(p_hwfn, p_ll2_conn,564 cqe, &flags);565 break;566 case CORE_RX_CQE_TYPE_GSI_OFFLOAD:567 case CORE_RX_CQE_TYPE_REGULAR:568 rc = qed_ll2_rxq_handle_completion(p_hwfn, p_ll2_conn,569 cqe, &flags,570 b_last_cqe);571 break;572 default:573 rc = -EIO;574 }575 }576 577 spin_unlock_irqrestore(&p_rx->lock, flags);578 return rc;579}580 581static void qed_ll2_rxq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)582{583 struct qed_ll2_info *p_ll2_conn = NULL;584 struct qed_ll2_rx_packet *p_pkt = NULL;585 struct qed_ll2_rx_queue *p_rx;586 unsigned long flags = 0;587 588 p_ll2_conn = qed_ll2_handle_sanity_inactive(p_hwfn, connection_handle);589 if (!p_ll2_conn)590 return;591 592 p_rx = &p_ll2_conn->rx_queue;593 594 spin_lock_irqsave(&p_rx->lock, flags);595 while (!list_empty(&p_rx->active_descq)) {596 p_pkt = list_first_entry(&p_rx->active_descq,597 struct qed_ll2_rx_packet, list_entry);598 if (!p_pkt)599 break;600 list_move_tail(&p_pkt->list_entry, &p_rx->free_descq);601 spin_unlock_irqrestore(&p_rx->lock, flags);602 603 if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_OOO) {604 struct qed_ooo_buffer *p_buffer;605 606 p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;607 qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info,608 p_buffer);609 } else {610 dma_addr_t rx_buf_addr = p_pkt->rx_buf_addr;611 void *cookie = p_pkt->cookie;612 bool b_last;613 614 b_last = list_empty(&p_rx->active_descq);615 p_ll2_conn->cbs.rx_release_cb(p_ll2_conn->cbs.cookie,616 p_ll2_conn->my_id,617 cookie,618 rx_buf_addr, b_last);619 }620 spin_lock_irqsave(&p_rx->lock, flags);621 }622 spin_unlock_irqrestore(&p_rx->lock, flags);623}624 625static bool626qed_ll2_lb_rxq_handler_slowpath(struct qed_hwfn *p_hwfn,627 struct core_rx_slow_path_cqe *p_cqe)628{629 struct ooo_opaque *ooo_opq;630 u32 cid;631 632 if (p_cqe->ramrod_cmd_id != CORE_RAMROD_RX_QUEUE_FLUSH)633 return false;634 635 ooo_opq = (struct ooo_opaque *)&p_cqe->opaque_data;636 if (ooo_opq->ooo_opcode != TCP_EVENT_DELETE_ISLES)637 return false;638 639 /* Need to make a flush */640 cid = le32_to_cpu(ooo_opq->cid);641 qed_ooo_release_connection_isles(p_hwfn, p_hwfn->p_ooo_info, cid);642 643 return true;644}645 646static int qed_ll2_lb_rxq_handler(struct qed_hwfn *p_hwfn,647 struct qed_ll2_info *p_ll2_conn)648{649 struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;650 u16 packet_length = 0, parse_flags = 0, vlan = 0;651 struct qed_ll2_rx_packet *p_pkt = NULL;652 union core_rx_cqe_union *cqe = NULL;653 u16 cq_new_idx = 0, cq_old_idx = 0;654 struct qed_ooo_buffer *p_buffer;655 struct ooo_opaque *ooo_opq;656 u8 placement_offset = 0;657 u8 cqe_type;658 u32 cid;659 660 cq_new_idx = le16_to_cpu(*p_rx->p_fw_cons);661 cq_old_idx = qed_chain_get_cons_idx(&p_rx->rcq_chain);662 if (cq_new_idx == cq_old_idx)663 return 0;664 665 while (cq_new_idx != cq_old_idx) {666 struct core_rx_fast_path_cqe *p_cqe_fp;667 668 cqe = qed_chain_consume(&p_rx->rcq_chain);669 cq_old_idx = qed_chain_get_cons_idx(&p_rx->rcq_chain);670 cqe_type = cqe->rx_cqe_sp.type;671 672 if (cqe_type == CORE_RX_CQE_TYPE_SLOW_PATH)673 if (qed_ll2_lb_rxq_handler_slowpath(p_hwfn,674 &cqe->rx_cqe_sp))675 continue;676 677 if (unlikely(cqe_type != CORE_RX_CQE_TYPE_REGULAR)) {678 DP_NOTICE(p_hwfn,679 "Got a non-regular LB LL2 completion [type 0x%02x]\n",680 cqe_type);681 return -EINVAL;682 }683 p_cqe_fp = &cqe->rx_cqe_fp;684 685 placement_offset = p_cqe_fp->placement_offset;686 parse_flags = le16_to_cpu(p_cqe_fp->parse_flags.flags);687 packet_length = le16_to_cpu(p_cqe_fp->packet_length);688 vlan = le16_to_cpu(p_cqe_fp->vlan);689 ooo_opq = (struct ooo_opaque *)&p_cqe_fp->opaque_data;690 qed_ooo_save_history_entry(p_hwfn, p_hwfn->p_ooo_info, ooo_opq);691 cid = le32_to_cpu(ooo_opq->cid);692 693 /* Process delete isle first */694 if (ooo_opq->drop_size)695 qed_ooo_delete_isles(p_hwfn, p_hwfn->p_ooo_info, cid,696 ooo_opq->drop_isle,697 ooo_opq->drop_size);698 699 if (ooo_opq->ooo_opcode == TCP_EVENT_NOP)700 continue;701 702 /* Now process create/add/join isles */703 if (unlikely(list_empty(&p_rx->active_descq))) {704 DP_NOTICE(p_hwfn,705 "LL2 OOO RX chain has no submitted buffers\n"706 );707 return -EIO;708 }709 710 p_pkt = list_first_entry(&p_rx->active_descq,711 struct qed_ll2_rx_packet, list_entry);712 713 if (likely(ooo_opq->ooo_opcode == TCP_EVENT_ADD_NEW_ISLE ||714 ooo_opq->ooo_opcode == TCP_EVENT_ADD_ISLE_RIGHT ||715 ooo_opq->ooo_opcode == TCP_EVENT_ADD_ISLE_LEFT ||716 ooo_opq->ooo_opcode == TCP_EVENT_ADD_PEN ||717 ooo_opq->ooo_opcode == TCP_EVENT_JOIN)) {718 if (unlikely(!p_pkt)) {719 DP_NOTICE(p_hwfn,720 "LL2 OOO RX packet is not valid\n");721 return -EIO;722 }723 list_del(&p_pkt->list_entry);724 p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;725 p_buffer->packet_length = packet_length;726 p_buffer->parse_flags = parse_flags;727 p_buffer->vlan = vlan;728 p_buffer->placement_offset = placement_offset;729 qed_chain_consume(&p_rx->rxq_chain);730 list_add_tail(&p_pkt->list_entry, &p_rx->free_descq);731 732 switch (ooo_opq->ooo_opcode) {733 case TCP_EVENT_ADD_NEW_ISLE:734 qed_ooo_add_new_isle(p_hwfn,735 p_hwfn->p_ooo_info,736 cid,737 ooo_opq->ooo_isle,738 p_buffer);739 break;740 case TCP_EVENT_ADD_ISLE_RIGHT:741 qed_ooo_add_new_buffer(p_hwfn,742 p_hwfn->p_ooo_info,743 cid,744 ooo_opq->ooo_isle,745 p_buffer,746 QED_OOO_RIGHT_BUF);747 break;748 case TCP_EVENT_ADD_ISLE_LEFT:749 qed_ooo_add_new_buffer(p_hwfn,750 p_hwfn->p_ooo_info,751 cid,752 ooo_opq->ooo_isle,753 p_buffer,754 QED_OOO_LEFT_BUF);755 break;756 case TCP_EVENT_JOIN:757 qed_ooo_add_new_buffer(p_hwfn,758 p_hwfn->p_ooo_info,759 cid,760 ooo_opq->ooo_isle + 1,761 p_buffer,762 QED_OOO_LEFT_BUF);763 qed_ooo_join_isles(p_hwfn,764 p_hwfn->p_ooo_info,765 cid, ooo_opq->ooo_isle);766 break;767 case TCP_EVENT_ADD_PEN:768 qed_ooo_put_ready_buffer(p_hwfn,769 p_hwfn->p_ooo_info,770 p_buffer, true);771 break;772 }773 } else {774 DP_NOTICE(p_hwfn,775 "Unexpected event (%d) TX OOO completion\n",776 ooo_opq->ooo_opcode);777 }778 }779 780 return 0;781}782 783static void784qed_ooo_submit_tx_buffers(struct qed_hwfn *p_hwfn,785 struct qed_ll2_info *p_ll2_conn)786{787 struct qed_ll2_tx_pkt_info tx_pkt;788 struct qed_ooo_buffer *p_buffer;789 u16 l4_hdr_offset_w;790 dma_addr_t first_frag;791 u8 bd_flags;792 int rc;793 794 /* Submit Tx buffers here */795 while ((p_buffer = qed_ooo_get_ready_buffer(p_hwfn,796 p_hwfn->p_ooo_info))) {797 l4_hdr_offset_w = 0;798 bd_flags = 0;799 800 first_frag = p_buffer->rx_buffer_phys_addr +801 p_buffer->placement_offset;802 SET_FIELD(bd_flags, CORE_TX_BD_DATA_FORCE_VLAN_MODE, 1);803 SET_FIELD(bd_flags, CORE_TX_BD_DATA_L4_PROTOCOL, 1);804 805 memset(&tx_pkt, 0, sizeof(tx_pkt));806 tx_pkt.num_of_bds = 1;807 tx_pkt.vlan = p_buffer->vlan;808 tx_pkt.bd_flags = bd_flags;809 tx_pkt.l4_hdr_offset_w = l4_hdr_offset_w;810 switch (p_ll2_conn->tx_dest) {811 case CORE_TX_DEST_NW:812 tx_pkt.tx_dest = QED_LL2_TX_DEST_NW;813 break;814 case CORE_TX_DEST_LB:815 tx_pkt.tx_dest = QED_LL2_TX_DEST_LB;816 break;817 case CORE_TX_DEST_DROP:818 default:819 tx_pkt.tx_dest = QED_LL2_TX_DEST_DROP;820 break;821 }822 tx_pkt.first_frag = first_frag;823 tx_pkt.first_frag_len = p_buffer->packet_length;824 tx_pkt.cookie = p_buffer;825 826 rc = qed_ll2_prepare_tx_packet(p_hwfn, p_ll2_conn->my_id,827 &tx_pkt, true);828 if (rc) {829 qed_ooo_put_ready_buffer(p_hwfn, p_hwfn->p_ooo_info,830 p_buffer, false);831 break;832 }833 }834}835 836static void837qed_ooo_submit_rx_buffers(struct qed_hwfn *p_hwfn,838 struct qed_ll2_info *p_ll2_conn)839{840 struct qed_ooo_buffer *p_buffer;841 int rc;842 843 while ((p_buffer = qed_ooo_get_free_buffer(p_hwfn,844 p_hwfn->p_ooo_info))) {845 rc = qed_ll2_post_rx_buffer(p_hwfn,846 p_ll2_conn->my_id,847 p_buffer->rx_buffer_phys_addr,848 0, p_buffer, true);849 if (rc) {850 qed_ooo_put_free_buffer(p_hwfn,851 p_hwfn->p_ooo_info, p_buffer);852 break;853 }854 }855}856 857static int qed_ll2_lb_rxq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)858{859 struct qed_ll2_info *p_ll2_conn = (struct qed_ll2_info *)p_cookie;860 int rc;861 862 if (!p_ll2_conn)863 return 0;864 865 if (!QED_LL2_RX_REGISTERED(p_ll2_conn))866 return 0;867 868 rc = qed_ll2_lb_rxq_handler(p_hwfn, p_ll2_conn);869 if (rc)870 return rc;871 872 qed_ooo_submit_rx_buffers(p_hwfn, p_ll2_conn);873 qed_ooo_submit_tx_buffers(p_hwfn, p_ll2_conn);874 875 return 0;876}877 878static int qed_ll2_lb_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)879{880 struct qed_ll2_info *p_ll2_conn = (struct qed_ll2_info *)p_cookie;881 struct qed_ll2_tx_queue *p_tx = &p_ll2_conn->tx_queue;882 struct qed_ll2_tx_packet *p_pkt = NULL;883 struct qed_ooo_buffer *p_buffer;884 bool b_dont_submit_rx = false;885 u16 new_idx = 0, num_bds = 0;886 int rc;887 888 if (unlikely(!p_ll2_conn))889 return 0;890 891 if (unlikely(!QED_LL2_TX_REGISTERED(p_ll2_conn)))892 return 0;893 894 new_idx = le16_to_cpu(*p_tx->p_fw_cons);895 num_bds = ((s16)new_idx - (s16)p_tx->bds_idx);896 897 if (unlikely(!num_bds))898 return 0;899 900 while (num_bds) {901 if (list_empty(&p_tx->active_descq))902 return -EINVAL;903 904 p_pkt = list_first_entry(&p_tx->active_descq,905 struct qed_ll2_tx_packet, list_entry);906 if (unlikely(!p_pkt))907 return -EINVAL;908 909 if (unlikely(p_pkt->bd_used != 1)) {910 DP_NOTICE(p_hwfn,911 "Unexpectedly many BDs(%d) in TX OOO completion\n",912 p_pkt->bd_used);913 return -EINVAL;914 }915 916 list_del(&p_pkt->list_entry);917 918 num_bds--;919 p_tx->bds_idx++;920 qed_chain_consume(&p_tx->txq_chain);921 922 p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;923 list_add_tail(&p_pkt->list_entry, &p_tx->free_descq);924 925 if (b_dont_submit_rx) {926 qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info,927 p_buffer);928 continue;929 }930 931 rc = qed_ll2_post_rx_buffer(p_hwfn, p_ll2_conn->my_id,932 p_buffer->rx_buffer_phys_addr, 0,933 p_buffer, true);934 if (rc != 0) {935 qed_ooo_put_free_buffer(p_hwfn,936 p_hwfn->p_ooo_info, p_buffer);937 b_dont_submit_rx = true;938 }939 }940 941 qed_ooo_submit_tx_buffers(p_hwfn, p_ll2_conn);942 943 return 0;944}945 946static void qed_ll2_stop_ooo(struct qed_hwfn *p_hwfn)947{948 u8 *handle = &p_hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id;949 950 DP_VERBOSE(p_hwfn, (QED_MSG_STORAGE | QED_MSG_LL2),951 "Stopping LL2 OOO queue [%02x]\n", *handle);952 953 qed_ll2_terminate_connection(p_hwfn, *handle);954 qed_ll2_release_connection(p_hwfn, *handle);955 *handle = QED_LL2_UNUSED_HANDLE;956}957 958static int qed_sp_ll2_rx_queue_start(struct qed_hwfn *p_hwfn,959 struct qed_ll2_info *p_ll2_conn,960 u8 action_on_error)961{962 enum qed_ll2_conn_type conn_type = p_ll2_conn->input.conn_type;963 struct qed_ll2_rx_queue *p_rx = &p_ll2_conn->rx_queue;964 struct core_rx_start_ramrod_data *p_ramrod = NULL;965 struct qed_spq_entry *p_ent = NULL;966 struct qed_sp_init_data init_data;967 u16 cqe_pbl_size;968 int rc = 0;969 970 /* Get SPQ entry */971 memset(&init_data, 0, sizeof(init_data));972 init_data.cid = p_ll2_conn->cid;973 init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;974 init_data.comp_mode = QED_SPQ_MODE_EBLOCK;975 976 rc = qed_sp_init_request(p_hwfn, &p_ent,977 CORE_RAMROD_RX_QUEUE_START,978 PROTOCOLID_CORE, &init_data);979 if (rc)980 return rc;981 982 p_ramrod = &p_ent->ramrod.core_rx_queue_start;983 memset(p_ramrod, 0, sizeof(*p_ramrod));984 p_ramrod->sb_id = cpu_to_le16(qed_int_get_sp_sb_id(p_hwfn));985 p_ramrod->sb_index = p_rx->rx_sb_index;986 p_ramrod->complete_event_flg = 1;987 988 p_ramrod->mtu = cpu_to_le16(p_ll2_conn->input.mtu);989 DMA_REGPAIR_LE(p_ramrod->bd_base, p_rx->rxq_chain.p_phys_addr);990 cqe_pbl_size = (u16)qed_chain_get_page_cnt(&p_rx->rcq_chain);991 p_ramrod->num_of_pbl_pages = cpu_to_le16(cqe_pbl_size);992 DMA_REGPAIR_LE(p_ramrod->cqe_pbl_addr,993 qed_chain_get_pbl_phys(&p_rx->rcq_chain));994 995 p_ramrod->drop_ttl0_flg = p_ll2_conn->input.rx_drop_ttl0_flg;996 p_ramrod->inner_vlan_stripping_en =997 p_ll2_conn->input.rx_vlan_removal_en;998 999 if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits) &&1000 p_ll2_conn->input.conn_type == QED_LL2_TYPE_FCOE)1001 p_ramrod->report_outer_vlan = 1;1002 p_ramrod->queue_id = p_ll2_conn->queue_id;1003 p_ramrod->main_func_queue = p_ll2_conn->main_func_queue ? 1 : 0;1004 1005 if (test_bit(QED_MF_LL2_NON_UNICAST, &p_hwfn->cdev->mf_bits) &&1006 p_ramrod->main_func_queue && conn_type != QED_LL2_TYPE_ROCE &&1007 conn_type != QED_LL2_TYPE_IWARP &&1008 (!QED_IS_NVMETCP_PERSONALITY(p_hwfn))) {1009 p_ramrod->mf_si_bcast_accept_all = 1;1010 p_ramrod->mf_si_mcast_accept_all = 1;1011 } else {1012 p_ramrod->mf_si_bcast_accept_all = 0;1013 p_ramrod->mf_si_mcast_accept_all = 0;1014 }1015 1016 p_ramrod->action_on_error.error_type = action_on_error;1017 p_ramrod->gsi_offload_flag = p_ll2_conn->input.gsi_enable;1018 p_ramrod->zero_prod_flg = 1;1019 1020 return qed_spq_post(p_hwfn, p_ent, NULL);1021}1022 1023static int qed_sp_ll2_tx_queue_start(struct qed_hwfn *p_hwfn,1024 struct qed_ll2_info *p_ll2_conn)1025{1026 enum qed_ll2_conn_type conn_type = p_ll2_conn->input.conn_type;1027 struct qed_ll2_tx_queue *p_tx = &p_ll2_conn->tx_queue;1028 struct core_tx_start_ramrod_data *p_ramrod = NULL;1029 struct qed_spq_entry *p_ent = NULL;1030 struct qed_sp_init_data init_data;1031 u16 pq_id = 0, pbl_size;1032 int rc = -EINVAL;1033 1034 if (!QED_LL2_TX_REGISTERED(p_ll2_conn))1035 return 0;1036 1037 if (likely(p_ll2_conn->input.conn_type == QED_LL2_TYPE_OOO))1038 p_ll2_conn->tx_stats_en = 0;1039 else1040 p_ll2_conn->tx_stats_en = 1;1041 1042 /* Get SPQ entry */1043 memset(&init_data, 0, sizeof(init_data));1044 init_data.cid = p_ll2_conn->cid;1045 init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;1046 init_data.comp_mode = QED_SPQ_MODE_EBLOCK;1047 1048 rc = qed_sp_init_request(p_hwfn, &p_ent,1049 CORE_RAMROD_TX_QUEUE_START,1050 PROTOCOLID_CORE, &init_data);1051 if (rc)1052 return rc;1053 1054 p_ramrod = &p_ent->ramrod.core_tx_queue_start;1055 1056 p_ramrod->sb_id = cpu_to_le16(qed_int_get_sp_sb_id(p_hwfn));1057 p_ramrod->sb_index = p_tx->tx_sb_index;1058 p_ramrod->mtu = cpu_to_le16(p_ll2_conn->input.mtu);1059 p_ramrod->stats_en = p_ll2_conn->tx_stats_en;1060 p_ramrod->stats_id = p_ll2_conn->tx_stats_id;1061 1062 DMA_REGPAIR_LE(p_ramrod->pbl_base_addr,1063 qed_chain_get_pbl_phys(&p_tx->txq_chain));1064 pbl_size = qed_chain_get_page_cnt(&p_tx->txq_chain);1065 p_ramrod->pbl_size = cpu_to_le16(pbl_size);1066 1067 switch (p_ll2_conn->input.tx_tc) {1068 case PURE_LB_TC:1069 pq_id = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_LB);1070 break;1071 case PKT_LB_TC:1072 pq_id = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OOO);1073 break;1074 default:1075 pq_id = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OFLD);1076 break;1077 }1078 1079 p_ramrod->qm_pq_id = cpu_to_le16(pq_id);1080 1081 switch (conn_type) {1082 case QED_LL2_TYPE_FCOE:1083 p_ramrod->conn_type = PROTOCOLID_FCOE;1084 break;1085 case QED_LL2_TYPE_TCP_ULP:1086 p_ramrod->conn_type = PROTOCOLID_TCP_ULP;1087 break;1088 case QED_LL2_TYPE_ROCE:1089 p_ramrod->conn_type = PROTOCOLID_ROCE;1090 break;1091 case QED_LL2_TYPE_IWARP:1092 p_ramrod->conn_type = PROTOCOLID_IWARP;1093 break;1094 case QED_LL2_TYPE_OOO:1095 if (p_hwfn->hw_info.personality == QED_PCI_ISCSI ||1096 p_hwfn->hw_info.personality == QED_PCI_NVMETCP)1097 p_ramrod->conn_type = PROTOCOLID_TCP_ULP;1098 else1099 p_ramrod->conn_type = PROTOCOLID_IWARP;1100 break;1101 default:1102 p_ramrod->conn_type = PROTOCOLID_ETH;1103 DP_NOTICE(p_hwfn, "Unknown connection type: %d\n", conn_type);1104 }1105 1106 p_ramrod->gsi_offload_flag = p_ll2_conn->input.gsi_enable;1107 1108 rc = qed_spq_post(p_hwfn, p_ent, NULL);1109 if (rc)1110 return rc;1111 1112 rc = qed_db_recovery_add(p_hwfn->cdev, p_tx->doorbell_addr,1113 &p_tx->db_msg, DB_REC_WIDTH_32B,1114 DB_REC_KERNEL);1115 return rc;1116}1117 1118static int qed_sp_ll2_rx_queue_stop(struct qed_hwfn *p_hwfn,1119 struct qed_ll2_info *p_ll2_conn)1120{1121 struct core_rx_stop_ramrod_data *p_ramrod = NULL;1122 struct qed_spq_entry *p_ent = NULL;1123 struct qed_sp_init_data init_data;1124 int rc = -EINVAL;1125 1126 /* Get SPQ entry */1127 memset(&init_data, 0, sizeof(init_data));1128 init_data.cid = p_ll2_conn->cid;1129 init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;1130 init_data.comp_mode = QED_SPQ_MODE_EBLOCK;1131 1132 rc = qed_sp_init_request(p_hwfn, &p_ent,1133 CORE_RAMROD_RX_QUEUE_STOP,1134 PROTOCOLID_CORE, &init_data);1135 if (rc)1136 return rc;1137 1138 p_ramrod = &p_ent->ramrod.core_rx_queue_stop;1139 1140 p_ramrod->complete_event_flg = 1;1141 p_ramrod->queue_id = p_ll2_conn->queue_id;1142 1143 return qed_spq_post(p_hwfn, p_ent, NULL);1144}1145 1146static int qed_sp_ll2_tx_queue_stop(struct qed_hwfn *p_hwfn,1147 struct qed_ll2_info *p_ll2_conn)1148{1149 struct qed_ll2_tx_queue *p_tx = &p_ll2_conn->tx_queue;1150 struct qed_spq_entry *p_ent = NULL;1151 struct qed_sp_init_data init_data;1152 int rc = -EINVAL;1153 1154 qed_db_recovery_del(p_hwfn->cdev, p_tx->doorbell_addr, &p_tx->db_msg);1155 1156 /* Get SPQ entry */1157 memset(&init_data, 0, sizeof(init_data));1158 init_data.cid = p_ll2_conn->cid;1159 init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;1160 init_data.comp_mode = QED_SPQ_MODE_EBLOCK;1161 1162 rc = qed_sp_init_request(p_hwfn, &p_ent,1163 CORE_RAMROD_TX_QUEUE_STOP,1164 PROTOCOLID_CORE, &init_data);1165 if (rc)1166 return rc;1167 1168 return qed_spq_post(p_hwfn, p_ent, NULL);1169}1170 1171static int1172qed_ll2_acquire_connection_rx(struct qed_hwfn *p_hwfn,1173 struct qed_ll2_info *p_ll2_info)1174{1175 struct qed_chain_init_params params = {1176 .intended_use = QED_CHAIN_USE_TO_CONSUME_PRODUCE,1177 .cnt_type = QED_CHAIN_CNT_TYPE_U16,1178 .num_elems = p_ll2_info->input.rx_num_desc,1179 };1180 struct qed_dev *cdev = p_hwfn->cdev;1181 struct qed_ll2_rx_packet *p_descq;1182 u32 capacity;1183 int rc = 0;1184 1185 if (!p_ll2_info->input.rx_num_desc)1186 goto out;1187 1188 params.mode = QED_CHAIN_MODE_NEXT_PTR;1189 params.elem_size = sizeof(struct core_rx_bd);1190 1191 rc = qed_chain_alloc(cdev, &p_ll2_info->rx_queue.rxq_chain, ¶ms);1192 if (rc) {1193 DP_NOTICE(p_hwfn, "Failed to allocate ll2 rxq chain\n");1194 goto out;1195 }1196 1197 capacity = qed_chain_get_capacity(&p_ll2_info->rx_queue.rxq_chain);1198 p_descq = kcalloc(capacity, sizeof(struct qed_ll2_rx_packet),1199 GFP_KERNEL);1200 if (!p_descq) {1201 rc = -ENOMEM;1202 DP_NOTICE(p_hwfn, "Failed to allocate ll2 Rx desc\n");1203 goto out;1204 }1205 p_ll2_info->rx_queue.descq_array = p_descq;1206 1207 params.mode = QED_CHAIN_MODE_PBL;1208 params.elem_size = sizeof(struct core_rx_fast_path_cqe);1209 1210 rc = qed_chain_alloc(cdev, &p_ll2_info->rx_queue.rcq_chain, ¶ms);1211 if (rc) {1212 DP_NOTICE(p_hwfn, "Failed to allocate ll2 rcq chain\n");1213 goto out;1214 }1215 1216 DP_VERBOSE(p_hwfn, QED_MSG_LL2,1217 "Allocated LL2 Rxq [Type %08x] with 0x%08x buffers\n",1218 p_ll2_info->input.conn_type, p_ll2_info->input.rx_num_desc);1219 1220out:1221 return rc;1222}1223 1224static int qed_ll2_acquire_connection_tx(struct qed_hwfn *p_hwfn,1225 struct qed_ll2_info *p_ll2_info)1226{1227 struct qed_chain_init_params params = {1228 .mode = QED_CHAIN_MODE_PBL,1229 .intended_use = QED_CHAIN_USE_TO_CONSUME_PRODUCE,1230 .cnt_type = QED_CHAIN_CNT_TYPE_U16,1231 .num_elems = p_ll2_info->input.tx_num_desc,1232 .elem_size = sizeof(struct core_tx_bd),1233 };1234 struct qed_ll2_tx_packet *p_descq;1235 size_t desc_size;1236 u32 capacity;1237 int rc = 0;1238 1239 if (!p_ll2_info->input.tx_num_desc)1240 goto out;1241 1242 rc = qed_chain_alloc(p_hwfn->cdev, &p_ll2_info->tx_queue.txq_chain,1243 ¶ms);1244 if (rc)1245 goto out;1246 1247 capacity = qed_chain_get_capacity(&p_ll2_info->tx_queue.txq_chain);1248 /* All bds_set elements are flexibily added. */1249 desc_size = struct_size(p_descq, bds_set,1250 p_ll2_info->input.tx_max_bds_per_packet);1251 1252 p_descq = kcalloc(capacity, desc_size, GFP_KERNEL);1253 if (!p_descq) {1254 rc = -ENOMEM;1255 goto out;1256 }1257 p_ll2_info->tx_queue.descq_mem = p_descq;1258 1259 DP_VERBOSE(p_hwfn, QED_MSG_LL2,1260 "Allocated LL2 Txq [Type %08x] with 0x%08x buffers\n",1261 p_ll2_info->input.conn_type, p_ll2_info->input.tx_num_desc);1262 1263out:1264 if (rc)1265 DP_NOTICE(p_hwfn,1266 "Can't allocate memory for Tx LL2 with 0x%08x buffers\n",1267 p_ll2_info->input.tx_num_desc);1268 return rc;1269}1270 1271static int1272qed_ll2_acquire_connection_ooo(struct qed_hwfn *p_hwfn,1273 struct qed_ll2_info *p_ll2_info, u16 mtu)1274{1275 struct qed_ooo_buffer *p_buf = NULL;1276 void *p_virt;1277 u16 buf_idx;1278 int rc = 0;1279 1280 if (p_ll2_info->input.conn_type != QED_LL2_TYPE_OOO)1281 return rc;1282 1283 /* Correct number of requested OOO buffers if needed */1284 if (!p_ll2_info->input.rx_num_ooo_buffers) {1285 u16 num_desc = p_ll2_info->input.rx_num_desc;1286 1287 if (!num_desc)1288 return -EINVAL;1289 p_ll2_info->input.rx_num_ooo_buffers = num_desc * 2;1290 }1291 1292 for (buf_idx = 0; buf_idx < p_ll2_info->input.rx_num_ooo_buffers;1293 buf_idx++) {1294 p_buf = kzalloc(sizeof(*p_buf), GFP_KERNEL);1295 if (!p_buf) {1296 rc = -ENOMEM;1297 goto out;1298 }1299 1300 p_buf->rx_buffer_size = mtu + 26 + ETH_CACHE_LINE_SIZE;1301 p_buf->rx_buffer_size = (p_buf->rx_buffer_size +1302 ETH_CACHE_LINE_SIZE - 1) &1303 ~(ETH_CACHE_LINE_SIZE - 1);1304 p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,1305 p_buf->rx_buffer_size,1306 &p_buf->rx_buffer_phys_addr,1307 GFP_KERNEL);1308 if (!p_virt) {1309 kfree(p_buf);1310 rc = -ENOMEM;1311 goto out;1312 }1313 1314 p_buf->rx_buffer_virt_addr = p_virt;1315 qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info, p_buf);1316 }1317 1318 DP_VERBOSE(p_hwfn, QED_MSG_LL2,1319 "Allocated [%04x] LL2 OOO buffers [each of size 0x%08x]\n",1320 p_ll2_info->input.rx_num_ooo_buffers, p_buf->rx_buffer_size);1321 1322out:1323 return rc;1324}1325 1326static int1327qed_ll2_set_cbs(struct qed_ll2_info *p_ll2_info, const struct qed_ll2_cbs *cbs)1328{1329 if (!cbs || (!cbs->rx_comp_cb ||1330 !cbs->rx_release_cb ||1331 !cbs->tx_comp_cb || !cbs->tx_release_cb || !cbs->cookie))1332 return -EINVAL;1333 1334 p_ll2_info->cbs.rx_comp_cb = cbs->rx_comp_cb;1335 p_ll2_info->cbs.rx_release_cb = cbs->rx_release_cb;1336 p_ll2_info->cbs.tx_comp_cb = cbs->tx_comp_cb;1337 p_ll2_info->cbs.tx_release_cb = cbs->tx_release_cb;1338 p_ll2_info->cbs.slowpath_cb = cbs->slowpath_cb;1339 p_ll2_info->cbs.cookie = cbs->cookie;1340 1341 return 0;1342}1343 1344static void _qed_ll2_calc_allowed_conns(struct qed_hwfn *p_hwfn,1345 struct qed_ll2_acquire_data *data,1346 u8 *start_idx, u8 *last_idx)1347{1348 /* LL2 queues handles will be split as follows:1349 * First will be the legacy queues, and then the ctx based.1350 */1351 if (data->input.rx_conn_type == QED_LL2_RX_TYPE_LEGACY) {1352 *start_idx = QED_LL2_LEGACY_CONN_BASE_PF;1353 *last_idx = *start_idx +1354 QED_MAX_NUM_OF_LEGACY_LL2_CONNS_PF;1355 } else {1356 /* QED_LL2_RX_TYPE_CTX */1357 *start_idx = QED_LL2_CTX_CONN_BASE_PF;1358 *last_idx = *start_idx +1359 QED_MAX_NUM_OF_CTX_LL2_CONNS_PF;1360 }1361}1362 1363static enum core_error_handle1364qed_ll2_get_error_choice(enum qed_ll2_error_handle err)1365{1366 switch (err) {1367 case QED_LL2_DROP_PACKET:1368 return LL2_DROP_PACKET;1369 case QED_LL2_DO_NOTHING:1370 return LL2_DO_NOTHING;1371 case QED_LL2_ASSERT:1372 return LL2_ASSERT;1373 default:1374 return LL2_DO_NOTHING;1375 }1376}1377 1378int qed_ll2_acquire_connection(void *cxt, struct qed_ll2_acquire_data *data)1379{1380 struct qed_hwfn *p_hwfn = cxt;1381 qed_int_comp_cb_t comp_rx_cb, comp_tx_cb;1382 struct qed_ll2_info *p_ll2_info = NULL;1383 u8 i, first_idx, last_idx, *p_tx_max;1384 int rc;1385 1386 if (!data->p_connection_handle || !p_hwfn->p_ll2_info)1387 return -EINVAL;1388 1389 _qed_ll2_calc_allowed_conns(p_hwfn, data, &first_idx, &last_idx);1390 1391 /* Find a free connection to be used */1392 for (i = first_idx; i < last_idx; i++) {1393 mutex_lock(&p_hwfn->p_ll2_info[i].mutex);1394 if (p_hwfn->p_ll2_info[i].b_active) {1395 mutex_unlock(&p_hwfn->p_ll2_info[i].mutex);1396 continue;1397 }1398 1399 p_hwfn->p_ll2_info[i].b_active = true;1400 p_ll2_info = &p_hwfn->p_ll2_info[i];1401 mutex_unlock(&p_hwfn->p_ll2_info[i].mutex);1402 break;1403 }1404 if (!p_ll2_info)1405 return -EBUSY;1406 1407 memcpy(&p_ll2_info->input, &data->input, sizeof(p_ll2_info->input));1408 1409 switch (data->input.tx_dest) {1410 case QED_LL2_TX_DEST_NW:1411 p_ll2_info->tx_dest = CORE_TX_DEST_NW;1412 break;1413 case QED_LL2_TX_DEST_LB:1414 p_ll2_info->tx_dest = CORE_TX_DEST_LB;1415 break;1416 case QED_LL2_TX_DEST_DROP:1417 p_ll2_info->tx_dest = CORE_TX_DEST_DROP;1418 break;1419 default:1420 return -EINVAL;1421 }1422 1423 if (data->input.conn_type == QED_LL2_TYPE_OOO ||1424 data->input.secondary_queue)1425 p_ll2_info->main_func_queue = false;1426 else1427 p_ll2_info->main_func_queue = true;1428 1429 /* Correct maximum number of Tx BDs */1430 p_tx_max = &p_ll2_info->input.tx_max_bds_per_packet;1431 if (*p_tx_max == 0)1432 *p_tx_max = CORE_LL2_TX_MAX_BDS_PER_PACKET;1433 else1434 *p_tx_max = min_t(u8, *p_tx_max,1435 CORE_LL2_TX_MAX_BDS_PER_PACKET);1436 1437 rc = qed_ll2_set_cbs(p_ll2_info, data->cbs);1438 if (rc) {1439 DP_NOTICE(p_hwfn, "Invalid callback functions\n");1440 goto q_allocate_fail;1441 }1442 1443 rc = qed_ll2_acquire_connection_rx(p_hwfn, p_ll2_info);1444 if (rc)1445 goto q_allocate_fail;1446 1447 rc = qed_ll2_acquire_connection_tx(p_hwfn, p_ll2_info);1448 if (rc)1449 goto q_allocate_fail;1450 1451 rc = qed_ll2_acquire_connection_ooo(p_hwfn, p_ll2_info,1452 data->input.mtu);1453 if (rc)1454 goto q_allocate_fail;1455 1456 /* Register callbacks for the Rx/Tx queues */1457 if (data->input.conn_type == QED_LL2_TYPE_OOO) {1458 comp_rx_cb = qed_ll2_lb_rxq_completion;1459 comp_tx_cb = qed_ll2_lb_txq_completion;1460 } else {1461 comp_rx_cb = qed_ll2_rxq_completion;1462 comp_tx_cb = qed_ll2_txq_completion;1463 }1464 1465 if (data->input.rx_num_desc) {1466 qed_int_register_cb(p_hwfn, comp_rx_cb,1467 &p_hwfn->p_ll2_info[i],1468 &p_ll2_info->rx_queue.rx_sb_index,1469 &p_ll2_info->rx_queue.p_fw_cons);1470 p_ll2_info->rx_queue.b_cb_registered = true;1471 }1472 1473 if (data->input.tx_num_desc) {1474 qed_int_register_cb(p_hwfn,1475 comp_tx_cb,1476 &p_hwfn->p_ll2_info[i],1477 &p_ll2_info->tx_queue.tx_sb_index,1478 &p_ll2_info->tx_queue.p_fw_cons);1479 p_ll2_info->tx_queue.b_cb_registered = true;1480 }1481 1482 *data->p_connection_handle = i;1483 return rc;1484 1485q_allocate_fail:1486 qed_ll2_release_connection(p_hwfn, i);1487 return -ENOMEM;1488}1489 1490static int qed_ll2_establish_connection_rx(struct qed_hwfn *p_hwfn,1491 struct qed_ll2_info *p_ll2_conn)1492{1493 enum qed_ll2_error_handle error_input;1494 enum core_error_handle error_mode;1495 u8 action_on_error = 0;1496 int rc;1497 1498 if (!QED_LL2_RX_REGISTERED(p_ll2_conn))1499 return 0;1500 1501 DIRECT_REG_WR(p_ll2_conn->rx_queue.set_prod_addr, 0x0);1502 error_input = p_ll2_conn->input.ai_err_packet_too_big;1503 error_mode = qed_ll2_get_error_choice(error_input);1504 SET_FIELD(action_on_error,1505 CORE_RX_ACTION_ON_ERROR_PACKET_TOO_BIG, error_mode);1506 error_input = p_ll2_conn->input.ai_err_no_buf;1507 error_mode = qed_ll2_get_error_choice(error_input);1508 SET_FIELD(action_on_error, CORE_RX_ACTION_ON_ERROR_NO_BUFF, error_mode);1509 1510 rc = qed_sp_ll2_rx_queue_start(p_hwfn, p_ll2_conn, action_on_error);1511 if (rc)1512 return rc;1513 1514 if (p_ll2_conn->rx_queue.ctx_based) {1515 rc = qed_db_recovery_add(p_hwfn->cdev,1516 p_ll2_conn->rx_queue.set_prod_addr,1517 &p_ll2_conn->rx_queue.db_data,1518 DB_REC_WIDTH_64B, DB_REC_KERNEL);1519 }1520 1521 return rc;1522}1523 1524static void1525qed_ll2_establish_connection_ooo(struct qed_hwfn *p_hwfn,1526 struct qed_ll2_info *p_ll2_conn)1527{1528 if (p_ll2_conn->input.conn_type != QED_LL2_TYPE_OOO)1529 return;1530 1531 qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);1532 qed_ooo_submit_rx_buffers(p_hwfn, p_ll2_conn);1533}1534 1535static inline u8 qed_ll2_handle_to_queue_id(struct qed_hwfn *p_hwfn,1536 u8 handle,1537 u8 ll2_queue_type)1538{1539 u8 qid;1540 1541 if (ll2_queue_type == QED_LL2_RX_TYPE_LEGACY)1542 return p_hwfn->hw_info.resc_start[QED_LL2_RAM_QUEUE] + handle;1543 1544 /* QED_LL2_RX_TYPE_CTX1545 * FW distinguishes between the legacy queues (ram based) and the1546 * ctx based queues by the queue_id.1547 * The first MAX_NUM_LL2_RX_RAM_QUEUES queues are legacy1548 * and the queue ids above that are ctx base.1549 */1550 qid = p_hwfn->hw_info.resc_start[QED_LL2_CTX_QUEUE] +1551 MAX_NUM_LL2_RX_RAM_QUEUES;1552 1553 /* See comment on the acquire connection for how the ll21554 * queues handles are divided.1555 */1556 qid += (handle - QED_MAX_NUM_OF_LEGACY_LL2_CONNS_PF);1557 1558 return qid;1559}1560 1561int qed_ll2_establish_connection(void *cxt, u8 connection_handle)1562{1563 struct core_conn_context *p_cxt;1564 struct qed_ll2_tx_packet *p_pkt;1565 struct qed_ll2_info *p_ll2_conn;1566 struct qed_hwfn *p_hwfn = cxt;1567 struct qed_ll2_rx_queue *p_rx;1568 struct qed_ll2_tx_queue *p_tx;1569 struct qed_cxt_info cxt_info;1570 struct qed_ptt *p_ptt;1571 int rc = -EINVAL;1572 u32 i, capacity;1573 size_t desc_size;1574 u8 qid, stats_id;1575 1576 p_ptt = qed_ptt_acquire(p_hwfn);1577 if (!p_ptt)1578 return -EAGAIN;1579 1580 p_ll2_conn = qed_ll2_handle_sanity_lock(p_hwfn, connection_handle);1581 if (!p_ll2_conn) {1582 rc = -EINVAL;1583 goto out;1584 }1585 1586 p_rx = &p_ll2_conn->rx_queue;1587 p_tx = &p_ll2_conn->tx_queue;1588 1589 qed_chain_reset(&p_rx->rxq_chain);1590 qed_chain_reset(&p_rx->rcq_chain);1591 INIT_LIST_HEAD(&p_rx->active_descq);1592 INIT_LIST_HEAD(&p_rx->free_descq);1593 INIT_LIST_HEAD(&p_rx->posting_descq);1594 spin_lock_init(&p_rx->lock);1595 capacity = qed_chain_get_capacity(&p_rx->rxq_chain);1596 for (i = 0; i < capacity; i++)1597 list_add_tail(&p_rx->descq_array[i].list_entry,1598 &p_rx->free_descq);1599 *p_rx->p_fw_cons = 0;1600 1601 qed_chain_reset(&p_tx->txq_chain);1602 INIT_LIST_HEAD(&p_tx->active_descq);1603 INIT_LIST_HEAD(&p_tx->free_descq);1604 INIT_LIST_HEAD(&p_tx->sending_descq);1605 spin_lock_init(&p_tx->lock);1606 capacity = qed_chain_get_capacity(&p_tx->txq_chain);1607 /* All bds_set elements are flexibily added. */1608 desc_size = struct_size(p_pkt, bds_set,1609 p_ll2_conn->input.tx_max_bds_per_packet);1610 1611 for (i = 0; i < capacity; i++) {1612 p_pkt = p_tx->descq_mem + desc_size * i;1613 list_add_tail(&p_pkt->list_entry, &p_tx->free_descq);1614 }1615 p_tx->cur_completing_bd_idx = 0;1616 p_tx->bds_idx = 0;1617 p_tx->b_completing_packet = false;1618 p_tx->cur_send_packet = NULL;1619 p_tx->cur_send_frag_num = 0;1620 p_tx->cur_completing_frag_num = 0;1621 *p_tx->p_fw_cons = 0;1622 1623 rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_CORE, &p_ll2_conn->cid);1624 if (rc)1625 goto out;1626 cxt_info.iid = p_ll2_conn->cid;1627 rc = qed_cxt_get_cid_info(p_hwfn, &cxt_info);1628 if (rc) {1629 DP_NOTICE(p_hwfn, "Cannot find context info for cid=%d\n",1630 p_ll2_conn->cid);1631 goto out;1632 }1633 1634 p_cxt = cxt_info.p_cxt;1635 1636 memset(p_cxt, 0, sizeof(*p_cxt));1637 1638 qid = qed_ll2_handle_to_queue_id(p_hwfn, connection_handle,1639 p_ll2_conn->input.rx_conn_type);1640 stats_id = qed_ll2_handle_to_stats_id(p_hwfn,1641 p_ll2_conn->input.rx_conn_type,1642 qid);1643 p_ll2_conn->queue_id = qid;1644 p_ll2_conn->tx_stats_id = stats_id;1645 1646 /* If there is no valid stats id for this connection, disable stats */1647 if (p_ll2_conn->tx_stats_id == QED_LL2_INVALID_STATS_ID) {1648 p_ll2_conn->tx_stats_en = 0;1649 DP_VERBOSE(p_hwfn,1650 QED_MSG_LL2,1651 "Disabling stats for queue %d - not enough counters\n",1652 qid);1653 }1654 1655 DP_VERBOSE(p_hwfn,1656 QED_MSG_LL2,1657 "Establishing ll2 queue. PF %d ctx_based=%d abs qid=%d stats_id=%d\n",1658 p_hwfn->rel_pf_id,1659 p_ll2_conn->input.rx_conn_type, qid, stats_id);1660 1661 if (p_ll2_conn->input.rx_conn_type == QED_LL2_RX_TYPE_LEGACY) {1662 p_rx->set_prod_addr =1663 (u8 __iomem *)p_hwfn->regview +1664 GET_GTT_REG_ADDR(GTT_BAR0_MAP_REG_TSDM_RAM,1665 TSTORM_LL2_RX_PRODS, qid);1666 } else {1667 /* QED_LL2_RX_TYPE_CTX - using doorbell */1668 p_rx->ctx_based = 1;1669 1670 p_rx->set_prod_addr = p_hwfn->doorbells +1671 p_hwfn->dpi_start_offset +1672 DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_LL2_PROD_UPDATE);1673 1674 /* prepare db data */1675 p_rx->db_data.icid = cpu_to_le16((u16)p_ll2_conn->cid);1676 SET_FIELD(p_rx->db_data.params,1677 CORE_PWM_PROD_UPDATE_DATA_AGG_CMD, DB_AGG_CMD_SET);1678 SET_FIELD(p_rx->db_data.params,1679 CORE_PWM_PROD_UPDATE_DATA_RESERVED1, 0);1680 }1681 1682 p_tx->doorbell_addr = (u8 __iomem *)p_hwfn->doorbells +1683 qed_db_addr(p_ll2_conn->cid,1684 DQ_DEMS_LEGACY);1685 /* prepare db data */1686 SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM);1687 SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET);1688 SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_VAL_SEL,1689 DQ_XCM_CORE_TX_BD_PROD_CMD);1690 p_tx->db_msg.agg_flags = DQ_XCM_CORE_DQ_CF_CMD;1691 1692 rc = qed_ll2_establish_connection_rx(p_hwfn, p_ll2_conn);1693 if (rc)1694 goto out;1695 1696 rc = qed_sp_ll2_tx_queue_start(p_hwfn, p_ll2_conn);1697 if (rc)1698 goto out;1699 1700 if (!QED_IS_RDMA_PERSONALITY(p_hwfn) &&1701 !QED_IS_NVMETCP_PERSONALITY(p_hwfn))1702 qed_wr(p_hwfn, p_ptt, PRS_REG_USE_LIGHT_L2, 1);1703 1704 qed_ll2_establish_connection_ooo(p_hwfn, p_ll2_conn);1705 1706 if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_FCOE) {1707 if (!test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits))1708 qed_llh_add_protocol_filter(p_hwfn->cdev, 0,1709 QED_LLH_FILTER_ETHERTYPE,1710 ETH_P_FCOE, 0);1711 qed_llh_add_protocol_filter(p_hwfn->cdev, 0,1712 QED_LLH_FILTER_ETHERTYPE,1713 ETH_P_FIP, 0);1714 }1715 1716out:1717 qed_ptt_release(p_hwfn, p_ptt);1718 return rc;1719}1720 1721static void qed_ll2_post_rx_buffer_notify_fw(struct qed_hwfn *p_hwfn,1722 struct qed_ll2_rx_queue *p_rx,1723 struct qed_ll2_rx_packet *p_curp)1724{1725 struct qed_ll2_rx_packet *p_posting_packet = NULL;1726 struct core_ll2_rx_prod rx_prod = { 0, 0 };1727 bool b_notify_fw = false;1728 u16 bd_prod, cq_prod;1729 1730 /* This handles the flushing of already posted buffers */1731 while (!list_empty(&p_rx->posting_descq)) {1732 p_posting_packet = list_first_entry(&p_rx->posting_descq,1733 struct qed_ll2_rx_packet,1734 list_entry);1735 list_move_tail(&p_posting_packet->list_entry,1736 &p_rx->active_descq);1737 b_notify_fw = true;1738 }1739 1740 /* This handles the supplied packet [if there is one] */1741 if (p_curp) {1742 list_add_tail(&p_curp->list_entry, &p_rx->active_descq);1743 b_notify_fw = true;1744 }1745 1746 if (!b_notify_fw)1747 return;1748 1749 bd_prod = qed_chain_get_prod_idx(&p_rx->rxq_chain);1750 cq_prod = qed_chain_get_prod_idx(&p_rx->rcq_chain);1751 if (p_rx->ctx_based) {1752 /* update producer by giving a doorbell */1753 p_rx->db_data.prod.bd_prod = cpu_to_le16(bd_prod);1754 p_rx->db_data.prod.cqe_prod = cpu_to_le16(cq_prod);1755 /* Make sure chain element is updated before ringing the1756 * doorbell1757 */1758 dma_wmb();1759 DIRECT_REG_WR64(p_rx->set_prod_addr,1760 *((u64 *)&p_rx->db_data));1761 } else {1762 rx_prod.bd_prod = cpu_to_le16(bd_prod);1763 rx_prod.cqe_prod = cpu_to_le16(cq_prod);1764 1765 /* Make sure chain element is updated before ringing the1766 * doorbell1767 */1768 dma_wmb();1769 1770 DIRECT_REG_WR(p_rx->set_prod_addr, *((u32 *)&rx_prod));1771 }1772}1773 1774int qed_ll2_post_rx_buffer(void *cxt,1775 u8 connection_handle,1776 dma_addr_t addr,1777 u16 buf_len, void *cookie, u8 notify_fw)1778{1779 struct qed_hwfn *p_hwfn = cxt;1780 struct core_rx_bd_with_buff_len *p_curb = NULL;1781 struct qed_ll2_rx_packet *p_curp = NULL;1782 struct qed_ll2_info *p_ll2_conn;1783 struct qed_ll2_rx_queue *p_rx;1784 unsigned long flags;1785 void *p_data;1786 int rc = 0;1787 1788 p_ll2_conn = qed_ll2_handle_sanity(p_hwfn, connection_handle);1789 if (!p_ll2_conn)1790 return -EINVAL;1791 p_rx = &p_ll2_conn->rx_queue;1792 if (!p_rx->set_prod_addr)1793 return -EIO;1794 1795 spin_lock_irqsave(&p_rx->lock, flags);1796 if (!list_empty(&p_rx->free_descq))1797 p_curp = list_first_entry(&p_rx->free_descq,1798 struct qed_ll2_rx_packet, list_entry);1799 if (p_curp) {1800 if (qed_chain_get_elem_left(&p_rx->rxq_chain) &&1801 qed_chain_get_elem_left(&p_rx->rcq_chain)) {1802 p_data = qed_chain_produce(&p_rx->rxq_chain);1803 p_curb = (struct core_rx_bd_with_buff_len *)p_data;1804 qed_chain_produce(&p_rx->rcq_chain);1805 }1806 }1807 1808 /* If we're lacking entries, let's try to flush buffers to FW */1809 if (!p_curp || !p_curb) {1810 rc = -EBUSY;1811 p_curp = NULL;1812 goto out_notify;1813 }1814 1815 /* We have an Rx packet we can fill */1816 DMA_REGPAIR_LE(p_curb->addr, addr);1817 p_curb->buff_length = cpu_to_le16(buf_len);1818 p_curp->rx_buf_addr = addr;1819 p_curp->cookie = cookie;1820 p_curp->rxq_bd = p_curb;1821 p_curp->buf_length = buf_len;1822 list_del(&p_curp->list_entry);1823 1824 /* Check if we only want to enqueue this packet without informing FW */1825 if (!notify_fw) {1826 list_add_tail(&p_curp->list_entry, &p_rx->posting_descq);1827 goto out;1828 }1829 1830out_notify:1831 qed_ll2_post_rx_buffer_notify_fw(p_hwfn, p_rx, p_curp);1832out:1833 spin_unlock_irqrestore(&p_rx->lock, flags);1834 return rc;1835}1836 1837static void qed_ll2_prepare_tx_packet_set(struct qed_hwfn *p_hwfn,1838 struct qed_ll2_tx_queue *p_tx,1839 struct qed_ll2_tx_packet *p_curp,1840 struct qed_ll2_tx_pkt_info *pkt,1841 u8 notify_fw)1842{1843 list_del(&p_curp->list_entry);1844 p_curp->cookie = pkt->cookie;1845 p_curp->bd_used = pkt->num_of_bds;1846 p_curp->notify_fw = notify_fw;1847 p_tx->cur_send_packet = p_curp;1848 p_tx->cur_send_frag_num = 0;1849 1850 p_curp->bds_set[p_tx->cur_send_frag_num].tx_frag = pkt->first_frag;1851 p_curp->bds_set[p_tx->cur_send_frag_num].frag_len = pkt->first_frag_len;1852 p_tx->cur_send_frag_num++;1853}1854 1855static void1856qed_ll2_prepare_tx_packet_set_bd(struct qed_hwfn *p_hwfn,1857 struct qed_ll2_info *p_ll2,1858 struct qed_ll2_tx_packet *p_curp,1859 struct qed_ll2_tx_pkt_info *pkt)1860{1861 struct qed_chain *p_tx_chain = &p_ll2->tx_queue.txq_chain;1862 u16 prod_idx = qed_chain_get_prod_idx(p_tx_chain);1863 struct core_tx_bd *start_bd = NULL;1864 enum core_roce_flavor_type roce_flavor;1865 enum core_tx_dest tx_dest;1866 u16 bd_data = 0, frag_idx;1867 u16 bitfield1;1868 1869 roce_flavor = (pkt->qed_roce_flavor == QED_LL2_ROCE) ? CORE_ROCE1870 : CORE_RROCE;1871 1872 switch (pkt->tx_dest) {1873 case QED_LL2_TX_DEST_NW:1874 tx_dest = CORE_TX_DEST_NW;1875 break;1876 case QED_LL2_TX_DEST_LB:1877 tx_dest = CORE_TX_DEST_LB;1878 break;1879 case QED_LL2_TX_DEST_DROP:1880 tx_dest = CORE_TX_DEST_DROP;1881 break;1882 default:1883 tx_dest = CORE_TX_DEST_LB;1884 break;1885 }1886 1887 start_bd = (struct core_tx_bd *)qed_chain_produce(p_tx_chain);1888 if (likely(QED_IS_IWARP_PERSONALITY(p_hwfn) &&1889 p_ll2->input.conn_type == QED_LL2_TYPE_OOO)) {1890 start_bd->nw_vlan_or_lb_echo =1891 cpu_to_le16(IWARP_LL2_IN_ORDER_TX_QUEUE);1892 } else {1893 start_bd->nw_vlan_or_lb_echo = cpu_to_le16(pkt->vlan);1894 if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits) &&1895 p_ll2->input.conn_type == QED_LL2_TYPE_FCOE)1896 pkt->remove_stag = true;1897 }1898 1899 bitfield1 = le16_to_cpu(start_bd->bitfield1);1900 SET_FIELD(bitfield1, CORE_TX_BD_L4_HDR_OFFSET_W, pkt->l4_hdr_offset_w);1901 SET_FIELD(bitfield1, CORE_TX_BD_TX_DST, tx_dest);1902 start_bd->bitfield1 = cpu_to_le16(bitfield1);1903 1904 bd_data |= pkt->bd_flags;1905 SET_FIELD(bd_data, CORE_TX_BD_DATA_START_BD, 0x1);1906 SET_FIELD(bd_data, CORE_TX_BD_DATA_NBDS, pkt->num_of_bds);1907 SET_FIELD(bd_data, CORE_TX_BD_DATA_ROCE_FLAV, roce_flavor);1908 SET_FIELD(bd_data, CORE_TX_BD_DATA_IP_CSUM, !!(pkt->enable_ip_cksum));1909 SET_FIELD(bd_data, CORE_TX_BD_DATA_L4_CSUM, !!(pkt->enable_l4_cksum));1910 SET_FIELD(bd_data, CORE_TX_BD_DATA_IP_LEN, !!(pkt->calc_ip_len));1911 SET_FIELD(bd_data, CORE_TX_BD_DATA_DISABLE_STAG_INSERTION,1912 !!(pkt->remove_stag));1913 1914 start_bd->bd_data.as_bitfield = cpu_to_le16(bd_data);1915 DMA_REGPAIR_LE(start_bd->addr, pkt->first_frag);1916 start_bd->nbytes = cpu_to_le16(pkt->first_frag_len);1917 1918 DP_VERBOSE(p_hwfn,1919 (NETIF_MSG_TX_QUEUED | QED_MSG_LL2),1920 "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",1921 p_ll2->queue_id,1922 p_ll2->cid,1923 p_ll2->input.conn_type,1924 prod_idx,1925 pkt->first_frag_len,1926 pkt->num_of_bds,1927 le32_to_cpu(start_bd->addr.hi),1928 le32_to_cpu(start_bd->addr.lo));1929 1930 if (p_ll2->tx_queue.cur_send_frag_num == pkt->num_of_bds)1931 return;1932 1933 /* Need to provide the packet with additional BDs for frags */1934 for (frag_idx = p_ll2->tx_queue.cur_send_frag_num;1935 frag_idx < pkt->num_of_bds; frag_idx++) {1936 struct core_tx_bd **p_bd = &p_curp->bds_set[frag_idx].txq_bd;1937 1938 *p_bd = (struct core_tx_bd *)qed_chain_produce(p_tx_chain);1939 (*p_bd)->bd_data.as_bitfield = 0;1940 (*p_bd)->bitfield1 = 0;1941 p_curp->bds_set[frag_idx].tx_frag = 0;1942 p_curp->bds_set[frag_idx].frag_len = 0;1943 }1944}1945 1946/* This should be called while the Txq spinlock is being held */1947static void qed_ll2_tx_packet_notify(struct qed_hwfn *p_hwfn,1948 struct qed_ll2_info *p_ll2_conn)1949{1950 bool b_notify = p_ll2_conn->tx_queue.cur_send_packet->notify_fw;1951 struct qed_ll2_tx_queue *p_tx = &p_ll2_conn->tx_queue;1952 struct qed_ll2_tx_packet *p_pkt = NULL;1953 u16 bd_prod;1954 1955 /* If there are missing BDs, don't do anything now */1956 if (p_ll2_conn->tx_queue.cur_send_frag_num !=1957 p_ll2_conn->tx_queue.cur_send_packet->bd_used)1958 return;1959 1960 /* Push the current packet to the list and clean after it */1961 list_add_tail(&p_ll2_conn->tx_queue.cur_send_packet->list_entry,1962 &p_ll2_conn->tx_queue.sending_descq);1963 p_ll2_conn->tx_queue.cur_send_packet = NULL;1964 p_ll2_conn->tx_queue.cur_send_frag_num = 0;1965 1966 /* Notify FW of packet only if requested to */1967 if (!b_notify)1968 return;1969 1970 bd_prod = qed_chain_get_prod_idx(&p_ll2_conn->tx_queue.txq_chain);1971 1972 while (!list_empty(&p_tx->sending_descq)) {1973 p_pkt = list_first_entry(&p_tx->sending_descq,1974 struct qed_ll2_tx_packet, list_entry);1975 if (!p_pkt)1976 break;1977 1978 list_move_tail(&p_pkt->list_entry, &p_tx->active_descq);1979 }1980 1981 p_tx->db_msg.spq_prod = cpu_to_le16(bd_prod);1982 1983 /* Make sure the BDs data is updated before ringing the doorbell */1984 wmb();1985 1986 DIRECT_REG_WR(p_tx->doorbell_addr, *((u32 *)&p_tx->db_msg));1987 1988 DP_VERBOSE(p_hwfn,1989 (NETIF_MSG_TX_QUEUED | QED_MSG_LL2),1990 "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Doorbelled [producer 0x%04x]\n",1991 p_ll2_conn->queue_id,1992 p_ll2_conn->cid,1993 p_ll2_conn->input.conn_type, p_tx->db_msg.spq_prod);1994}1995 1996int qed_ll2_prepare_tx_packet(void *cxt,1997 u8 connection_handle,1998 struct qed_ll2_tx_pkt_info *pkt,1999 bool notify_fw)2000{2001 struct qed_hwfn *p_hwfn = cxt;2002 struct qed_ll2_tx_packet *p_curp = NULL;2003 struct qed_ll2_info *p_ll2_conn = NULL;2004 struct qed_ll2_tx_queue *p_tx;2005 struct qed_chain *p_tx_chain;2006 unsigned long flags;2007 int rc = 0;2008 2009 p_ll2_conn = qed_ll2_handle_sanity(p_hwfn, connection_handle);2010 if (unlikely(!p_ll2_conn))2011 return -EINVAL;2012 p_tx = &p_ll2_conn->tx_queue;2013 p_tx_chain = &p_tx->txq_chain;2014 2015 if (unlikely(pkt->num_of_bds > p_ll2_conn->input.tx_max_bds_per_packet))2016 return -EIO;2017 2018 spin_lock_irqsave(&p_tx->lock, flags);2019 if (unlikely(p_tx->cur_send_packet)) {2020 rc = -EEXIST;2021 goto out;2022 }2023 2024 /* Get entry, but only if we have tx elements for it */2025 if (unlikely(!list_empty(&p_tx->free_descq)))2026 p_curp = list_first_entry(&p_tx->free_descq,2027 struct qed_ll2_tx_packet, list_entry);2028 if (unlikely(p_curp &&2029 qed_chain_get_elem_left(p_tx_chain) < pkt->num_of_bds))2030 p_curp = NULL;2031 2032 if (unlikely(!p_curp)) {2033 rc = -EBUSY;2034 goto out;2035 }2036 2037 /* Prepare packet and BD, and perhaps send a doorbell to FW */2038 qed_ll2_prepare_tx_packet_set(p_hwfn, p_tx, p_curp, pkt, notify_fw);2039 2040 qed_ll2_prepare_tx_packet_set_bd(p_hwfn, p_ll2_conn, p_curp, pkt);2041 2042 qed_ll2_tx_packet_notify(p_hwfn, p_ll2_conn);2043 2044out:2045 spin_unlock_irqrestore(&p_tx->lock, flags);2046 return rc;2047}2048 2049int qed_ll2_set_fragment_of_tx_packet(void *cxt,2050 u8 connection_handle,2051 dma_addr_t addr, u16 nbytes)2052{2053 struct qed_ll2_tx_packet *p_cur_send_packet = NULL;2054 struct qed_hwfn *p_hwfn = cxt;2055 struct qed_ll2_info *p_ll2_conn = NULL;2056 u16 cur_send_frag_num = 0;2057 struct core_tx_bd *p_bd;2058 unsigned long flags;2059 2060 p_ll2_conn = qed_ll2_handle_sanity(p_hwfn, connection_handle);2061 if (unlikely(!p_ll2_conn))2062 return -EINVAL;2063 2064 if (unlikely(!p_ll2_conn->tx_queue.cur_send_packet))2065 return -EINVAL;2066 2067 p_cur_send_packet = p_ll2_conn->tx_queue.cur_send_packet;2068 cur_send_frag_num = p_ll2_conn->tx_queue.cur_send_frag_num;2069 2070 if (unlikely(cur_send_frag_num >= p_cur_send_packet->bd_used))2071 return -EINVAL;2072 2073 /* Fill the BD information, and possibly notify FW */2074 p_bd = p_cur_send_packet->bds_set[cur_send_frag_num].txq_bd;2075 DMA_REGPAIR_LE(p_bd->addr, addr);2076 p_bd->nbytes = cpu_to_le16(nbytes);2077 p_cur_send_packet->bds_set[cur_send_frag_num].tx_frag = addr;2078 p_cur_send_packet->bds_set[cur_send_frag_num].frag_len = nbytes;2079 2080 p_ll2_conn->tx_queue.cur_send_frag_num++;2081 2082 spin_lock_irqsave(&p_ll2_conn->tx_queue.lock, flags);2083 qed_ll2_tx_packet_notify(p_hwfn, p_ll2_conn);2084 spin_unlock_irqrestore(&p_ll2_conn->tx_queue.lock, flags);2085 2086 return 0;2087}2088 2089int qed_ll2_terminate_connection(void *cxt, u8 connection_handle)2090{2091 struct qed_hwfn *p_hwfn = cxt;2092 struct qed_ll2_info *p_ll2_conn = NULL;2093 int rc = -EINVAL;2094 struct qed_ptt *p_ptt;2095 2096 p_ptt = qed_ptt_acquire(p_hwfn);2097 if (!p_ptt)2098 return -EAGAIN;2099 2100 p_ll2_conn = qed_ll2_handle_sanity_lock(p_hwfn, connection_handle);2101 if (!p_ll2_conn) {2102 rc = -EINVAL;2103 goto out;2104 }2105 2106 /* Stop Tx & Rx of connection, if needed */2107 if (QED_LL2_TX_REGISTERED(p_ll2_conn)) {2108 p_ll2_conn->tx_queue.b_cb_registered = false;2109 smp_wmb(); /* Make sure this is seen by ll2_lb_rxq_completion */2110 rc = qed_sp_ll2_tx_queue_stop(p_hwfn, p_ll2_conn);2111 if (rc)2112 goto out;2113 2114 qed_ll2_txq_flush(p_hwfn, connection_handle);2115 qed_int_unregister_cb(p_hwfn, p_ll2_conn->tx_queue.tx_sb_index);2116 }2117 2118 if (QED_LL2_RX_REGISTERED(p_ll2_conn)) {2119 p_ll2_conn->rx_queue.b_cb_registered = false;2120 smp_wmb(); /* Make sure this is seen by ll2_lb_rxq_completion */2121 2122 if (p_ll2_conn->rx_queue.ctx_based)2123 qed_db_recovery_del(p_hwfn->cdev,2124 p_ll2_conn->rx_queue.set_prod_addr,2125 &p_ll2_conn->rx_queue.db_data);2126 2127 rc = qed_sp_ll2_rx_queue_stop(p_hwfn, p_ll2_conn);2128 if (rc)2129 goto out;2130 2131 qed_ll2_rxq_flush(p_hwfn, connection_handle);2132 qed_int_unregister_cb(p_hwfn, p_ll2_conn->rx_queue.rx_sb_index);2133 }2134 2135 if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_OOO)2136 qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);2137 2138 if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_FCOE) {2139 if (!test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits))2140 qed_llh_remove_protocol_filter(p_hwfn->cdev, 0,2141 QED_LLH_FILTER_ETHERTYPE,2142 ETH_P_FCOE, 0);2143 qed_llh_remove_protocol_filter(p_hwfn->cdev, 0,2144 QED_LLH_FILTER_ETHERTYPE,2145 ETH_P_FIP, 0);2146 }2147 2148out:2149 qed_ptt_release(p_hwfn, p_ptt);2150 return rc;2151}2152 2153static void qed_ll2_release_connection_ooo(struct qed_hwfn *p_hwfn,2154 struct qed_ll2_info *p_ll2_conn)2155{2156 struct qed_ooo_buffer *p_buffer;2157 2158 if (p_ll2_conn->input.conn_type != QED_LL2_TYPE_OOO)2159 return;2160 2161 qed_ooo_release_all_isles(p_hwfn, p_hwfn->p_ooo_info);2162 while ((p_buffer = qed_ooo_get_free_buffer(p_hwfn,2163 p_hwfn->p_ooo_info))) {2164 dma_free_coherent(&p_hwfn->cdev->pdev->dev,2165 p_buffer->rx_buffer_size,2166 p_buffer->rx_buffer_virt_addr,2167 p_buffer->rx_buffer_phys_addr);2168 kfree(p_buffer);2169 }2170}2171 2172void qed_ll2_release_connection(void *cxt, u8 connection_handle)2173{2174 struct qed_hwfn *p_hwfn = cxt;2175 struct qed_ll2_info *p_ll2_conn = NULL;2176 2177 p_ll2_conn = qed_ll2_handle_sanity(p_hwfn, connection_handle);2178 if (!p_ll2_conn)2179 return;2180 2181 kfree(p_ll2_conn->tx_queue.descq_mem);2182 qed_chain_free(p_hwfn->cdev, &p_ll2_conn->tx_queue.txq_chain);2183 2184 kfree(p_ll2_conn->rx_queue.descq_array);2185 qed_chain_free(p_hwfn->cdev, &p_ll2_conn->rx_queue.rxq_chain);2186 qed_chain_free(p_hwfn->cdev, &p_ll2_conn->rx_queue.rcq_chain);2187 2188 qed_cxt_release_cid(p_hwfn, p_ll2_conn->cid);2189 2190 qed_ll2_release_connection_ooo(p_hwfn, p_ll2_conn);2191 2192 mutex_lock(&p_ll2_conn->mutex);2193 p_ll2_conn->b_active = false;2194 mutex_unlock(&p_ll2_conn->mutex);2195}2196 2197int qed_ll2_alloc(struct qed_hwfn *p_hwfn)2198{2199 struct qed_ll2_info *p_ll2_connections;2200 u8 i;2201 2202 /* Allocate LL2's set struct */2203 p_ll2_connections = kcalloc(QED_MAX_NUM_OF_LL2_CONNECTIONS,2204 sizeof(struct qed_ll2_info), GFP_KERNEL);2205 if (!p_ll2_connections) {2206 DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_ll2'\n");2207 return -ENOMEM;2208 }2209 2210 for (i = 0; i < QED_MAX_NUM_OF_LL2_CONNECTIONS; i++)2211 p_ll2_connections[i].my_id = i;2212 2213 p_hwfn->p_ll2_info = p_ll2_connections;2214 return 0;2215}2216 2217void qed_ll2_setup(struct qed_hwfn *p_hwfn)2218{2219 int i;2220 2221 for (i = 0; i < QED_MAX_NUM_OF_LL2_CONNECTIONS; i++)2222 mutex_init(&p_hwfn->p_ll2_info[i].mutex);2223}2224 2225void qed_ll2_free(struct qed_hwfn *p_hwfn)2226{2227 if (!p_hwfn->p_ll2_info)2228 return;2229 2230 kfree(p_hwfn->p_ll2_info);2231 p_hwfn->p_ll2_info = NULL;2232}2233 2234static void _qed_ll2_get_port_stats(struct qed_hwfn *p_hwfn,2235 struct qed_ptt *p_ptt,2236 struct qed_ll2_stats *p_stats)2237{2238 struct core_ll2_port_stats port_stats;2239 2240 memset(&port_stats, 0, sizeof(port_stats));2241 qed_memcpy_from(p_hwfn, p_ptt, &port_stats,2242 BAR0_MAP_REG_TSDM_RAM +2243 TSTORM_LL2_PORT_STAT_OFFSET(MFW_PORT(p_hwfn)),2244 sizeof(port_stats));2245 2246 p_stats->gsi_invalid_hdr += HILO_64_REGPAIR(port_stats.gsi_invalid_hdr);2247 p_stats->gsi_invalid_pkt_length +=2248 HILO_64_REGPAIR(port_stats.gsi_invalid_pkt_length);2249 p_stats->gsi_unsupported_pkt_typ +=2250 HILO_64_REGPAIR(port_stats.gsi_unsupported_pkt_typ);2251 p_stats->gsi_crcchksm_error +=2252 HILO_64_REGPAIR(port_stats.gsi_crcchksm_error);2253}2254 2255static void _qed_ll2_get_tstats(struct qed_hwfn *p_hwfn,2256 struct qed_ptt *p_ptt,2257 struct qed_ll2_info *p_ll2_conn,2258 struct qed_ll2_stats *p_stats)2259{2260 struct core_ll2_tstorm_per_queue_stat tstats;2261 u8 qid = p_ll2_conn->queue_id;2262 u32 tstats_addr;2263 2264 memset(&tstats, 0, sizeof(tstats));2265 tstats_addr = BAR0_MAP_REG_TSDM_RAM +2266 CORE_LL2_TSTORM_PER_QUEUE_STAT_OFFSET(qid);2267 qed_memcpy_from(p_hwfn, p_ptt, &tstats, tstats_addr, sizeof(tstats));2268 2269 p_stats->packet_too_big_discard +=2270 HILO_64_REGPAIR(tstats.packet_too_big_discard);2271 p_stats->no_buff_discard += HILO_64_REGPAIR(tstats.no_buff_discard);2272}2273 2274static void _qed_ll2_get_ustats(struct qed_hwfn *p_hwfn,2275 struct qed_ptt *p_ptt,2276 struct qed_ll2_info *p_ll2_conn,2277 struct qed_ll2_stats *p_stats)2278{2279 struct core_ll2_ustorm_per_queue_stat ustats;2280 u8 qid = p_ll2_conn->queue_id;2281 u32 ustats_addr;2282 2283 memset(&ustats, 0, sizeof(ustats));2284 ustats_addr = BAR0_MAP_REG_USDM_RAM +2285 CORE_LL2_USTORM_PER_QUEUE_STAT_OFFSET(qid);2286 qed_memcpy_from(p_hwfn, p_ptt, &ustats, ustats_addr, sizeof(ustats));2287 2288 p_stats->rcv_ucast_bytes += HILO_64_REGPAIR(ustats.rcv_ucast_bytes);2289 p_stats->rcv_mcast_bytes += HILO_64_REGPAIR(ustats.rcv_mcast_bytes);2290 p_stats->rcv_bcast_bytes += HILO_64_REGPAIR(ustats.rcv_bcast_bytes);2291 p_stats->rcv_ucast_pkts += HILO_64_REGPAIR(ustats.rcv_ucast_pkts);2292 p_stats->rcv_mcast_pkts += HILO_64_REGPAIR(ustats.rcv_mcast_pkts);2293 p_stats->rcv_bcast_pkts += HILO_64_REGPAIR(ustats.rcv_bcast_pkts);2294}2295 2296static void _qed_ll2_get_pstats(struct qed_hwfn *p_hwfn,2297 struct qed_ptt *p_ptt,2298 struct qed_ll2_info *p_ll2_conn,2299 struct qed_ll2_stats *p_stats)2300{2301 struct core_ll2_pstorm_per_queue_stat pstats;2302 u8 stats_id = p_ll2_conn->tx_stats_id;2303 u32 pstats_addr;2304 2305 memset(&pstats, 0, sizeof(pstats));2306 pstats_addr = BAR0_MAP_REG_PSDM_RAM +2307 CORE_LL2_PSTORM_PER_QUEUE_STAT_OFFSET(stats_id);2308 qed_memcpy_from(p_hwfn, p_ptt, &pstats, pstats_addr, sizeof(pstats));2309 2310 p_stats->sent_ucast_bytes += HILO_64_REGPAIR(pstats.sent_ucast_bytes);2311 p_stats->sent_mcast_bytes += HILO_64_REGPAIR(pstats.sent_mcast_bytes);2312 p_stats->sent_bcast_bytes += HILO_64_REGPAIR(pstats.sent_bcast_bytes);2313 p_stats->sent_ucast_pkts += HILO_64_REGPAIR(pstats.sent_ucast_pkts);2314 p_stats->sent_mcast_pkts += HILO_64_REGPAIR(pstats.sent_mcast_pkts);2315 p_stats->sent_bcast_pkts += HILO_64_REGPAIR(pstats.sent_bcast_pkts);2316}2317 2318static int __qed_ll2_get_stats(void *cxt, u8 connection_handle,2319 struct qed_ll2_stats *p_stats)2320{2321 struct qed_hwfn *p_hwfn = cxt;2322 struct qed_ll2_info *p_ll2_conn = NULL;2323 struct qed_ptt *p_ptt;2324 2325 if ((connection_handle >= QED_MAX_NUM_OF_LL2_CONNECTIONS) ||2326 !p_hwfn->p_ll2_info)2327 return -EINVAL;2328 2329 p_ll2_conn = &p_hwfn->p_ll2_info[connection_handle];2330 2331 p_ptt = qed_ptt_acquire(p_hwfn);2332 if (!p_ptt) {2333 DP_ERR(p_hwfn, "Failed to acquire ptt\n");2334 return -EINVAL;2335 }2336 2337 if (p_ll2_conn->input.gsi_enable)2338 _qed_ll2_get_port_stats(p_hwfn, p_ptt, p_stats);2339 2340 _qed_ll2_get_tstats(p_hwfn, p_ptt, p_ll2_conn, p_stats);2341 2342 _qed_ll2_get_ustats(p_hwfn, p_ptt, p_ll2_conn, p_stats);2343 2344 if (p_ll2_conn->tx_stats_en)2345 _qed_ll2_get_pstats(p_hwfn, p_ptt, p_ll2_conn, p_stats);2346 2347 qed_ptt_release(p_hwfn, p_ptt);2348 2349 return 0;2350}2351 2352int qed_ll2_get_stats(void *cxt,2353 u8 connection_handle, struct qed_ll2_stats *p_stats)2354{2355 memset(p_stats, 0, sizeof(*p_stats));2356 return __qed_ll2_get_stats(cxt, connection_handle, p_stats);2357}2358 2359static void qed_ll2b_release_rx_packet(void *cxt,2360 u8 connection_handle,2361 void *cookie,2362 dma_addr_t rx_buf_addr,2363 bool b_last_packet)2364{2365 struct qed_hwfn *p_hwfn = cxt;2366 2367 qed_ll2_dealloc_buffer(p_hwfn->cdev, cookie);2368}2369 2370static void qed_ll2_register_cb_ops(struct qed_dev *cdev,2371 const struct qed_ll2_cb_ops *ops,2372 void *cookie)2373{2374 cdev->ll2->cbs = ops;2375 cdev->ll2->cb_cookie = cookie;2376}2377 2378static struct qed_ll2_cbs ll2_cbs = {2379 .rx_comp_cb = &qed_ll2b_complete_rx_packet,2380 .rx_release_cb = &qed_ll2b_release_rx_packet,2381 .tx_comp_cb = &qed_ll2b_complete_tx_packet,2382 .tx_release_cb = &qed_ll2b_complete_tx_packet,2383};2384 2385static void qed_ll2_set_conn_data(struct qed_hwfn *p_hwfn,2386 struct qed_ll2_acquire_data *data,2387 struct qed_ll2_params *params,2388 enum qed_ll2_conn_type conn_type,2389 u8 *handle, bool lb)2390{2391 memset(data, 0, sizeof(*data));2392 2393 data->input.conn_type = conn_type;2394 data->input.mtu = params->mtu;2395 data->input.rx_num_desc = QED_LL2_RX_SIZE;2396 data->input.rx_drop_ttl0_flg = params->drop_ttl0_packets;2397 data->input.rx_vlan_removal_en = params->rx_vlan_stripping;2398 data->input.tx_num_desc = QED_LL2_TX_SIZE;2399 data->p_connection_handle = handle;2400 data->cbs = &ll2_cbs;2401 ll2_cbs.cookie = p_hwfn;2402 2403 if (lb) {2404 data->input.tx_tc = PKT_LB_TC;2405 data->input.tx_dest = QED_LL2_TX_DEST_LB;2406 } else {2407 data->input.tx_tc = 0;2408 data->input.tx_dest = QED_LL2_TX_DEST_NW;2409 }2410}2411 2412static int qed_ll2_start_ooo(struct qed_hwfn *p_hwfn,2413 struct qed_ll2_params *params)2414{2415 u8 *handle = &p_hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id;2416 struct qed_ll2_acquire_data data;2417 int rc;2418 2419 qed_ll2_set_conn_data(p_hwfn, &data, params,2420 QED_LL2_TYPE_OOO, handle, true);2421 2422 rc = qed_ll2_acquire_connection(p_hwfn, &data);2423 if (rc) {2424 DP_INFO(p_hwfn, "Failed to acquire LL2 OOO connection\n");2425 goto out;2426 }2427 2428 rc = qed_ll2_establish_connection(p_hwfn, *handle);2429 if (rc) {2430 DP_INFO(p_hwfn, "Failed to establish LL2 OOO connection\n");2431 goto fail;2432 }2433 2434 return 0;2435 2436fail:2437 qed_ll2_release_connection(p_hwfn, *handle);2438out:2439 *handle = QED_LL2_UNUSED_HANDLE;2440 return rc;2441}2442 2443static bool qed_ll2_is_storage_eng1(struct qed_dev *cdev)2444{2445 return (QED_IS_FCOE_PERSONALITY(QED_LEADING_HWFN(cdev)) ||2446 QED_IS_ISCSI_PERSONALITY(QED_LEADING_HWFN(cdev)) ||2447 QED_IS_NVMETCP_PERSONALITY(QED_LEADING_HWFN(cdev))) &&2448 (QED_AFFIN_HWFN(cdev) != QED_LEADING_HWFN(cdev));2449}2450 2451static int __qed_ll2_stop(struct qed_hwfn *p_hwfn)2452{2453 struct qed_dev *cdev = p_hwfn->cdev;2454 int rc;2455 2456 rc = qed_ll2_terminate_connection(p_hwfn, cdev->ll2->handle);2457 if (rc)2458 DP_INFO(cdev, "Failed to terminate LL2 connection\n");2459 2460 qed_ll2_release_connection(p_hwfn, cdev->ll2->handle);2461 2462 return rc;2463}2464 2465static int qed_ll2_stop(struct qed_dev *cdev)2466{2467 bool b_is_storage_eng1 = qed_ll2_is_storage_eng1(cdev);2468 struct qed_hwfn *p_hwfn = QED_AFFIN_HWFN(cdev);2469 int rc = 0, rc2 = 0;2470 2471 if (cdev->ll2->handle == QED_LL2_UNUSED_HANDLE)2472 return 0;2473 if (!QED_IS_NVMETCP_PERSONALITY(p_hwfn))2474 qed_llh_remove_mac_filter(cdev, 0, cdev->ll2_mac_address);2475 2476 qed_llh_remove_mac_filter(cdev, 0, cdev->ll2_mac_address);2477 eth_zero_addr(cdev->ll2_mac_address);2478 2479 if (QED_IS_ISCSI_PERSONALITY(p_hwfn) || QED_IS_NVMETCP_PERSONALITY(p_hwfn))2480 qed_ll2_stop_ooo(p_hwfn);2481 2482 /* In CMT mode, LL2 is always started on engine 0 for a storage PF */2483 if (b_is_storage_eng1) {2484 rc2 = __qed_ll2_stop(QED_LEADING_HWFN(cdev));2485 if (rc2)2486 DP_NOTICE(QED_LEADING_HWFN(cdev),2487 "Failed to stop LL2 on engine 0\n");2488 }2489 2490 rc = __qed_ll2_stop(p_hwfn);2491 if (rc)2492 DP_NOTICE(p_hwfn, "Failed to stop LL2\n");2493 2494 qed_ll2_kill_buffers(cdev);2495 2496 cdev->ll2->handle = QED_LL2_UNUSED_HANDLE;2497 2498 return rc | rc2;2499}2500 2501static int __qed_ll2_start(struct qed_hwfn *p_hwfn,2502 struct qed_ll2_params *params)2503{2504 struct qed_ll2_buffer *buffer, *tmp_buffer;2505 struct qed_dev *cdev = p_hwfn->cdev;2506 enum qed_ll2_conn_type conn_type;2507 struct qed_ll2_acquire_data data;2508 int rc, rx_cnt;2509 2510 switch (p_hwfn->hw_info.personality) {2511 case QED_PCI_FCOE:2512 conn_type = QED_LL2_TYPE_FCOE;2513 break;2514 case QED_PCI_ISCSI:2515 case QED_PCI_NVMETCP:2516 conn_type = QED_LL2_TYPE_TCP_ULP;2517 break;2518 case QED_PCI_ETH_ROCE:2519 conn_type = QED_LL2_TYPE_ROCE;2520 break;2521 default:2522 2523 conn_type = QED_LL2_TYPE_TEST;2524 }2525 2526 qed_ll2_set_conn_data(p_hwfn, &data, params, conn_type,2527 &cdev->ll2->handle, false);2528 2529 rc = qed_ll2_acquire_connection(p_hwfn, &data);2530 if (rc) {2531 DP_INFO(p_hwfn, "Failed to acquire LL2 connection\n");2532 return rc;2533 }2534 2535 rc = qed_ll2_establish_connection(p_hwfn, cdev->ll2->handle);2536 if (rc) {2537 DP_INFO(p_hwfn, "Failed to establish LL2 connection\n");2538 goto release_conn;2539 }2540 2541 /* Post all Rx buffers to FW */2542 spin_lock_bh(&cdev->ll2->lock);2543 rx_cnt = cdev->ll2->rx_cnt;2544 list_for_each_entry_safe(buffer, tmp_buffer, &cdev->ll2->list, list) {2545 rc = qed_ll2_post_rx_buffer(p_hwfn,2546 cdev->ll2->handle,2547 buffer->phys_addr, 0, buffer, 1);2548 if (rc) {2549 DP_INFO(p_hwfn,2550 "Failed to post an Rx buffer; Deleting it\n");2551 dma_unmap_single(&cdev->pdev->dev, buffer->phys_addr,2552 cdev->ll2->rx_size, DMA_FROM_DEVICE);2553 kfree(buffer->data);2554 list_del(&buffer->list);2555 kfree(buffer);2556 } else {2557 rx_cnt++;2558 }2559 }2560 spin_unlock_bh(&cdev->ll2->lock);2561 2562 if (rx_cnt == cdev->ll2->rx_cnt) {2563 DP_NOTICE(p_hwfn, "Failed passing even a single Rx buffer\n");2564 goto terminate_conn;2565 }2566 cdev->ll2->rx_cnt = rx_cnt;2567 2568 return 0;2569 2570terminate_conn:2571 qed_ll2_terminate_connection(p_hwfn, cdev->ll2->handle);2572release_conn:2573 qed_ll2_release_connection(p_hwfn, cdev->ll2->handle);2574 return rc;2575}2576 2577static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)2578{2579 bool b_is_storage_eng1 = qed_ll2_is_storage_eng1(cdev);2580 struct qed_hwfn *p_hwfn = QED_AFFIN_HWFN(cdev);2581 struct qed_ll2_buffer *buffer;2582 int rx_num_desc, i, rc;2583 2584 if (!is_valid_ether_addr(params->ll2_mac_address)) {2585 DP_NOTICE(cdev, "Invalid Ethernet address\n");2586 return -EINVAL;2587 }2588 2589 WARN_ON(!cdev->ll2->cbs);2590 2591 /* Initialize LL2 locks & lists */2592 INIT_LIST_HEAD(&cdev->ll2->list);2593 spin_lock_init(&cdev->ll2->lock);2594 2595 cdev->ll2->rx_size = PRM_DMA_PAD_BYTES_NUM + ETH_HLEN +2596 L1_CACHE_BYTES + params->mtu;2597 2598 /* Allocate memory for LL2.2599 * In CMT mode, in case of a storage PF which is affintized to engine 1,2600 * LL2 is started also on engine 0 and thus we need twofold buffers.2601 */2602 rx_num_desc = QED_LL2_RX_SIZE * (b_is_storage_eng1 ? 2 : 1);2603 DP_INFO(cdev, "Allocating %d LL2 buffers of size %08x bytes\n",2604 rx_num_desc, cdev->ll2->rx_size);2605 for (i = 0; i < rx_num_desc; i++) {2606 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);2607 if (!buffer) {2608 DP_INFO(cdev, "Failed to allocate LL2 buffers\n");2609 rc = -ENOMEM;2610 goto err0;2611 }2612 2613 rc = qed_ll2_alloc_buffer(cdev, (u8 **)&buffer->data,2614 &buffer->phys_addr);2615 if (rc) {2616 kfree(buffer);2617 goto err0;2618 }2619 2620 list_add_tail(&buffer->list, &cdev->ll2->list);2621 }2622 2623 rc = __qed_ll2_start(p_hwfn, params);2624 if (rc) {2625 DP_NOTICE(cdev, "Failed to start LL2\n");2626 goto err0;2627 }2628 2629 /* In CMT mode, always need to start LL2 on engine 0 for a storage PF,2630 * since broadcast/mutlicast packets are routed to engine 0.2631 */2632 if (b_is_storage_eng1) {2633 rc = __qed_ll2_start(QED_LEADING_HWFN(cdev), params);2634 if (rc) {2635 DP_NOTICE(QED_LEADING_HWFN(cdev),2636 "Failed to start LL2 on engine 0\n");2637 goto err1;2638 }2639 }2640 2641 if (QED_IS_ISCSI_PERSONALITY(p_hwfn) || QED_IS_NVMETCP_PERSONALITY(p_hwfn)) {2642 DP_VERBOSE(cdev, QED_MSG_STORAGE, "Starting OOO LL2 queue\n");2643 rc = qed_ll2_start_ooo(p_hwfn, params);2644 if (rc) {2645 DP_NOTICE(cdev, "Failed to start OOO LL2\n");2646 goto err2;2647 }2648 }2649 2650 if (!QED_IS_NVMETCP_PERSONALITY(p_hwfn)) {2651 rc = qed_llh_add_mac_filter(cdev, 0, params->ll2_mac_address);2652 if (rc) {2653 DP_NOTICE(cdev, "Failed to add an LLH filter\n");2654 goto err3;2655 }2656 }2657 2658 ether_addr_copy(cdev->ll2_mac_address, params->ll2_mac_address);2659 2660 return 0;2661 2662err3:2663 if (QED_IS_ISCSI_PERSONALITY(p_hwfn) || QED_IS_NVMETCP_PERSONALITY(p_hwfn))2664 qed_ll2_stop_ooo(p_hwfn);2665err2:2666 if (b_is_storage_eng1)2667 __qed_ll2_stop(QED_LEADING_HWFN(cdev));2668err1:2669 __qed_ll2_stop(p_hwfn);2670err0:2671 qed_ll2_kill_buffers(cdev);2672 cdev->ll2->handle = QED_LL2_UNUSED_HANDLE;2673 return rc;2674}2675 2676static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,2677 unsigned long xmit_flags)2678{2679 struct qed_hwfn *p_hwfn = QED_AFFIN_HWFN(cdev);2680 struct qed_ll2_tx_pkt_info pkt;2681 const skb_frag_t *frag;2682 u8 flags = 0, nr_frags;2683 int rc = -EINVAL, i;2684 dma_addr_t mapping;2685 u16 vlan = 0;2686 2687 if (unlikely(skb->ip_summed != CHECKSUM_NONE)) {2688 DP_INFO(cdev, "Cannot transmit a checksummed packet\n");2689 return -EINVAL;2690 }2691 2692 /* Cache number of fragments from SKB since SKB may be freed by2693 * the completion routine after calling qed_ll2_prepare_tx_packet()2694 */2695 nr_frags = skb_shinfo(skb)->nr_frags;2696 2697 if (unlikely(1 + nr_frags > CORE_LL2_TX_MAX_BDS_PER_PACKET)) {2698 DP_ERR(cdev, "Cannot transmit a packet with %d fragments\n",2699 1 + nr_frags);2700 return -EINVAL;2701 }2702 2703 mapping = dma_map_single(&cdev->pdev->dev, skb->data,2704 skb->len, DMA_TO_DEVICE);2705 if (unlikely(dma_mapping_error(&cdev->pdev->dev, mapping))) {2706 DP_NOTICE(cdev, "SKB mapping failed\n");2707 return -EINVAL;2708 }2709 2710 /* Request HW to calculate IP csum */2711 if (!((vlan_get_protocol(skb) == htons(ETH_P_IPV6)) &&2712 ipv6_hdr(skb)->nexthdr == NEXTHDR_IPV6))2713 flags |= BIT(CORE_TX_BD_DATA_IP_CSUM_SHIFT);2714 2715 if (skb_vlan_tag_present(skb)) {2716 vlan = skb_vlan_tag_get(skb);2717 flags |= BIT(CORE_TX_BD_DATA_VLAN_INSERTION_SHIFT);2718 }2719 2720 memset(&pkt, 0, sizeof(pkt));2721 pkt.num_of_bds = 1 + nr_frags;2722 pkt.vlan = vlan;2723 pkt.bd_flags = flags;2724 pkt.tx_dest = QED_LL2_TX_DEST_NW;2725 pkt.first_frag = mapping;2726 pkt.first_frag_len = skb->len;2727 pkt.cookie = skb;2728 if (test_bit(QED_MF_UFP_SPECIFIC, &cdev->mf_bits) &&2729 test_bit(QED_LL2_XMIT_FLAGS_FIP_DISCOVERY, &xmit_flags))2730 pkt.remove_stag = true;2731 2732 /* qed_ll2_prepare_tx_packet() may actually send the packet if2733 * there are no fragments in the skb and subsequently the completion2734 * routine may run and free the SKB, so no dereferencing the SKB2735 * beyond this point unless skb has any fragments.2736 */2737 rc = qed_ll2_prepare_tx_packet(p_hwfn, cdev->ll2->handle,2738 &pkt, 1);2739 if (unlikely(rc))2740 goto err;2741 2742 for (i = 0; i < nr_frags; i++) {2743 frag = &skb_shinfo(skb)->frags[i];2744 2745 mapping = skb_frag_dma_map(&cdev->pdev->dev, frag, 0,2746 skb_frag_size(frag), DMA_TO_DEVICE);2747 2748 if (unlikely(dma_mapping_error(&cdev->pdev->dev, mapping))) {2749 DP_NOTICE(cdev,2750 "Unable to map frag - dropping packet\n");2751 rc = -ENOMEM;2752 goto err;2753 }2754 2755 rc = qed_ll2_set_fragment_of_tx_packet(p_hwfn,2756 cdev->ll2->handle,2757 mapping,2758 skb_frag_size(frag));2759 2760 /* if failed not much to do here, partial packet has been posted2761 * we can't free memory, will need to wait for completion2762 */2763 if (unlikely(rc))2764 goto err2;2765 }2766 2767 return 0;2768 2769err:2770 dma_unmap_single(&cdev->pdev->dev, mapping, skb->len, DMA_TO_DEVICE);2771err2:2772 return rc;2773}2774 2775static int qed_ll2_stats(struct qed_dev *cdev, struct qed_ll2_stats *stats)2776{2777 bool b_is_storage_eng1 = qed_ll2_is_storage_eng1(cdev);2778 struct qed_hwfn *p_hwfn = QED_AFFIN_HWFN(cdev);2779 int rc;2780 2781 if (!cdev->ll2)2782 return -EINVAL;2783 2784 rc = qed_ll2_get_stats(p_hwfn, cdev->ll2->handle, stats);2785 if (rc) {2786 DP_NOTICE(p_hwfn, "Failed to get LL2 stats\n");2787 return rc;2788 }2789 2790 /* In CMT mode, LL2 is always started on engine 0 for a storage PF */2791 if (b_is_storage_eng1) {2792 rc = __qed_ll2_get_stats(QED_LEADING_HWFN(cdev),2793 cdev->ll2->handle, stats);2794 if (rc) {2795 DP_NOTICE(QED_LEADING_HWFN(cdev),2796 "Failed to get LL2 stats on engine 0\n");2797 return rc;2798 }2799 }2800 2801 return 0;2802}2803 2804const struct qed_ll2_ops qed_ll2_ops_pass = {2805 .start = &qed_ll2_start,2806 .stop = &qed_ll2_stop,2807 .start_xmit = &qed_ll2_start_xmit,2808 .register_cb_ops = &qed_ll2_register_cb_ops,2809 .get_stats = &qed_ll2_stats,2810};2811 2812int qed_ll2_alloc_if(struct qed_dev *cdev)2813{2814 cdev->ll2 = kzalloc(sizeof(*cdev->ll2), GFP_KERNEL);2815 return cdev->ll2 ? 0 : -ENOMEM;2816}2817 2818void qed_ll2_dealloc_if(struct qed_dev *cdev)2819{2820 kfree(cdev->ll2);2821 cdev->ll2 = NULL;2822}2823