brintos

brintos / linux-shallow public Read only

0
0
Text · 40.4 KiB · 980e728 Raw
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, &params);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, &params);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, &params);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