1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) |
2 | /* QLogic qed NIC Driver |
3 | * Copyright (c) 2015-2017 QLogic Corporation |
4 | * Copyright (c) 2019-2020 Marvell International Ltd. |
5 | */ |
6 | |
7 | #include <linux/types.h> |
8 | #include <asm/byteorder.h> |
9 | #include <asm/param.h> |
10 | #include <linux/delay.h> |
11 | #include <linux/dma-mapping.h> |
12 | #include <linux/etherdevice.h> |
13 | #include <linux/interrupt.h> |
14 | #include <linux/kernel.h> |
15 | #include <linux/log2.h> |
16 | #include <linux/module.h> |
17 | #include <linux/pci.h> |
18 | #include <linux/slab.h> |
19 | #include <linux/stddef.h> |
20 | #include <linux/string.h> |
21 | #include <linux/workqueue.h> |
22 | #include <linux/errno.h> |
23 | #include <linux/list.h> |
24 | #include <linux/spinlock.h> |
25 | #include <linux/qed/qed_iscsi_if.h> |
26 | #include "qed.h" |
27 | #include "qed_cxt.h" |
28 | #include "qed_dev_api.h" |
29 | #include "qed_hsi.h" |
30 | #include "qed_hw.h" |
31 | #include "qed_int.h" |
32 | #include "qed_iro_hsi.h" |
33 | #include "qed_iscsi.h" |
34 | #include "qed_ll2.h" |
35 | #include "qed_mcp.h" |
36 | #include "qed_sp.h" |
37 | #include "qed_sriov.h" |
38 | #include "qed_reg_addr.h" |
39 | |
40 | struct qed_iscsi_conn { |
41 | struct list_head list_entry; |
42 | bool free_on_delete; |
43 | |
44 | u16 conn_id; |
45 | u32 icid; |
46 | u32 fw_cid; |
47 | |
48 | u8 layer_code; |
49 | u8 offl_flags; |
50 | u8 connect_mode; |
51 | u32 initial_ack; |
52 | dma_addr_t sq_pbl_addr; |
53 | struct qed_chain r2tq; |
54 | struct qed_chain xhq; |
55 | struct qed_chain uhq; |
56 | |
57 | struct tcp_upload_params *tcp_upload_params_virt_addr; |
58 | dma_addr_t tcp_upload_params_phys_addr; |
59 | struct scsi_terminate_extra_params *queue_cnts_virt_addr; |
60 | dma_addr_t queue_cnts_phys_addr; |
61 | dma_addr_t syn_phy_addr; |
62 | |
63 | u16 syn_ip_payload_length; |
64 | u8 local_mac[6]; |
65 | u8 remote_mac[6]; |
66 | u16 vlan_id; |
67 | u16 tcp_flags; |
68 | u8 ip_version; |
69 | u32 remote_ip[4]; |
70 | u32 local_ip[4]; |
71 | u8 ka_max_probe_cnt; |
72 | u8 dup_ack_theshold; |
73 | u32 rcv_next; |
74 | u32 snd_una; |
75 | u32 snd_next; |
76 | u32 snd_max; |
77 | u32 snd_wnd; |
78 | u32 rcv_wnd; |
79 | u32 snd_wl1; |
80 | u32 cwnd; |
81 | u32 ss_thresh; |
82 | u16 srtt; |
83 | u16 rtt_var; |
84 | u32 ts_recent; |
85 | u32 ts_recent_age; |
86 | u32 total_rt; |
87 | u32 ka_timeout_delta; |
88 | u32 rt_timeout_delta; |
89 | u8 dup_ack_cnt; |
90 | u8 snd_wnd_probe_cnt; |
91 | u8 ka_probe_cnt; |
92 | u8 rt_cnt; |
93 | u32 flow_label; |
94 | u32 ka_timeout; |
95 | u32 ka_interval; |
96 | u32 max_rt_time; |
97 | u32 initial_rcv_wnd; |
98 | u8 ttl; |
99 | u8 tos_or_tc; |
100 | u16 remote_port; |
101 | u16 local_port; |
102 | u16 mss; |
103 | u8 snd_wnd_scale; |
104 | u8 rcv_wnd_scale; |
105 | u16 da_timeout_value; |
106 | u8 ack_frequency; |
107 | |
108 | u8 update_flag; |
109 | u8 default_cq; |
110 | u32 max_seq_size; |
111 | u32 max_recv_pdu_length; |
112 | u32 max_send_pdu_length; |
113 | u32 first_seq_length; |
114 | u32 exp_stat_sn; |
115 | u32 stat_sn; |
116 | u16 physical_q0; |
117 | u16 physical_q1; |
118 | u8 abortive_dsconnect; |
119 | }; |
120 | |
121 | static int qed_iscsi_async_event(struct qed_hwfn *p_hwfn, u8 fw_event_code, |
122 | __le16 echo, union event_ring_data *data, |
123 | u8 fw_return_code) |
124 | { |
125 | if (p_hwfn->p_iscsi_info->event_cb) { |
126 | struct qed_iscsi_info *p_iscsi = p_hwfn->p_iscsi_info; |
127 | |
128 | return p_iscsi->event_cb(p_iscsi->event_context, |
129 | fw_event_code, data); |
130 | } else { |
131 | DP_NOTICE(p_hwfn, "iSCSI async completion is not set\n" ); |
132 | return -EINVAL; |
133 | } |
134 | } |
135 | |
136 | static int |
137 | qed_sp_iscsi_func_start(struct qed_hwfn *p_hwfn, |
138 | enum spq_mode comp_mode, |
139 | struct qed_spq_comp_cb *p_comp_addr, |
140 | void *event_context, iscsi_event_cb_t async_event_cb) |
141 | { |
142 | struct iscsi_init_ramrod_params *p_ramrod = NULL; |
143 | struct scsi_init_func_queues *p_queue = NULL; |
144 | struct qed_iscsi_pf_params *p_params = NULL; |
145 | struct iscsi_spe_func_init *p_init = NULL; |
146 | struct qed_spq_entry *p_ent = NULL; |
147 | struct qed_sp_init_data init_data; |
148 | int rc = 0; |
149 | u32 dval; |
150 | u16 val; |
151 | u8 i; |
152 | |
153 | /* Get SPQ entry */ |
154 | memset(&init_data, 0, sizeof(init_data)); |
155 | init_data.cid = qed_spq_get_cid(p_hwfn); |
156 | init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; |
157 | init_data.comp_mode = comp_mode; |
158 | init_data.p_comp_data = p_comp_addr; |
159 | |
160 | rc = qed_sp_init_request(p_hwfn, pp_ent: &p_ent, |
161 | cmd: ISCSI_RAMROD_CMD_ID_INIT_FUNC, |
162 | protocol: PROTOCOLID_TCP_ULP, p_data: &init_data); |
163 | if (rc) |
164 | return rc; |
165 | |
166 | p_ramrod = &p_ent->ramrod.iscsi_init; |
167 | p_init = &p_ramrod->iscsi_init_spe; |
168 | p_params = &p_hwfn->pf_params.iscsi_pf_params; |
169 | p_queue = &p_init->q_params; |
170 | |
171 | /* Sanity */ |
172 | if (p_params->num_queues > p_hwfn->hw_info.feat_num[QED_ISCSI_CQ]) { |
173 | DP_ERR(p_hwfn, |
174 | "Cannot satisfy CQ amount. Queues requested %d, CQs available %d. Aborting function start\n" , |
175 | p_params->num_queues, |
176 | p_hwfn->hw_info.feat_num[QED_ISCSI_CQ]); |
177 | qed_sp_destroy_request(p_hwfn, p_ent); |
178 | return -EINVAL; |
179 | } |
180 | |
181 | val = p_params->half_way_close_timeout; |
182 | p_init->half_way_close_timeout = cpu_to_le16(val); |
183 | p_init->num_sq_pages_in_ring = p_params->num_sq_pages_in_ring; |
184 | p_init->num_r2tq_pages_in_ring = p_params->num_r2tq_pages_in_ring; |
185 | p_init->num_uhq_pages_in_ring = p_params->num_uhq_pages_in_ring; |
186 | p_init->ll2_rx_queue_id = |
187 | p_hwfn->hw_info.resc_start[QED_LL2_RAM_QUEUE] + |
188 | p_params->ll2_ooo_queue_id; |
189 | |
190 | p_init->func_params.log_page_size = p_params->log_page_size; |
191 | val = p_params->num_tasks; |
192 | p_init->func_params.num_tasks = cpu_to_le16(val); |
193 | p_init->debug_mode.flags = p_params->debug_mode; |
194 | |
195 | DMA_REGPAIR_LE(p_queue->glbl_q_params_addr, |
196 | p_params->glbl_q_params_addr); |
197 | |
198 | val = p_params->cq_num_entries; |
199 | p_queue->cq_num_entries = cpu_to_le16(val); |
200 | val = p_params->cmdq_num_entries; |
201 | p_queue->cmdq_num_entries = cpu_to_le16(val); |
202 | p_queue->num_queues = p_params->num_queues; |
203 | dval = (u8)p_hwfn->hw_info.resc_start[QED_CMDQS_CQS]; |
204 | p_queue->queue_relative_offset = (u8)dval; |
205 | p_queue->cq_sb_pi = p_params->gl_rq_pi; |
206 | p_queue->cmdq_sb_pi = p_params->gl_cmd_pi; |
207 | |
208 | for (i = 0; i < p_params->num_queues; i++) { |
209 | val = qed_get_igu_sb_id(p_hwfn, sb_id: i); |
210 | p_queue->cq_cmdq_sb_num_arr[i] = cpu_to_le16(val); |
211 | } |
212 | |
213 | p_queue->bdq_resource_id = (u8)RESC_START(p_hwfn, QED_BDQ); |
214 | |
215 | DMA_REGPAIR_LE(p_queue->bdq_pbl_base_address[BDQ_ID_RQ], |
216 | p_params->bdq_pbl_base_addr[BDQ_ID_RQ]); |
217 | p_queue->bdq_pbl_num_entries[BDQ_ID_RQ] = |
218 | p_params->bdq_pbl_num_entries[BDQ_ID_RQ]; |
219 | val = p_params->bdq_xoff_threshold[BDQ_ID_RQ]; |
220 | p_queue->bdq_xoff_threshold[BDQ_ID_RQ] = cpu_to_le16(val); |
221 | val = p_params->bdq_xon_threshold[BDQ_ID_RQ]; |
222 | p_queue->bdq_xon_threshold[BDQ_ID_RQ] = cpu_to_le16(val); |
223 | |
224 | DMA_REGPAIR_LE(p_queue->bdq_pbl_base_address[BDQ_ID_IMM_DATA], |
225 | p_params->bdq_pbl_base_addr[BDQ_ID_IMM_DATA]); |
226 | p_queue->bdq_pbl_num_entries[BDQ_ID_IMM_DATA] = |
227 | p_params->bdq_pbl_num_entries[BDQ_ID_IMM_DATA]; |
228 | val = p_params->bdq_xoff_threshold[BDQ_ID_IMM_DATA]; |
229 | p_queue->bdq_xoff_threshold[BDQ_ID_IMM_DATA] = cpu_to_le16(val); |
230 | val = p_params->bdq_xon_threshold[BDQ_ID_IMM_DATA]; |
231 | p_queue->bdq_xon_threshold[BDQ_ID_IMM_DATA] = cpu_to_le16(val); |
232 | val = p_params->rq_buffer_size; |
233 | p_queue->rq_buffer_size = cpu_to_le16(val); |
234 | if (p_params->is_target) { |
235 | SET_FIELD(p_queue->q_validity, |
236 | SCSI_INIT_FUNC_QUEUES_RQ_VALID, 1); |
237 | if (p_queue->bdq_pbl_num_entries[BDQ_ID_IMM_DATA]) |
238 | SET_FIELD(p_queue->q_validity, |
239 | SCSI_INIT_FUNC_QUEUES_IMM_DATA_VALID, 1); |
240 | SET_FIELD(p_queue->q_validity, |
241 | SCSI_INIT_FUNC_QUEUES_CMD_VALID, 1); |
242 | } else { |
243 | SET_FIELD(p_queue->q_validity, |
244 | SCSI_INIT_FUNC_QUEUES_RQ_VALID, 1); |
245 | } |
246 | p_ramrod->tcp_init.two_msl_timer = cpu_to_le32(p_params->two_msl_timer); |
247 | val = p_params->tx_sws_timer; |
248 | p_ramrod->tcp_init.tx_sws_timer = cpu_to_le16(val); |
249 | p_ramrod->tcp_init.max_fin_rt = p_params->max_fin_rt; |
250 | |
251 | p_hwfn->p_iscsi_info->event_context = event_context; |
252 | p_hwfn->p_iscsi_info->event_cb = async_event_cb; |
253 | |
254 | qed_spq_register_async_cb(p_hwfn, protocol_id: PROTOCOLID_TCP_ULP, |
255 | cb: qed_iscsi_async_event); |
256 | |
257 | return qed_spq_post(p_hwfn, p_ent, NULL); |
258 | } |
259 | |
260 | static int qed_sp_iscsi_conn_offload(struct qed_hwfn *p_hwfn, |
261 | struct qed_iscsi_conn *p_conn, |
262 | enum spq_mode comp_mode, |
263 | struct qed_spq_comp_cb *p_comp_addr) |
264 | { |
265 | struct iscsi_spe_conn_offload *p_ramrod = NULL; |
266 | struct tcp_offload_params_opt2 *p_tcp2 = NULL; |
267 | struct tcp_offload_params *p_tcp = NULL; |
268 | struct qed_spq_entry *p_ent = NULL; |
269 | struct qed_sp_init_data init_data; |
270 | dma_addr_t r2tq_pbl_addr; |
271 | dma_addr_t xhq_pbl_addr; |
272 | dma_addr_t uhq_pbl_addr; |
273 | u16 physical_q; |
274 | __le16 tmp; |
275 | int rc = 0; |
276 | u32 dval; |
277 | u16 wval; |
278 | u16 *p; |
279 | u8 i; |
280 | |
281 | /* Get SPQ entry */ |
282 | memset(&init_data, 0, sizeof(init_data)); |
283 | init_data.cid = p_conn->icid; |
284 | init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; |
285 | init_data.comp_mode = comp_mode; |
286 | init_data.p_comp_data = p_comp_addr; |
287 | |
288 | rc = qed_sp_init_request(p_hwfn, pp_ent: &p_ent, |
289 | cmd: ISCSI_RAMROD_CMD_ID_OFFLOAD_CONN, |
290 | protocol: PROTOCOLID_TCP_ULP, p_data: &init_data); |
291 | if (rc) |
292 | return rc; |
293 | |
294 | p_ramrod = &p_ent->ramrod.iscsi_conn_offload; |
295 | |
296 | /* Transmission PQ is the first of the PF */ |
297 | physical_q = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_OFLD); |
298 | p_conn->physical_q0 = physical_q; |
299 | p_ramrod->iscsi.physical_q0 = cpu_to_le16(physical_q); |
300 | |
301 | /* iSCSI Pure-ACK PQ */ |
302 | physical_q = qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_ACK); |
303 | p_conn->physical_q1 = physical_q; |
304 | p_ramrod->iscsi.physical_q1 = cpu_to_le16(physical_q); |
305 | |
306 | p_ramrod->conn_id = cpu_to_le16(p_conn->conn_id); |
307 | |
308 | DMA_REGPAIR_LE(p_ramrod->iscsi.sq_pbl_addr, p_conn->sq_pbl_addr); |
309 | |
310 | r2tq_pbl_addr = qed_chain_get_pbl_phys(chain: &p_conn->r2tq); |
311 | DMA_REGPAIR_LE(p_ramrod->iscsi.r2tq_pbl_addr, r2tq_pbl_addr); |
312 | |
313 | xhq_pbl_addr = qed_chain_get_pbl_phys(chain: &p_conn->xhq); |
314 | DMA_REGPAIR_LE(p_ramrod->iscsi.xhq_pbl_addr, xhq_pbl_addr); |
315 | |
316 | uhq_pbl_addr = qed_chain_get_pbl_phys(chain: &p_conn->uhq); |
317 | DMA_REGPAIR_LE(p_ramrod->iscsi.uhq_pbl_addr, uhq_pbl_addr); |
318 | |
319 | p_ramrod->iscsi.initial_ack = cpu_to_le32(p_conn->initial_ack); |
320 | p_ramrod->iscsi.flags = p_conn->offl_flags; |
321 | p_ramrod->iscsi.default_cq = p_conn->default_cq; |
322 | p_ramrod->iscsi.stat_sn = cpu_to_le32(p_conn->stat_sn); |
323 | |
324 | if (!GET_FIELD(p_ramrod->iscsi.flags, |
325 | ISCSI_CONN_OFFLOAD_PARAMS_TCP_ON_CHIP_1B)) { |
326 | p_tcp = &p_ramrod->tcp; |
327 | |
328 | p = (u16 *)p_conn->local_mac; |
329 | tmp = cpu_to_le16(get_unaligned_be16(p)); |
330 | p_tcp->local_mac_addr_hi = tmp; |
331 | tmp = cpu_to_le16(get_unaligned_be16(p + 1)); |
332 | p_tcp->local_mac_addr_mid = tmp; |
333 | tmp = cpu_to_le16(get_unaligned_be16(p + 2)); |
334 | p_tcp->local_mac_addr_lo = tmp; |
335 | |
336 | p = (u16 *)p_conn->remote_mac; |
337 | tmp = cpu_to_le16(get_unaligned_be16(p)); |
338 | p_tcp->remote_mac_addr_hi = tmp; |
339 | tmp = cpu_to_le16(get_unaligned_be16(p + 1)); |
340 | p_tcp->remote_mac_addr_mid = tmp; |
341 | tmp = cpu_to_le16(get_unaligned_be16(p + 2)); |
342 | p_tcp->remote_mac_addr_lo = tmp; |
343 | |
344 | p_tcp->vlan_id = cpu_to_le16(p_conn->vlan_id); |
345 | |
346 | p_tcp->flags = cpu_to_le16(p_conn->tcp_flags); |
347 | p_tcp->ip_version = p_conn->ip_version; |
348 | for (i = 0; i < 4; i++) { |
349 | dval = p_conn->remote_ip[i]; |
350 | p_tcp->remote_ip[i] = cpu_to_le32(dval); |
351 | dval = p_conn->local_ip[i]; |
352 | p_tcp->local_ip[i] = cpu_to_le32(dval); |
353 | } |
354 | p_tcp->ka_max_probe_cnt = p_conn->ka_max_probe_cnt; |
355 | p_tcp->dup_ack_theshold = p_conn->dup_ack_theshold; |
356 | |
357 | p_tcp->rcv_next = cpu_to_le32(p_conn->rcv_next); |
358 | p_tcp->snd_una = cpu_to_le32(p_conn->snd_una); |
359 | p_tcp->snd_next = cpu_to_le32(p_conn->snd_next); |
360 | p_tcp->snd_max = cpu_to_le32(p_conn->snd_max); |
361 | p_tcp->snd_wnd = cpu_to_le32(p_conn->snd_wnd); |
362 | p_tcp->rcv_wnd = cpu_to_le32(p_conn->rcv_wnd); |
363 | p_tcp->snd_wl1 = cpu_to_le32(p_conn->snd_wl1); |
364 | p_tcp->cwnd = cpu_to_le32(p_conn->cwnd); |
365 | p_tcp->ss_thresh = cpu_to_le32(p_conn->ss_thresh); |
366 | p_tcp->srtt = cpu_to_le16(p_conn->srtt); |
367 | p_tcp->rtt_var = cpu_to_le16(p_conn->rtt_var); |
368 | p_tcp->ts_recent = cpu_to_le32(p_conn->ts_recent); |
369 | p_tcp->ts_recent_age = cpu_to_le32(p_conn->ts_recent_age); |
370 | p_tcp->total_rt = cpu_to_le32(p_conn->total_rt); |
371 | dval = p_conn->ka_timeout_delta; |
372 | p_tcp->ka_timeout_delta = cpu_to_le32(dval); |
373 | dval = p_conn->rt_timeout_delta; |
374 | p_tcp->rt_timeout_delta = cpu_to_le32(dval); |
375 | p_tcp->dup_ack_cnt = p_conn->dup_ack_cnt; |
376 | p_tcp->snd_wnd_probe_cnt = p_conn->snd_wnd_probe_cnt; |
377 | p_tcp->ka_probe_cnt = p_conn->ka_probe_cnt; |
378 | p_tcp->rt_cnt = p_conn->rt_cnt; |
379 | p_tcp->flow_label = cpu_to_le32(p_conn->flow_label); |
380 | p_tcp->ka_timeout = cpu_to_le32(p_conn->ka_timeout); |
381 | p_tcp->ka_interval = cpu_to_le32(p_conn->ka_interval); |
382 | p_tcp->max_rt_time = cpu_to_le32(p_conn->max_rt_time); |
383 | dval = p_conn->initial_rcv_wnd; |
384 | p_tcp->initial_rcv_wnd = cpu_to_le32(dval); |
385 | p_tcp->ttl = p_conn->ttl; |
386 | p_tcp->tos_or_tc = p_conn->tos_or_tc; |
387 | p_tcp->remote_port = cpu_to_le16(p_conn->remote_port); |
388 | p_tcp->local_port = cpu_to_le16(p_conn->local_port); |
389 | p_tcp->mss = cpu_to_le16(p_conn->mss); |
390 | p_tcp->snd_wnd_scale = p_conn->snd_wnd_scale; |
391 | p_tcp->rcv_wnd_scale = p_conn->rcv_wnd_scale; |
392 | wval = p_conn->da_timeout_value; |
393 | p_tcp->da_timeout_value = cpu_to_le16(wval); |
394 | p_tcp->ack_frequency = p_conn->ack_frequency; |
395 | p_tcp->connect_mode = p_conn->connect_mode; |
396 | } else { |
397 | p_tcp2 = |
398 | &((struct iscsi_spe_conn_offload_option2 *)p_ramrod)->tcp; |
399 | |
400 | p = (u16 *)p_conn->local_mac; |
401 | tmp = cpu_to_le16(get_unaligned_be16(p)); |
402 | p_tcp2->local_mac_addr_hi = tmp; |
403 | tmp = cpu_to_le16(get_unaligned_be16(p + 1)); |
404 | p_tcp2->local_mac_addr_mid = tmp; |
405 | tmp = cpu_to_le16(get_unaligned_be16(p + 2)); |
406 | p_tcp2->local_mac_addr_lo = tmp; |
407 | |
408 | p = (u16 *)p_conn->remote_mac; |
409 | tmp = cpu_to_le16(get_unaligned_be16(p)); |
410 | p_tcp2->remote_mac_addr_hi = tmp; |
411 | tmp = cpu_to_le16(get_unaligned_be16(p + 1)); |
412 | p_tcp2->remote_mac_addr_mid = tmp; |
413 | tmp = cpu_to_le16(get_unaligned_be16(p + 2)); |
414 | p_tcp2->remote_mac_addr_lo = tmp; |
415 | |
416 | p_tcp2->vlan_id = cpu_to_le16(p_conn->vlan_id); |
417 | p_tcp2->flags = cpu_to_le16(p_conn->tcp_flags); |
418 | |
419 | p_tcp2->ip_version = p_conn->ip_version; |
420 | for (i = 0; i < 4; i++) { |
421 | dval = p_conn->remote_ip[i]; |
422 | p_tcp2->remote_ip[i] = cpu_to_le32(dval); |
423 | dval = p_conn->local_ip[i]; |
424 | p_tcp2->local_ip[i] = cpu_to_le32(dval); |
425 | } |
426 | |
427 | p_tcp2->flow_label = cpu_to_le32(p_conn->flow_label); |
428 | p_tcp2->ttl = p_conn->ttl; |
429 | p_tcp2->tos_or_tc = p_conn->tos_or_tc; |
430 | p_tcp2->remote_port = cpu_to_le16(p_conn->remote_port); |
431 | p_tcp2->local_port = cpu_to_le16(p_conn->local_port); |
432 | p_tcp2->mss = cpu_to_le16(p_conn->mss); |
433 | p_tcp2->rcv_wnd_scale = p_conn->rcv_wnd_scale; |
434 | p_tcp2->connect_mode = p_conn->connect_mode; |
435 | wval = p_conn->syn_ip_payload_length; |
436 | p_tcp2->syn_ip_payload_length = cpu_to_le16(wval); |
437 | p_tcp2->syn_phy_addr_lo = DMA_LO_LE(p_conn->syn_phy_addr); |
438 | p_tcp2->syn_phy_addr_hi = DMA_HI_LE(p_conn->syn_phy_addr); |
439 | p_tcp2->cwnd = cpu_to_le32(p_conn->cwnd); |
440 | p_tcp2->ka_max_probe_cnt = p_conn->ka_probe_cnt; |
441 | p_tcp2->ka_timeout = cpu_to_le32(p_conn->ka_timeout); |
442 | p_tcp2->max_rt_time = cpu_to_le32(p_conn->max_rt_time); |
443 | p_tcp2->ka_interval = cpu_to_le32(p_conn->ka_interval); |
444 | } |
445 | |
446 | return qed_spq_post(p_hwfn, p_ent, NULL); |
447 | } |
448 | |
449 | static int qed_sp_iscsi_conn_update(struct qed_hwfn *p_hwfn, |
450 | struct qed_iscsi_conn *p_conn, |
451 | enum spq_mode comp_mode, |
452 | struct qed_spq_comp_cb *p_comp_addr) |
453 | { |
454 | struct iscsi_conn_update_ramrod_params *p_ramrod = NULL; |
455 | struct qed_spq_entry *p_ent = NULL; |
456 | struct qed_sp_init_data init_data; |
457 | int rc; |
458 | u32 dval; |
459 | |
460 | /* Get SPQ entry */ |
461 | memset(&init_data, 0, sizeof(init_data)); |
462 | init_data.cid = p_conn->icid; |
463 | init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; |
464 | init_data.comp_mode = comp_mode; |
465 | init_data.p_comp_data = p_comp_addr; |
466 | |
467 | rc = qed_sp_init_request(p_hwfn, pp_ent: &p_ent, |
468 | cmd: ISCSI_RAMROD_CMD_ID_UPDATE_CONN, |
469 | protocol: PROTOCOLID_TCP_ULP, p_data: &init_data); |
470 | if (rc) |
471 | return rc; |
472 | |
473 | p_ramrod = &p_ent->ramrod.iscsi_conn_update; |
474 | |
475 | p_ramrod->conn_id = cpu_to_le16(p_conn->conn_id); |
476 | p_ramrod->flags = p_conn->update_flag; |
477 | p_ramrod->max_seq_size = cpu_to_le32(p_conn->max_seq_size); |
478 | dval = p_conn->max_recv_pdu_length; |
479 | p_ramrod->max_recv_pdu_length = cpu_to_le32(dval); |
480 | dval = p_conn->max_send_pdu_length; |
481 | p_ramrod->max_send_pdu_length = cpu_to_le32(dval); |
482 | dval = p_conn->first_seq_length; |
483 | p_ramrod->first_seq_length = cpu_to_le32(dval); |
484 | p_ramrod->exp_stat_sn = cpu_to_le32(p_conn->exp_stat_sn); |
485 | |
486 | return qed_spq_post(p_hwfn, p_ent, NULL); |
487 | } |
488 | |
489 | static int |
490 | qed_sp_iscsi_mac_update(struct qed_hwfn *p_hwfn, |
491 | struct qed_iscsi_conn *p_conn, |
492 | enum spq_mode comp_mode, |
493 | struct qed_spq_comp_cb *p_comp_addr) |
494 | { |
495 | struct iscsi_spe_conn_mac_update *p_ramrod = NULL; |
496 | struct qed_spq_entry *p_ent = NULL; |
497 | struct qed_sp_init_data init_data; |
498 | int rc = -EINVAL; |
499 | u8 ucval; |
500 | |
501 | /* Get SPQ entry */ |
502 | memset(&init_data, 0, sizeof(init_data)); |
503 | init_data.cid = p_conn->icid; |
504 | init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; |
505 | init_data.comp_mode = comp_mode; |
506 | init_data.p_comp_data = p_comp_addr; |
507 | |
508 | rc = qed_sp_init_request(p_hwfn, pp_ent: &p_ent, |
509 | cmd: ISCSI_RAMROD_CMD_ID_MAC_UPDATE, |
510 | protocol: PROTOCOLID_TCP_ULP, p_data: &init_data); |
511 | if (rc) |
512 | return rc; |
513 | |
514 | p_ramrod = &p_ent->ramrod.iscsi_conn_mac_update; |
515 | |
516 | p_ramrod->conn_id = cpu_to_le16(p_conn->conn_id); |
517 | ucval = p_conn->remote_mac[1]; |
518 | ((u8 *)(&p_ramrod->remote_mac_addr_hi))[0] = ucval; |
519 | ucval = p_conn->remote_mac[0]; |
520 | ((u8 *)(&p_ramrod->remote_mac_addr_hi))[1] = ucval; |
521 | ucval = p_conn->remote_mac[3]; |
522 | ((u8 *)(&p_ramrod->remote_mac_addr_mid))[0] = ucval; |
523 | ucval = p_conn->remote_mac[2]; |
524 | ((u8 *)(&p_ramrod->remote_mac_addr_mid))[1] = ucval; |
525 | ucval = p_conn->remote_mac[5]; |
526 | ((u8 *)(&p_ramrod->remote_mac_addr_lo))[0] = ucval; |
527 | ucval = p_conn->remote_mac[4]; |
528 | ((u8 *)(&p_ramrod->remote_mac_addr_lo))[1] = ucval; |
529 | |
530 | return qed_spq_post(p_hwfn, p_ent, NULL); |
531 | } |
532 | |
533 | static int qed_sp_iscsi_conn_terminate(struct qed_hwfn *p_hwfn, |
534 | struct qed_iscsi_conn *p_conn, |
535 | enum spq_mode comp_mode, |
536 | struct qed_spq_comp_cb *p_comp_addr) |
537 | { |
538 | struct iscsi_spe_conn_termination *p_ramrod = NULL; |
539 | struct qed_spq_entry *p_ent = NULL; |
540 | struct qed_sp_init_data init_data; |
541 | int rc = -EINVAL; |
542 | |
543 | /* Get SPQ entry */ |
544 | memset(&init_data, 0, sizeof(init_data)); |
545 | init_data.cid = p_conn->icid; |
546 | init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; |
547 | init_data.comp_mode = comp_mode; |
548 | init_data.p_comp_data = p_comp_addr; |
549 | |
550 | rc = qed_sp_init_request(p_hwfn, pp_ent: &p_ent, |
551 | cmd: ISCSI_RAMROD_CMD_ID_TERMINATION_CONN, |
552 | protocol: PROTOCOLID_TCP_ULP, p_data: &init_data); |
553 | if (rc) |
554 | return rc; |
555 | |
556 | p_ramrod = &p_ent->ramrod.iscsi_conn_terminate; |
557 | |
558 | p_ramrod->conn_id = cpu_to_le16(p_conn->conn_id); |
559 | p_ramrod->abortive = p_conn->abortive_dsconnect; |
560 | |
561 | DMA_REGPAIR_LE(p_ramrod->query_params_addr, |
562 | p_conn->tcp_upload_params_phys_addr); |
563 | DMA_REGPAIR_LE(p_ramrod->queue_cnts_addr, p_conn->queue_cnts_phys_addr); |
564 | |
565 | return qed_spq_post(p_hwfn, p_ent, NULL); |
566 | } |
567 | |
568 | static int qed_sp_iscsi_conn_clear_sq(struct qed_hwfn *p_hwfn, |
569 | struct qed_iscsi_conn *p_conn, |
570 | enum spq_mode comp_mode, |
571 | struct qed_spq_comp_cb *p_comp_addr) |
572 | { |
573 | struct qed_spq_entry *p_ent = NULL; |
574 | struct qed_sp_init_data init_data; |
575 | int rc = -EINVAL; |
576 | |
577 | /* Get SPQ entry */ |
578 | memset(&init_data, 0, sizeof(init_data)); |
579 | init_data.cid = p_conn->icid; |
580 | init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; |
581 | init_data.comp_mode = comp_mode; |
582 | init_data.p_comp_data = p_comp_addr; |
583 | |
584 | rc = qed_sp_init_request(p_hwfn, pp_ent: &p_ent, |
585 | cmd: ISCSI_RAMROD_CMD_ID_CLEAR_SQ, |
586 | protocol: PROTOCOLID_TCP_ULP, p_data: &init_data); |
587 | if (rc) |
588 | return rc; |
589 | |
590 | return qed_spq_post(p_hwfn, p_ent, NULL); |
591 | } |
592 | |
593 | static int qed_sp_iscsi_func_stop(struct qed_hwfn *p_hwfn, |
594 | enum spq_mode comp_mode, |
595 | struct qed_spq_comp_cb *p_comp_addr) |
596 | { |
597 | struct qed_spq_entry *p_ent = NULL; |
598 | struct qed_sp_init_data init_data; |
599 | int rc = 0; |
600 | |
601 | /* Get SPQ entry */ |
602 | memset(&init_data, 0, sizeof(init_data)); |
603 | init_data.cid = qed_spq_get_cid(p_hwfn); |
604 | init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; |
605 | init_data.comp_mode = comp_mode; |
606 | init_data.p_comp_data = p_comp_addr; |
607 | |
608 | rc = qed_sp_init_request(p_hwfn, pp_ent: &p_ent, |
609 | cmd: ISCSI_RAMROD_CMD_ID_DESTROY_FUNC, |
610 | protocol: PROTOCOLID_TCP_ULP, p_data: &init_data); |
611 | if (rc) |
612 | return rc; |
613 | |
614 | rc = qed_spq_post(p_hwfn, p_ent, NULL); |
615 | |
616 | qed_spq_unregister_async_cb(p_hwfn, protocol_id: PROTOCOLID_TCP_ULP); |
617 | return rc; |
618 | } |
619 | |
620 | static void __iomem *qed_iscsi_get_db_addr(struct qed_hwfn *p_hwfn, u32 cid) |
621 | { |
622 | return (u8 __iomem *)p_hwfn->doorbells + |
623 | qed_db_addr(cid, DQ_DEMS_LEGACY); |
624 | } |
625 | |
626 | static void __iomem *qed_iscsi_get_primary_bdq_prod(struct qed_hwfn *p_hwfn, |
627 | u8 bdq_id) |
628 | { |
629 | if (RESC_NUM(p_hwfn, QED_BDQ)) { |
630 | return (u8 __iomem *)p_hwfn->regview + |
631 | GET_GTT_BDQ_REG_ADDR(GTT_BAR0_MAP_REG_MSDM_RAM, |
632 | MSTORM_SCSI_BDQ_EXT_PROD, |
633 | RESC_START(p_hwfn, QED_BDQ), bdq_id); |
634 | } else { |
635 | DP_NOTICE(p_hwfn, "BDQ is not allocated!\n" ); |
636 | return NULL; |
637 | } |
638 | } |
639 | |
640 | static void __iomem *qed_iscsi_get_secondary_bdq_prod(struct qed_hwfn *p_hwfn, |
641 | u8 bdq_id) |
642 | { |
643 | if (RESC_NUM(p_hwfn, QED_BDQ)) { |
644 | return (u8 __iomem *)p_hwfn->regview + |
645 | GET_GTT_BDQ_REG_ADDR(GTT_BAR0_MAP_REG_TSDM_RAM, |
646 | TSTORM_SCSI_BDQ_EXT_PROD, |
647 | RESC_START(p_hwfn, QED_BDQ), bdq_id); |
648 | } else { |
649 | DP_NOTICE(p_hwfn, "BDQ is not allocated!\n" ); |
650 | return NULL; |
651 | } |
652 | } |
653 | |
654 | static int qed_iscsi_setup_connection(struct qed_iscsi_conn *p_conn) |
655 | { |
656 | if (!p_conn->queue_cnts_virt_addr) |
657 | goto nomem; |
658 | memset(p_conn->queue_cnts_virt_addr, 0, |
659 | sizeof(*p_conn->queue_cnts_virt_addr)); |
660 | |
661 | if (!p_conn->tcp_upload_params_virt_addr) |
662 | goto nomem; |
663 | memset(p_conn->tcp_upload_params_virt_addr, 0, |
664 | sizeof(*p_conn->tcp_upload_params_virt_addr)); |
665 | |
666 | if (!p_conn->r2tq.p_virt_addr) |
667 | goto nomem; |
668 | qed_chain_pbl_zero_mem(p_chain: &p_conn->r2tq); |
669 | |
670 | if (!p_conn->uhq.p_virt_addr) |
671 | goto nomem; |
672 | qed_chain_pbl_zero_mem(p_chain: &p_conn->uhq); |
673 | |
674 | if (!p_conn->xhq.p_virt_addr) |
675 | goto nomem; |
676 | qed_chain_pbl_zero_mem(p_chain: &p_conn->xhq); |
677 | |
678 | return 0; |
679 | nomem: |
680 | return -ENOMEM; |
681 | } |
682 | |
683 | static int qed_iscsi_allocate_connection(struct qed_hwfn *p_hwfn, |
684 | struct qed_iscsi_conn **p_out_conn) |
685 | { |
686 | struct scsi_terminate_extra_params *p_q_cnts = NULL; |
687 | struct qed_iscsi_pf_params *p_params = NULL; |
688 | struct qed_chain_init_params params = { |
689 | .mode = QED_CHAIN_MODE_PBL, |
690 | .intended_use = QED_CHAIN_USE_TO_CONSUME_PRODUCE, |
691 | .cnt_type = QED_CHAIN_CNT_TYPE_U16, |
692 | }; |
693 | struct tcp_upload_params *p_tcp = NULL; |
694 | struct qed_iscsi_conn *p_conn = NULL; |
695 | int rc = 0; |
696 | |
697 | /* Try finding a free connection that can be used */ |
698 | spin_lock_bh(lock: &p_hwfn->p_iscsi_info->lock); |
699 | if (!list_empty(head: &p_hwfn->p_iscsi_info->free_list)) |
700 | p_conn = list_first_entry(&p_hwfn->p_iscsi_info->free_list, |
701 | struct qed_iscsi_conn, list_entry); |
702 | if (p_conn) { |
703 | list_del(entry: &p_conn->list_entry); |
704 | spin_unlock_bh(lock: &p_hwfn->p_iscsi_info->lock); |
705 | *p_out_conn = p_conn; |
706 | return 0; |
707 | } |
708 | spin_unlock_bh(lock: &p_hwfn->p_iscsi_info->lock); |
709 | |
710 | /* Need to allocate a new connection */ |
711 | p_params = &p_hwfn->pf_params.iscsi_pf_params; |
712 | |
713 | p_conn = kzalloc(size: sizeof(*p_conn), GFP_KERNEL); |
714 | if (!p_conn) |
715 | return -ENOMEM; |
716 | |
717 | p_q_cnts = dma_alloc_coherent(dev: &p_hwfn->cdev->pdev->dev, |
718 | size: sizeof(*p_q_cnts), |
719 | dma_handle: &p_conn->queue_cnts_phys_addr, |
720 | GFP_KERNEL); |
721 | if (!p_q_cnts) |
722 | goto nomem_queue_cnts_param; |
723 | p_conn->queue_cnts_virt_addr = p_q_cnts; |
724 | |
725 | p_tcp = dma_alloc_coherent(dev: &p_hwfn->cdev->pdev->dev, |
726 | size: sizeof(*p_tcp), |
727 | dma_handle: &p_conn->tcp_upload_params_phys_addr, |
728 | GFP_KERNEL); |
729 | if (!p_tcp) |
730 | goto nomem_upload_param; |
731 | p_conn->tcp_upload_params_virt_addr = p_tcp; |
732 | |
733 | params.num_elems = p_params->num_r2tq_pages_in_ring * |
734 | QED_CHAIN_PAGE_SIZE / sizeof(struct iscsi_wqe); |
735 | params.elem_size = sizeof(struct iscsi_wqe); |
736 | |
737 | rc = qed_chain_alloc(cdev: p_hwfn->cdev, chain: &p_conn->r2tq, params: ¶ms); |
738 | if (rc) |
739 | goto nomem_r2tq; |
740 | |
741 | params.num_elems = p_params->num_uhq_pages_in_ring * |
742 | QED_CHAIN_PAGE_SIZE / sizeof(struct iscsi_uhqe); |
743 | params.elem_size = sizeof(struct iscsi_uhqe); |
744 | |
745 | rc = qed_chain_alloc(cdev: p_hwfn->cdev, chain: &p_conn->uhq, params: ¶ms); |
746 | if (rc) |
747 | goto nomem_uhq; |
748 | |
749 | params.elem_size = sizeof(struct iscsi_xhqe); |
750 | |
751 | rc = qed_chain_alloc(cdev: p_hwfn->cdev, chain: &p_conn->xhq, params: ¶ms); |
752 | if (rc) |
753 | goto nomem; |
754 | |
755 | p_conn->free_on_delete = true; |
756 | *p_out_conn = p_conn; |
757 | return 0; |
758 | |
759 | nomem: |
760 | qed_chain_free(cdev: p_hwfn->cdev, chain: &p_conn->uhq); |
761 | nomem_uhq: |
762 | qed_chain_free(cdev: p_hwfn->cdev, chain: &p_conn->r2tq); |
763 | nomem_r2tq: |
764 | dma_free_coherent(dev: &p_hwfn->cdev->pdev->dev, |
765 | size: sizeof(struct tcp_upload_params), |
766 | cpu_addr: p_conn->tcp_upload_params_virt_addr, |
767 | dma_handle: p_conn->tcp_upload_params_phys_addr); |
768 | nomem_upload_param: |
769 | dma_free_coherent(dev: &p_hwfn->cdev->pdev->dev, |
770 | size: sizeof(struct scsi_terminate_extra_params), |
771 | cpu_addr: p_conn->queue_cnts_virt_addr, |
772 | dma_handle: p_conn->queue_cnts_phys_addr); |
773 | nomem_queue_cnts_param: |
774 | kfree(objp: p_conn); |
775 | |
776 | return -ENOMEM; |
777 | } |
778 | |
779 | static int qed_iscsi_acquire_connection(struct qed_hwfn *p_hwfn, |
780 | struct qed_iscsi_conn *p_in_conn, |
781 | struct qed_iscsi_conn **p_out_conn) |
782 | { |
783 | struct qed_iscsi_conn *p_conn = NULL; |
784 | int rc = 0; |
785 | u32 icid; |
786 | |
787 | spin_lock_bh(lock: &p_hwfn->p_iscsi_info->lock); |
788 | rc = qed_cxt_acquire_cid(p_hwfn, type: PROTOCOLID_TCP_ULP, p_cid: &icid); |
789 | spin_unlock_bh(lock: &p_hwfn->p_iscsi_info->lock); |
790 | if (rc) |
791 | return rc; |
792 | |
793 | /* Use input connection or allocate a new one */ |
794 | if (p_in_conn) |
795 | p_conn = p_in_conn; |
796 | else |
797 | rc = qed_iscsi_allocate_connection(p_hwfn, p_out_conn: &p_conn); |
798 | |
799 | if (!rc) |
800 | rc = qed_iscsi_setup_connection(p_conn); |
801 | |
802 | if (rc) { |
803 | spin_lock_bh(lock: &p_hwfn->p_iscsi_info->lock); |
804 | qed_cxt_release_cid(p_hwfn, cid: icid); |
805 | spin_unlock_bh(lock: &p_hwfn->p_iscsi_info->lock); |
806 | return rc; |
807 | } |
808 | |
809 | p_conn->icid = icid; |
810 | p_conn->conn_id = (u16)icid; |
811 | p_conn->fw_cid = (p_hwfn->hw_info.opaque_fid << 16) | icid; |
812 | |
813 | *p_out_conn = p_conn; |
814 | |
815 | return rc; |
816 | } |
817 | |
818 | static void qed_iscsi_release_connection(struct qed_hwfn *p_hwfn, |
819 | struct qed_iscsi_conn *p_conn) |
820 | { |
821 | spin_lock_bh(lock: &p_hwfn->p_iscsi_info->lock); |
822 | list_add_tail(new: &p_conn->list_entry, head: &p_hwfn->p_iscsi_info->free_list); |
823 | qed_cxt_release_cid(p_hwfn, cid: p_conn->icid); |
824 | spin_unlock_bh(lock: &p_hwfn->p_iscsi_info->lock); |
825 | } |
826 | |
827 | static void qed_iscsi_free_connection(struct qed_hwfn *p_hwfn, |
828 | struct qed_iscsi_conn *p_conn) |
829 | { |
830 | qed_chain_free(cdev: p_hwfn->cdev, chain: &p_conn->xhq); |
831 | qed_chain_free(cdev: p_hwfn->cdev, chain: &p_conn->uhq); |
832 | qed_chain_free(cdev: p_hwfn->cdev, chain: &p_conn->r2tq); |
833 | dma_free_coherent(dev: &p_hwfn->cdev->pdev->dev, |
834 | size: sizeof(struct tcp_upload_params), |
835 | cpu_addr: p_conn->tcp_upload_params_virt_addr, |
836 | dma_handle: p_conn->tcp_upload_params_phys_addr); |
837 | dma_free_coherent(dev: &p_hwfn->cdev->pdev->dev, |
838 | size: sizeof(struct scsi_terminate_extra_params), |
839 | cpu_addr: p_conn->queue_cnts_virt_addr, |
840 | dma_handle: p_conn->queue_cnts_phys_addr); |
841 | kfree(objp: p_conn); |
842 | } |
843 | |
844 | int qed_iscsi_alloc(struct qed_hwfn *p_hwfn) |
845 | { |
846 | struct qed_iscsi_info *p_iscsi_info; |
847 | |
848 | p_iscsi_info = kzalloc(size: sizeof(*p_iscsi_info), GFP_KERNEL); |
849 | if (!p_iscsi_info) |
850 | return -ENOMEM; |
851 | |
852 | INIT_LIST_HEAD(list: &p_iscsi_info->free_list); |
853 | |
854 | p_hwfn->p_iscsi_info = p_iscsi_info; |
855 | return 0; |
856 | } |
857 | |
858 | void qed_iscsi_setup(struct qed_hwfn *p_hwfn) |
859 | { |
860 | spin_lock_init(&p_hwfn->p_iscsi_info->lock); |
861 | } |
862 | |
863 | void qed_iscsi_free(struct qed_hwfn *p_hwfn) |
864 | { |
865 | struct qed_iscsi_conn *p_conn = NULL; |
866 | |
867 | if (!p_hwfn->p_iscsi_info) |
868 | return; |
869 | |
870 | while (!list_empty(head: &p_hwfn->p_iscsi_info->free_list)) { |
871 | p_conn = list_first_entry(&p_hwfn->p_iscsi_info->free_list, |
872 | struct qed_iscsi_conn, list_entry); |
873 | if (p_conn) { |
874 | list_del(entry: &p_conn->list_entry); |
875 | qed_iscsi_free_connection(p_hwfn, p_conn); |
876 | } |
877 | } |
878 | |
879 | kfree(objp: p_hwfn->p_iscsi_info); |
880 | p_hwfn->p_iscsi_info = NULL; |
881 | } |
882 | |
883 | static void _qed_iscsi_get_tstats(struct qed_hwfn *p_hwfn, |
884 | struct qed_ptt *p_ptt, |
885 | struct qed_iscsi_stats *p_stats) |
886 | { |
887 | struct tstorm_iscsi_stats_drv tstats; |
888 | u32 tstats_addr; |
889 | |
890 | memset(&tstats, 0, sizeof(tstats)); |
891 | tstats_addr = BAR0_MAP_REG_TSDM_RAM + |
892 | TSTORM_ISCSI_RX_STATS_OFFSET(p_hwfn->rel_pf_id); |
893 | qed_memcpy_from(p_hwfn, p_ptt, dest: &tstats, hw_addr: tstats_addr, n: sizeof(tstats)); |
894 | |
895 | p_stats->iscsi_rx_bytes_cnt = |
896 | HILO_64_REGPAIR(tstats.iscsi_rx_bytes_cnt); |
897 | p_stats->iscsi_rx_packet_cnt = |
898 | HILO_64_REGPAIR(tstats.iscsi_rx_packet_cnt); |
899 | p_stats->iscsi_rx_new_ooo_isle_events_cnt = |
900 | HILO_64_REGPAIR(tstats.iscsi_rx_new_ooo_isle_events_cnt); |
901 | p_stats->iscsi_cmdq_threshold_cnt = |
902 | le32_to_cpu(tstats.iscsi_cmdq_threshold_cnt); |
903 | p_stats->iscsi_rq_threshold_cnt = |
904 | le32_to_cpu(tstats.iscsi_rq_threshold_cnt); |
905 | p_stats->iscsi_immq_threshold_cnt = |
906 | le32_to_cpu(tstats.iscsi_immq_threshold_cnt); |
907 | } |
908 | |
909 | static void _qed_iscsi_get_mstats(struct qed_hwfn *p_hwfn, |
910 | struct qed_ptt *p_ptt, |
911 | struct qed_iscsi_stats *p_stats) |
912 | { |
913 | struct mstorm_iscsi_stats_drv mstats; |
914 | u32 mstats_addr; |
915 | |
916 | memset(&mstats, 0, sizeof(mstats)); |
917 | mstats_addr = BAR0_MAP_REG_MSDM_RAM + |
918 | MSTORM_ISCSI_RX_STATS_OFFSET(p_hwfn->rel_pf_id); |
919 | qed_memcpy_from(p_hwfn, p_ptt, dest: &mstats, hw_addr: mstats_addr, n: sizeof(mstats)); |
920 | |
921 | p_stats->iscsi_rx_dropped_pdus_task_not_valid = |
922 | HILO_64_REGPAIR(mstats.iscsi_rx_dropped_pdus_task_not_valid); |
923 | } |
924 | |
925 | static void _qed_iscsi_get_ustats(struct qed_hwfn *p_hwfn, |
926 | struct qed_ptt *p_ptt, |
927 | struct qed_iscsi_stats *p_stats) |
928 | { |
929 | struct ustorm_iscsi_stats_drv ustats; |
930 | u32 ustats_addr; |
931 | |
932 | memset(&ustats, 0, sizeof(ustats)); |
933 | ustats_addr = BAR0_MAP_REG_USDM_RAM + |
934 | USTORM_ISCSI_RX_STATS_OFFSET(p_hwfn->rel_pf_id); |
935 | qed_memcpy_from(p_hwfn, p_ptt, dest: &ustats, hw_addr: ustats_addr, n: sizeof(ustats)); |
936 | |
937 | p_stats->iscsi_rx_data_pdu_cnt = |
938 | HILO_64_REGPAIR(ustats.iscsi_rx_data_pdu_cnt); |
939 | p_stats->iscsi_rx_r2t_pdu_cnt = |
940 | HILO_64_REGPAIR(ustats.iscsi_rx_r2t_pdu_cnt); |
941 | p_stats->iscsi_rx_total_pdu_cnt = |
942 | HILO_64_REGPAIR(ustats.iscsi_rx_total_pdu_cnt); |
943 | } |
944 | |
945 | static void _qed_iscsi_get_xstats(struct qed_hwfn *p_hwfn, |
946 | struct qed_ptt *p_ptt, |
947 | struct qed_iscsi_stats *p_stats) |
948 | { |
949 | struct xstorm_iscsi_stats_drv xstats; |
950 | u32 xstats_addr; |
951 | |
952 | memset(&xstats, 0, sizeof(xstats)); |
953 | xstats_addr = BAR0_MAP_REG_XSDM_RAM + |
954 | XSTORM_ISCSI_TX_STATS_OFFSET(p_hwfn->rel_pf_id); |
955 | qed_memcpy_from(p_hwfn, p_ptt, dest: &xstats, hw_addr: xstats_addr, n: sizeof(xstats)); |
956 | |
957 | p_stats->iscsi_tx_go_to_slow_start_event_cnt = |
958 | HILO_64_REGPAIR(xstats.iscsi_tx_go_to_slow_start_event_cnt); |
959 | p_stats->iscsi_tx_fast_retransmit_event_cnt = |
960 | HILO_64_REGPAIR(xstats.iscsi_tx_fast_retransmit_event_cnt); |
961 | } |
962 | |
963 | static void _qed_iscsi_get_ystats(struct qed_hwfn *p_hwfn, |
964 | struct qed_ptt *p_ptt, |
965 | struct qed_iscsi_stats *p_stats) |
966 | { |
967 | struct ystorm_iscsi_stats_drv ystats; |
968 | u32 ystats_addr; |
969 | |
970 | memset(&ystats, 0, sizeof(ystats)); |
971 | ystats_addr = BAR0_MAP_REG_YSDM_RAM + |
972 | YSTORM_ISCSI_TX_STATS_OFFSET(p_hwfn->rel_pf_id); |
973 | qed_memcpy_from(p_hwfn, p_ptt, dest: &ystats, hw_addr: ystats_addr, n: sizeof(ystats)); |
974 | |
975 | p_stats->iscsi_tx_data_pdu_cnt = |
976 | HILO_64_REGPAIR(ystats.iscsi_tx_data_pdu_cnt); |
977 | p_stats->iscsi_tx_r2t_pdu_cnt = |
978 | HILO_64_REGPAIR(ystats.iscsi_tx_r2t_pdu_cnt); |
979 | p_stats->iscsi_tx_total_pdu_cnt = |
980 | HILO_64_REGPAIR(ystats.iscsi_tx_total_pdu_cnt); |
981 | } |
982 | |
983 | static void _qed_iscsi_get_pstats(struct qed_hwfn *p_hwfn, |
984 | struct qed_ptt *p_ptt, |
985 | struct qed_iscsi_stats *p_stats) |
986 | { |
987 | struct pstorm_iscsi_stats_drv pstats; |
988 | u32 pstats_addr; |
989 | |
990 | memset(&pstats, 0, sizeof(pstats)); |
991 | pstats_addr = BAR0_MAP_REG_PSDM_RAM + |
992 | PSTORM_ISCSI_TX_STATS_OFFSET(p_hwfn->rel_pf_id); |
993 | qed_memcpy_from(p_hwfn, p_ptt, dest: &pstats, hw_addr: pstats_addr, n: sizeof(pstats)); |
994 | |
995 | p_stats->iscsi_tx_bytes_cnt = |
996 | HILO_64_REGPAIR(pstats.iscsi_tx_bytes_cnt); |
997 | p_stats->iscsi_tx_packet_cnt = |
998 | HILO_64_REGPAIR(pstats.iscsi_tx_packet_cnt); |
999 | } |
1000 | |
1001 | static int qed_iscsi_get_stats(struct qed_hwfn *p_hwfn, |
1002 | struct qed_iscsi_stats *stats, |
1003 | bool is_atomic) |
1004 | { |
1005 | struct qed_ptt *p_ptt; |
1006 | |
1007 | memset(stats, 0, sizeof(*stats)); |
1008 | |
1009 | p_ptt = qed_ptt_acquire_context(p_hwfn, is_atomic); |
1010 | if (!p_ptt) { |
1011 | DP_ERR(p_hwfn, "Failed to acquire ptt\n" ); |
1012 | return -EAGAIN; |
1013 | } |
1014 | |
1015 | _qed_iscsi_get_tstats(p_hwfn, p_ptt, p_stats: stats); |
1016 | _qed_iscsi_get_mstats(p_hwfn, p_ptt, p_stats: stats); |
1017 | _qed_iscsi_get_ustats(p_hwfn, p_ptt, p_stats: stats); |
1018 | |
1019 | _qed_iscsi_get_xstats(p_hwfn, p_ptt, p_stats: stats); |
1020 | _qed_iscsi_get_ystats(p_hwfn, p_ptt, p_stats: stats); |
1021 | _qed_iscsi_get_pstats(p_hwfn, p_ptt, p_stats: stats); |
1022 | |
1023 | qed_ptt_release(p_hwfn, p_ptt); |
1024 | |
1025 | return 0; |
1026 | } |
1027 | |
1028 | struct qed_hash_iscsi_con { |
1029 | struct hlist_node node; |
1030 | struct qed_iscsi_conn *con; |
1031 | }; |
1032 | |
1033 | static int qed_fill_iscsi_dev_info(struct qed_dev *cdev, |
1034 | struct qed_dev_iscsi_info *info) |
1035 | { |
1036 | struct qed_hwfn *hwfn = QED_AFFIN_HWFN(cdev); |
1037 | |
1038 | int rc; |
1039 | |
1040 | memset(info, 0, sizeof(*info)); |
1041 | rc = qed_fill_dev_info(cdev, dev_info: &info->common); |
1042 | |
1043 | info->primary_dbq_rq_addr = |
1044 | qed_iscsi_get_primary_bdq_prod(p_hwfn: hwfn, BDQ_ID_RQ); |
1045 | info->secondary_bdq_rq_addr = |
1046 | qed_iscsi_get_secondary_bdq_prod(p_hwfn: hwfn, BDQ_ID_RQ); |
1047 | |
1048 | info->num_cqs = FEAT_NUM(hwfn, QED_ISCSI_CQ); |
1049 | |
1050 | return rc; |
1051 | } |
1052 | |
1053 | static void qed_register_iscsi_ops(struct qed_dev *cdev, |
1054 | struct qed_iscsi_cb_ops *ops, void *cookie) |
1055 | { |
1056 | cdev->protocol_ops.iscsi = ops; |
1057 | cdev->ops_cookie = cookie; |
1058 | } |
1059 | |
1060 | static struct qed_hash_iscsi_con *qed_iscsi_get_hash(struct qed_dev *cdev, |
1061 | u32 handle) |
1062 | { |
1063 | struct qed_hash_iscsi_con *hash_con = NULL; |
1064 | |
1065 | if (!(cdev->flags & QED_FLAG_STORAGE_STARTED)) |
1066 | return NULL; |
1067 | |
1068 | hash_for_each_possible(cdev->connections, hash_con, node, handle) { |
1069 | if (hash_con->con->icid == handle) |
1070 | break; |
1071 | } |
1072 | |
1073 | if (!hash_con || (hash_con->con->icid != handle)) |
1074 | return NULL; |
1075 | |
1076 | return hash_con; |
1077 | } |
1078 | |
1079 | static int qed_iscsi_stop(struct qed_dev *cdev) |
1080 | { |
1081 | int rc; |
1082 | |
1083 | if (!(cdev->flags & QED_FLAG_STORAGE_STARTED)) { |
1084 | DP_NOTICE(cdev, "iscsi already stopped\n" ); |
1085 | return 0; |
1086 | } |
1087 | |
1088 | if (!hash_empty(cdev->connections)) { |
1089 | DP_NOTICE(cdev, |
1090 | "Can't stop iscsi - not all connections were returned\n" ); |
1091 | return -EINVAL; |
1092 | } |
1093 | |
1094 | /* Stop the iscsi */ |
1095 | rc = qed_sp_iscsi_func_stop(QED_AFFIN_HWFN(cdev), comp_mode: QED_SPQ_MODE_EBLOCK, |
1096 | NULL); |
1097 | cdev->flags &= ~QED_FLAG_STORAGE_STARTED; |
1098 | |
1099 | return rc; |
1100 | } |
1101 | |
1102 | static int qed_iscsi_start(struct qed_dev *cdev, |
1103 | struct qed_iscsi_tid *tasks, |
1104 | void *event_context, |
1105 | iscsi_event_cb_t async_event_cb) |
1106 | { |
1107 | int rc; |
1108 | struct qed_tid_mem *tid_info; |
1109 | |
1110 | if (cdev->flags & QED_FLAG_STORAGE_STARTED) { |
1111 | DP_NOTICE(cdev, "iscsi already started;\n" ); |
1112 | return 0; |
1113 | } |
1114 | |
1115 | rc = qed_sp_iscsi_func_start(QED_AFFIN_HWFN(cdev), comp_mode: QED_SPQ_MODE_EBLOCK, |
1116 | NULL, event_context, async_event_cb); |
1117 | if (rc) { |
1118 | DP_NOTICE(cdev, "Failed to start iscsi\n" ); |
1119 | return rc; |
1120 | } |
1121 | |
1122 | cdev->flags |= QED_FLAG_STORAGE_STARTED; |
1123 | hash_init(cdev->connections); |
1124 | |
1125 | if (!tasks) |
1126 | return 0; |
1127 | |
1128 | tid_info = kzalloc(size: sizeof(*tid_info), GFP_KERNEL); |
1129 | |
1130 | if (!tid_info) { |
1131 | qed_iscsi_stop(cdev); |
1132 | return -ENOMEM; |
1133 | } |
1134 | |
1135 | rc = qed_cxt_get_tid_mem_info(QED_AFFIN_HWFN(cdev), p_info: tid_info); |
1136 | if (rc) { |
1137 | DP_NOTICE(cdev, "Failed to gather task information\n" ); |
1138 | qed_iscsi_stop(cdev); |
1139 | kfree(objp: tid_info); |
1140 | return rc; |
1141 | } |
1142 | |
1143 | /* Fill task information */ |
1144 | tasks->size = tid_info->tid_size; |
1145 | tasks->num_tids_per_block = tid_info->num_tids_per_block; |
1146 | memcpy(tasks->blocks, tid_info->blocks, |
1147 | MAX_TID_BLOCKS_ISCSI * sizeof(u8 *)); |
1148 | |
1149 | kfree(objp: tid_info); |
1150 | |
1151 | return 0; |
1152 | } |
1153 | |
1154 | static int qed_iscsi_acquire_conn(struct qed_dev *cdev, |
1155 | u32 *handle, |
1156 | u32 *fw_cid, void __iomem **p_doorbell) |
1157 | { |
1158 | struct qed_hash_iscsi_con *hash_con; |
1159 | int rc; |
1160 | |
1161 | /* Allocate a hashed connection */ |
1162 | hash_con = kzalloc(size: sizeof(*hash_con), GFP_ATOMIC); |
1163 | if (!hash_con) |
1164 | return -ENOMEM; |
1165 | |
1166 | /* Acquire the connection */ |
1167 | rc = qed_iscsi_acquire_connection(QED_AFFIN_HWFN(cdev), NULL, |
1168 | p_out_conn: &hash_con->con); |
1169 | if (rc) { |
1170 | DP_NOTICE(cdev, "Failed to acquire Connection\n" ); |
1171 | kfree(objp: hash_con); |
1172 | return rc; |
1173 | } |
1174 | |
1175 | /* Added the connection to hash table */ |
1176 | *handle = hash_con->con->icid; |
1177 | *fw_cid = hash_con->con->fw_cid; |
1178 | hash_add(cdev->connections, &hash_con->node, *handle); |
1179 | |
1180 | if (p_doorbell) |
1181 | *p_doorbell = qed_iscsi_get_db_addr(QED_AFFIN_HWFN(cdev), |
1182 | cid: *handle); |
1183 | |
1184 | return 0; |
1185 | } |
1186 | |
1187 | static int qed_iscsi_release_conn(struct qed_dev *cdev, u32 handle) |
1188 | { |
1189 | struct qed_hash_iscsi_con *hash_con; |
1190 | |
1191 | hash_con = qed_iscsi_get_hash(cdev, handle); |
1192 | if (!hash_con) { |
1193 | DP_NOTICE(cdev, "Failed to find connection for handle %d\n" , |
1194 | handle); |
1195 | return -EINVAL; |
1196 | } |
1197 | |
1198 | hlist_del(n: &hash_con->node); |
1199 | qed_iscsi_release_connection(QED_AFFIN_HWFN(cdev), p_conn: hash_con->con); |
1200 | kfree(objp: hash_con); |
1201 | |
1202 | return 0; |
1203 | } |
1204 | |
1205 | static int qed_iscsi_offload_conn(struct qed_dev *cdev, |
1206 | u32 handle, |
1207 | struct qed_iscsi_params_offload *conn_info) |
1208 | { |
1209 | struct qed_hash_iscsi_con *hash_con; |
1210 | struct qed_iscsi_conn *con; |
1211 | |
1212 | hash_con = qed_iscsi_get_hash(cdev, handle); |
1213 | if (!hash_con) { |
1214 | DP_NOTICE(cdev, "Failed to find connection for handle %d\n" , |
1215 | handle); |
1216 | return -EINVAL; |
1217 | } |
1218 | |
1219 | /* Update the connection with information from the params */ |
1220 | con = hash_con->con; |
1221 | |
1222 | ether_addr_copy(dst: con->local_mac, src: conn_info->src.mac); |
1223 | ether_addr_copy(dst: con->remote_mac, src: conn_info->dst.mac); |
1224 | memcpy(con->local_ip, conn_info->src.ip, sizeof(con->local_ip)); |
1225 | memcpy(con->remote_ip, conn_info->dst.ip, sizeof(con->remote_ip)); |
1226 | con->local_port = conn_info->src.port; |
1227 | con->remote_port = conn_info->dst.port; |
1228 | |
1229 | con->layer_code = conn_info->layer_code; |
1230 | con->sq_pbl_addr = conn_info->sq_pbl_addr; |
1231 | con->initial_ack = conn_info->initial_ack; |
1232 | con->vlan_id = conn_info->vlan_id; |
1233 | con->tcp_flags = conn_info->tcp_flags; |
1234 | con->ip_version = conn_info->ip_version; |
1235 | con->default_cq = conn_info->default_cq; |
1236 | con->ka_max_probe_cnt = conn_info->ka_max_probe_cnt; |
1237 | con->dup_ack_theshold = conn_info->dup_ack_theshold; |
1238 | con->rcv_next = conn_info->rcv_next; |
1239 | con->snd_una = conn_info->snd_una; |
1240 | con->snd_next = conn_info->snd_next; |
1241 | con->snd_max = conn_info->snd_max; |
1242 | con->snd_wnd = conn_info->snd_wnd; |
1243 | con->rcv_wnd = conn_info->rcv_wnd; |
1244 | con->snd_wl1 = conn_info->snd_wl1; |
1245 | con->cwnd = conn_info->cwnd; |
1246 | con->ss_thresh = conn_info->ss_thresh; |
1247 | con->srtt = conn_info->srtt; |
1248 | con->rtt_var = conn_info->rtt_var; |
1249 | con->ts_recent = conn_info->ts_recent; |
1250 | con->ts_recent_age = conn_info->ts_recent_age; |
1251 | con->total_rt = conn_info->total_rt; |
1252 | con->ka_timeout_delta = conn_info->ka_timeout_delta; |
1253 | con->rt_timeout_delta = conn_info->rt_timeout_delta; |
1254 | con->dup_ack_cnt = conn_info->dup_ack_cnt; |
1255 | con->snd_wnd_probe_cnt = conn_info->snd_wnd_probe_cnt; |
1256 | con->ka_probe_cnt = conn_info->ka_probe_cnt; |
1257 | con->rt_cnt = conn_info->rt_cnt; |
1258 | con->flow_label = conn_info->flow_label; |
1259 | con->ka_timeout = conn_info->ka_timeout; |
1260 | con->ka_interval = conn_info->ka_interval; |
1261 | con->max_rt_time = conn_info->max_rt_time; |
1262 | con->initial_rcv_wnd = conn_info->initial_rcv_wnd; |
1263 | con->ttl = conn_info->ttl; |
1264 | con->tos_or_tc = conn_info->tos_or_tc; |
1265 | con->remote_port = conn_info->remote_port; |
1266 | con->local_port = conn_info->local_port; |
1267 | con->mss = conn_info->mss; |
1268 | con->snd_wnd_scale = conn_info->snd_wnd_scale; |
1269 | con->rcv_wnd_scale = conn_info->rcv_wnd_scale; |
1270 | con->da_timeout_value = conn_info->da_timeout_value; |
1271 | con->ack_frequency = conn_info->ack_frequency; |
1272 | |
1273 | /* Set default values on other connection fields */ |
1274 | con->offl_flags = 0x1; |
1275 | |
1276 | return qed_sp_iscsi_conn_offload(QED_AFFIN_HWFN(cdev), p_conn: con, |
1277 | comp_mode: QED_SPQ_MODE_EBLOCK, NULL); |
1278 | } |
1279 | |
1280 | static int qed_iscsi_update_conn(struct qed_dev *cdev, |
1281 | u32 handle, |
1282 | struct qed_iscsi_params_update *conn_info) |
1283 | { |
1284 | struct qed_hash_iscsi_con *hash_con; |
1285 | struct qed_iscsi_conn *con; |
1286 | |
1287 | hash_con = qed_iscsi_get_hash(cdev, handle); |
1288 | if (!hash_con) { |
1289 | DP_NOTICE(cdev, "Failed to find connection for handle %d\n" , |
1290 | handle); |
1291 | return -EINVAL; |
1292 | } |
1293 | |
1294 | /* Update the connection with information from the params */ |
1295 | con = hash_con->con; |
1296 | con->update_flag = conn_info->update_flag; |
1297 | con->max_seq_size = conn_info->max_seq_size; |
1298 | con->max_recv_pdu_length = conn_info->max_recv_pdu_length; |
1299 | con->max_send_pdu_length = conn_info->max_send_pdu_length; |
1300 | con->first_seq_length = conn_info->first_seq_length; |
1301 | con->exp_stat_sn = conn_info->exp_stat_sn; |
1302 | |
1303 | return qed_sp_iscsi_conn_update(QED_AFFIN_HWFN(cdev), p_conn: con, |
1304 | comp_mode: QED_SPQ_MODE_EBLOCK, NULL); |
1305 | } |
1306 | |
1307 | static int qed_iscsi_clear_conn_sq(struct qed_dev *cdev, u32 handle) |
1308 | { |
1309 | struct qed_hash_iscsi_con *hash_con; |
1310 | |
1311 | hash_con = qed_iscsi_get_hash(cdev, handle); |
1312 | if (!hash_con) { |
1313 | DP_NOTICE(cdev, "Failed to find connection for handle %d\n" , |
1314 | handle); |
1315 | return -EINVAL; |
1316 | } |
1317 | |
1318 | return qed_sp_iscsi_conn_clear_sq(QED_AFFIN_HWFN(cdev), p_conn: hash_con->con, |
1319 | comp_mode: QED_SPQ_MODE_EBLOCK, NULL); |
1320 | } |
1321 | |
1322 | static int qed_iscsi_destroy_conn(struct qed_dev *cdev, |
1323 | u32 handle, u8 abrt_conn) |
1324 | { |
1325 | struct qed_hash_iscsi_con *hash_con; |
1326 | |
1327 | hash_con = qed_iscsi_get_hash(cdev, handle); |
1328 | if (!hash_con) { |
1329 | DP_NOTICE(cdev, "Failed to find connection for handle %d\n" , |
1330 | handle); |
1331 | return -EINVAL; |
1332 | } |
1333 | |
1334 | hash_con->con->abortive_dsconnect = abrt_conn; |
1335 | |
1336 | return qed_sp_iscsi_conn_terminate(QED_AFFIN_HWFN(cdev), p_conn: hash_con->con, |
1337 | comp_mode: QED_SPQ_MODE_EBLOCK, NULL); |
1338 | } |
1339 | |
1340 | static int qed_iscsi_stats_context(struct qed_dev *cdev, |
1341 | struct qed_iscsi_stats *stats, |
1342 | bool is_atomic) |
1343 | { |
1344 | return qed_iscsi_get_stats(QED_AFFIN_HWFN(cdev), stats, is_atomic); |
1345 | } |
1346 | |
1347 | static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats) |
1348 | { |
1349 | return qed_iscsi_stats_context(cdev, stats, is_atomic: false); |
1350 | } |
1351 | |
1352 | static int qed_iscsi_change_mac(struct qed_dev *cdev, |
1353 | u32 handle, const u8 *mac) |
1354 | { |
1355 | struct qed_hash_iscsi_con *hash_con; |
1356 | |
1357 | hash_con = qed_iscsi_get_hash(cdev, handle); |
1358 | if (!hash_con) { |
1359 | DP_NOTICE(cdev, "Failed to find connection for handle %d\n" , |
1360 | handle); |
1361 | return -EINVAL; |
1362 | } |
1363 | |
1364 | return qed_sp_iscsi_mac_update(QED_AFFIN_HWFN(cdev), p_conn: hash_con->con, |
1365 | comp_mode: QED_SPQ_MODE_EBLOCK, NULL); |
1366 | } |
1367 | |
1368 | void qed_get_protocol_stats_iscsi(struct qed_dev *cdev, |
1369 | struct qed_mcp_iscsi_stats *stats, |
1370 | bool is_atomic) |
1371 | { |
1372 | struct qed_iscsi_stats proto_stats; |
1373 | |
1374 | /* Retrieve FW statistics */ |
1375 | memset(&proto_stats, 0, sizeof(proto_stats)); |
1376 | if (qed_iscsi_stats_context(cdev, stats: &proto_stats, is_atomic)) { |
1377 | DP_VERBOSE(cdev, QED_MSG_STORAGE, |
1378 | "Failed to collect ISCSI statistics\n" ); |
1379 | return; |
1380 | } |
1381 | |
1382 | /* Translate FW statistics into struct */ |
1383 | stats->rx_pdus = proto_stats.iscsi_rx_total_pdu_cnt; |
1384 | stats->tx_pdus = proto_stats.iscsi_tx_total_pdu_cnt; |
1385 | stats->rx_bytes = proto_stats.iscsi_rx_bytes_cnt; |
1386 | stats->tx_bytes = proto_stats.iscsi_tx_bytes_cnt; |
1387 | } |
1388 | |
1389 | static const struct qed_iscsi_ops qed_iscsi_ops_pass = { |
1390 | .common = &qed_common_ops_pass, |
1391 | .ll2 = &qed_ll2_ops_pass, |
1392 | .fill_dev_info = &qed_fill_iscsi_dev_info, |
1393 | .register_ops = &qed_register_iscsi_ops, |
1394 | .start = &qed_iscsi_start, |
1395 | .stop = &qed_iscsi_stop, |
1396 | .acquire_conn = &qed_iscsi_acquire_conn, |
1397 | .release_conn = &qed_iscsi_release_conn, |
1398 | .offload_conn = &qed_iscsi_offload_conn, |
1399 | .update_conn = &qed_iscsi_update_conn, |
1400 | .destroy_conn = &qed_iscsi_destroy_conn, |
1401 | .clear_sq = &qed_iscsi_clear_conn_sq, |
1402 | .get_stats = &qed_iscsi_stats, |
1403 | .change_mac = &qed_iscsi_change_mac, |
1404 | }; |
1405 | |
1406 | const struct qed_iscsi_ops *qed_get_iscsi_ops(void) |
1407 | { |
1408 | return &qed_iscsi_ops_pass; |
1409 | } |
1410 | EXPORT_SYMBOL(qed_get_iscsi_ops); |
1411 | |
1412 | void qed_put_iscsi_ops(void) |
1413 | { |
1414 | } |
1415 | EXPORT_SYMBOL(qed_put_iscsi_ops); |
1416 | |