1416 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)2/* QLogic qed NIC Driver3 * Copyright (c) 2015-2017 QLogic Corporation4 * Copyright (c) 2019-2020 Marvell International Ltd.5 */6 7#include <linux/types.h>8#include <asm/byteorder.h>9#include <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 40struct 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 121static 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 136static int137qed_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, &p_ent,161 ISCSI_RAMROD_CMD_ID_INIT_FUNC,162 PROTOCOLID_TCP_ULP, &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, 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, PROTOCOLID_TCP_ULP,255 qed_iscsi_async_event);256 257 return qed_spq_post(p_hwfn, p_ent, NULL);258}259 260static 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, &p_ent,289 ISCSI_RAMROD_CMD_ID_OFFLOAD_CONN,290 PROTOCOLID_TCP_ULP, &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(&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(&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(&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 449static 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, &p_ent,468 ISCSI_RAMROD_CMD_ID_UPDATE_CONN,469 PROTOCOLID_TCP_ULP, &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 489static int490qed_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, &p_ent,509 ISCSI_RAMROD_CMD_ID_MAC_UPDATE,510 PROTOCOLID_TCP_ULP, &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 533static 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, &p_ent,551 ISCSI_RAMROD_CMD_ID_TERMINATION_CONN,552 PROTOCOLID_TCP_ULP, &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 568static 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, &p_ent,585 ISCSI_RAMROD_CMD_ID_CLEAR_SQ,586 PROTOCOLID_TCP_ULP, &init_data);587 if (rc)588 return rc;589 590 return qed_spq_post(p_hwfn, p_ent, NULL);591}592 593static 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, &p_ent,609 ISCSI_RAMROD_CMD_ID_DESTROY_FUNC,610 PROTOCOLID_TCP_ULP, &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, PROTOCOLID_TCP_ULP);617 return rc;618}619 620static 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 626static 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 640static 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 654static 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_conn->r2tq);669 670 if (!p_conn->uhq.p_virt_addr)671 goto nomem;672 qed_chain_pbl_zero_mem(&p_conn->uhq);673 674 if (!p_conn->xhq.p_virt_addr)675 goto nomem;676 qed_chain_pbl_zero_mem(&p_conn->xhq);677 678 return 0;679nomem:680 return -ENOMEM;681}682 683static 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(&p_hwfn->p_iscsi_info->lock);699 if (!list_empty(&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(&p_conn->list_entry);704 spin_unlock_bh(&p_hwfn->p_iscsi_info->lock);705 *p_out_conn = p_conn;706 return 0;707 }708 spin_unlock_bh(&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(sizeof(*p_conn), GFP_KERNEL);714 if (!p_conn)715 return -ENOMEM;716 717 p_q_cnts = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,718 sizeof(*p_q_cnts),719 &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(&p_hwfn->cdev->pdev->dev,726 sizeof(*p_tcp),727 &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(p_hwfn->cdev, &p_conn->r2tq, ¶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(p_hwfn->cdev, &p_conn->uhq, ¶ms);746 if (rc)747 goto nomem_uhq;748 749 params.elem_size = sizeof(struct iscsi_xhqe);750 751 rc = qed_chain_alloc(p_hwfn->cdev, &p_conn->xhq, ¶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 759nomem:760 qed_chain_free(p_hwfn->cdev, &p_conn->uhq);761nomem_uhq:762 qed_chain_free(p_hwfn->cdev, &p_conn->r2tq);763nomem_r2tq:764 dma_free_coherent(&p_hwfn->cdev->pdev->dev,765 sizeof(struct tcp_upload_params),766 p_conn->tcp_upload_params_virt_addr,767 p_conn->tcp_upload_params_phys_addr);768nomem_upload_param:769 dma_free_coherent(&p_hwfn->cdev->pdev->dev,770 sizeof(struct scsi_terminate_extra_params),771 p_conn->queue_cnts_virt_addr,772 p_conn->queue_cnts_phys_addr);773nomem_queue_cnts_param:774 kfree(p_conn);775 776 return -ENOMEM;777}778 779static 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(&p_hwfn->p_iscsi_info->lock);788 rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_TCP_ULP, &icid);789 spin_unlock_bh(&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 else797 rc = qed_iscsi_allocate_connection(p_hwfn, &p_conn);798 799 if (!rc)800 rc = qed_iscsi_setup_connection(p_conn);801 802 if (rc) {803 spin_lock_bh(&p_hwfn->p_iscsi_info->lock);804 qed_cxt_release_cid(p_hwfn, icid);805 spin_unlock_bh(&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 818static void qed_iscsi_release_connection(struct qed_hwfn *p_hwfn,819 struct qed_iscsi_conn *p_conn)820{821 spin_lock_bh(&p_hwfn->p_iscsi_info->lock);822 list_add_tail(&p_conn->list_entry, &p_hwfn->p_iscsi_info->free_list);823 qed_cxt_release_cid(p_hwfn, p_conn->icid);824 spin_unlock_bh(&p_hwfn->p_iscsi_info->lock);825}826 827static void qed_iscsi_free_connection(struct qed_hwfn *p_hwfn,828 struct qed_iscsi_conn *p_conn)829{830 qed_chain_free(p_hwfn->cdev, &p_conn->xhq);831 qed_chain_free(p_hwfn->cdev, &p_conn->uhq);832 qed_chain_free(p_hwfn->cdev, &p_conn->r2tq);833 dma_free_coherent(&p_hwfn->cdev->pdev->dev,834 sizeof(struct tcp_upload_params),835 p_conn->tcp_upload_params_virt_addr,836 p_conn->tcp_upload_params_phys_addr);837 dma_free_coherent(&p_hwfn->cdev->pdev->dev,838 sizeof(struct scsi_terminate_extra_params),839 p_conn->queue_cnts_virt_addr,840 p_conn->queue_cnts_phys_addr);841 kfree(p_conn);842}843 844int qed_iscsi_alloc(struct qed_hwfn *p_hwfn)845{846 struct qed_iscsi_info *p_iscsi_info;847 848 p_iscsi_info = kzalloc(sizeof(*p_iscsi_info), GFP_KERNEL);849 if (!p_iscsi_info)850 return -ENOMEM;851 852 INIT_LIST_HEAD(&p_iscsi_info->free_list);853 854 p_hwfn->p_iscsi_info = p_iscsi_info;855 return 0;856}857 858void qed_iscsi_setup(struct qed_hwfn *p_hwfn)859{860 spin_lock_init(&p_hwfn->p_iscsi_info->lock);861}862 863void 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(&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(&p_conn->list_entry);875 qed_iscsi_free_connection(p_hwfn, p_conn);876 }877 }878 879 kfree(p_hwfn->p_iscsi_info);880 p_hwfn->p_iscsi_info = NULL;881}882 883static 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, &tstats, tstats_addr, 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 909static 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, &mstats, mstats_addr, 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 925static 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, &ustats, ustats_addr, 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 945static 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, &xstats, xstats_addr, 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 963static 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, &ystats, ystats_addr, 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 983static 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, &pstats, pstats_addr, 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 1001static 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, stats);1016 _qed_iscsi_get_mstats(p_hwfn, p_ptt, stats);1017 _qed_iscsi_get_ustats(p_hwfn, p_ptt, stats);1018 1019 _qed_iscsi_get_xstats(p_hwfn, p_ptt, stats);1020 _qed_iscsi_get_ystats(p_hwfn, p_ptt, stats);1021 _qed_iscsi_get_pstats(p_hwfn, p_ptt, stats);1022 1023 qed_ptt_release(p_hwfn, p_ptt);1024 1025 return 0;1026}1027 1028struct qed_hash_iscsi_con {1029 struct hlist_node node;1030 struct qed_iscsi_conn *con;1031};1032 1033static 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, &info->common);1042 1043 info->primary_dbq_rq_addr =1044 qed_iscsi_get_primary_bdq_prod(hwfn, BDQ_ID_RQ);1045 info->secondary_bdq_rq_addr =1046 qed_iscsi_get_secondary_bdq_prod(hwfn, BDQ_ID_RQ);1047 1048 info->num_cqs = FEAT_NUM(hwfn, QED_ISCSI_CQ);1049 1050 return rc;1051}1052 1053static 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 1060static 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 1079static 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), QED_SPQ_MODE_EBLOCK,1096 NULL);1097 cdev->flags &= ~QED_FLAG_STORAGE_STARTED;1098 1099 return rc;1100}1101 1102static 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), 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(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), tid_info);1136 if (rc) {1137 DP_NOTICE(cdev, "Failed to gather task information\n");1138 qed_iscsi_stop(cdev);1139 kfree(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(tid_info);1150 1151 return 0;1152}1153 1154static 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(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 &hash_con->con);1169 if (rc) {1170 DP_NOTICE(cdev, "Failed to acquire Connection\n");1171 kfree(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 *handle);1183 1184 return 0;1185}1186 1187static 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(&hash_con->node);1199 qed_iscsi_release_connection(QED_AFFIN_HWFN(cdev), hash_con->con);1200 kfree(hash_con);1201 1202 return 0;1203}1204 1205static 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(con->local_mac, conn_info->src.mac);1223 ether_addr_copy(con->remote_mac, 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), con,1277 QED_SPQ_MODE_EBLOCK, NULL);1278}1279 1280static 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), con,1304 QED_SPQ_MODE_EBLOCK, NULL);1305}1306 1307static 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), hash_con->con,1319 QED_SPQ_MODE_EBLOCK, NULL);1320}1321 1322static 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), hash_con->con,1337 QED_SPQ_MODE_EBLOCK, NULL);1338}1339 1340static 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 1347static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats)1348{1349 return qed_iscsi_stats_context(cdev, stats, false);1350}1351 1352static 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), hash_con->con,1365 QED_SPQ_MODE_EBLOCK, NULL);1366}1367 1368void 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, &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 1389static 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 1406const struct qed_iscsi_ops *qed_get_iscsi_ops(void)1407{1408 return &qed_iscsi_ops_pass;1409}1410EXPORT_SYMBOL(qed_get_iscsi_ops);1411 1412void qed_put_iscsi_ops(void)1413{1414}1415EXPORT_SYMBOL(qed_put_iscsi_ops);1416