linux/drivers/net/ethernet/qlogic/qed/qed_fcoe.c
<<
>>
Prefs
   1/* QLogic qed NIC Driver
   2 * Copyright (c) 2015-2017  QLogic Corporation
   3 *
   4 * This software is available to you under a choice of one of two
   5 * licenses.  You may choose to be licensed under the terms of the GNU
   6 * General Public License (GPL) Version 2, available from the file
   7 * COPYING in the main directory of this source tree, or the
   8 * OpenIB.org BSD license below:
   9 *
  10 *     Redistribution and use in source and binary forms, with or
  11 *     without modification, are permitted provided that the following
  12 *     conditions are met:
  13 *
  14 *      - Redistributions of source code must retain the above
  15 *        copyright notice, this list of conditions and the following
  16 *        disclaimer.
  17 *
  18 *      - Redistributions in binary form must reproduce the above
  19 *        copyright notice, this list of conditions and the following
  20 *        disclaimer in the documentation and /or other materials
  21 *        provided with the distribution.
  22 *
  23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30 * SOFTWARE.
  31 */
  32
  33#include <linux/types.h>
  34#include <asm/byteorder.h>
  35#include <asm/param.h>
  36#include <linux/delay.h>
  37#include <linux/dma-mapping.h>
  38#include <linux/interrupt.h>
  39#include <linux/kernel.h>
  40#include <linux/log2.h>
  41#include <linux/module.h>
  42#include <linux/pci.h>
  43#include <linux/slab.h>
  44#include <linux/stddef.h>
  45#include <linux/string.h>
  46#include <linux/workqueue.h>
  47#include <linux/errno.h>
  48#include <linux/list.h>
  49#include <linux/spinlock.h>
  50#define __PREVENT_DUMP_MEM_ARR__
  51#define __PREVENT_PXP_GLOBAL_WIN__
  52#include "qed.h"
  53#include "qed_cxt.h"
  54#include "qed_dev_api.h"
  55#include "qed_fcoe.h"
  56#include "qed_hsi.h"
  57#include "qed_hw.h"
  58#include "qed_int.h"
  59#include "qed_ll2.h"
  60#include "qed_mcp.h"
  61#include "qed_reg_addr.h"
  62#include "qed_sp.h"
  63#include "qed_sriov.h"
  64#include <linux/qed/qed_fcoe_if.h>
  65
  66struct qed_fcoe_conn {
  67        struct list_head list_entry;
  68        bool free_on_delete;
  69
  70        u16 conn_id;
  71        u32 icid;
  72        u32 fw_cid;
  73        u8 layer_code;
  74
  75        dma_addr_t sq_pbl_addr;
  76        dma_addr_t sq_curr_page_addr;
  77        dma_addr_t sq_next_page_addr;
  78        dma_addr_t xferq_pbl_addr;
  79        void *xferq_pbl_addr_virt_addr;
  80        dma_addr_t xferq_addr[4];
  81        void *xferq_addr_virt_addr[4];
  82        dma_addr_t confq_pbl_addr;
  83        void *confq_pbl_addr_virt_addr;
  84        dma_addr_t confq_addr[2];
  85        void *confq_addr_virt_addr[2];
  86
  87        dma_addr_t terminate_params;
  88
  89        u16 dst_mac_addr_lo;
  90        u16 dst_mac_addr_mid;
  91        u16 dst_mac_addr_hi;
  92        u16 src_mac_addr_lo;
  93        u16 src_mac_addr_mid;
  94        u16 src_mac_addr_hi;
  95
  96        u16 tx_max_fc_pay_len;
  97        u16 e_d_tov_timer_val;
  98        u16 rec_tov_timer_val;
  99        u16 rx_max_fc_pay_len;
 100        u16 vlan_tag;
 101        u16 physical_q0;
 102
 103        struct fc_addr_nw s_id;
 104        u8 max_conc_seqs_c3;
 105        struct fc_addr_nw d_id;
 106        u8 flags;
 107        u8 def_q_idx;
 108};
 109
 110static int
 111qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn,
 112                       enum spq_mode comp_mode,
 113                       struct qed_spq_comp_cb *p_comp_addr)
 114{
 115        struct qed_fcoe_pf_params *fcoe_pf_params = NULL;
 116        struct fcoe_init_ramrod_params *p_ramrod = NULL;
 117        struct fcoe_init_func_ramrod_data *p_data;
 118        struct e4_fcoe_conn_context *p_cxt = NULL;
 119        struct qed_spq_entry *p_ent = NULL;
 120        struct qed_sp_init_data init_data;
 121        struct qed_cxt_info cxt_info;
 122        u32 dummy_cid;
 123        int rc = 0;
 124        u16 tmp;
 125        u8 i;
 126
 127        /* Get SPQ entry */
 128        memset(&init_data, 0, sizeof(init_data));
 129        init_data.cid = qed_spq_get_cid(p_hwfn);
 130        init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
 131        init_data.comp_mode = comp_mode;
 132        init_data.p_comp_data = p_comp_addr;
 133
 134        rc = qed_sp_init_request(p_hwfn, &p_ent,
 135                                 FCOE_RAMROD_CMD_ID_INIT_FUNC,
 136                                 PROTOCOLID_FCOE, &init_data);
 137        if (rc)
 138                return rc;
 139
 140        p_ramrod = &p_ent->ramrod.fcoe_init;
 141        p_data = &p_ramrod->init_ramrod_data;
 142        fcoe_pf_params = &p_hwfn->pf_params.fcoe_pf_params;
 143
 144        /* Sanity */
 145        if (fcoe_pf_params->num_cqs > p_hwfn->hw_info.feat_num[QED_FCOE_CQ]) {
 146                DP_ERR(p_hwfn,
 147                       "Cannot satisfy CQ amount. CQs requested %d, CQs available %d. Aborting function start\n",
 148                       fcoe_pf_params->num_cqs,
 149                       p_hwfn->hw_info.feat_num[QED_FCOE_CQ]);
 150                rc = -EINVAL;
 151                goto err;
 152        }
 153
 154        p_data->mtu = cpu_to_le16(fcoe_pf_params->mtu);
 155        tmp = cpu_to_le16(fcoe_pf_params->sq_num_pbl_pages);
 156        p_data->sq_num_pages_in_pbl = tmp;
 157
 158        rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_FCOE, &dummy_cid);
 159        if (rc)
 160                goto err;
 161
 162        cxt_info.iid = dummy_cid;
 163        rc = qed_cxt_get_cid_info(p_hwfn, &cxt_info);
 164        if (rc) {
 165                DP_NOTICE(p_hwfn, "Cannot find context info for dummy cid=%d\n",
 166                          dummy_cid);
 167                goto err;
 168        }
 169        p_cxt = cxt_info.p_cxt;
 170        SET_FIELD(p_cxt->tstorm_ag_context.flags3,
 171                  E4_TSTORM_FCOE_CONN_AG_CTX_DUMMY_TIMER_CF_EN, 1);
 172
 173        fcoe_pf_params->dummy_icid = (u16)dummy_cid;
 174
 175        tmp = cpu_to_le16(fcoe_pf_params->num_tasks);
 176        p_data->func_params.num_tasks = tmp;
 177        p_data->func_params.log_page_size = fcoe_pf_params->log_page_size;
 178        p_data->func_params.debug_mode = fcoe_pf_params->debug_mode;
 179
 180        DMA_REGPAIR_LE(p_data->q_params.glbl_q_params_addr,
 181                       fcoe_pf_params->glbl_q_params_addr);
 182
 183        tmp = cpu_to_le16(fcoe_pf_params->cq_num_entries);
 184        p_data->q_params.cq_num_entries = tmp;
 185
 186        tmp = cpu_to_le16(fcoe_pf_params->cmdq_num_entries);
 187        p_data->q_params.cmdq_num_entries = tmp;
 188
 189        tmp = fcoe_pf_params->num_cqs;
 190        p_data->q_params.num_queues = (u8)tmp;
 191
 192        tmp = (u16)p_hwfn->hw_info.resc_start[QED_CMDQS_CQS];
 193        p_data->q_params.queue_relative_offset = (u8)tmp;
 194
 195        for (i = 0; i < fcoe_pf_params->num_cqs; i++) {
 196                u16 igu_sb_id;
 197
 198                igu_sb_id = qed_get_igu_sb_id(p_hwfn, i);
 199                tmp = cpu_to_le16(igu_sb_id);
 200                p_data->q_params.cq_cmdq_sb_num_arr[i] = tmp;
 201        }
 202
 203        p_data->q_params.cq_sb_pi = fcoe_pf_params->gl_rq_pi;
 204        p_data->q_params.cmdq_sb_pi = fcoe_pf_params->gl_cmd_pi;
 205
 206        p_data->q_params.bdq_resource_id = (u8)RESC_START(p_hwfn, QED_BDQ);
 207
 208        DMA_REGPAIR_LE(p_data->q_params.bdq_pbl_base_address[BDQ_ID_RQ],
 209                       fcoe_pf_params->bdq_pbl_base_addr[BDQ_ID_RQ]);
 210        p_data->q_params.bdq_pbl_num_entries[BDQ_ID_RQ] =
 211            fcoe_pf_params->bdq_pbl_num_entries[BDQ_ID_RQ];
 212        tmp = fcoe_pf_params->bdq_xoff_threshold[BDQ_ID_RQ];
 213        p_data->q_params.bdq_xoff_threshold[BDQ_ID_RQ] = cpu_to_le16(tmp);
 214        tmp = fcoe_pf_params->bdq_xon_threshold[BDQ_ID_RQ];
 215        p_data->q_params.bdq_xon_threshold[BDQ_ID_RQ] = cpu_to_le16(tmp);
 216
 217        DMA_REGPAIR_LE(p_data->q_params.bdq_pbl_base_address[BDQ_ID_IMM_DATA],
 218                       fcoe_pf_params->bdq_pbl_base_addr[BDQ_ID_IMM_DATA]);
 219        p_data->q_params.bdq_pbl_num_entries[BDQ_ID_IMM_DATA] =
 220            fcoe_pf_params->bdq_pbl_num_entries[BDQ_ID_IMM_DATA];
 221        tmp = fcoe_pf_params->bdq_xoff_threshold[BDQ_ID_IMM_DATA];
 222        p_data->q_params.bdq_xoff_threshold[BDQ_ID_IMM_DATA] = cpu_to_le16(tmp);
 223        tmp = fcoe_pf_params->bdq_xon_threshold[BDQ_ID_IMM_DATA];
 224        p_data->q_params.bdq_xon_threshold[BDQ_ID_IMM_DATA] = cpu_to_le16(tmp);
 225        tmp = fcoe_pf_params->rq_buffer_size;
 226        p_data->q_params.rq_buffer_size = cpu_to_le16(tmp);
 227
 228        if (fcoe_pf_params->is_target) {
 229                SET_FIELD(p_data->q_params.q_validity,
 230                          SCSI_INIT_FUNC_QUEUES_RQ_VALID, 1);
 231                if (p_data->q_params.bdq_pbl_num_entries[BDQ_ID_IMM_DATA])
 232                        SET_FIELD(p_data->q_params.q_validity,
 233                                  SCSI_INIT_FUNC_QUEUES_IMM_DATA_VALID, 1);
 234                SET_FIELD(p_data->q_params.q_validity,
 235                          SCSI_INIT_FUNC_QUEUES_CMD_VALID, 1);
 236        } else {
 237                SET_FIELD(p_data->q_params.q_validity,
 238                          SCSI_INIT_FUNC_QUEUES_RQ_VALID, 1);
 239        }
 240
 241        rc = qed_spq_post(p_hwfn, p_ent, NULL);
 242
 243        return rc;
 244
 245err:
 246        qed_sp_destroy_request(p_hwfn, p_ent);
 247        return rc;
 248}
 249
 250static int
 251qed_sp_fcoe_conn_offload(struct qed_hwfn *p_hwfn,
 252                         struct qed_fcoe_conn *p_conn,
 253                         enum spq_mode comp_mode,
 254                         struct qed_spq_comp_cb *p_comp_addr)
 255{
 256        struct fcoe_conn_offload_ramrod_params *p_ramrod = NULL;
 257        struct fcoe_conn_offload_ramrod_data *p_data;
 258        struct qed_spq_entry *p_ent = NULL;
 259        struct qed_sp_init_data init_data;
 260        u16 physical_q0, tmp;
 261        int rc;
 262
 263        /* Get SPQ entry */
 264        memset(&init_data, 0, sizeof(init_data));
 265        init_data.cid = p_conn->icid;
 266        init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
 267        init_data.comp_mode = comp_mode;
 268        init_data.p_comp_data = p_comp_addr;
 269
 270        rc = qed_sp_init_request(p_hwfn, &p_ent,
 271                                 FCOE_RAMROD_CMD_ID_OFFLOAD_CONN,
 272                                 PROTOCOLID_FCOE, &init_data);
 273        if (rc)
 274                return rc;
 275
 276        p_ramrod = &p_ent->ramrod.fcoe_conn_ofld;
 277        p_data = &p_ramrod->offload_ramrod_data;
 278
 279        /* Transmission PQ is the first of the PF */
 280        physical_q0 = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OFLD);
 281        p_conn->physical_q0 = cpu_to_le16(physical_q0);
 282        p_data->physical_q0 = cpu_to_le16(physical_q0);
 283
 284        p_data->conn_id = cpu_to_le16(p_conn->conn_id);
 285        DMA_REGPAIR_LE(p_data->sq_pbl_addr, p_conn->sq_pbl_addr);
 286        DMA_REGPAIR_LE(p_data->sq_curr_page_addr, p_conn->sq_curr_page_addr);
 287        DMA_REGPAIR_LE(p_data->sq_next_page_addr, p_conn->sq_next_page_addr);
 288        DMA_REGPAIR_LE(p_data->xferq_pbl_addr, p_conn->xferq_pbl_addr);
 289        DMA_REGPAIR_LE(p_data->xferq_curr_page_addr, p_conn->xferq_addr[0]);
 290        DMA_REGPAIR_LE(p_data->xferq_next_page_addr, p_conn->xferq_addr[1]);
 291
 292        DMA_REGPAIR_LE(p_data->respq_pbl_addr, p_conn->confq_pbl_addr);
 293        DMA_REGPAIR_LE(p_data->respq_curr_page_addr, p_conn->confq_addr[0]);
 294        DMA_REGPAIR_LE(p_data->respq_next_page_addr, p_conn->confq_addr[1]);
 295
 296        p_data->dst_mac_addr_lo = cpu_to_le16(p_conn->dst_mac_addr_lo);
 297        p_data->dst_mac_addr_mid = cpu_to_le16(p_conn->dst_mac_addr_mid);
 298        p_data->dst_mac_addr_hi = cpu_to_le16(p_conn->dst_mac_addr_hi);
 299        p_data->src_mac_addr_lo = cpu_to_le16(p_conn->src_mac_addr_lo);
 300        p_data->src_mac_addr_mid = cpu_to_le16(p_conn->src_mac_addr_mid);
 301        p_data->src_mac_addr_hi = cpu_to_le16(p_conn->src_mac_addr_hi);
 302
 303        tmp = cpu_to_le16(p_conn->tx_max_fc_pay_len);
 304        p_data->tx_max_fc_pay_len = tmp;
 305        tmp = cpu_to_le16(p_conn->e_d_tov_timer_val);
 306        p_data->e_d_tov_timer_val = tmp;
 307        tmp = cpu_to_le16(p_conn->rec_tov_timer_val);
 308        p_data->rec_rr_tov_timer_val = tmp;
 309        tmp = cpu_to_le16(p_conn->rx_max_fc_pay_len);
 310        p_data->rx_max_fc_pay_len = tmp;
 311
 312        p_data->vlan_tag = cpu_to_le16(p_conn->vlan_tag);
 313        p_data->s_id.addr_hi = p_conn->s_id.addr_hi;
 314        p_data->s_id.addr_mid = p_conn->s_id.addr_mid;
 315        p_data->s_id.addr_lo = p_conn->s_id.addr_lo;
 316        p_data->max_conc_seqs_c3 = p_conn->max_conc_seqs_c3;
 317        p_data->d_id.addr_hi = p_conn->d_id.addr_hi;
 318        p_data->d_id.addr_mid = p_conn->d_id.addr_mid;
 319        p_data->d_id.addr_lo = p_conn->d_id.addr_lo;
 320        p_data->flags = p_conn->flags;
 321        if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits))
 322                SET_FIELD(p_data->flags,
 323                          FCOE_CONN_OFFLOAD_RAMROD_DATA_B_SINGLE_VLAN, 1);
 324        p_data->def_q_idx = p_conn->def_q_idx;
 325
 326        return qed_spq_post(p_hwfn, p_ent, NULL);
 327}
 328
 329static int
 330qed_sp_fcoe_conn_destroy(struct qed_hwfn *p_hwfn,
 331                         struct qed_fcoe_conn *p_conn,
 332                         enum spq_mode comp_mode,
 333                         struct qed_spq_comp_cb *p_comp_addr)
 334{
 335        struct fcoe_conn_terminate_ramrod_params *p_ramrod = NULL;
 336        struct qed_spq_entry *p_ent = NULL;
 337        struct qed_sp_init_data init_data;
 338        int rc = 0;
 339
 340        /* Get SPQ entry */
 341        memset(&init_data, 0, sizeof(init_data));
 342        init_data.cid = p_conn->icid;
 343        init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
 344        init_data.comp_mode = comp_mode;
 345        init_data.p_comp_data = p_comp_addr;
 346
 347        rc = qed_sp_init_request(p_hwfn, &p_ent,
 348                                 FCOE_RAMROD_CMD_ID_TERMINATE_CONN,
 349                                 PROTOCOLID_FCOE, &init_data);
 350        if (rc)
 351                return rc;
 352
 353        p_ramrod = &p_ent->ramrod.fcoe_conn_terminate;
 354        DMA_REGPAIR_LE(p_ramrod->terminate_ramrod_data.terminate_params_addr,
 355                       p_conn->terminate_params);
 356
 357        return qed_spq_post(p_hwfn, p_ent, NULL);
 358}
 359
 360static int
 361qed_sp_fcoe_func_stop(struct qed_hwfn *p_hwfn,
 362                      struct qed_ptt *p_ptt,
 363                      enum spq_mode comp_mode,
 364                      struct qed_spq_comp_cb *p_comp_addr)
 365{
 366        struct qed_spq_entry *p_ent = NULL;
 367        struct qed_sp_init_data init_data;
 368        u32 active_segs = 0;
 369        int rc = 0;
 370
 371        /* Get SPQ entry */
 372        memset(&init_data, 0, sizeof(init_data));
 373        init_data.cid = p_hwfn->pf_params.fcoe_pf_params.dummy_icid;
 374        init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
 375        init_data.comp_mode = comp_mode;
 376        init_data.p_comp_data = p_comp_addr;
 377
 378        rc = qed_sp_init_request(p_hwfn, &p_ent,
 379                                 FCOE_RAMROD_CMD_ID_DESTROY_FUNC,
 380                                 PROTOCOLID_FCOE, &init_data);
 381        if (rc)
 382                return rc;
 383
 384        active_segs = qed_rd(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK);
 385        active_segs &= ~BIT(QED_CXT_FCOE_TID_SEG);
 386        qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, active_segs);
 387
 388        return qed_spq_post(p_hwfn, p_ent, NULL);
 389}
 390
 391static int
 392qed_fcoe_allocate_connection(struct qed_hwfn *p_hwfn,
 393                             struct qed_fcoe_conn **p_out_conn)
 394{
 395        struct qed_fcoe_conn *p_conn = NULL;
 396        void *p_addr;
 397        u32 i;
 398
 399        spin_lock_bh(&p_hwfn->p_fcoe_info->lock);
 400        if (!list_empty(&p_hwfn->p_fcoe_info->free_list))
 401                p_conn =
 402                    list_first_entry(&p_hwfn->p_fcoe_info->free_list,
 403                                     struct qed_fcoe_conn, list_entry);
 404        if (p_conn) {
 405                list_del(&p_conn->list_entry);
 406                spin_unlock_bh(&p_hwfn->p_fcoe_info->lock);
 407                *p_out_conn = p_conn;
 408                return 0;
 409        }
 410        spin_unlock_bh(&p_hwfn->p_fcoe_info->lock);
 411
 412        p_conn = kzalloc(sizeof(*p_conn), GFP_KERNEL);
 413        if (!p_conn)
 414                return -ENOMEM;
 415
 416        p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
 417                                    QED_CHAIN_PAGE_SIZE,
 418                                    &p_conn->xferq_pbl_addr, GFP_KERNEL);
 419        if (!p_addr)
 420                goto nomem_pbl_xferq;
 421        p_conn->xferq_pbl_addr_virt_addr = p_addr;
 422
 423        for (i = 0; i < ARRAY_SIZE(p_conn->xferq_addr); i++) {
 424                p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
 425                                            QED_CHAIN_PAGE_SIZE,
 426                                            &p_conn->xferq_addr[i], GFP_KERNEL);
 427                if (!p_addr)
 428                        goto nomem_xferq;
 429                p_conn->xferq_addr_virt_addr[i] = p_addr;
 430
 431                p_addr = p_conn->xferq_pbl_addr_virt_addr;
 432                ((dma_addr_t *)p_addr)[i] = p_conn->xferq_addr[i];
 433        }
 434
 435        p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
 436                                    QED_CHAIN_PAGE_SIZE,
 437                                    &p_conn->confq_pbl_addr, GFP_KERNEL);
 438        if (!p_addr)
 439                goto nomem_xferq;
 440        p_conn->confq_pbl_addr_virt_addr = p_addr;
 441
 442        for (i = 0; i < ARRAY_SIZE(p_conn->confq_addr); i++) {
 443                p_addr = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
 444                                            QED_CHAIN_PAGE_SIZE,
 445                                            &p_conn->confq_addr[i], GFP_KERNEL);
 446                if (!p_addr)
 447                        goto nomem_confq;
 448                p_conn->confq_addr_virt_addr[i] = p_addr;
 449
 450                p_addr = p_conn->confq_pbl_addr_virt_addr;
 451                ((dma_addr_t *)p_addr)[i] = p_conn->confq_addr[i];
 452        }
 453
 454        p_conn->free_on_delete = true;
 455        *p_out_conn = p_conn;
 456        return 0;
 457
 458nomem_confq:
 459        dma_free_coherent(&p_hwfn->cdev->pdev->dev,
 460                          QED_CHAIN_PAGE_SIZE,
 461                          p_conn->confq_pbl_addr_virt_addr,
 462                          p_conn->confq_pbl_addr);
 463        for (i = 0; i < ARRAY_SIZE(p_conn->confq_addr); i++)
 464                if (p_conn->confq_addr_virt_addr[i])
 465                        dma_free_coherent(&p_hwfn->cdev->pdev->dev,
 466                                          QED_CHAIN_PAGE_SIZE,
 467                                          p_conn->confq_addr_virt_addr[i],
 468                                          p_conn->confq_addr[i]);
 469nomem_xferq:
 470        dma_free_coherent(&p_hwfn->cdev->pdev->dev,
 471                          QED_CHAIN_PAGE_SIZE,
 472                          p_conn->xferq_pbl_addr_virt_addr,
 473                          p_conn->xferq_pbl_addr);
 474        for (i = 0; i < ARRAY_SIZE(p_conn->xferq_addr); i++)
 475                if (p_conn->xferq_addr_virt_addr[i])
 476                        dma_free_coherent(&p_hwfn->cdev->pdev->dev,
 477                                          QED_CHAIN_PAGE_SIZE,
 478                                          p_conn->xferq_addr_virt_addr[i],
 479                                          p_conn->xferq_addr[i]);
 480nomem_pbl_xferq:
 481        kfree(p_conn);
 482        return -ENOMEM;
 483}
 484
 485static void qed_fcoe_free_connection(struct qed_hwfn *p_hwfn,
 486                                     struct qed_fcoe_conn *p_conn)
 487{
 488        u32 i;
 489
 490        if (!p_conn)
 491                return;
 492
 493        if (p_conn->confq_pbl_addr_virt_addr)
 494                dma_free_coherent(&p_hwfn->cdev->pdev->dev,
 495                                  QED_CHAIN_PAGE_SIZE,
 496                                  p_conn->confq_pbl_addr_virt_addr,
 497                                  p_conn->confq_pbl_addr);
 498
 499        for (i = 0; i < ARRAY_SIZE(p_conn->confq_addr); i++) {
 500                if (!p_conn->confq_addr_virt_addr[i])
 501                        continue;
 502                dma_free_coherent(&p_hwfn->cdev->pdev->dev,
 503                                  QED_CHAIN_PAGE_SIZE,
 504                                  p_conn->confq_addr_virt_addr[i],
 505                                  p_conn->confq_addr[i]);
 506        }
 507
 508        if (p_conn->xferq_pbl_addr_virt_addr)
 509                dma_free_coherent(&p_hwfn->cdev->pdev->dev,
 510                                  QED_CHAIN_PAGE_SIZE,
 511                                  p_conn->xferq_pbl_addr_virt_addr,
 512                                  p_conn->xferq_pbl_addr);
 513
 514        for (i = 0; i < ARRAY_SIZE(p_conn->xferq_addr); i++) {
 515                if (!p_conn->xferq_addr_virt_addr[i])
 516                        continue;
 517                dma_free_coherent(&p_hwfn->cdev->pdev->dev,
 518                                  QED_CHAIN_PAGE_SIZE,
 519                                  p_conn->xferq_addr_virt_addr[i],
 520                                  p_conn->xferq_addr[i]);
 521        }
 522        kfree(p_conn);
 523}
 524
 525static void __iomem *qed_fcoe_get_db_addr(struct qed_hwfn *p_hwfn, u32 cid)
 526{
 527        return (u8 __iomem *)p_hwfn->doorbells +
 528               qed_db_addr(cid, DQ_DEMS_LEGACY);
 529}
 530
 531static void __iomem *qed_fcoe_get_primary_bdq_prod(struct qed_hwfn *p_hwfn,
 532                                                   u8 bdq_id)
 533{
 534        if (RESC_NUM(p_hwfn, QED_BDQ)) {
 535                return (u8 __iomem *)p_hwfn->regview +
 536                       GTT_BAR0_MAP_REG_MSDM_RAM +
 537                       MSTORM_SCSI_BDQ_EXT_PROD_OFFSET(RESC_START(p_hwfn,
 538                                                                  QED_BDQ),
 539                                                       bdq_id);
 540        } else {
 541                DP_NOTICE(p_hwfn, "BDQ is not allocated!\n");
 542                return NULL;
 543        }
 544}
 545
 546static void __iomem *qed_fcoe_get_secondary_bdq_prod(struct qed_hwfn *p_hwfn,
 547                                                     u8 bdq_id)
 548{
 549        if (RESC_NUM(p_hwfn, QED_BDQ)) {
 550                return (u8 __iomem *)p_hwfn->regview +
 551                       GTT_BAR0_MAP_REG_TSDM_RAM +
 552                       TSTORM_SCSI_BDQ_EXT_PROD_OFFSET(RESC_START(p_hwfn,
 553                                                                  QED_BDQ),
 554                                                       bdq_id);
 555        } else {
 556                DP_NOTICE(p_hwfn, "BDQ is not allocated!\n");
 557                return NULL;
 558        }
 559}
 560
 561int qed_fcoe_alloc(struct qed_hwfn *p_hwfn)
 562{
 563        struct qed_fcoe_info *p_fcoe_info;
 564
 565        /* Allocate LL2's set struct */
 566        p_fcoe_info = kzalloc(sizeof(*p_fcoe_info), GFP_KERNEL);
 567        if (!p_fcoe_info) {
 568                DP_NOTICE(p_hwfn, "Failed to allocate qed_fcoe_info'\n");
 569                return -ENOMEM;
 570        }
 571        INIT_LIST_HEAD(&p_fcoe_info->free_list);
 572
 573        p_hwfn->p_fcoe_info = p_fcoe_info;
 574        return 0;
 575}
 576
 577void qed_fcoe_setup(struct qed_hwfn *p_hwfn)
 578{
 579        struct e4_fcoe_task_context *p_task_ctx = NULL;
 580        int rc;
 581        u32 i;
 582
 583        spin_lock_init(&p_hwfn->p_fcoe_info->lock);
 584        for (i = 0; i < p_hwfn->pf_params.fcoe_pf_params.num_tasks; i++) {
 585                rc = qed_cxt_get_task_ctx(p_hwfn, i,
 586                                          QED_CTX_WORKING_MEM,
 587                                          (void **)&p_task_ctx);
 588                if (rc)
 589                        continue;
 590
 591                memset(p_task_ctx, 0, sizeof(struct e4_fcoe_task_context));
 592                SET_FIELD(p_task_ctx->timer_context.logical_client_0,
 593                          TIMERS_CONTEXT_VALIDLC0, 1);
 594                SET_FIELD(p_task_ctx->timer_context.logical_client_1,
 595                          TIMERS_CONTEXT_VALIDLC1, 1);
 596                SET_FIELD(p_task_ctx->tstorm_ag_context.flags0,
 597                          E4_TSTORM_FCOE_TASK_AG_CTX_CONNECTION_TYPE, 1);
 598        }
 599}
 600
 601void qed_fcoe_free(struct qed_hwfn *p_hwfn)
 602{
 603        struct qed_fcoe_conn *p_conn = NULL;
 604
 605        if (!p_hwfn->p_fcoe_info)
 606                return;
 607
 608        while (!list_empty(&p_hwfn->p_fcoe_info->free_list)) {
 609                p_conn = list_first_entry(&p_hwfn->p_fcoe_info->free_list,
 610                                          struct qed_fcoe_conn, list_entry);
 611                if (!p_conn)
 612                        break;
 613                list_del(&p_conn->list_entry);
 614                qed_fcoe_free_connection(p_hwfn, p_conn);
 615        }
 616
 617        kfree(p_hwfn->p_fcoe_info);
 618        p_hwfn->p_fcoe_info = NULL;
 619}
 620
 621static int
 622qed_fcoe_acquire_connection(struct qed_hwfn *p_hwfn,
 623                            struct qed_fcoe_conn *p_in_conn,
 624                            struct qed_fcoe_conn **p_out_conn)
 625{
 626        struct qed_fcoe_conn *p_conn = NULL;
 627        int rc = 0;
 628        u32 icid;
 629
 630        spin_lock_bh(&p_hwfn->p_fcoe_info->lock);
 631        rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_FCOE, &icid);
 632        spin_unlock_bh(&p_hwfn->p_fcoe_info->lock);
 633        if (rc)
 634                return rc;
 635
 636        /* Use input connection [if provided] or allocate a new one */
 637        if (p_in_conn) {
 638                p_conn = p_in_conn;
 639        } else {
 640                rc = qed_fcoe_allocate_connection(p_hwfn, &p_conn);
 641                if (rc) {
 642                        spin_lock_bh(&p_hwfn->p_fcoe_info->lock);
 643                        qed_cxt_release_cid(p_hwfn, icid);
 644                        spin_unlock_bh(&p_hwfn->p_fcoe_info->lock);
 645                        return rc;
 646                }
 647        }
 648
 649        p_conn->icid = icid;
 650        p_conn->fw_cid = (p_hwfn->hw_info.opaque_fid << 16) | icid;
 651        *p_out_conn = p_conn;
 652
 653        return rc;
 654}
 655
 656static void qed_fcoe_release_connection(struct qed_hwfn *p_hwfn,
 657                                        struct qed_fcoe_conn *p_conn)
 658{
 659        spin_lock_bh(&p_hwfn->p_fcoe_info->lock);
 660        list_add_tail(&p_conn->list_entry, &p_hwfn->p_fcoe_info->free_list);
 661        qed_cxt_release_cid(p_hwfn, p_conn->icid);
 662        spin_unlock_bh(&p_hwfn->p_fcoe_info->lock);
 663}
 664
 665static void _qed_fcoe_get_tstats(struct qed_hwfn *p_hwfn,
 666                                 struct qed_ptt *p_ptt,
 667                                 struct qed_fcoe_stats *p_stats)
 668{
 669        struct fcoe_rx_stat tstats;
 670        u32 tstats_addr;
 671
 672        memset(&tstats, 0, sizeof(tstats));
 673        tstats_addr = BAR0_MAP_REG_TSDM_RAM +
 674            TSTORM_FCOE_RX_STATS_OFFSET(p_hwfn->rel_pf_id);
 675        qed_memcpy_from(p_hwfn, p_ptt, &tstats, tstats_addr, sizeof(tstats));
 676
 677        p_stats->fcoe_rx_byte_cnt = HILO_64_REGPAIR(tstats.fcoe_rx_byte_cnt);
 678        p_stats->fcoe_rx_data_pkt_cnt =
 679            HILO_64_REGPAIR(tstats.fcoe_rx_data_pkt_cnt);
 680        p_stats->fcoe_rx_xfer_pkt_cnt =
 681            HILO_64_REGPAIR(tstats.fcoe_rx_xfer_pkt_cnt);
 682        p_stats->fcoe_rx_other_pkt_cnt =
 683            HILO_64_REGPAIR(tstats.fcoe_rx_other_pkt_cnt);
 684
 685        p_stats->fcoe_silent_drop_pkt_cmdq_full_cnt =
 686            le32_to_cpu(tstats.fcoe_silent_drop_pkt_cmdq_full_cnt);
 687        p_stats->fcoe_silent_drop_pkt_rq_full_cnt =
 688            le32_to_cpu(tstats.fcoe_silent_drop_pkt_rq_full_cnt);
 689        p_stats->fcoe_silent_drop_pkt_crc_error_cnt =
 690            le32_to_cpu(tstats.fcoe_silent_drop_pkt_crc_error_cnt);
 691        p_stats->fcoe_silent_drop_pkt_task_invalid_cnt =
 692            le32_to_cpu(tstats.fcoe_silent_drop_pkt_task_invalid_cnt);
 693        p_stats->fcoe_silent_drop_total_pkt_cnt =
 694            le32_to_cpu(tstats.fcoe_silent_drop_total_pkt_cnt);
 695}
 696
 697static void _qed_fcoe_get_pstats(struct qed_hwfn *p_hwfn,
 698                                 struct qed_ptt *p_ptt,
 699                                 struct qed_fcoe_stats *p_stats)
 700{
 701        struct fcoe_tx_stat pstats;
 702        u32 pstats_addr;
 703
 704        memset(&pstats, 0, sizeof(pstats));
 705        pstats_addr = BAR0_MAP_REG_PSDM_RAM +
 706            PSTORM_FCOE_TX_STATS_OFFSET(p_hwfn->rel_pf_id);
 707        qed_memcpy_from(p_hwfn, p_ptt, &pstats, pstats_addr, sizeof(pstats));
 708
 709        p_stats->fcoe_tx_byte_cnt = HILO_64_REGPAIR(pstats.fcoe_tx_byte_cnt);
 710        p_stats->fcoe_tx_data_pkt_cnt =
 711            HILO_64_REGPAIR(pstats.fcoe_tx_data_pkt_cnt);
 712        p_stats->fcoe_tx_xfer_pkt_cnt =
 713            HILO_64_REGPAIR(pstats.fcoe_tx_xfer_pkt_cnt);
 714        p_stats->fcoe_tx_other_pkt_cnt =
 715            HILO_64_REGPAIR(pstats.fcoe_tx_other_pkt_cnt);
 716}
 717
 718static int qed_fcoe_get_stats(struct qed_hwfn *p_hwfn,
 719                              struct qed_fcoe_stats *p_stats)
 720{
 721        struct qed_ptt *p_ptt;
 722
 723        memset(p_stats, 0, sizeof(*p_stats));
 724
 725        p_ptt = qed_ptt_acquire(p_hwfn);
 726
 727        if (!p_ptt) {
 728                DP_ERR(p_hwfn, "Failed to acquire ptt\n");
 729                return -EINVAL;
 730        }
 731
 732        _qed_fcoe_get_tstats(p_hwfn, p_ptt, p_stats);
 733        _qed_fcoe_get_pstats(p_hwfn, p_ptt, p_stats);
 734
 735        qed_ptt_release(p_hwfn, p_ptt);
 736
 737        return 0;
 738}
 739
 740struct qed_hash_fcoe_con {
 741        struct hlist_node node;
 742        struct qed_fcoe_conn *con;
 743};
 744
 745static int qed_fill_fcoe_dev_info(struct qed_dev *cdev,
 746                                  struct qed_dev_fcoe_info *info)
 747{
 748        struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev);
 749        int rc;
 750
 751        memset(info, 0, sizeof(*info));
 752        rc = qed_fill_dev_info(cdev, &info->common);
 753
 754        info->primary_dbq_rq_addr =
 755            qed_fcoe_get_primary_bdq_prod(hwfn, BDQ_ID_RQ);
 756        info->secondary_bdq_rq_addr =
 757            qed_fcoe_get_secondary_bdq_prod(hwfn, BDQ_ID_RQ);
 758
 759        info->wwpn = hwfn->mcp_info->func_info.wwn_port;
 760        info->wwnn = hwfn->mcp_info->func_info.wwn_node;
 761
 762        info->num_cqs = FEAT_NUM(hwfn, QED_FCOE_CQ);
 763
 764        return rc;
 765}
 766
 767static void qed_register_fcoe_ops(struct qed_dev *cdev,
 768                                  struct qed_fcoe_cb_ops *ops, void *cookie)
 769{
 770        cdev->protocol_ops.fcoe = ops;
 771        cdev->ops_cookie = cookie;
 772}
 773
 774static struct qed_hash_fcoe_con *qed_fcoe_get_hash(struct qed_dev *cdev,
 775                                                   u32 handle)
 776{
 777        struct qed_hash_fcoe_con *hash_con = NULL;
 778
 779        if (!(cdev->flags & QED_FLAG_STORAGE_STARTED))
 780                return NULL;
 781
 782        hash_for_each_possible(cdev->connections, hash_con, node, handle) {
 783                if (hash_con->con->icid == handle)
 784                        break;
 785        }
 786
 787        if (!hash_con || (hash_con->con->icid != handle))
 788                return NULL;
 789
 790        return hash_con;
 791}
 792
 793static int qed_fcoe_stop(struct qed_dev *cdev)
 794{
 795        struct qed_ptt *p_ptt;
 796        int rc;
 797
 798        if (!(cdev->flags & QED_FLAG_STORAGE_STARTED)) {
 799                DP_NOTICE(cdev, "fcoe already stopped\n");
 800                return 0;
 801        }
 802
 803        if (!hash_empty(cdev->connections)) {
 804                DP_NOTICE(cdev,
 805                          "Can't stop fcoe - not all connections were returned\n");
 806                return -EINVAL;
 807        }
 808
 809        p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev));
 810        if (!p_ptt)
 811                return -EAGAIN;
 812
 813        /* Stop the fcoe */
 814        rc = qed_sp_fcoe_func_stop(QED_LEADING_HWFN(cdev), p_ptt,
 815                                   QED_SPQ_MODE_EBLOCK, NULL);
 816        cdev->flags &= ~QED_FLAG_STORAGE_STARTED;
 817        qed_ptt_release(QED_LEADING_HWFN(cdev), p_ptt);
 818
 819        return rc;
 820}
 821
 822static int qed_fcoe_start(struct qed_dev *cdev, struct qed_fcoe_tid *tasks)
 823{
 824        int rc;
 825
 826        if (cdev->flags & QED_FLAG_STORAGE_STARTED) {
 827                DP_NOTICE(cdev, "fcoe already started;\n");
 828                return 0;
 829        }
 830
 831        rc = qed_sp_fcoe_func_start(QED_LEADING_HWFN(cdev),
 832                                    QED_SPQ_MODE_EBLOCK, NULL);
 833        if (rc) {
 834                DP_NOTICE(cdev, "Failed to start fcoe\n");
 835                return rc;
 836        }
 837
 838        cdev->flags |= QED_FLAG_STORAGE_STARTED;
 839        hash_init(cdev->connections);
 840
 841        if (tasks) {
 842                struct qed_tid_mem *tid_info = kzalloc(sizeof(*tid_info),
 843                                                       GFP_ATOMIC);
 844
 845                if (!tid_info) {
 846                        DP_NOTICE(cdev,
 847                                  "Failed to allocate tasks information\n");
 848                        qed_fcoe_stop(cdev);
 849                        return -ENOMEM;
 850                }
 851
 852                rc = qed_cxt_get_tid_mem_info(QED_LEADING_HWFN(cdev), tid_info);
 853                if (rc) {
 854                        DP_NOTICE(cdev, "Failed to gather task information\n");
 855                        qed_fcoe_stop(cdev);
 856                        kfree(tid_info);
 857                        return rc;
 858                }
 859
 860                /* Fill task information */
 861                tasks->size = tid_info->tid_size;
 862                tasks->num_tids_per_block = tid_info->num_tids_per_block;
 863                memcpy(tasks->blocks, tid_info->blocks,
 864                       MAX_TID_BLOCKS_FCOE * sizeof(u8 *));
 865
 866                kfree(tid_info);
 867        }
 868
 869        return 0;
 870}
 871
 872static int qed_fcoe_acquire_conn(struct qed_dev *cdev,
 873                                 u32 *handle,
 874                                 u32 *fw_cid, void __iomem **p_doorbell)
 875{
 876        struct qed_hash_fcoe_con *hash_con;
 877        int rc;
 878
 879        /* Allocate a hashed connection */
 880        hash_con = kzalloc(sizeof(*hash_con), GFP_KERNEL);
 881        if (!hash_con) {
 882                DP_NOTICE(cdev, "Failed to allocate hashed connection\n");
 883                return -ENOMEM;
 884        }
 885
 886        /* Acquire the connection */
 887        rc = qed_fcoe_acquire_connection(QED_LEADING_HWFN(cdev), NULL,
 888                                         &hash_con->con);
 889        if (rc) {
 890                DP_NOTICE(cdev, "Failed to acquire Connection\n");
 891                kfree(hash_con);
 892                return rc;
 893        }
 894
 895        /* Added the connection to hash table */
 896        *handle = hash_con->con->icid;
 897        *fw_cid = hash_con->con->fw_cid;
 898        hash_add(cdev->connections, &hash_con->node, *handle);
 899
 900        if (p_doorbell)
 901                *p_doorbell = qed_fcoe_get_db_addr(QED_LEADING_HWFN(cdev),
 902                                                   *handle);
 903
 904        return 0;
 905}
 906
 907static int qed_fcoe_release_conn(struct qed_dev *cdev, u32 handle)
 908{
 909        struct qed_hash_fcoe_con *hash_con;
 910
 911        hash_con = qed_fcoe_get_hash(cdev, handle);
 912        if (!hash_con) {
 913                DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
 914                          handle);
 915                return -EINVAL;
 916        }
 917
 918        hlist_del(&hash_con->node);
 919        qed_fcoe_release_connection(QED_LEADING_HWFN(cdev), hash_con->con);
 920        kfree(hash_con);
 921
 922        return 0;
 923}
 924
 925static int qed_fcoe_offload_conn(struct qed_dev *cdev,
 926                                 u32 handle,
 927                                 struct qed_fcoe_params_offload *conn_info)
 928{
 929        struct qed_hash_fcoe_con *hash_con;
 930        struct qed_fcoe_conn *con;
 931
 932        hash_con = qed_fcoe_get_hash(cdev, handle);
 933        if (!hash_con) {
 934                DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
 935                          handle);
 936                return -EINVAL;
 937        }
 938
 939        /* Update the connection with information from the params */
 940        con = hash_con->con;
 941
 942        con->sq_pbl_addr = conn_info->sq_pbl_addr;
 943        con->sq_curr_page_addr = conn_info->sq_curr_page_addr;
 944        con->sq_next_page_addr = conn_info->sq_next_page_addr;
 945        con->tx_max_fc_pay_len = conn_info->tx_max_fc_pay_len;
 946        con->e_d_tov_timer_val = conn_info->e_d_tov_timer_val;
 947        con->rec_tov_timer_val = conn_info->rec_tov_timer_val;
 948        con->rx_max_fc_pay_len = conn_info->rx_max_fc_pay_len;
 949        con->vlan_tag = conn_info->vlan_tag;
 950        con->max_conc_seqs_c3 = conn_info->max_conc_seqs_c3;
 951        con->flags = conn_info->flags;
 952        con->def_q_idx = conn_info->def_q_idx;
 953
 954        con->src_mac_addr_hi = (conn_info->src_mac[5] << 8) |
 955            conn_info->src_mac[4];
 956        con->src_mac_addr_mid = (conn_info->src_mac[3] << 8) |
 957            conn_info->src_mac[2];
 958        con->src_mac_addr_lo = (conn_info->src_mac[1] << 8) |
 959            conn_info->src_mac[0];
 960        con->dst_mac_addr_hi = (conn_info->dst_mac[5] << 8) |
 961            conn_info->dst_mac[4];
 962        con->dst_mac_addr_mid = (conn_info->dst_mac[3] << 8) |
 963            conn_info->dst_mac[2];
 964        con->dst_mac_addr_lo = (conn_info->dst_mac[1] << 8) |
 965            conn_info->dst_mac[0];
 966
 967        con->s_id.addr_hi = conn_info->s_id.addr_hi;
 968        con->s_id.addr_mid = conn_info->s_id.addr_mid;
 969        con->s_id.addr_lo = conn_info->s_id.addr_lo;
 970        con->d_id.addr_hi = conn_info->d_id.addr_hi;
 971        con->d_id.addr_mid = conn_info->d_id.addr_mid;
 972        con->d_id.addr_lo = conn_info->d_id.addr_lo;
 973
 974        return qed_sp_fcoe_conn_offload(QED_LEADING_HWFN(cdev), con,
 975                                        QED_SPQ_MODE_EBLOCK, NULL);
 976}
 977
 978static int qed_fcoe_destroy_conn(struct qed_dev *cdev,
 979                                 u32 handle, dma_addr_t terminate_params)
 980{
 981        struct qed_hash_fcoe_con *hash_con;
 982        struct qed_fcoe_conn *con;
 983
 984        hash_con = qed_fcoe_get_hash(cdev, handle);
 985        if (!hash_con) {
 986                DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
 987                          handle);
 988                return -EINVAL;
 989        }
 990
 991        /* Update the connection with information from the params */
 992        con = hash_con->con;
 993        con->terminate_params = terminate_params;
 994
 995        return qed_sp_fcoe_conn_destroy(QED_LEADING_HWFN(cdev), con,
 996                                        QED_SPQ_MODE_EBLOCK, NULL);
 997}
 998
 999static int qed_fcoe_stats(struct qed_dev *cdev, struct qed_fcoe_stats *stats)
1000{
1001        return qed_fcoe_get_stats(QED_LEADING_HWFN(cdev), stats);
1002}
1003
1004void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
1005                                 struct qed_mcp_fcoe_stats *stats)
1006{
1007        struct qed_fcoe_stats proto_stats;
1008
1009        /* Retrieve FW statistics */
1010        memset(&proto_stats, 0, sizeof(proto_stats));
1011        if (qed_fcoe_stats(cdev, &proto_stats)) {
1012                DP_VERBOSE(cdev, QED_MSG_STORAGE,
1013                           "Failed to collect FCoE statistics\n");
1014                return;
1015        }
1016
1017        /* Translate FW statistics into struct */
1018        stats->rx_pkts = proto_stats.fcoe_rx_data_pkt_cnt +
1019                         proto_stats.fcoe_rx_xfer_pkt_cnt +
1020                         proto_stats.fcoe_rx_other_pkt_cnt;
1021        stats->tx_pkts = proto_stats.fcoe_tx_data_pkt_cnt +
1022                         proto_stats.fcoe_tx_xfer_pkt_cnt +
1023                         proto_stats.fcoe_tx_other_pkt_cnt;
1024        stats->fcs_err = proto_stats.fcoe_silent_drop_pkt_crc_error_cnt;
1025
1026        /* Request protocol driver to fill-in the rest */
1027        if (cdev->protocol_ops.fcoe && cdev->ops_cookie) {
1028                struct qed_fcoe_cb_ops *ops = cdev->protocol_ops.fcoe;
1029                void *cookie = cdev->ops_cookie;
1030
1031                if (ops->get_login_failures)
1032                        stats->login_failure = ops->get_login_failures(cookie);
1033        }
1034}
1035
1036static const struct qed_fcoe_ops qed_fcoe_ops_pass = {
1037        .common = &qed_common_ops_pass,
1038        .ll2 = &qed_ll2_ops_pass,
1039        .fill_dev_info = &qed_fill_fcoe_dev_info,
1040        .start = &qed_fcoe_start,
1041        .stop = &qed_fcoe_stop,
1042        .register_ops = &qed_register_fcoe_ops,
1043        .acquire_conn = &qed_fcoe_acquire_conn,
1044        .release_conn = &qed_fcoe_release_conn,
1045        .offload_conn = &qed_fcoe_offload_conn,
1046        .destroy_conn = &qed_fcoe_destroy_conn,
1047        .get_stats = &qed_fcoe_stats,
1048};
1049
1050const struct qed_fcoe_ops *qed_get_fcoe_ops(void)
1051{
1052        return &qed_fcoe_ops_pass;
1053}
1054EXPORT_SYMBOL(qed_get_fcoe_ops);
1055
1056void qed_put_fcoe_ops(void)
1057{
1058}
1059EXPORT_SYMBOL(qed_put_fcoe_ops);
1060