1 /* QLogic qed NIC Driver
2 * Copyright (c) 2015-2017 QLogic Corporation
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:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
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.
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
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/version.h>
47 #include <linux/workqueue.h>
48 #include <linux/errno.h>
49 #include <linux/list.h>
50 #include <linux/spinlock.h>
51 #define __PREVENT_DUMP_MEM_ARR__
52 #define __PREVENT_PXP_GLOBAL_WIN__
55 #include "qed_dev_api.h"
62 #include "qed_reg_addr.h"
64 #include "qed_sriov.h"
65 #include <linux/qed/qed_fcoe_if.h>
67 struct qed_fcoe_conn
{
68 struct list_head list_entry
;
76 dma_addr_t sq_pbl_addr
;
77 dma_addr_t sq_curr_page_addr
;
78 dma_addr_t sq_next_page_addr
;
79 dma_addr_t xferq_pbl_addr
;
80 void *xferq_pbl_addr_virt_addr
;
81 dma_addr_t xferq_addr
[4];
82 void *xferq_addr_virt_addr
[4];
83 dma_addr_t confq_pbl_addr
;
84 void *confq_pbl_addr_virt_addr
;
85 dma_addr_t confq_addr
[2];
86 void *confq_addr_virt_addr
[2];
88 dma_addr_t terminate_params
;
97 u16 tx_max_fc_pay_len
;
98 u16 e_d_tov_timer_val
;
99 u16 rec_tov_timer_val
;
100 u16 rx_max_fc_pay_len
;
104 struct fc_addr_nw s_id
;
106 struct fc_addr_nw d_id
;
112 qed_sp_fcoe_func_start(struct qed_hwfn
*p_hwfn
,
113 enum spq_mode comp_mode
,
114 struct qed_spq_comp_cb
*p_comp_addr
)
116 struct qed_fcoe_pf_params
*fcoe_pf_params
= NULL
;
117 struct fcoe_init_ramrod_params
*p_ramrod
= NULL
;
118 struct fcoe_init_func_ramrod_data
*p_data
;
119 struct fcoe_conn_context
*p_cxt
= NULL
;
120 struct qed_spq_entry
*p_ent
= NULL
;
121 struct qed_sp_init_data init_data
;
122 struct qed_cxt_info cxt_info
;
129 memset(&init_data
, 0, sizeof(init_data
));
130 init_data
.cid
= qed_spq_get_cid(p_hwfn
);
131 init_data
.opaque_fid
= p_hwfn
->hw_info
.opaque_fid
;
132 init_data
.comp_mode
= comp_mode
;
133 init_data
.p_comp_data
= p_comp_addr
;
135 rc
= qed_sp_init_request(p_hwfn
, &p_ent
,
136 FCOE_RAMROD_CMD_ID_INIT_FUNC
,
137 PROTOCOLID_FCOE
, &init_data
);
141 p_ramrod
= &p_ent
->ramrod
.fcoe_init
;
142 p_data
= &p_ramrod
->init_ramrod_data
;
143 fcoe_pf_params
= &p_hwfn
->pf_params
.fcoe_pf_params
;
145 p_data
->mtu
= cpu_to_le16(fcoe_pf_params
->mtu
);
146 tmp
= cpu_to_le16(fcoe_pf_params
->sq_num_pbl_pages
);
147 p_data
->sq_num_pages_in_pbl
= tmp
;
149 rc
= qed_cxt_acquire_cid(p_hwfn
, PROTOCOLID_FCOE
, &dummy_cid
);
153 cxt_info
.iid
= dummy_cid
;
154 rc
= qed_cxt_get_cid_info(p_hwfn
, &cxt_info
);
156 DP_NOTICE(p_hwfn
, "Cannot find context info for dummy cid=%d\n",
160 p_cxt
= cxt_info
.p_cxt
;
161 SET_FIELD(p_cxt
->tstorm_ag_context
.flags3
,
162 TSTORM_FCOE_CONN_AG_CTX_DUMMY_TIMER_CF_EN
, 1);
164 fcoe_pf_params
->dummy_icid
= (u16
)dummy_cid
;
166 tmp
= cpu_to_le16(fcoe_pf_params
->num_tasks
);
167 p_data
->func_params
.num_tasks
= tmp
;
168 p_data
->func_params
.log_page_size
= fcoe_pf_params
->log_page_size
;
169 p_data
->func_params
.debug_mode
= fcoe_pf_params
->debug_mode
;
171 DMA_REGPAIR_LE(p_data
->q_params
.glbl_q_params_addr
,
172 fcoe_pf_params
->glbl_q_params_addr
);
174 tmp
= cpu_to_le16(fcoe_pf_params
->cq_num_entries
);
175 p_data
->q_params
.cq_num_entries
= tmp
;
177 tmp
= cpu_to_le16(fcoe_pf_params
->cmdq_num_entries
);
178 p_data
->q_params
.cmdq_num_entries
= tmp
;
180 tmp
= fcoe_pf_params
->num_cqs
;
181 p_data
->q_params
.num_queues
= (u8
)tmp
;
183 tmp
= (u16
)p_hwfn
->hw_info
.resc_start
[QED_CMDQS_CQS
];
184 p_data
->q_params
.queue_relative_offset
= (u8
)tmp
;
186 for (i
= 0; i
< fcoe_pf_params
->num_cqs
; i
++) {
187 tmp
= cpu_to_le16(p_hwfn
->sbs_info
[i
]->igu_sb_id
);
188 p_data
->q_params
.cq_cmdq_sb_num_arr
[i
] = tmp
;
191 p_data
->q_params
.cq_sb_pi
= fcoe_pf_params
->gl_rq_pi
;
192 p_data
->q_params
.cmdq_sb_pi
= fcoe_pf_params
->gl_cmd_pi
;
194 p_data
->q_params
.bdq_resource_id
= (u8
)RESC_START(p_hwfn
, QED_BDQ
);
196 DMA_REGPAIR_LE(p_data
->q_params
.bdq_pbl_base_address
[BDQ_ID_RQ
],
197 fcoe_pf_params
->bdq_pbl_base_addr
[BDQ_ID_RQ
]);
198 p_data
->q_params
.bdq_pbl_num_entries
[BDQ_ID_RQ
] =
199 fcoe_pf_params
->bdq_pbl_num_entries
[BDQ_ID_RQ
];
200 tmp
= fcoe_pf_params
->bdq_xoff_threshold
[BDQ_ID_RQ
];
201 p_data
->q_params
.bdq_xoff_threshold
[BDQ_ID_RQ
] = cpu_to_le16(tmp
);
202 tmp
= fcoe_pf_params
->bdq_xon_threshold
[BDQ_ID_RQ
];
203 p_data
->q_params
.bdq_xon_threshold
[BDQ_ID_RQ
] = cpu_to_le16(tmp
);
205 DMA_REGPAIR_LE(p_data
->q_params
.bdq_pbl_base_address
[BDQ_ID_IMM_DATA
],
206 fcoe_pf_params
->bdq_pbl_base_addr
[BDQ_ID_IMM_DATA
]);
207 p_data
->q_params
.bdq_pbl_num_entries
[BDQ_ID_IMM_DATA
] =
208 fcoe_pf_params
->bdq_pbl_num_entries
[BDQ_ID_IMM_DATA
];
209 tmp
= fcoe_pf_params
->bdq_xoff_threshold
[BDQ_ID_IMM_DATA
];
210 p_data
->q_params
.bdq_xoff_threshold
[BDQ_ID_IMM_DATA
] = cpu_to_le16(tmp
);
211 tmp
= fcoe_pf_params
->bdq_xon_threshold
[BDQ_ID_IMM_DATA
];
212 p_data
->q_params
.bdq_xon_threshold
[BDQ_ID_IMM_DATA
] = cpu_to_le16(tmp
);
213 tmp
= fcoe_pf_params
->rq_buffer_size
;
214 p_data
->q_params
.rq_buffer_size
= cpu_to_le16(tmp
);
216 if (fcoe_pf_params
->is_target
) {
217 SET_FIELD(p_data
->q_params
.q_validity
,
218 SCSI_INIT_FUNC_QUEUES_RQ_VALID
, 1);
219 if (p_data
->q_params
.bdq_pbl_num_entries
[BDQ_ID_IMM_DATA
])
220 SET_FIELD(p_data
->q_params
.q_validity
,
221 SCSI_INIT_FUNC_QUEUES_IMM_DATA_VALID
, 1);
222 SET_FIELD(p_data
->q_params
.q_validity
,
223 SCSI_INIT_FUNC_QUEUES_CMD_VALID
, 1);
225 SET_FIELD(p_data
->q_params
.q_validity
,
226 SCSI_INIT_FUNC_QUEUES_RQ_VALID
, 1);
229 rc
= qed_spq_post(p_hwfn
, p_ent
, NULL
);
235 qed_sp_fcoe_conn_offload(struct qed_hwfn
*p_hwfn
,
236 struct qed_fcoe_conn
*p_conn
,
237 enum spq_mode comp_mode
,
238 struct qed_spq_comp_cb
*p_comp_addr
)
240 struct fcoe_conn_offload_ramrod_params
*p_ramrod
= NULL
;
241 struct fcoe_conn_offload_ramrod_data
*p_data
;
242 struct qed_spq_entry
*p_ent
= NULL
;
243 struct qed_sp_init_data init_data
;
248 memset(&init_data
, 0, sizeof(init_data
));
249 init_data
.cid
= p_conn
->icid
;
250 init_data
.opaque_fid
= p_hwfn
->hw_info
.opaque_fid
;
251 init_data
.comp_mode
= comp_mode
;
252 init_data
.p_comp_data
= p_comp_addr
;
254 rc
= qed_sp_init_request(p_hwfn
, &p_ent
,
255 FCOE_RAMROD_CMD_ID_OFFLOAD_CONN
,
256 PROTOCOLID_FCOE
, &init_data
);
260 p_ramrod
= &p_ent
->ramrod
.fcoe_conn_ofld
;
261 p_data
= &p_ramrod
->offload_ramrod_data
;
263 /* Transmission PQ is the first of the PF */
264 pq_id
= qed_get_qm_pq(p_hwfn
, PROTOCOLID_FCOE
, NULL
);
265 p_conn
->physical_q0
= cpu_to_le16(pq_id
);
266 p_data
->physical_q0
= cpu_to_le16(pq_id
);
268 p_data
->conn_id
= cpu_to_le16(p_conn
->conn_id
);
269 DMA_REGPAIR_LE(p_data
->sq_pbl_addr
, p_conn
->sq_pbl_addr
);
270 DMA_REGPAIR_LE(p_data
->sq_curr_page_addr
, p_conn
->sq_curr_page_addr
);
271 DMA_REGPAIR_LE(p_data
->sq_next_page_addr
, p_conn
->sq_next_page_addr
);
272 DMA_REGPAIR_LE(p_data
->xferq_pbl_addr
, p_conn
->xferq_pbl_addr
);
273 DMA_REGPAIR_LE(p_data
->xferq_curr_page_addr
, p_conn
->xferq_addr
[0]);
274 DMA_REGPAIR_LE(p_data
->xferq_next_page_addr
, p_conn
->xferq_addr
[1]);
276 DMA_REGPAIR_LE(p_data
->respq_pbl_addr
, p_conn
->confq_pbl_addr
);
277 DMA_REGPAIR_LE(p_data
->respq_curr_page_addr
, p_conn
->confq_addr
[0]);
278 DMA_REGPAIR_LE(p_data
->respq_next_page_addr
, p_conn
->confq_addr
[1]);
280 p_data
->dst_mac_addr_lo
= cpu_to_le16(p_conn
->dst_mac_addr_lo
);
281 p_data
->dst_mac_addr_mid
= cpu_to_le16(p_conn
->dst_mac_addr_mid
);
282 p_data
->dst_mac_addr_hi
= cpu_to_le16(p_conn
->dst_mac_addr_hi
);
283 p_data
->src_mac_addr_lo
= cpu_to_le16(p_conn
->src_mac_addr_lo
);
284 p_data
->src_mac_addr_mid
= cpu_to_le16(p_conn
->src_mac_addr_mid
);
285 p_data
->src_mac_addr_hi
= cpu_to_le16(p_conn
->src_mac_addr_hi
);
287 tmp
= cpu_to_le16(p_conn
->tx_max_fc_pay_len
);
288 p_data
->tx_max_fc_pay_len
= tmp
;
289 tmp
= cpu_to_le16(p_conn
->e_d_tov_timer_val
);
290 p_data
->e_d_tov_timer_val
= tmp
;
291 tmp
= cpu_to_le16(p_conn
->rec_tov_timer_val
);
292 p_data
->rec_rr_tov_timer_val
= tmp
;
293 tmp
= cpu_to_le16(p_conn
->rx_max_fc_pay_len
);
294 p_data
->rx_max_fc_pay_len
= tmp
;
296 p_data
->vlan_tag
= cpu_to_le16(p_conn
->vlan_tag
);
297 p_data
->s_id
.addr_hi
= p_conn
->s_id
.addr_hi
;
298 p_data
->s_id
.addr_mid
= p_conn
->s_id
.addr_mid
;
299 p_data
->s_id
.addr_lo
= p_conn
->s_id
.addr_lo
;
300 p_data
->max_conc_seqs_c3
= p_conn
->max_conc_seqs_c3
;
301 p_data
->d_id
.addr_hi
= p_conn
->d_id
.addr_hi
;
302 p_data
->d_id
.addr_mid
= p_conn
->d_id
.addr_mid
;
303 p_data
->d_id
.addr_lo
= p_conn
->d_id
.addr_lo
;
304 p_data
->flags
= p_conn
->flags
;
305 p_data
->def_q_idx
= p_conn
->def_q_idx
;
307 return qed_spq_post(p_hwfn
, p_ent
, NULL
);
311 qed_sp_fcoe_conn_destroy(struct qed_hwfn
*p_hwfn
,
312 struct qed_fcoe_conn
*p_conn
,
313 enum spq_mode comp_mode
,
314 struct qed_spq_comp_cb
*p_comp_addr
)
316 struct fcoe_conn_terminate_ramrod_params
*p_ramrod
= NULL
;
317 struct qed_spq_entry
*p_ent
= NULL
;
318 struct qed_sp_init_data init_data
;
322 memset(&init_data
, 0, sizeof(init_data
));
323 init_data
.cid
= p_conn
->icid
;
324 init_data
.opaque_fid
= p_hwfn
->hw_info
.opaque_fid
;
325 init_data
.comp_mode
= comp_mode
;
326 init_data
.p_comp_data
= p_comp_addr
;
328 rc
= qed_sp_init_request(p_hwfn
, &p_ent
,
329 FCOE_RAMROD_CMD_ID_TERMINATE_CONN
,
330 PROTOCOLID_FCOE
, &init_data
);
334 p_ramrod
= &p_ent
->ramrod
.fcoe_conn_terminate
;
335 DMA_REGPAIR_LE(p_ramrod
->terminate_ramrod_data
.terminate_params_addr
,
336 p_conn
->terminate_params
);
338 return qed_spq_post(p_hwfn
, p_ent
, NULL
);
342 qed_sp_fcoe_func_stop(struct qed_hwfn
*p_hwfn
,
343 enum spq_mode comp_mode
,
344 struct qed_spq_comp_cb
*p_comp_addr
)
346 struct qed_ptt
*p_ptt
= p_hwfn
->p_main_ptt
;
347 struct qed_spq_entry
*p_ent
= NULL
;
348 struct qed_sp_init_data init_data
;
353 memset(&init_data
, 0, sizeof(init_data
));
354 init_data
.cid
= p_hwfn
->pf_params
.fcoe_pf_params
.dummy_icid
;
355 init_data
.opaque_fid
= p_hwfn
->hw_info
.opaque_fid
;
356 init_data
.comp_mode
= comp_mode
;
357 init_data
.p_comp_data
= p_comp_addr
;
359 rc
= qed_sp_init_request(p_hwfn
, &p_ent
,
360 FCOE_RAMROD_CMD_ID_DESTROY_FUNC
,
361 PROTOCOLID_FCOE
, &init_data
);
365 active_segs
= qed_rd(p_hwfn
, p_ptt
, TM_REG_PF_ENABLE_TASK
);
366 active_segs
&= ~BIT(QED_CXT_FCOE_TID_SEG
);
367 qed_wr(p_hwfn
, p_ptt
, TM_REG_PF_ENABLE_TASK
, active_segs
);
369 return qed_spq_post(p_hwfn
, p_ent
, NULL
);
373 qed_fcoe_allocate_connection(struct qed_hwfn
*p_hwfn
,
374 struct qed_fcoe_conn
**p_out_conn
)
376 struct qed_fcoe_conn
*p_conn
= NULL
;
380 spin_lock_bh(&p_hwfn
->p_fcoe_info
->lock
);
381 if (!list_empty(&p_hwfn
->p_fcoe_info
->free_list
))
383 list_first_entry(&p_hwfn
->p_fcoe_info
->free_list
,
384 struct qed_fcoe_conn
, list_entry
);
386 list_del(&p_conn
->list_entry
);
387 spin_unlock_bh(&p_hwfn
->p_fcoe_info
->lock
);
388 *p_out_conn
= p_conn
;
391 spin_unlock_bh(&p_hwfn
->p_fcoe_info
->lock
);
393 p_conn
= kzalloc(sizeof(*p_conn
), GFP_KERNEL
);
397 p_addr
= dma_alloc_coherent(&p_hwfn
->cdev
->pdev
->dev
,
399 &p_conn
->xferq_pbl_addr
, GFP_KERNEL
);
401 goto nomem_pbl_xferq
;
402 p_conn
->xferq_pbl_addr_virt_addr
= p_addr
;
404 for (i
= 0; i
< ARRAY_SIZE(p_conn
->xferq_addr
); i
++) {
405 p_addr
= dma_alloc_coherent(&p_hwfn
->cdev
->pdev
->dev
,
407 &p_conn
->xferq_addr
[i
], GFP_KERNEL
);
410 p_conn
->xferq_addr_virt_addr
[i
] = p_addr
;
412 p_addr
= p_conn
->xferq_pbl_addr_virt_addr
;
413 ((dma_addr_t
*)p_addr
)[i
] = p_conn
->xferq_addr
[i
];
416 p_addr
= dma_alloc_coherent(&p_hwfn
->cdev
->pdev
->dev
,
418 &p_conn
->confq_pbl_addr
, GFP_KERNEL
);
421 p_conn
->confq_pbl_addr_virt_addr
= p_addr
;
423 for (i
= 0; i
< ARRAY_SIZE(p_conn
->confq_addr
); i
++) {
424 p_addr
= dma_alloc_coherent(&p_hwfn
->cdev
->pdev
->dev
,
426 &p_conn
->confq_addr
[i
], GFP_KERNEL
);
429 p_conn
->confq_addr_virt_addr
[i
] = p_addr
;
431 p_addr
= p_conn
->confq_pbl_addr_virt_addr
;
432 ((dma_addr_t
*)p_addr
)[i
] = p_conn
->confq_addr
[i
];
435 p_conn
->free_on_delete
= true;
436 *p_out_conn
= p_conn
;
440 dma_free_coherent(&p_hwfn
->cdev
->pdev
->dev
,
442 p_conn
->confq_pbl_addr_virt_addr
,
443 p_conn
->confq_pbl_addr
);
444 for (i
= 0; i
< ARRAY_SIZE(p_conn
->confq_addr
); i
++)
445 if (p_conn
->confq_addr_virt_addr
[i
])
446 dma_free_coherent(&p_hwfn
->cdev
->pdev
->dev
,
448 p_conn
->confq_addr_virt_addr
[i
],
449 p_conn
->confq_addr
[i
]);
451 dma_free_coherent(&p_hwfn
->cdev
->pdev
->dev
,
453 p_conn
->xferq_pbl_addr_virt_addr
,
454 p_conn
->xferq_pbl_addr
);
455 for (i
= 0; i
< ARRAY_SIZE(p_conn
->xferq_addr
); i
++)
456 if (p_conn
->xferq_addr_virt_addr
[i
])
457 dma_free_coherent(&p_hwfn
->cdev
->pdev
->dev
,
459 p_conn
->xferq_addr_virt_addr
[i
],
460 p_conn
->xferq_addr
[i
]);
466 static void qed_fcoe_free_connection(struct qed_hwfn
*p_hwfn
,
467 struct qed_fcoe_conn
*p_conn
)
474 if (p_conn
->confq_pbl_addr_virt_addr
)
475 dma_free_coherent(&p_hwfn
->cdev
->pdev
->dev
,
477 p_conn
->confq_pbl_addr_virt_addr
,
478 p_conn
->confq_pbl_addr
);
480 for (i
= 0; i
< ARRAY_SIZE(p_conn
->confq_addr
); i
++) {
481 if (!p_conn
->confq_addr_virt_addr
[i
])
483 dma_free_coherent(&p_hwfn
->cdev
->pdev
->dev
,
485 p_conn
->confq_addr_virt_addr
[i
],
486 p_conn
->confq_addr
[i
]);
489 if (p_conn
->xferq_pbl_addr_virt_addr
)
490 dma_free_coherent(&p_hwfn
->cdev
->pdev
->dev
,
492 p_conn
->xferq_pbl_addr_virt_addr
,
493 p_conn
->xferq_pbl_addr
);
495 for (i
= 0; i
< ARRAY_SIZE(p_conn
->xferq_addr
); i
++) {
496 if (!p_conn
->xferq_addr_virt_addr
[i
])
498 dma_free_coherent(&p_hwfn
->cdev
->pdev
->dev
,
500 p_conn
->xferq_addr_virt_addr
[i
],
501 p_conn
->xferq_addr
[i
]);
506 static void __iomem
*qed_fcoe_get_db_addr(struct qed_hwfn
*p_hwfn
, u32 cid
)
508 return (u8 __iomem
*)p_hwfn
->doorbells
+
509 qed_db_addr(cid
, DQ_DEMS_LEGACY
);
512 static void __iomem
*qed_fcoe_get_primary_bdq_prod(struct qed_hwfn
*p_hwfn
,
515 if (RESC_NUM(p_hwfn
, QED_BDQ
)) {
516 return (u8 __iomem
*)p_hwfn
->regview
+
517 GTT_BAR0_MAP_REG_MSDM_RAM
+
518 MSTORM_SCSI_BDQ_EXT_PROD_OFFSET(RESC_START(p_hwfn
,
522 DP_NOTICE(p_hwfn
, "BDQ is not allocated!\n");
527 static void __iomem
*qed_fcoe_get_secondary_bdq_prod(struct qed_hwfn
*p_hwfn
,
530 if (RESC_NUM(p_hwfn
, QED_BDQ
)) {
531 return (u8 __iomem
*)p_hwfn
->regview
+
532 GTT_BAR0_MAP_REG_TSDM_RAM
+
533 TSTORM_SCSI_BDQ_EXT_PROD_OFFSET(RESC_START(p_hwfn
,
537 DP_NOTICE(p_hwfn
, "BDQ is not allocated!\n");
542 struct qed_fcoe_info
*qed_fcoe_alloc(struct qed_hwfn
*p_hwfn
)
544 struct qed_fcoe_info
*p_fcoe_info
;
546 /* Allocate LL2's set struct */
547 p_fcoe_info
= kzalloc(sizeof(*p_fcoe_info
), GFP_KERNEL
);
549 DP_NOTICE(p_hwfn
, "Failed to allocate qed_fcoe_info'\n");
552 INIT_LIST_HEAD(&p_fcoe_info
->free_list
);
556 void qed_fcoe_setup(struct qed_hwfn
*p_hwfn
, struct qed_fcoe_info
*p_fcoe_info
)
558 struct fcoe_task_context
*p_task_ctx
= NULL
;
562 spin_lock_init(&p_fcoe_info
->lock
);
563 for (i
= 0; i
< p_hwfn
->pf_params
.fcoe_pf_params
.num_tasks
; i
++) {
564 rc
= qed_cxt_get_task_ctx(p_hwfn
, i
,
566 (void **)&p_task_ctx
);
570 memset(p_task_ctx
, 0, sizeof(struct fcoe_task_context
));
571 SET_FIELD(p_task_ctx
->timer_context
.logical_client_0
,
572 TIMERS_CONTEXT_VALIDLC0
, 1);
573 SET_FIELD(p_task_ctx
->timer_context
.logical_client_1
,
574 TIMERS_CONTEXT_VALIDLC1
, 1);
575 SET_FIELD(p_task_ctx
->tstorm_ag_context
.flags0
,
576 TSTORM_FCOE_TASK_AG_CTX_CONNECTION_TYPE
, 1);
580 void qed_fcoe_free(struct qed_hwfn
*p_hwfn
, struct qed_fcoe_info
*p_fcoe_info
)
582 struct qed_fcoe_conn
*p_conn
= NULL
;
587 while (!list_empty(&p_fcoe_info
->free_list
)) {
588 p_conn
= list_first_entry(&p_fcoe_info
->free_list
,
589 struct qed_fcoe_conn
, list_entry
);
592 list_del(&p_conn
->list_entry
);
593 qed_fcoe_free_connection(p_hwfn
, p_conn
);
600 qed_fcoe_acquire_connection(struct qed_hwfn
*p_hwfn
,
601 struct qed_fcoe_conn
*p_in_conn
,
602 struct qed_fcoe_conn
**p_out_conn
)
604 struct qed_fcoe_conn
*p_conn
= NULL
;
608 spin_lock_bh(&p_hwfn
->p_fcoe_info
->lock
);
609 rc
= qed_cxt_acquire_cid(p_hwfn
, PROTOCOLID_FCOE
, &icid
);
610 spin_unlock_bh(&p_hwfn
->p_fcoe_info
->lock
);
614 /* Use input connection [if provided] or allocate a new one */
618 rc
= qed_fcoe_allocate_connection(p_hwfn
, &p_conn
);
620 spin_lock_bh(&p_hwfn
->p_fcoe_info
->lock
);
621 qed_cxt_release_cid(p_hwfn
, icid
);
622 spin_unlock_bh(&p_hwfn
->p_fcoe_info
->lock
);
628 p_conn
->fw_cid
= (p_hwfn
->hw_info
.opaque_fid
<< 16) | icid
;
629 *p_out_conn
= p_conn
;
634 static void qed_fcoe_release_connection(struct qed_hwfn
*p_hwfn
,
635 struct qed_fcoe_conn
*p_conn
)
637 spin_lock_bh(&p_hwfn
->p_fcoe_info
->lock
);
638 list_add_tail(&p_conn
->list_entry
, &p_hwfn
->p_fcoe_info
->free_list
);
639 qed_cxt_release_cid(p_hwfn
, p_conn
->icid
);
640 spin_unlock_bh(&p_hwfn
->p_fcoe_info
->lock
);
643 static void _qed_fcoe_get_tstats(struct qed_hwfn
*p_hwfn
,
644 struct qed_ptt
*p_ptt
,
645 struct qed_fcoe_stats
*p_stats
)
647 struct fcoe_rx_stat tstats
;
650 memset(&tstats
, 0, sizeof(tstats
));
651 tstats_addr
= BAR0_MAP_REG_TSDM_RAM
+
652 TSTORM_FCOE_RX_STATS_OFFSET(p_hwfn
->rel_pf_id
);
653 qed_memcpy_from(p_hwfn
, p_ptt
, &tstats
, tstats_addr
, sizeof(tstats
));
655 p_stats
->fcoe_rx_byte_cnt
= HILO_64_REGPAIR(tstats
.fcoe_rx_byte_cnt
);
656 p_stats
->fcoe_rx_data_pkt_cnt
=
657 HILO_64_REGPAIR(tstats
.fcoe_rx_data_pkt_cnt
);
658 p_stats
->fcoe_rx_xfer_pkt_cnt
=
659 HILO_64_REGPAIR(tstats
.fcoe_rx_xfer_pkt_cnt
);
660 p_stats
->fcoe_rx_other_pkt_cnt
=
661 HILO_64_REGPAIR(tstats
.fcoe_rx_other_pkt_cnt
);
663 p_stats
->fcoe_silent_drop_pkt_cmdq_full_cnt
=
664 le32_to_cpu(tstats
.fcoe_silent_drop_pkt_cmdq_full_cnt
);
665 p_stats
->fcoe_silent_drop_pkt_rq_full_cnt
=
666 le32_to_cpu(tstats
.fcoe_silent_drop_pkt_rq_full_cnt
);
667 p_stats
->fcoe_silent_drop_pkt_crc_error_cnt
=
668 le32_to_cpu(tstats
.fcoe_silent_drop_pkt_crc_error_cnt
);
669 p_stats
->fcoe_silent_drop_pkt_task_invalid_cnt
=
670 le32_to_cpu(tstats
.fcoe_silent_drop_pkt_task_invalid_cnt
);
671 p_stats
->fcoe_silent_drop_total_pkt_cnt
=
672 le32_to_cpu(tstats
.fcoe_silent_drop_total_pkt_cnt
);
675 static void _qed_fcoe_get_pstats(struct qed_hwfn
*p_hwfn
,
676 struct qed_ptt
*p_ptt
,
677 struct qed_fcoe_stats
*p_stats
)
679 struct fcoe_tx_stat pstats
;
682 memset(&pstats
, 0, sizeof(pstats
));
683 pstats_addr
= BAR0_MAP_REG_PSDM_RAM
+
684 PSTORM_FCOE_TX_STATS_OFFSET(p_hwfn
->rel_pf_id
);
685 qed_memcpy_from(p_hwfn
, p_ptt
, &pstats
, pstats_addr
, sizeof(pstats
));
687 p_stats
->fcoe_tx_byte_cnt
= HILO_64_REGPAIR(pstats
.fcoe_tx_byte_cnt
);
688 p_stats
->fcoe_tx_data_pkt_cnt
=
689 HILO_64_REGPAIR(pstats
.fcoe_tx_data_pkt_cnt
);
690 p_stats
->fcoe_tx_xfer_pkt_cnt
=
691 HILO_64_REGPAIR(pstats
.fcoe_tx_xfer_pkt_cnt
);
692 p_stats
->fcoe_tx_other_pkt_cnt
=
693 HILO_64_REGPAIR(pstats
.fcoe_tx_other_pkt_cnt
);
696 static int qed_fcoe_get_stats(struct qed_hwfn
*p_hwfn
,
697 struct qed_fcoe_stats
*p_stats
)
699 struct qed_ptt
*p_ptt
;
701 memset(p_stats
, 0, sizeof(*p_stats
));
703 p_ptt
= qed_ptt_acquire(p_hwfn
);
706 DP_ERR(p_hwfn
, "Failed to acquire ptt\n");
710 _qed_fcoe_get_tstats(p_hwfn
, p_ptt
, p_stats
);
711 _qed_fcoe_get_pstats(p_hwfn
, p_ptt
, p_stats
);
713 qed_ptt_release(p_hwfn
, p_ptt
);
718 struct qed_hash_fcoe_con
{
719 struct hlist_node node
;
720 struct qed_fcoe_conn
*con
;
723 static int qed_fill_fcoe_dev_info(struct qed_dev
*cdev
,
724 struct qed_dev_fcoe_info
*info
)
726 struct qed_hwfn
*hwfn
= QED_LEADING_HWFN(cdev
);
729 memset(info
, 0, sizeof(*info
));
730 rc
= qed_fill_dev_info(cdev
, &info
->common
);
732 info
->primary_dbq_rq_addr
=
733 qed_fcoe_get_primary_bdq_prod(hwfn
, BDQ_ID_RQ
);
734 info
->secondary_bdq_rq_addr
=
735 qed_fcoe_get_secondary_bdq_prod(hwfn
, BDQ_ID_RQ
);
740 static void qed_register_fcoe_ops(struct qed_dev
*cdev
,
741 struct qed_fcoe_cb_ops
*ops
, void *cookie
)
743 cdev
->protocol_ops
.fcoe
= ops
;
744 cdev
->ops_cookie
= cookie
;
747 static struct qed_hash_fcoe_con
*qed_fcoe_get_hash(struct qed_dev
*cdev
,
750 struct qed_hash_fcoe_con
*hash_con
= NULL
;
752 if (!(cdev
->flags
& QED_FLAG_STORAGE_STARTED
))
755 hash_for_each_possible(cdev
->connections
, hash_con
, node
, handle
) {
756 if (hash_con
->con
->icid
== handle
)
760 if (!hash_con
|| (hash_con
->con
->icid
!= handle
))
766 static int qed_fcoe_stop(struct qed_dev
*cdev
)
770 if (!(cdev
->flags
& QED_FLAG_STORAGE_STARTED
)) {
771 DP_NOTICE(cdev
, "fcoe already stopped\n");
775 if (!hash_empty(cdev
->connections
)) {
777 "Can't stop fcoe - not all connections were returned\n");
782 rc
= qed_sp_fcoe_func_stop(QED_LEADING_HWFN(cdev
),
783 QED_SPQ_MODE_EBLOCK
, NULL
);
784 cdev
->flags
&= ~QED_FLAG_STORAGE_STARTED
;
789 static int qed_fcoe_start(struct qed_dev
*cdev
, struct qed_fcoe_tid
*tasks
)
793 if (cdev
->flags
& QED_FLAG_STORAGE_STARTED
) {
794 DP_NOTICE(cdev
, "fcoe already started;\n");
798 rc
= qed_sp_fcoe_func_start(QED_LEADING_HWFN(cdev
),
799 QED_SPQ_MODE_EBLOCK
, NULL
);
801 DP_NOTICE(cdev
, "Failed to start fcoe\n");
805 cdev
->flags
|= QED_FLAG_STORAGE_STARTED
;
806 hash_init(cdev
->connections
);
809 struct qed_tid_mem
*tid_info
= kzalloc(sizeof(*tid_info
),
814 "Failed to allocate tasks information\n");
819 rc
= qed_cxt_get_tid_mem_info(QED_LEADING_HWFN(cdev
), tid_info
);
821 DP_NOTICE(cdev
, "Failed to gather task information\n");
827 /* Fill task information */
828 tasks
->size
= tid_info
->tid_size
;
829 tasks
->num_tids_per_block
= tid_info
->num_tids_per_block
;
830 memcpy(tasks
->blocks
, tid_info
->blocks
,
831 MAX_TID_BLOCKS_FCOE
* sizeof(u8
*));
839 static int qed_fcoe_acquire_conn(struct qed_dev
*cdev
,
841 u32
*fw_cid
, void __iomem
**p_doorbell
)
843 struct qed_hash_fcoe_con
*hash_con
;
846 /* Allocate a hashed connection */
847 hash_con
= kzalloc(sizeof(*hash_con
), GFP_KERNEL
);
849 DP_NOTICE(cdev
, "Failed to allocate hashed connection\n");
853 /* Acquire the connection */
854 rc
= qed_fcoe_acquire_connection(QED_LEADING_HWFN(cdev
), NULL
,
857 DP_NOTICE(cdev
, "Failed to acquire Connection\n");
862 /* Added the connection to hash table */
863 *handle
= hash_con
->con
->icid
;
864 *fw_cid
= hash_con
->con
->fw_cid
;
865 hash_add(cdev
->connections
, &hash_con
->node
, *handle
);
868 *p_doorbell
= qed_fcoe_get_db_addr(QED_LEADING_HWFN(cdev
),
874 static int qed_fcoe_release_conn(struct qed_dev
*cdev
, u32 handle
)
876 struct qed_hash_fcoe_con
*hash_con
;
878 hash_con
= qed_fcoe_get_hash(cdev
, handle
);
880 DP_NOTICE(cdev
, "Failed to find connection for handle %d\n",
885 hlist_del(&hash_con
->node
);
886 qed_fcoe_release_connection(QED_LEADING_HWFN(cdev
), hash_con
->con
);
892 static int qed_fcoe_offload_conn(struct qed_dev
*cdev
,
894 struct qed_fcoe_params_offload
*conn_info
)
896 struct qed_hash_fcoe_con
*hash_con
;
897 struct qed_fcoe_conn
*con
;
899 hash_con
= qed_fcoe_get_hash(cdev
, handle
);
901 DP_NOTICE(cdev
, "Failed to find connection for handle %d\n",
906 /* Update the connection with information from the params */
909 con
->sq_pbl_addr
= conn_info
->sq_pbl_addr
;
910 con
->sq_curr_page_addr
= conn_info
->sq_curr_page_addr
;
911 con
->sq_next_page_addr
= conn_info
->sq_next_page_addr
;
912 con
->tx_max_fc_pay_len
= conn_info
->tx_max_fc_pay_len
;
913 con
->e_d_tov_timer_val
= conn_info
->e_d_tov_timer_val
;
914 con
->rec_tov_timer_val
= conn_info
->rec_tov_timer_val
;
915 con
->rx_max_fc_pay_len
= conn_info
->rx_max_fc_pay_len
;
916 con
->vlan_tag
= conn_info
->vlan_tag
;
917 con
->max_conc_seqs_c3
= conn_info
->max_conc_seqs_c3
;
918 con
->flags
= conn_info
->flags
;
919 con
->def_q_idx
= conn_info
->def_q_idx
;
921 con
->src_mac_addr_hi
= (conn_info
->src_mac
[5] << 8) |
922 conn_info
->src_mac
[4];
923 con
->src_mac_addr_mid
= (conn_info
->src_mac
[3] << 8) |
924 conn_info
->src_mac
[2];
925 con
->src_mac_addr_lo
= (conn_info
->src_mac
[1] << 8) |
926 conn_info
->src_mac
[0];
927 con
->dst_mac_addr_hi
= (conn_info
->dst_mac
[5] << 8) |
928 conn_info
->dst_mac
[4];
929 con
->dst_mac_addr_mid
= (conn_info
->dst_mac
[3] << 8) |
930 conn_info
->dst_mac
[2];
931 con
->dst_mac_addr_lo
= (conn_info
->dst_mac
[1] << 8) |
932 conn_info
->dst_mac
[0];
934 con
->s_id
.addr_hi
= conn_info
->s_id
.addr_hi
;
935 con
->s_id
.addr_mid
= conn_info
->s_id
.addr_mid
;
936 con
->s_id
.addr_lo
= conn_info
->s_id
.addr_lo
;
937 con
->d_id
.addr_hi
= conn_info
->d_id
.addr_hi
;
938 con
->d_id
.addr_mid
= conn_info
->d_id
.addr_mid
;
939 con
->d_id
.addr_lo
= conn_info
->d_id
.addr_lo
;
941 return qed_sp_fcoe_conn_offload(QED_LEADING_HWFN(cdev
), con
,
942 QED_SPQ_MODE_EBLOCK
, NULL
);
945 static int qed_fcoe_destroy_conn(struct qed_dev
*cdev
,
946 u32 handle
, dma_addr_t terminate_params
)
948 struct qed_hash_fcoe_con
*hash_con
;
949 struct qed_fcoe_conn
*con
;
951 hash_con
= qed_fcoe_get_hash(cdev
, handle
);
953 DP_NOTICE(cdev
, "Failed to find connection for handle %d\n",
958 /* Update the connection with information from the params */
960 con
->terminate_params
= terminate_params
;
962 return qed_sp_fcoe_conn_destroy(QED_LEADING_HWFN(cdev
), con
,
963 QED_SPQ_MODE_EBLOCK
, NULL
);
966 static int qed_fcoe_stats(struct qed_dev
*cdev
, struct qed_fcoe_stats
*stats
)
968 return qed_fcoe_get_stats(QED_LEADING_HWFN(cdev
), stats
);
971 void qed_get_protocol_stats_fcoe(struct qed_dev
*cdev
,
972 struct qed_mcp_fcoe_stats
*stats
)
974 struct qed_fcoe_stats proto_stats
;
976 /* Retrieve FW statistics */
977 memset(&proto_stats
, 0, sizeof(proto_stats
));
978 if (qed_fcoe_stats(cdev
, &proto_stats
)) {
979 DP_VERBOSE(cdev
, QED_MSG_STORAGE
,
980 "Failed to collect FCoE statistics\n");
984 /* Translate FW statistics into struct */
985 stats
->rx_pkts
= proto_stats
.fcoe_rx_data_pkt_cnt
+
986 proto_stats
.fcoe_rx_xfer_pkt_cnt
+
987 proto_stats
.fcoe_rx_other_pkt_cnt
;
988 stats
->tx_pkts
= proto_stats
.fcoe_tx_data_pkt_cnt
+
989 proto_stats
.fcoe_tx_xfer_pkt_cnt
+
990 proto_stats
.fcoe_tx_other_pkt_cnt
;
991 stats
->fcs_err
= proto_stats
.fcoe_silent_drop_pkt_crc_error_cnt
;
993 /* Request protocol driver to fill-in the rest */
994 if (cdev
->protocol_ops
.fcoe
&& cdev
->ops_cookie
) {
995 struct qed_fcoe_cb_ops
*ops
= cdev
->protocol_ops
.fcoe
;
996 void *cookie
= cdev
->ops_cookie
;
998 if (ops
->get_login_failures
)
999 stats
->login_failure
= ops
->get_login_failures(cookie
);
1003 static const struct qed_fcoe_ops qed_fcoe_ops_pass
= {
1004 .common
= &qed_common_ops_pass
,
1005 .ll2
= &qed_ll2_ops_pass
,
1006 .fill_dev_info
= &qed_fill_fcoe_dev_info
,
1007 .start
= &qed_fcoe_start
,
1008 .stop
= &qed_fcoe_stop
,
1009 .register_ops
= &qed_register_fcoe_ops
,
1010 .acquire_conn
= &qed_fcoe_acquire_conn
,
1011 .release_conn
= &qed_fcoe_release_conn
,
1012 .offload_conn
= &qed_fcoe_offload_conn
,
1013 .destroy_conn
= &qed_fcoe_destroy_conn
,
1014 .get_stats
= &qed_fcoe_stats
,
1017 const struct qed_fcoe_ops
*qed_get_fcoe_ops(void)
1019 return &qed_fcoe_ops_pass
;
1021 EXPORT_SYMBOL(qed_get_fcoe_ops
);
1023 void qed_put_fcoe_ops(void)
1026 EXPORT_SYMBOL(qed_put_fcoe_ops
);