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