root/drivers/net/ethernet/qlogic/qed/qed_fcoe.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. qed_sp_fcoe_func_start
  2. qed_sp_fcoe_conn_offload
  3. qed_sp_fcoe_conn_destroy
  4. qed_sp_fcoe_func_stop
  5. qed_fcoe_allocate_connection
  6. qed_fcoe_free_connection
  7. qed_fcoe_get_db_addr
  8. qed_fcoe_get_primary_bdq_prod
  9. qed_fcoe_get_secondary_bdq_prod
  10. qed_fcoe_alloc
  11. qed_fcoe_setup
  12. qed_fcoe_free
  13. qed_fcoe_acquire_connection
  14. qed_fcoe_release_connection
  15. _qed_fcoe_get_tstats
  16. _qed_fcoe_get_pstats
  17. qed_fcoe_get_stats
  18. qed_fill_fcoe_dev_info
  19. qed_register_fcoe_ops
  20. qed_fcoe_get_hash
  21. qed_fcoe_stop
  22. qed_fcoe_start
  23. qed_fcoe_acquire_conn
  24. qed_fcoe_release_conn
  25. qed_fcoe_offload_conn
  26. qed_fcoe_destroy_conn
  27. qed_fcoe_stats
  28. qed_get_protocol_stats_fcoe
  29. qed_get_fcoe_ops
  30. qed_put_fcoe_ops

   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 
  66 struct 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 
 110 static int
 111 qed_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 
 245 err:
 246         qed_sp_destroy_request(p_hwfn, p_ent);
 247         return rc;
 248 }
 249 
 250 static int
 251 qed_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 
 329 static int
 330 qed_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 
 360 static int
 361 qed_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 
 391 static int
 392 qed_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 
 458 nomem_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]);
 469 nomem_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]);
 480 nomem_pbl_xferq:
 481         kfree(p_conn);
 482         return -ENOMEM;
 483 }
 484 
 485 static 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 
 525 static 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 
 531 static 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 
 546 static 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 
 561 int 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 
 577 void 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 
 601 void 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 
 621 static int
 622 qed_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 
 656 static 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 
 665 static 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 
 697 static 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 
 718 static 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 
 740 struct qed_hash_fcoe_con {
 741         struct hlist_node node;
 742         struct qed_fcoe_conn *con;
 743 };
 744 
 745 static int qed_fill_fcoe_dev_info(struct qed_dev *cdev,
 746                                   struct qed_dev_fcoe_info *info)
 747 {
 748         struct qed_hwfn *hwfn = QED_AFFIN_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 
 767 static 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 
 774 static 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 
 793 static 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_AFFIN_HWFN(cdev));
 810         if (!p_ptt)
 811                 return -EAGAIN;
 812 
 813         /* Stop the fcoe */
 814         rc = qed_sp_fcoe_func_stop(QED_AFFIN_HWFN(cdev), p_ptt,
 815                                    QED_SPQ_MODE_EBLOCK, NULL);
 816         cdev->flags &= ~QED_FLAG_STORAGE_STARTED;
 817         qed_ptt_release(QED_AFFIN_HWFN(cdev), p_ptt);
 818 
 819         return rc;
 820 }
 821 
 822 static 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_AFFIN_HWFN(cdev), QED_SPQ_MODE_EBLOCK,
 832                                     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_AFFIN_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 
 872 static 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_AFFIN_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_AFFIN_HWFN(cdev),
 902                                                    *handle);
 903 
 904         return 0;
 905 }
 906 
 907 static 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_AFFIN_HWFN(cdev), hash_con->con);
 920         kfree(hash_con);
 921 
 922         return 0;
 923 }
 924 
 925 static 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_AFFIN_HWFN(cdev), con,
 975                                         QED_SPQ_MODE_EBLOCK, NULL);
 976 }
 977 
 978 static 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_AFFIN_HWFN(cdev), con,
 996                                         QED_SPQ_MODE_EBLOCK, NULL);
 997 }
 998 
 999 static int qed_fcoe_stats(struct qed_dev *cdev, struct qed_fcoe_stats *stats)
1000 {
1001         return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats);
1002 }
1003 
1004 void 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 
1036 static 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 
1050 const struct qed_fcoe_ops *qed_get_fcoe_ops(void)
1051 {
1052         return &qed_fcoe_ops_pass;
1053 }
1054 EXPORT_SYMBOL(qed_get_fcoe_ops);
1055 
1056 void qed_put_fcoe_ops(void)
1057 {
1058 }
1059 EXPORT_SYMBOL(qed_put_fcoe_ops);

/* [<][>][^][v][top][bottom][index][help] */