1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * This file is part of the Emulex Linux Device Driver for Enterprise iSCSI
4 * Host Bus Adapters. Refer to the README file included with this package
5 * for driver version and adapter compatibility.
6 *
7 * Copyright (c) 2018 Broadcom. All Rights Reserved.
8 * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
9 *
10 * Contact Information:
11 * linux-drivers@broadcom.com
12 */
13
14#include <scsi/libiscsi.h>
15#include <scsi/scsi_transport_iscsi.h>
16#include <scsi/scsi_transport.h>
17#include <scsi/scsi_cmnd.h>
18#include <scsi/scsi_device.h>
19#include <scsi/scsi_host.h>
20#include <scsi/scsi_netlink.h>
21#include <net/netlink.h>
22#include <scsi/scsi.h>
23
24#include "be_iscsi.h"
25
26extern struct iscsi_transport beiscsi_iscsi_transport;
27
28/**
29 * beiscsi_session_create - creates a new iscsi session
30 * @ep: pointer to iscsi ep
31 * @cmds_max: max commands supported
32 * @qdepth: max queue depth supported
33 * @initial_cmdsn: initial iscsi CMDSN
34 */
35struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
36						 u16 cmds_max,
37						 u16 qdepth,
38						 u32 initial_cmdsn)
39{
40	struct Scsi_Host *shost;
41	struct beiscsi_endpoint *beiscsi_ep;
42	struct iscsi_cls_session *cls_session;
43	struct beiscsi_hba *phba;
44	struct iscsi_session *sess;
45	struct beiscsi_session *beiscsi_sess;
46	struct beiscsi_io_task *io_task;
47
48
49	if (!ep) {
50		pr_err("beiscsi_session_create: invalid ep\n");
51		return NULL;
52	}
53	beiscsi_ep = ep->dd_data;
54	phba = beiscsi_ep->phba;
55
56	if (!beiscsi_hba_is_online(phba)) {
57		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
58			    "BS_%d : HBA in error 0x%lx\n", phba->state);
59		return NULL;
60	}
61
62	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
63		    "BS_%d : In beiscsi_session_create\n");
64	if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) {
65		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
66			    "BS_%d : Cannot handle %d cmds."
67			    "Max cmds per session supported is %d. Using %d."
68			    "\n", cmds_max,
69			    beiscsi_ep->phba->params.wrbs_per_cxn,
70			    beiscsi_ep->phba->params.wrbs_per_cxn);
71
72		cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn;
73	}
74
75	shost = phba->shost;
76	cls_session = iscsi_session_setup(&beiscsi_iscsi_transport,
77					  shost, cmds_max,
78					  sizeof(*beiscsi_sess),
79					  sizeof(*io_task),
80					  initial_cmdsn, ISCSI_MAX_TARGET);
81	if (!cls_session)
82		return NULL;
83	sess = cls_session->dd_data;
84	beiscsi_sess = sess->dd_data;
85	beiscsi_sess->bhs_pool =  dma_pool_create("beiscsi_bhs_pool",
86						   &phba->pcidev->dev,
87						   sizeof(struct be_cmd_bhs),
88						   64, 0);
89	if (!beiscsi_sess->bhs_pool)
90		goto destroy_sess;
91
92	return cls_session;
93destroy_sess:
94	iscsi_session_teardown(cls_session);
95	return NULL;
96}
97
98/**
99 * beiscsi_session_destroy - destroys iscsi session
100 * @cls_session:	pointer to iscsi cls session
101 *
102 * Destroys iSCSI session instance and releases
103 * resources allocated for it.
104 */
105void beiscsi_session_destroy(struct iscsi_cls_session *cls_session)
106{
107	struct iscsi_session *sess = cls_session->dd_data;
108	struct beiscsi_session *beiscsi_sess = sess->dd_data;
109
110	printk(KERN_INFO "In beiscsi_session_destroy\n");
111	dma_pool_destroy(beiscsi_sess->bhs_pool);
112	iscsi_session_teardown(cls_session);
113}
114
115/**
116 * beiscsi_session_fail(): Closing session with appropriate error
117 * @cls_session: ptr to session
118 **/
119void beiscsi_session_fail(struct iscsi_cls_session *cls_session)
120{
121	iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED);
122}
123
124
125/**
126 * beiscsi_conn_create - create an instance of iscsi connection
127 * @cls_session: ptr to iscsi_cls_session
128 * @cid: iscsi cid
129 */
130struct iscsi_cls_conn *
131beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid)
132{
133	struct beiscsi_hba *phba;
134	struct Scsi_Host *shost;
135	struct iscsi_cls_conn *cls_conn;
136	struct beiscsi_conn *beiscsi_conn;
137	struct iscsi_conn *conn;
138	struct iscsi_session *sess;
139	struct beiscsi_session *beiscsi_sess;
140
141	shost = iscsi_session_to_shost(cls_session);
142	phba = iscsi_host_priv(shost);
143
144	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
145		    "BS_%d : In beiscsi_conn_create ,cid"
146		    "from iscsi layer=%d\n", cid);
147
148	cls_conn = iscsi_conn_setup(cls_session, sizeof(*beiscsi_conn), cid);
149	if (!cls_conn)
150		return NULL;
151
152	conn = cls_conn->dd_data;
153	beiscsi_conn = conn->dd_data;
154	beiscsi_conn->ep = NULL;
155	beiscsi_conn->phba = phba;
156	beiscsi_conn->conn = conn;
157	sess = cls_session->dd_data;
158	beiscsi_sess = sess->dd_data;
159	beiscsi_conn->beiscsi_sess = beiscsi_sess;
160	return cls_conn;
161}
162
163/**
164 * beiscsi_conn_bind - Binds iscsi session/connection with TCP connection
165 * @cls_session: pointer to iscsi cls session
166 * @cls_conn: pointer to iscsi cls conn
167 * @transport_fd: EP handle(64 bit)
168 * @is_leading: indicate if this is the session leading connection (MCS)
169 *
170 * This function binds the TCP Conn with iSCSI Connection and Session.
171 */
172int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
173		      struct iscsi_cls_conn *cls_conn,
174		      u64 transport_fd, int is_leading)
175{
176	struct iscsi_conn *conn = cls_conn->dd_data;
177	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
178	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
179	struct beiscsi_hba *phba = iscsi_host_priv(shost);
180	struct hwi_controller *phwi_ctrlr = phba->phwi_ctrlr;
181	struct hwi_wrb_context *pwrb_context;
182	struct beiscsi_endpoint *beiscsi_ep;
183	struct iscsi_endpoint *ep;
184	uint16_t cri_index;
185	int rc = 0;
186
187	ep = iscsi_lookup_endpoint(transport_fd);
188	if (!ep)
189		return -EINVAL;
190
191	beiscsi_ep = ep->dd_data;
192
193	if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) {
194		rc = -EINVAL;
195		goto put_ep;
196	}
197
198	if (beiscsi_ep->phba != phba) {
199		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
200			    "BS_%d : beiscsi_ep->hba=%p not equal to phba=%p\n",
201			    beiscsi_ep->phba, phba);
202		rc = -EEXIST;
203		goto put_ep;
204	}
205	cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid);
206	if (phba->conn_table[cri_index]) {
207		if (beiscsi_conn != phba->conn_table[cri_index] ||
208		    beiscsi_ep != phba->conn_table[cri_index]->ep) {
209			__beiscsi_log(phba, KERN_ERR,
210				      "BS_%d : conn_table not empty at %u: cid %u conn %p:%p\n",
211				      cri_index,
212				      beiscsi_ep->ep_cid,
213				      beiscsi_conn,
214				      phba->conn_table[cri_index]);
215			rc = -EINVAL;
216			goto put_ep;
217		}
218	}
219
220	beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid;
221	beiscsi_conn->ep = beiscsi_ep;
222	beiscsi_ep->conn = beiscsi_conn;
223	/**
224	 * Each connection is associated with a WRBQ kept in wrb_context.
225	 * Store doorbell offset for transmit path.
226	 */
227	pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
228	beiscsi_conn->doorbell_offset = pwrb_context->doorbell_offset;
229	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
230		    "BS_%d : cid %d phba->conn_table[%u]=%p\n",
231		    beiscsi_ep->ep_cid, cri_index, beiscsi_conn);
232	phba->conn_table[cri_index] = beiscsi_conn;
233
234put_ep:
235	iscsi_put_endpoint(ep);
236	return rc;
237}
238
239static int beiscsi_iface_create_ipv4(struct beiscsi_hba *phba)
240{
241	if (phba->ipv4_iface)
242		return 0;
243
244	phba->ipv4_iface = iscsi_create_iface(phba->shost,
245					      &beiscsi_iscsi_transport,
246					      ISCSI_IFACE_TYPE_IPV4,
247					      0, 0);
248	if (!phba->ipv4_iface) {
249		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
250			    "BS_%d : Could not "
251			    "create default IPv4 address.\n");
252		return -ENODEV;
253	}
254
255	return 0;
256}
257
258static int beiscsi_iface_create_ipv6(struct beiscsi_hba *phba)
259{
260	if (phba->ipv6_iface)
261		return 0;
262
263	phba->ipv6_iface = iscsi_create_iface(phba->shost,
264					      &beiscsi_iscsi_transport,
265					      ISCSI_IFACE_TYPE_IPV6,
266					      0, 0);
267	if (!phba->ipv6_iface) {
268		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
269			    "BS_%d : Could not "
270			    "create default IPv6 address.\n");
271		return -ENODEV;
272	}
273
274	return 0;
275}
276
277void beiscsi_iface_create_default(struct beiscsi_hba *phba)
278{
279	struct be_cmd_get_if_info_resp *if_info;
280
281	if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V4, &if_info)) {
282		beiscsi_iface_create_ipv4(phba);
283		kfree(if_info);
284	}
285
286	if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V6, &if_info)) {
287		beiscsi_iface_create_ipv6(phba);
288		kfree(if_info);
289	}
290}
291
292void beiscsi_iface_destroy_default(struct beiscsi_hba *phba)
293{
294	if (phba->ipv6_iface) {
295		iscsi_destroy_iface(phba->ipv6_iface);
296		phba->ipv6_iface = NULL;
297	}
298	if (phba->ipv4_iface) {
299		iscsi_destroy_iface(phba->ipv4_iface);
300		phba->ipv4_iface = NULL;
301	}
302}
303
304/**
305 * beiscsi_set_vlan_tag()- Set the VLAN TAG
306 * @shost: Scsi Host for the driver instance
307 * @iface_param: Interface paramters
308 *
309 * Set the VLAN TAG for the adapter or disable
310 * the VLAN config
311 *
312 * returns
313 *	Success: 0
314 *	Failure: Non-Zero Value
315 **/
316static int
317beiscsi_iface_config_vlan(struct Scsi_Host *shost,
318			  struct iscsi_iface_param_info *iface_param)
319{
320	struct beiscsi_hba *phba = iscsi_host_priv(shost);
321	int ret = -EPERM;
322
323	switch (iface_param->param) {
324	case ISCSI_NET_PARAM_VLAN_ENABLED:
325		ret = 0;
326		if (iface_param->value[0] != ISCSI_VLAN_ENABLE)
327			ret = beiscsi_if_set_vlan(phba, BEISCSI_VLAN_DISABLE);
328		break;
329	case ISCSI_NET_PARAM_VLAN_TAG:
330		ret = beiscsi_if_set_vlan(phba,
331					  *((uint16_t *)iface_param->value));
332		break;
333	}
334	return ret;
335}
336
337
338static int
339beiscsi_iface_config_ipv4(struct Scsi_Host *shost,
340			  struct iscsi_iface_param_info *info,
341			  void *data, uint32_t dt_len)
342{
343	struct beiscsi_hba *phba = iscsi_host_priv(shost);
344	u8 *ip = NULL, *subnet = NULL, *gw;
345	struct nlattr *nla;
346	int ret = -EPERM;
347
348	/* Check the param */
349	switch (info->param) {
350	case ISCSI_NET_PARAM_IFACE_ENABLE:
351		if (info->value[0] == ISCSI_IFACE_ENABLE)
352			ret = beiscsi_iface_create_ipv4(phba);
353		else {
354			iscsi_destroy_iface(phba->ipv4_iface);
355			phba->ipv4_iface = NULL;
356		}
357		break;
358	case ISCSI_NET_PARAM_IPV4_GW:
359		gw = info->value;
360		ret = beiscsi_if_set_gw(phba, BEISCSI_IP_TYPE_V4, gw);
361		break;
362	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
363		if (info->value[0] == ISCSI_BOOTPROTO_DHCP)
364			ret = beiscsi_if_en_dhcp(phba, BEISCSI_IP_TYPE_V4);
365		else if (info->value[0] == ISCSI_BOOTPROTO_STATIC)
366			/* release DHCP IP address */
367			ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
368						   NULL, NULL);
369		else
370			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
371				    "BS_%d : Invalid BOOTPROTO: %d\n",
372				    info->value[0]);
373		break;
374	case ISCSI_NET_PARAM_IPV4_ADDR:
375		ip = info->value;
376		nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
377		if (nla) {
378			info = nla_data(nla);
379			subnet = info->value;
380		}
381		ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
382					   ip, subnet);
383		break;
384	case ISCSI_NET_PARAM_IPV4_SUBNET:
385		/*
386		 * OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR ioctl needs IP
387		 * and subnet both. Find IP to be applied for this subnet.
388		 */
389		subnet = info->value;
390		nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
391		if (nla) {
392			info = nla_data(nla);
393			ip = info->value;
394		}
395		ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
396					   ip, subnet);
397		break;
398	}
399
400	return ret;
401}
402
403static int
404beiscsi_iface_config_ipv6(struct Scsi_Host *shost,
405			  struct iscsi_iface_param_info *iface_param,
406			  void *data, uint32_t dt_len)
407{
408	struct beiscsi_hba *phba = iscsi_host_priv(shost);
409	int ret = -EPERM;
410
411	switch (iface_param->param) {
412	case ISCSI_NET_PARAM_IFACE_ENABLE:
413		if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
414			ret = beiscsi_iface_create_ipv6(phba);
415		else {
416			iscsi_destroy_iface(phba->ipv6_iface);
417			phba->ipv6_iface = NULL;
418		}
419		break;
420	case ISCSI_NET_PARAM_IPV6_ADDR:
421		ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V6,
422					   iface_param->value, NULL);
423		break;
424	}
425
426	return ret;
427}
428
429int beiscsi_iface_set_param(struct Scsi_Host *shost,
430			    void *data, uint32_t dt_len)
431{
432	struct iscsi_iface_param_info *iface_param = NULL;
433	struct beiscsi_hba *phba = iscsi_host_priv(shost);
434	struct nlattr *attrib;
435	uint32_t rm_len = dt_len;
436	int ret;
437
438	if (!beiscsi_hba_is_online(phba)) {
439		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
440			    "BS_%d : HBA in error 0x%lx\n", phba->state);
441		return -EBUSY;
442	}
443
444	/* update interface_handle */
445	ret = beiscsi_if_get_handle(phba);
446	if (ret) {
447		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
448			    "BS_%d : Getting Interface Handle Failed\n");
449		return ret;
450	}
451
452	nla_for_each_attr(attrib, data, dt_len, rm_len) {
453		/* ignore nla_type as it is never used */
454		if (nla_len(attrib) < sizeof(*iface_param))
455			return -EINVAL;
456
457		iface_param = nla_data(attrib);
458
459		if (iface_param->param_type != ISCSI_NET_PARAM)
460			continue;
461
462		/*
463		 * BE2ISCSI only supports 1 interface
464		 */
465		if (iface_param->iface_num) {
466			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
467				    "BS_%d : Invalid iface_num %d."
468				    "Only iface_num 0 is supported.\n",
469				    iface_param->iface_num);
470
471			return -EINVAL;
472		}
473
474		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
475			    "BS_%d : %s.0 set param %d",
476			    (iface_param->iface_type == ISCSI_IFACE_TYPE_IPV4) ?
477			    "ipv4" : "ipv6", iface_param->param);
478
479		ret = -EPERM;
480		switch (iface_param->param) {
481		case ISCSI_NET_PARAM_VLAN_ENABLED:
482		case ISCSI_NET_PARAM_VLAN_TAG:
483			ret = beiscsi_iface_config_vlan(shost, iface_param);
484			break;
485		default:
486			switch (iface_param->iface_type) {
487			case ISCSI_IFACE_TYPE_IPV4:
488				ret = beiscsi_iface_config_ipv4(shost,
489								iface_param,
490								data, dt_len);
491				break;
492			case ISCSI_IFACE_TYPE_IPV6:
493				ret = beiscsi_iface_config_ipv6(shost,
494								iface_param,
495								data, dt_len);
496				break;
497			}
498		}
499
500		if (ret == -EPERM) {
501			__beiscsi_log(phba, KERN_ERR,
502				      "BS_%d : %s.0 set param %d not permitted",
503				      (iface_param->iface_type ==
504				       ISCSI_IFACE_TYPE_IPV4) ? "ipv4" : "ipv6",
505				      iface_param->param);
506			ret = 0;
507		}
508		if (ret)
509			break;
510	}
511
512	return ret;
513}
514
515static int __beiscsi_iface_get_param(struct beiscsi_hba *phba,
516				     struct iscsi_iface *iface,
517				     int param, char *buf)
518{
519	struct be_cmd_get_if_info_resp *if_info;
520	int len, ip_type = BEISCSI_IP_TYPE_V4;
521
522	if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
523		ip_type = BEISCSI_IP_TYPE_V6;
524
525	len = beiscsi_if_get_info(phba, ip_type, &if_info);
526	if (len)
527		return len;
528
529	switch (param) {
530	case ISCSI_NET_PARAM_IPV4_ADDR:
531		len = sprintf(buf, "%pI4\n", if_info->ip_addr.addr);
532		break;
533	case ISCSI_NET_PARAM_IPV6_ADDR:
534		len = sprintf(buf, "%pI6\n", if_info->ip_addr.addr);
535		break;
536	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
537		if (!if_info->dhcp_state)
538			len = sprintf(buf, "static\n");
539		else
540			len = sprintf(buf, "dhcp\n");
541		break;
542	case ISCSI_NET_PARAM_IPV4_SUBNET:
543		len = sprintf(buf, "%pI4\n", if_info->ip_addr.subnet_mask);
544		break;
545	case ISCSI_NET_PARAM_VLAN_ENABLED:
546		len = sprintf(buf, "%s\n",
547			      (if_info->vlan_priority == BEISCSI_VLAN_DISABLE) ?
548			      "disable" : "enable");
549		break;
550	case ISCSI_NET_PARAM_VLAN_ID:
551		if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
552			len = -EINVAL;
553		else
554			len = sprintf(buf, "%d\n",
555				      (if_info->vlan_priority &
556				       ISCSI_MAX_VLAN_ID));
557		break;
558	case ISCSI_NET_PARAM_VLAN_PRIORITY:
559		if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
560			len = -EINVAL;
561		else
562			len = sprintf(buf, "%d\n",
563				      ((if_info->vlan_priority >> 13) &
564				       ISCSI_MAX_VLAN_PRIORITY));
565		break;
566	default:
567		WARN_ON(1);
568	}
569
570	kfree(if_info);
571	return len;
572}
573
574int beiscsi_iface_get_param(struct iscsi_iface *iface,
575			    enum iscsi_param_type param_type,
576			    int param, char *buf)
577{
578	struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
579	struct beiscsi_hba *phba = iscsi_host_priv(shost);
580	struct be_cmd_get_def_gateway_resp gateway;
581	int len = -EPERM;
582
583	if (param_type != ISCSI_NET_PARAM)
584		return 0;
585	if (!beiscsi_hba_is_online(phba)) {
586		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
587			    "BS_%d : HBA in error 0x%lx\n", phba->state);
588		return -EBUSY;
589	}
590
591	switch (param) {
592	case ISCSI_NET_PARAM_IPV4_ADDR:
593	case ISCSI_NET_PARAM_IPV4_SUBNET:
594	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
595	case ISCSI_NET_PARAM_IPV6_ADDR:
596	case ISCSI_NET_PARAM_VLAN_ENABLED:
597	case ISCSI_NET_PARAM_VLAN_ID:
598	case ISCSI_NET_PARAM_VLAN_PRIORITY:
599		len = __beiscsi_iface_get_param(phba, iface, param, buf);
600		break;
601	case ISCSI_NET_PARAM_IFACE_ENABLE:
602		if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4)
603			len = sprintf(buf, "%s\n",
604				      phba->ipv4_iface ? "enable" : "disable");
605		else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
606			len = sprintf(buf, "%s\n",
607				      phba->ipv6_iface ? "enable" : "disable");
608		break;
609	case ISCSI_NET_PARAM_IPV4_GW:
610		memset(&gateway, 0, sizeof(gateway));
611		len = beiscsi_if_get_gw(phba, BEISCSI_IP_TYPE_V4, &gateway);
612		if (!len)
613			len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr);
614		break;
615	}
616
617	return len;
618}
619
620/**
621 * beiscsi_ep_get_param - get the iscsi parameter
622 * @ep: pointer to iscsi ep
623 * @param: parameter type identifier
624 * @buf: buffer pointer
625 *
626 * returns iscsi parameter
627 */
628int beiscsi_ep_get_param(struct iscsi_endpoint *ep,
629			   enum iscsi_param param, char *buf)
630{
631	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
632	int len;
633
634	beiscsi_log(beiscsi_ep->phba, KERN_INFO,
635		    BEISCSI_LOG_CONFIG,
636		    "BS_%d : In beiscsi_ep_get_param,"
637		    " param= %d\n", param);
638
639	switch (param) {
640	case ISCSI_PARAM_CONN_PORT:
641		len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport);
642		break;
643	case ISCSI_PARAM_CONN_ADDRESS:
644		if (beiscsi_ep->ip_type == BEISCSI_IP_TYPE_V4)
645			len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr);
646		else
647			len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
648		break;
649	default:
650		len = -EPERM;
651	}
652	return len;
653}
654
655int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
656		      enum iscsi_param param, char *buf, int buflen)
657{
658	struct iscsi_conn *conn = cls_conn->dd_data;
659	struct iscsi_session *session = conn->session;
660	struct beiscsi_hba *phba = NULL;
661	int ret;
662
663	phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
664	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
665		    "BS_%d : In beiscsi_conn_set_param,"
666		    " param= %d\n", param);
667
668	ret = iscsi_set_param(cls_conn, param, buf, buflen);
669	if (ret)
670		return ret;
671	/*
672	 * If userspace tried to set the value to higher than we can
673	 * support override here.
674	 */
675	switch (param) {
676	case ISCSI_PARAM_FIRST_BURST:
677		if (session->first_burst > 8192)
678			session->first_burst = 8192;
679		break;
680	case ISCSI_PARAM_MAX_RECV_DLENGTH:
681		if (conn->max_recv_dlength > 65536)
682			conn->max_recv_dlength = 65536;
683		break;
684	case ISCSI_PARAM_MAX_BURST:
685		if (session->max_burst > 262144)
686			session->max_burst = 262144;
687		break;
688	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
689		if (conn->max_xmit_dlength > 65536)
690			conn->max_xmit_dlength = 65536;
691		fallthrough;
692	default:
693		return 0;
694	}
695
696	return 0;
697}
698
699/**
700 * beiscsi_get_port_state - Get the Port State
701 * @shost : pointer to scsi_host structure
702 *
703 */
704static void beiscsi_get_port_state(struct Scsi_Host *shost)
705{
706	struct beiscsi_hba *phba = iscsi_host_priv(shost);
707	struct iscsi_cls_host *ihost = shost->shost_data;
708
709	ihost->port_state = test_bit(BEISCSI_HBA_LINK_UP, &phba->state) ?
710		ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN;
711}
712
713/**
714 * beiscsi_get_port_speed  - Get the Port Speed from Adapter
715 * @shost : pointer to scsi_host structure
716 *
717 */
718static void beiscsi_get_port_speed(struct Scsi_Host *shost)
719{
720	struct beiscsi_hba *phba = iscsi_host_priv(shost);
721	struct iscsi_cls_host *ihost = shost->shost_data;
722
723	switch (phba->port_speed) {
724	case BE2ISCSI_LINK_SPEED_10MBPS:
725		ihost->port_speed = ISCSI_PORT_SPEED_10MBPS;
726		break;
727	case BE2ISCSI_LINK_SPEED_100MBPS:
728		ihost->port_speed = ISCSI_PORT_SPEED_100MBPS;
729		break;
730	case BE2ISCSI_LINK_SPEED_1GBPS:
731		ihost->port_speed = ISCSI_PORT_SPEED_1GBPS;
732		break;
733	case BE2ISCSI_LINK_SPEED_10GBPS:
734		ihost->port_speed = ISCSI_PORT_SPEED_10GBPS;
735		break;
736	case BE2ISCSI_LINK_SPEED_25GBPS:
737		ihost->port_speed = ISCSI_PORT_SPEED_25GBPS;
738		break;
739	case BE2ISCSI_LINK_SPEED_40GBPS:
740		ihost->port_speed = ISCSI_PORT_SPEED_40GBPS;
741		break;
742	default:
743		ihost->port_speed = ISCSI_PORT_SPEED_UNKNOWN;
744	}
745}
746
747/**
748 * beiscsi_get_host_param - get the iscsi parameter
749 * @shost: pointer to scsi_host structure
750 * @param: parameter type identifier
751 * @buf: buffer pointer
752 *
753 */
754int beiscsi_get_host_param(struct Scsi_Host *shost,
755			   enum iscsi_host_param param, char *buf)
756{
757	struct beiscsi_hba *phba = iscsi_host_priv(shost);
758	int status = 0;
759
760	if (!beiscsi_hba_is_online(phba)) {
761		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
762			    "BS_%d : HBA in error 0x%lx\n", phba->state);
763		return 0;
764	}
765	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
766		    "BS_%d : In beiscsi_get_host_param, param = %d\n", param);
767
768	switch (param) {
769	case ISCSI_HOST_PARAM_HWADDRESS:
770		status = beiscsi_get_macaddr(buf, phba);
771		if (status < 0) {
772			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
773				    "BS_%d : beiscsi_get_macaddr Failed\n");
774			return 0;
775		}
776		break;
777	case ISCSI_HOST_PARAM_INITIATOR_NAME:
778		/* try fetching user configured name first */
779		status = beiscsi_get_initiator_name(phba, buf, true);
780		if (status < 0) {
781			status = beiscsi_get_initiator_name(phba, buf, false);
782			if (status < 0) {
783				beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
784					    "BS_%d : Retrieving Initiator Name Failed\n");
785				status = 0;
786			}
787		}
788		break;
789	case ISCSI_HOST_PARAM_PORT_STATE:
790		beiscsi_get_port_state(shost);
791		status = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost));
792		break;
793	case ISCSI_HOST_PARAM_PORT_SPEED:
794		beiscsi_get_port_speed(shost);
795		status = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost));
796		break;
797	default:
798		return iscsi_host_get_param(shost, param, buf);
799	}
800	return status;
801}
802
803int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba)
804{
805	struct be_cmd_get_nic_conf_resp resp;
806	int rc;
807
808	if (phba->mac_addr_set)
809		return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
810
811	memset(&resp, 0, sizeof(resp));
812	rc = mgmt_get_nic_conf(phba, &resp);
813	if (rc)
814		return rc;
815
816	phba->mac_addr_set = true;
817	memcpy(phba->mac_address, resp.mac_address, ETH_ALEN);
818	return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
819}
820
821/**
822 * beiscsi_conn_get_stats - get the iscsi stats
823 * @cls_conn: pointer to iscsi cls conn
824 * @stats: pointer to iscsi_stats structure
825 *
826 * returns iscsi stats
827 */
828void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
829			    struct iscsi_stats *stats)
830{
831	struct iscsi_conn *conn = cls_conn->dd_data;
832	struct beiscsi_hba *phba = NULL;
833
834	phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
835	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
836		    "BS_%d : In beiscsi_conn_get_stats\n");
837
838	stats->txdata_octets = conn->txdata_octets;
839	stats->rxdata_octets = conn->rxdata_octets;
840	stats->dataout_pdus = conn->dataout_pdus_cnt;
841	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
842	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
843	stats->datain_pdus = conn->datain_pdus_cnt;
844	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
845	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
846	stats->r2t_pdus = conn->r2t_pdus_cnt;
847	stats->digest_err = 0;
848	stats->timeout_err = 0;
849	stats->custom_length = 1;
850	strcpy(stats->custom[0].desc, "eh_abort_cnt");
851	stats->custom[0].value = conn->eh_abort_cnt;
852}
853
854/**
855 * beiscsi_set_params_for_offld - get the parameters for offload
856 * @beiscsi_conn: pointer to beiscsi_conn
857 * @params: pointer to offload_params structure
858 */
859static void  beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn,
860					  struct beiscsi_offload_params *params)
861{
862	struct iscsi_conn *conn = beiscsi_conn->conn;
863	struct iscsi_session *session = conn->session;
864
865	AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length,
866		      params, session->max_burst);
867	AMAP_SET_BITS(struct amap_beiscsi_offload_params,
868		      max_send_data_segment_length, params,
869		      conn->max_xmit_dlength);
870	AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length,
871		      params, session->first_burst);
872	AMAP_SET_BITS(struct amap_beiscsi_offload_params, erl, params,
873		      session->erl);
874	AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params,
875		      conn->datadgst_en);
876	AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params,
877		      conn->hdrdgst_en);
878	AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params,
879		      session->initial_r2t_en);
880	AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params,
881		      session->imm_data_en);
882	AMAP_SET_BITS(struct amap_beiscsi_offload_params,
883		      data_seq_inorder, params,
884		      session->dataseq_inorder_en);
885	AMAP_SET_BITS(struct amap_beiscsi_offload_params,
886		      pdu_seq_inorder, params,
887		      session->pdu_inorder_en);
888	AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_r2t, params,
889		      session->max_r2t);
890	AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params,
891		      (conn->exp_statsn - 1));
892	AMAP_SET_BITS(struct amap_beiscsi_offload_params,
893		      max_recv_data_segment_length, params,
894		      conn->max_recv_dlength);
895
896}
897
898/**
899 * beiscsi_conn_start - offload of session to chip
900 * @cls_conn: pointer to beiscsi_conn
901 */
902int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
903{
904	struct iscsi_conn *conn = cls_conn->dd_data;
905	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
906	struct beiscsi_endpoint *beiscsi_ep;
907	struct beiscsi_offload_params params;
908	struct beiscsi_hba *phba;
909
910	phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
911
912	if (!beiscsi_hba_is_online(phba)) {
913		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
914			    "BS_%d : HBA in error 0x%lx\n", phba->state);
915		return -EBUSY;
916	}
917	beiscsi_log(beiscsi_conn->phba, KERN_INFO, BEISCSI_LOG_CONFIG,
918		    "BS_%d : In beiscsi_conn_start\n");
919
920	memset(&params, 0, sizeof(struct beiscsi_offload_params));
921	beiscsi_ep = beiscsi_conn->ep;
922	if (!beiscsi_ep)
923		beiscsi_log(beiscsi_conn->phba, KERN_ERR,
924			    BEISCSI_LOG_CONFIG,
925			    "BS_%d : In beiscsi_conn_start , no beiscsi_ep\n");
926
927	beiscsi_conn->login_in_progress = 0;
928	beiscsi_set_params_for_offld(beiscsi_conn, &params);
929	beiscsi_offload_connection(beiscsi_conn, &params);
930	iscsi_conn_start(cls_conn);
931	return 0;
932}
933
934/**
935 * beiscsi_get_cid - Allocate a cid
936 * @phba: The phba instance
937 */
938static int beiscsi_get_cid(struct beiscsi_hba *phba)
939{
940	uint16_t cid_avlbl_ulp0, cid_avlbl_ulp1;
941	unsigned short cid, cid_from_ulp;
942	struct ulp_cid_info *cid_info;
943
944	/* Find the ULP which has more CID available */
945	cid_avlbl_ulp0 = (phba->cid_array_info[BEISCSI_ULP0]) ?
946			  BEISCSI_ULP0_AVLBL_CID(phba) : 0;
947	cid_avlbl_ulp1 = (phba->cid_array_info[BEISCSI_ULP1]) ?
948			  BEISCSI_ULP1_AVLBL_CID(phba) : 0;
949	cid_from_ulp = (cid_avlbl_ulp0 > cid_avlbl_ulp1) ?
950			BEISCSI_ULP0 : BEISCSI_ULP1;
951	/**
952	 * If iSCSI protocol is loaded only on ULP 0, and when cid_avlbl_ulp
953	 * is ZERO for both, ULP 1 is returned.
954	 * Check if ULP is loaded before getting new CID.
955	 */
956	if (!test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported))
957		return BE_INVALID_CID;
958
959	cid_info = phba->cid_array_info[cid_from_ulp];
960	cid = cid_info->cid_array[cid_info->cid_alloc];
961	if (!cid_info->avlbl_cids || cid == BE_INVALID_CID) {
962		__beiscsi_log(phba, KERN_ERR,
963				"BS_%d : failed to get cid: available %u:%u\n",
964				cid_info->avlbl_cids, cid_info->cid_free);
965		return BE_INVALID_CID;
966	}
967	/* empty the slot */
968	cid_info->cid_array[cid_info->cid_alloc++] = BE_INVALID_CID;
969	if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT(phba, cid_from_ulp))
970		cid_info->cid_alloc = 0;
971	cid_info->avlbl_cids--;
972	return cid;
973}
974
975/**
976 * beiscsi_put_cid - Free the cid
977 * @phba: The phba for which the cid is being freed
978 * @cid: The cid to free
979 */
980static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
981{
982	uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
983	struct hwi_wrb_context *pwrb_context;
984	struct hwi_controller *phwi_ctrlr;
985	struct ulp_cid_info *cid_info;
986	uint16_t cid_post_ulp;
987
988	phwi_ctrlr = phba->phwi_ctrlr;
989	pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
990	cid_post_ulp = pwrb_context->ulp_num;
991
992	cid_info = phba->cid_array_info[cid_post_ulp];
993	/* fill only in empty slot */
994	if (cid_info->cid_array[cid_info->cid_free] != BE_INVALID_CID) {
995		__beiscsi_log(phba, KERN_ERR,
996			      "BS_%d : failed to put cid %u: available %u:%u\n",
997			      cid, cid_info->avlbl_cids, cid_info->cid_free);
998		return;
999	}
1000	cid_info->cid_array[cid_info->cid_free++] = cid;
1001	if (cid_info->cid_free == BEISCSI_GET_CID_COUNT(phba, cid_post_ulp))
1002		cid_info->cid_free = 0;
1003	cid_info->avlbl_cids++;
1004}
1005
1006/**
1007 * beiscsi_free_ep - free endpoint
1008 * @beiscsi_ep: pointer to device endpoint struct
1009 */
1010static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
1011{
1012	struct beiscsi_hba *phba = beiscsi_ep->phba;
1013	struct beiscsi_conn *beiscsi_conn;
1014
1015	beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
1016	beiscsi_ep->phba = NULL;
1017	/* clear this to track freeing in beiscsi_ep_disconnect */
1018	phba->ep_array[BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid)] = NULL;
1019
1020	/**
1021	 * Check if any connection resource allocated by driver
1022	 * is to be freed.This case occurs when target redirection
1023	 * or connection retry is done.
1024	 **/
1025	if (!beiscsi_ep->conn)
1026		return;
1027
1028	beiscsi_conn = beiscsi_ep->conn;
1029	/**
1030	 * Break ep->conn link here so that completions after
1031	 * this are ignored.
1032	 */
1033	beiscsi_ep->conn = NULL;
1034	if (beiscsi_conn->login_in_progress) {
1035		beiscsi_free_mgmt_task_handles(beiscsi_conn,
1036					       beiscsi_conn->task);
1037		beiscsi_conn->login_in_progress = 0;
1038	}
1039}
1040
1041/**
1042 * beiscsi_open_conn - Ask FW to open a TCP connection
1043 * @ep: pointer to device endpoint struct
1044 * @src_addr: The source IP address
1045 * @dst_addr: The Destination  IP address
1046 * @non_blocking: blocking or non-blocking call
1047 *
1048 * Asks the FW to open a TCP connection
1049 */
1050static int beiscsi_open_conn(struct iscsi_endpoint *ep,
1051			     struct sockaddr *src_addr,
1052			     struct sockaddr *dst_addr, int non_blocking)
1053{
1054	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
1055	struct beiscsi_hba *phba = beiscsi_ep->phba;
1056	struct tcp_connect_and_offload_out *ptcpcnct_out;
1057	struct be_dma_mem nonemb_cmd;
1058	unsigned int tag, req_memsize;
1059	int ret = -ENOMEM;
1060
1061	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1062		    "BS_%d : In beiscsi_open_conn\n");
1063
1064	beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
1065	if (beiscsi_ep->ep_cid == BE_INVALID_CID) {
1066		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1067			    "BS_%d : No free cid available\n");
1068		return ret;
1069	}
1070
1071	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1072		    "BS_%d : In beiscsi_open_conn, ep_cid=%d\n",
1073		    beiscsi_ep->ep_cid);
1074
1075	phba->ep_array[BE_GET_CRI_FROM_CID
1076		       (beiscsi_ep->ep_cid)] = ep;
1077
1078	beiscsi_ep->cid_vld = 0;
1079
1080	if (is_chip_be2_be3r(phba))
1081		req_memsize = sizeof(struct tcp_connect_and_offload_in);
1082	else
1083		req_memsize = sizeof(struct tcp_connect_and_offload_in_v1);
1084
1085	nonemb_cmd.va = dma_alloc_coherent(&phba->ctrl.pdev->dev,
1086				req_memsize,
1087				&nonemb_cmd.dma, GFP_KERNEL);
1088	if (nonemb_cmd.va == NULL) {
1089
1090		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1091			    "BS_%d : Failed to allocate memory for"
1092			    " mgmt_open_connection\n");
1093
1094		beiscsi_free_ep(beiscsi_ep);
1095		return -ENOMEM;
1096	}
1097	nonemb_cmd.size = req_memsize;
1098	memset(nonemb_cmd.va, 0, nonemb_cmd.size);
1099	tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd);
1100	if (!tag) {
1101		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1102			    "BS_%d : mgmt_open_connection Failed for cid=%d\n",
1103			    beiscsi_ep->ep_cid);
1104
1105		dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size,
1106				    nonemb_cmd.va, nonemb_cmd.dma);
1107		beiscsi_free_ep(beiscsi_ep);
1108		return -EAGAIN;
1109	}
1110
1111	ret = beiscsi_mccq_compl_wait(phba, tag, NULL, &nonemb_cmd);
1112	if (ret) {
1113		beiscsi_log(phba, KERN_ERR,
1114			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
1115			    "BS_%d : mgmt_open_connection Failed");
1116
1117		if (ret != -EBUSY)
1118			dma_free_coherent(&phba->ctrl.pdev->dev,
1119					nonemb_cmd.size, nonemb_cmd.va,
1120					nonemb_cmd.dma);
1121
1122		beiscsi_free_ep(beiscsi_ep);
1123		return ret;
1124	}
1125
1126	ptcpcnct_out = (struct tcp_connect_and_offload_out *)nonemb_cmd.va;
1127	beiscsi_ep = ep->dd_data;
1128	beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
1129	beiscsi_ep->cid_vld = 1;
1130	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1131		    "BS_%d : mgmt_open_connection Success\n");
1132
1133	dma_free_coherent(&phba->ctrl.pdev->dev, nonemb_cmd.size,
1134			    nonemb_cmd.va, nonemb_cmd.dma);
1135	return 0;
1136}
1137
1138/**
1139 * beiscsi_ep_connect - Ask chip to create TCP Conn
1140 * @shost: Pointer to scsi_host structure
1141 * @dst_addr: The IP address of Target
1142 * @non_blocking: blocking or non-blocking call
1143 *
1144 * This routines first asks chip to create a connection and then allocates an EP
1145 */
1146struct iscsi_endpoint *
1147beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
1148		   int non_blocking)
1149{
1150	struct beiscsi_hba *phba;
1151	struct beiscsi_endpoint *beiscsi_ep;
1152	struct iscsi_endpoint *ep;
1153	int ret;
1154
1155	if (!shost) {
1156		ret = -ENXIO;
1157		pr_err("beiscsi_ep_connect shost is NULL\n");
1158		return ERR_PTR(ret);
1159	}
1160
1161	phba = iscsi_host_priv(shost);
1162	if (!beiscsi_hba_is_online(phba)) {
1163		ret = -EIO;
1164		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1165			    "BS_%d : HBA in error 0x%lx\n", phba->state);
1166		return ERR_PTR(ret);
1167	}
1168	if (!test_bit(BEISCSI_HBA_LINK_UP, &phba->state)) {
1169		ret = -EBUSY;
1170		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
1171			    "BS_%d : The Adapter Port state is Down!!!\n");
1172		return ERR_PTR(ret);
1173	}
1174
1175	ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint));
1176	if (!ep) {
1177		ret = -ENOMEM;
1178		return ERR_PTR(ret);
1179	}
1180
1181	beiscsi_ep = ep->dd_data;
1182	beiscsi_ep->phba = phba;
1183	beiscsi_ep->openiscsi_ep = ep;
1184	ret = beiscsi_open_conn(ep, NULL, dst_addr, non_blocking);
1185	if (ret) {
1186		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1187			    "BS_%d : Failed in beiscsi_open_conn\n");
1188		goto free_ep;
1189	}
1190
1191	return ep;
1192
1193free_ep:
1194	iscsi_destroy_endpoint(ep);
1195	return ERR_PTR(ret);
1196}
1197
1198/**
1199 * beiscsi_ep_poll - Poll to see if connection is established
1200 * @ep:	endpoint to be used
1201 * @timeout_ms: timeout specified in millisecs
1202 *
1203 * Poll to see if TCP connection established
1204 */
1205int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
1206{
1207	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
1208
1209	beiscsi_log(beiscsi_ep->phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1210		    "BS_%d : In  beiscsi_ep_poll\n");
1211
1212	if (beiscsi_ep->cid_vld == 1)
1213		return 1;
1214	else
1215		return 0;
1216}
1217
1218/**
1219 * beiscsi_flush_cq()- Flush the CQ created.
1220 * @phba: ptr device priv structure.
1221 *
1222 * Before the connection resource are freed flush
1223 * all the CQ enteries
1224 **/
1225static void beiscsi_flush_cq(struct beiscsi_hba *phba)
1226{
1227	uint16_t i;
1228	struct be_eq_obj *pbe_eq;
1229	struct hwi_controller *phwi_ctrlr;
1230	struct hwi_context_memory *phwi_context;
1231
1232	phwi_ctrlr = phba->phwi_ctrlr;
1233	phwi_context = phwi_ctrlr->phwi_ctxt;
1234
1235	for (i = 0; i < phba->num_cpus; i++) {
1236		pbe_eq = &phwi_context->be_eq[i];
1237		irq_poll_disable(&pbe_eq->iopoll);
1238		beiscsi_process_cq(pbe_eq, BE2_MAX_NUM_CQ_PROC);
1239		irq_poll_enable(&pbe_eq->iopoll);
1240	}
1241}
1242
1243/**
1244 * beiscsi_conn_close - Invalidate and upload connection
1245 * @beiscsi_ep: pointer to device endpoint struct
1246 *
1247 * Returns 0 on success,  -1 on failure.
1248 */
1249static int beiscsi_conn_close(struct beiscsi_endpoint *beiscsi_ep)
1250{
1251	struct beiscsi_hba *phba = beiscsi_ep->phba;
1252	unsigned int tag, attempts;
1253	int ret;
1254
1255	/**
1256	 * Without successfully invalidating and uploading connection
1257	 * driver can't reuse the CID so attempt more than once.
1258	 */
1259	attempts = 0;
1260	while (attempts++ < 3) {
1261		tag = beiscsi_invalidate_cxn(phba, beiscsi_ep);
1262		if (tag) {
1263			ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
1264			if (!ret)
1265				break;
1266			beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1267				    "BS_%d : invalidate conn failed cid %d\n",
1268				    beiscsi_ep->ep_cid);
1269		}
1270	}
1271
1272	/* wait for all completions to arrive, then process them */
1273	msleep(250);
1274	/* flush CQ entries */
1275	beiscsi_flush_cq(phba);
1276
1277	if (attempts > 3)
1278		return -1;
1279
1280	attempts = 0;
1281	while (attempts++ < 3) {
1282		tag = beiscsi_upload_cxn(phba, beiscsi_ep);
1283		if (tag) {
1284			ret = beiscsi_mccq_compl_wait(phba, tag, NULL, NULL);
1285			if (!ret)
1286				break;
1287			beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1288				    "BS_%d : upload conn failed cid %d\n",
1289				    beiscsi_ep->ep_cid);
1290		}
1291	}
1292	if (attempts > 3)
1293		return -1;
1294
1295	return 0;
1296}
1297
1298/**
1299 * beiscsi_ep_disconnect - Tears down the TCP connection
1300 * @ep:	endpoint to be used
1301 *
1302 * Tears down the TCP connection
1303 */
1304void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
1305{
1306	struct beiscsi_endpoint *beiscsi_ep;
1307	struct beiscsi_conn *beiscsi_conn;
1308	struct beiscsi_hba *phba;
1309	uint16_t cri_index;
1310
1311	beiscsi_ep = ep->dd_data;
1312	phba = beiscsi_ep->phba;
1313	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1314		    "BS_%d : In beiscsi_ep_disconnect for ep_cid = %u\n",
1315		    beiscsi_ep->ep_cid);
1316
1317	cri_index = BE_GET_CRI_FROM_CID(beiscsi_ep->ep_cid);
1318	if (!phba->ep_array[cri_index]) {
1319		__beiscsi_log(phba, KERN_ERR,
1320			      "BS_%d : ep_array at %u cid %u empty\n",
1321			      cri_index,
1322			      beiscsi_ep->ep_cid);
1323		return;
1324	}
1325
1326	if (beiscsi_ep->conn) {
1327		beiscsi_conn = beiscsi_ep->conn;
1328		iscsi_suspend_queue(beiscsi_conn->conn);
1329	}
1330
1331	if (!beiscsi_hba_is_online(phba)) {
1332		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1333			    "BS_%d : HBA in error 0x%lx\n", phba->state);
1334	} else {
1335		/**
1336		 * Make CID available even if close fails.
1337		 * If not freed, FW might fail open using the CID.
1338		 */
1339		if (beiscsi_conn_close(beiscsi_ep) < 0)
1340			__beiscsi_log(phba, KERN_ERR,
1341				      "BS_%d : close conn failed cid %d\n",
1342				      beiscsi_ep->ep_cid);
1343	}
1344
1345	beiscsi_free_ep(beiscsi_ep);
1346	if (!phba->conn_table[cri_index])
1347		__beiscsi_log(phba, KERN_ERR,
1348			      "BS_%d : conn_table empty at %u: cid %u\n",
1349			      cri_index, beiscsi_ep->ep_cid);
1350	phba->conn_table[cri_index] = NULL;
1351	iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
1352}
1353
1354umode_t beiscsi_attr_is_visible(int param_type, int param)
1355{
1356	switch (param_type) {
1357	case ISCSI_NET_PARAM:
1358		switch (param) {
1359		case ISCSI_NET_PARAM_IFACE_ENABLE:
1360		case ISCSI_NET_PARAM_IPV4_ADDR:
1361		case ISCSI_NET_PARAM_IPV4_SUBNET:
1362		case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
1363		case ISCSI_NET_PARAM_IPV4_GW:
1364		case ISCSI_NET_PARAM_IPV6_ADDR:
1365		case ISCSI_NET_PARAM_VLAN_ID:
1366		case ISCSI_NET_PARAM_VLAN_PRIORITY:
1367		case ISCSI_NET_PARAM_VLAN_ENABLED:
1368			return S_IRUGO;
1369		default:
1370			return 0;
1371		}
1372	case ISCSI_HOST_PARAM:
1373		switch (param) {
1374		case ISCSI_HOST_PARAM_HWADDRESS:
1375		case ISCSI_HOST_PARAM_INITIATOR_NAME:
1376		case ISCSI_HOST_PARAM_PORT_STATE:
1377		case ISCSI_HOST_PARAM_PORT_SPEED:
1378			return S_IRUGO;
1379		default:
1380			return 0;
1381		}
1382	case ISCSI_PARAM:
1383		switch (param) {
1384		case ISCSI_PARAM_MAX_RECV_DLENGTH:
1385		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
1386		case ISCSI_PARAM_HDRDGST_EN:
1387		case ISCSI_PARAM_DATADGST_EN:
1388		case ISCSI_PARAM_CONN_ADDRESS:
1389		case ISCSI_PARAM_CONN_PORT:
1390		case ISCSI_PARAM_EXP_STATSN:
1391		case ISCSI_PARAM_PERSISTENT_ADDRESS:
1392		case ISCSI_PARAM_PERSISTENT_PORT:
1393		case ISCSI_PARAM_PING_TMO:
1394		case ISCSI_PARAM_RECV_TMO:
1395		case ISCSI_PARAM_INITIAL_R2T_EN:
1396		case ISCSI_PARAM_MAX_R2T:
1397		case ISCSI_PARAM_IMM_DATA_EN:
1398		case ISCSI_PARAM_FIRST_BURST:
1399		case ISCSI_PARAM_MAX_BURST:
1400		case ISCSI_PARAM_PDU_INORDER_EN:
1401		case ISCSI_PARAM_DATASEQ_INORDER_EN:
1402		case ISCSI_PARAM_ERL:
1403		case ISCSI_PARAM_TARGET_NAME:
1404		case ISCSI_PARAM_TPGT:
1405		case ISCSI_PARAM_USERNAME:
1406		case ISCSI_PARAM_PASSWORD:
1407		case ISCSI_PARAM_USERNAME_IN:
1408		case ISCSI_PARAM_PASSWORD_IN:
1409		case ISCSI_PARAM_FAST_ABORT:
1410		case ISCSI_PARAM_ABORT_TMO:
1411		case ISCSI_PARAM_LU_RESET_TMO:
1412		case ISCSI_PARAM_IFACE_NAME:
1413		case ISCSI_PARAM_INITIATOR_NAME:
1414			return S_IRUGO;
1415		default:
1416			return 0;
1417		}
1418	}
1419
1420	return 0;
1421}
1422