xref: /openbmc/linux/drivers/scsi/be2iscsi/be_iscsi.c (revision bc000245)
1 /**
2  * Copyright (C) 2005 - 2013 Emulex
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@emulex.com)
11  *
12  * Contact Information:
13  * linux-drivers@emulex.com
14  *
15  * Emulex
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 		kfree(if_info);
546 		return len;
547 	}
548 
549 	switch (param) {
550 	case ISCSI_NET_PARAM_IPV4_ADDR:
551 		len = sprintf(buf, "%pI4\n", if_info->ip_addr.addr);
552 		break;
553 	case ISCSI_NET_PARAM_IPV6_ADDR:
554 		len = sprintf(buf, "%pI6\n", if_info->ip_addr.addr);
555 		break;
556 	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
557 		if (!if_info->dhcp_state)
558 			len = sprintf(buf, "static\n");
559 		else
560 			len = sprintf(buf, "dhcp\n");
561 		break;
562 	case ISCSI_NET_PARAM_IPV4_SUBNET:
563 		len = sprintf(buf, "%pI4\n", if_info->ip_addr.subnet_mask);
564 		break;
565 	case ISCSI_NET_PARAM_VLAN_ENABLED:
566 		len = sprintf(buf, "%s\n",
567 			     (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
568 			     ? "Disabled\n" : "Enabled\n");
569 		break;
570 	case ISCSI_NET_PARAM_VLAN_ID:
571 		if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
572 			return -EINVAL;
573 		else
574 			len = sprintf(buf, "%d\n",
575 				     (if_info->vlan_priority &
576 				     ISCSI_MAX_VLAN_ID));
577 		break;
578 	case ISCSI_NET_PARAM_VLAN_PRIORITY:
579 		if (if_info->vlan_priority == BEISCSI_VLAN_DISABLE)
580 			return -EINVAL;
581 		else
582 			len = sprintf(buf, "%d\n",
583 				     ((if_info->vlan_priority >> 13) &
584 				     ISCSI_MAX_VLAN_PRIORITY));
585 		break;
586 	default:
587 		WARN_ON(1);
588 	}
589 
590 	kfree(if_info);
591 	return len;
592 }
593 
594 int be2iscsi_iface_get_param(struct iscsi_iface *iface,
595 		enum iscsi_param_type param_type,
596 		int param, char *buf)
597 {
598 	struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
599 	struct beiscsi_hba *phba = iscsi_host_priv(shost);
600 	struct be_cmd_get_def_gateway_resp gateway;
601 	int len = -ENOSYS;
602 
603 	if (phba->state & BE_ADAPTER_PCI_ERR) {
604 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
605 			    "BS_%d : In PCI_ERROR Recovery\n");
606 		return -EBUSY;
607 	}
608 
609 	switch (param) {
610 	case ISCSI_NET_PARAM_IPV4_ADDR:
611 	case ISCSI_NET_PARAM_IPV4_SUBNET:
612 	case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
613 	case ISCSI_NET_PARAM_IPV6_ADDR:
614 	case ISCSI_NET_PARAM_VLAN_ENABLED:
615 	case ISCSI_NET_PARAM_VLAN_ID:
616 	case ISCSI_NET_PARAM_VLAN_PRIORITY:
617 		len = be2iscsi_get_if_param(phba, iface, param, buf);
618 		break;
619 	case ISCSI_NET_PARAM_IFACE_ENABLE:
620 		len = sprintf(buf, "enabled\n");
621 		break;
622 	case ISCSI_NET_PARAM_IPV4_GW:
623 		memset(&gateway, 0, sizeof(gateway));
624 		len = mgmt_get_gateway(phba, BE2_IPV4, &gateway);
625 		if (!len)
626 			len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr);
627 		break;
628 	default:
629 		len = -ENOSYS;
630 	}
631 
632 	return len;
633 }
634 
635 /**
636  * beiscsi_ep_get_param - get the iscsi parameter
637  * @ep: pointer to iscsi ep
638  * @param: parameter type identifier
639  * @buf: buffer pointer
640  *
641  * returns iscsi parameter
642  */
643 int beiscsi_ep_get_param(struct iscsi_endpoint *ep,
644 			   enum iscsi_param param, char *buf)
645 {
646 	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
647 	int len = 0;
648 
649 	beiscsi_log(beiscsi_ep->phba, KERN_INFO,
650 		    BEISCSI_LOG_CONFIG,
651 		    "BS_%d : In beiscsi_ep_get_param,"
652 		    " param= %d\n", param);
653 
654 	switch (param) {
655 	case ISCSI_PARAM_CONN_PORT:
656 		len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport);
657 		break;
658 	case ISCSI_PARAM_CONN_ADDRESS:
659 		if (beiscsi_ep->ip_type == BE2_IPV4)
660 			len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr);
661 		else
662 			len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
663 		break;
664 	default:
665 		return -ENOSYS;
666 	}
667 	return len;
668 }
669 
670 int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
671 		      enum iscsi_param param, char *buf, int buflen)
672 {
673 	struct iscsi_conn *conn = cls_conn->dd_data;
674 	struct iscsi_session *session = conn->session;
675 	struct beiscsi_hba *phba = NULL;
676 	int ret;
677 
678 	phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
679 	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
680 		    "BS_%d : In beiscsi_conn_set_param,"
681 		    " param= %d\n", param);
682 
683 	ret = iscsi_set_param(cls_conn, param, buf, buflen);
684 	if (ret)
685 		return ret;
686 	/*
687 	 * If userspace tried to set the value to higher than we can
688 	 * support override here.
689 	 */
690 	switch (param) {
691 	case ISCSI_PARAM_FIRST_BURST:
692 		if (session->first_burst > 8192)
693 			session->first_burst = 8192;
694 		break;
695 	case ISCSI_PARAM_MAX_RECV_DLENGTH:
696 		if (conn->max_recv_dlength > 65536)
697 			conn->max_recv_dlength = 65536;
698 		break;
699 	case ISCSI_PARAM_MAX_BURST:
700 		if (session->max_burst > 262144)
701 			session->max_burst = 262144;
702 		break;
703 	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
704 		if (conn->max_xmit_dlength > 65536)
705 			conn->max_xmit_dlength = 65536;
706 	default:
707 		return 0;
708 	}
709 
710 	return 0;
711 }
712 
713 /**
714  * beiscsi_get_initname - Read Initiator Name from flash
715  * @buf: buffer bointer
716  * @phba: The device priv structure instance
717  *
718  * returns number of bytes
719  */
720 static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
721 {
722 	int rc;
723 	unsigned int tag;
724 	struct be_mcc_wrb *wrb;
725 	struct be_cmd_hba_name *resp;
726 
727 	tag = be_cmd_get_initname(phba);
728 	if (!tag) {
729 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
730 			    "BS_%d : Getting Initiator Name Failed\n");
731 
732 		return -EBUSY;
733 	}
734 
735 	rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
736 	if (rc) {
737 		beiscsi_log(phba, KERN_ERR,
738 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
739 			    "BS_%d : Initiator Name MBX Failed\n");
740 		return rc;
741 	}
742 
743 	resp = embedded_payload(wrb);
744 	rc = sprintf(buf, "%s\n", resp->initiator_name);
745 	return rc;
746 }
747 
748 /**
749  * beiscsi_get_port_state - Get the Port State
750  * @shost : pointer to scsi_host structure
751  *
752  */
753 static void beiscsi_get_port_state(struct Scsi_Host *shost)
754 {
755 	struct beiscsi_hba *phba = iscsi_host_priv(shost);
756 	struct iscsi_cls_host *ihost = shost->shost_data;
757 
758 	ihost->port_state = (phba->state == BE_ADAPTER_LINK_UP) ?
759 		ISCSI_PORT_STATE_UP : ISCSI_PORT_STATE_DOWN;
760 }
761 
762 /**
763  * beiscsi_get_port_speed  - Get the Port Speed from Adapter
764  * @shost : pointer to scsi_host structure
765  *
766  * returns Success/Failure
767  */
768 static int beiscsi_get_port_speed(struct Scsi_Host *shost)
769 {
770 	int rc;
771 	unsigned int tag;
772 	struct be_mcc_wrb *wrb;
773 	struct be_cmd_ntwk_link_status_resp *resp;
774 	struct beiscsi_hba *phba = iscsi_host_priv(shost);
775 	struct iscsi_cls_host *ihost = shost->shost_data;
776 
777 	tag = be_cmd_get_port_speed(phba);
778 	if (!tag) {
779 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
780 			    "BS_%d : Getting Port Speed Failed\n");
781 
782 		 return -EBUSY;
783 	}
784 	rc = beiscsi_mccq_compl(phba, tag, &wrb, NULL);
785 	if (rc) {
786 		beiscsi_log(phba, KERN_ERR,
787 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
788 			    "BS_%d : Port Speed MBX Failed\n");
789 		return rc;
790 	}
791 	resp = embedded_payload(wrb);
792 
793 	switch (resp->mac_speed) {
794 	case BE2ISCSI_LINK_SPEED_10MBPS:
795 		ihost->port_speed = ISCSI_PORT_SPEED_10MBPS;
796 		break;
797 	case BE2ISCSI_LINK_SPEED_100MBPS:
798 		ihost->port_speed = BE2ISCSI_LINK_SPEED_100MBPS;
799 		break;
800 	case BE2ISCSI_LINK_SPEED_1GBPS:
801 		ihost->port_speed = ISCSI_PORT_SPEED_1GBPS;
802 		break;
803 	case BE2ISCSI_LINK_SPEED_10GBPS:
804 		ihost->port_speed = ISCSI_PORT_SPEED_10GBPS;
805 		break;
806 	default:
807 		ihost->port_speed = ISCSI_PORT_SPEED_UNKNOWN;
808 	}
809 	return 0;
810 }
811 
812 /**
813  * beiscsi_get_host_param - get the iscsi parameter
814  * @shost: pointer to scsi_host structure
815  * @param: parameter type identifier
816  * @buf: buffer pointer
817  *
818  * returns host parameter
819  */
820 int beiscsi_get_host_param(struct Scsi_Host *shost,
821 			   enum iscsi_host_param param, char *buf)
822 {
823 	struct beiscsi_hba *phba = iscsi_host_priv(shost);
824 	int status = 0;
825 
826 
827 	if (phba->state & BE_ADAPTER_PCI_ERR) {
828 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
829 			    "BS_%d : In PCI_ERROR Recovery\n");
830 		return -EBUSY;
831 	} else {
832 		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
833 			    "BS_%d : In beiscsi_get_host_param,"
834 			    " param = %d\n", param);
835 	}
836 
837 	switch (param) {
838 	case ISCSI_HOST_PARAM_HWADDRESS:
839 		status = beiscsi_get_macaddr(buf, phba);
840 		if (status < 0) {
841 			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
842 				    "BS_%d : beiscsi_get_macaddr Failed\n");
843 			return status;
844 		}
845 		break;
846 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
847 		status = beiscsi_get_initname(buf, phba);
848 		if (status < 0) {
849 			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
850 				    "BS_%d : Retreiving Initiator Name Failed\n");
851 			return status;
852 		}
853 		break;
854 	case ISCSI_HOST_PARAM_PORT_STATE:
855 		beiscsi_get_port_state(shost);
856 		status = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost));
857 		break;
858 	case ISCSI_HOST_PARAM_PORT_SPEED:
859 		status = beiscsi_get_port_speed(shost);
860 		if (status) {
861 			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
862 				    "BS_%d : Retreiving Port Speed Failed\n");
863 			return status;
864 		}
865 		status = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost));
866 		break;
867 	default:
868 		return iscsi_host_get_param(shost, param, buf);
869 	}
870 	return status;
871 }
872 
873 int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba)
874 {
875 	struct be_cmd_get_nic_conf_resp resp;
876 	int rc;
877 
878 	if (phba->mac_addr_set)
879 		return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
880 
881 	memset(&resp, 0, sizeof(resp));
882 	rc = mgmt_get_nic_conf(phba, &resp);
883 	if (rc)
884 		return rc;
885 
886 	phba->mac_addr_set = true;
887 	memcpy(phba->mac_address, resp.mac_address, ETH_ALEN);
888 	return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
889 }
890 
891 /**
892  * beiscsi_conn_get_stats - get the iscsi stats
893  * @cls_conn: pointer to iscsi cls conn
894  * @stats: pointer to iscsi_stats structure
895  *
896  * returns iscsi stats
897  */
898 void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
899 			    struct iscsi_stats *stats)
900 {
901 	struct iscsi_conn *conn = cls_conn->dd_data;
902 	struct beiscsi_hba *phba = NULL;
903 
904 	phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
905 	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
906 		    "BS_%d : In beiscsi_conn_get_stats\n");
907 
908 	stats->txdata_octets = conn->txdata_octets;
909 	stats->rxdata_octets = conn->rxdata_octets;
910 	stats->dataout_pdus = conn->dataout_pdus_cnt;
911 	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
912 	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
913 	stats->datain_pdus = conn->datain_pdus_cnt;
914 	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
915 	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
916 	stats->r2t_pdus = conn->r2t_pdus_cnt;
917 	stats->digest_err = 0;
918 	stats->timeout_err = 0;
919 	stats->custom_length = 0;
920 	strcpy(stats->custom[0].desc, "eh_abort_cnt");
921 	stats->custom[0].value = conn->eh_abort_cnt;
922 }
923 
924 /**
925  * beiscsi_set_params_for_offld - get the parameters for offload
926  * @beiscsi_conn: pointer to beiscsi_conn
927  * @params: pointer to offload_params structure
928  */
929 static void  beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn,
930 					  struct beiscsi_offload_params *params)
931 {
932 	struct iscsi_conn *conn = beiscsi_conn->conn;
933 	struct iscsi_session *session = conn->session;
934 
935 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length,
936 		      params, session->max_burst);
937 	AMAP_SET_BITS(struct amap_beiscsi_offload_params,
938 		      max_send_data_segment_length, params,
939 		      conn->max_xmit_dlength);
940 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length,
941 		      params, session->first_burst);
942 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, erl, params,
943 		      session->erl);
944 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params,
945 		      conn->datadgst_en);
946 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params,
947 		      conn->hdrdgst_en);
948 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params,
949 		      session->initial_r2t_en);
950 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params,
951 		      session->imm_data_en);
952 	AMAP_SET_BITS(struct amap_beiscsi_offload_params,
953 		      data_seq_inorder, params,
954 		      session->dataseq_inorder_en);
955 	AMAP_SET_BITS(struct amap_beiscsi_offload_params,
956 		      pdu_seq_inorder, params,
957 		      session->pdu_inorder_en);
958 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_r2t, params,
959 		      session->max_r2t);
960 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params,
961 		      (conn->exp_statsn - 1));
962 	AMAP_SET_BITS(struct amap_beiscsi_offload_params,
963 		      max_recv_data_segment_length, params,
964 		      conn->max_recv_dlength);
965 
966 }
967 
968 /**
969  * beiscsi_conn_start - offload of session to chip
970  * @cls_conn: pointer to beiscsi_conn
971  */
972 int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
973 {
974 	struct iscsi_conn *conn = cls_conn->dd_data;
975 	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
976 	struct beiscsi_endpoint *beiscsi_ep;
977 	struct beiscsi_offload_params params;
978 	struct beiscsi_hba *phba;
979 
980 	phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
981 
982 	if (phba->state & BE_ADAPTER_PCI_ERR) {
983 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
984 			    "BS_%d : In PCI_ERROR Recovery\n");
985 		return -EBUSY;
986 	} else {
987 		beiscsi_log(beiscsi_conn->phba, KERN_INFO,
988 			    BEISCSI_LOG_CONFIG,
989 			    "BS_%d : In beiscsi_conn_start\n");
990 	}
991 
992 	memset(&params, 0, sizeof(struct beiscsi_offload_params));
993 	beiscsi_ep = beiscsi_conn->ep;
994 	if (!beiscsi_ep)
995 		beiscsi_log(beiscsi_conn->phba, KERN_ERR,
996 			    BEISCSI_LOG_CONFIG,
997 			    "BS_%d : In beiscsi_conn_start , no beiscsi_ep\n");
998 
999 	beiscsi_conn->login_in_progress = 0;
1000 	beiscsi_set_params_for_offld(beiscsi_conn, &params);
1001 	beiscsi_offload_connection(beiscsi_conn, &params);
1002 	iscsi_conn_start(cls_conn);
1003 	return 0;
1004 }
1005 
1006 /**
1007  * beiscsi_get_cid - Allocate a cid
1008  * @phba: The phba instance
1009  */
1010 static int beiscsi_get_cid(struct beiscsi_hba *phba)
1011 {
1012 	unsigned short cid = 0xFFFF, cid_from_ulp;
1013 	struct ulp_cid_info *cid_info = NULL;
1014 	uint16_t cid_avlbl_ulp0, cid_avlbl_ulp1;
1015 
1016 	/* Find the ULP which has more CID available */
1017 	cid_avlbl_ulp0 = (phba->cid_array_info[BEISCSI_ULP0]) ?
1018 			  BEISCSI_ULP0_AVLBL_CID(phba) : 0;
1019 	cid_avlbl_ulp1 = (phba->cid_array_info[BEISCSI_ULP1]) ?
1020 			  BEISCSI_ULP1_AVLBL_CID(phba) : 0;
1021 	cid_from_ulp = (cid_avlbl_ulp0 > cid_avlbl_ulp1) ?
1022 			BEISCSI_ULP0 : BEISCSI_ULP1;
1023 
1024 	if (test_bit(cid_from_ulp, (void *)&phba->fw_config.ulp_supported)) {
1025 		cid_info = phba->cid_array_info[cid_from_ulp];
1026 		if (!cid_info->avlbl_cids)
1027 			return cid;
1028 
1029 		cid = cid_info->cid_array[cid_info->cid_alloc++];
1030 
1031 		if (cid_info->cid_alloc == BEISCSI_GET_CID_COUNT(
1032 					   phba, cid_from_ulp))
1033 			cid_info->cid_alloc = 0;
1034 
1035 		cid_info->avlbl_cids--;
1036 	}
1037 	return cid;
1038 }
1039 
1040 /**
1041  * beiscsi_put_cid - Free the cid
1042  * @phba: The phba for which the cid is being freed
1043  * @cid: The cid to free
1044  */
1045 static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
1046 {
1047 	uint16_t cid_post_ulp;
1048 	struct hwi_controller *phwi_ctrlr;
1049 	struct hwi_wrb_context *pwrb_context;
1050 	struct ulp_cid_info *cid_info = NULL;
1051 	uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
1052 
1053 	phwi_ctrlr = phba->phwi_ctrlr;
1054 	pwrb_context = &phwi_ctrlr->wrb_context[cri_index];
1055 	cid_post_ulp = pwrb_context->ulp_num;
1056 
1057 	cid_info = phba->cid_array_info[cid_post_ulp];
1058 	cid_info->avlbl_cids++;
1059 
1060 	cid_info->cid_array[cid_info->cid_free++] = cid;
1061 	if (cid_info->cid_free == BEISCSI_GET_CID_COUNT(phba, cid_post_ulp))
1062 		cid_info->cid_free = 0;
1063 }
1064 
1065 /**
1066  * beiscsi_free_ep - free endpoint
1067  * @ep:	pointer to iscsi endpoint structure
1068  */
1069 static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
1070 {
1071 	struct beiscsi_hba *phba = beiscsi_ep->phba;
1072 	struct beiscsi_conn *beiscsi_conn;
1073 
1074 	beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
1075 	beiscsi_ep->phba = NULL;
1076 	phba->ep_array[BE_GET_CRI_FROM_CID
1077 		       (beiscsi_ep->ep_cid)] = NULL;
1078 
1079 	/**
1080 	 * Check if any connection resource allocated by driver
1081 	 * is to be freed.This case occurs when target redirection
1082 	 * or connection retry is done.
1083 	 **/
1084 	if (!beiscsi_ep->conn)
1085 		return;
1086 
1087 	beiscsi_conn = beiscsi_ep->conn;
1088 	if (beiscsi_conn->login_in_progress) {
1089 		beiscsi_free_mgmt_task_handles(beiscsi_conn,
1090 					       beiscsi_conn->task);
1091 		beiscsi_conn->login_in_progress = 0;
1092 	}
1093 }
1094 
1095 /**
1096  * beiscsi_open_conn - Ask FW to open a TCP connection
1097  * @ep:	endpoint to be used
1098  * @src_addr: The source IP address
1099  * @dst_addr: The Destination  IP address
1100  *
1101  * Asks the FW to open a TCP connection
1102  */
1103 static int beiscsi_open_conn(struct iscsi_endpoint *ep,
1104 			     struct sockaddr *src_addr,
1105 			     struct sockaddr *dst_addr, int non_blocking)
1106 {
1107 	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
1108 	struct beiscsi_hba *phba = beiscsi_ep->phba;
1109 	struct tcp_connect_and_offload_out *ptcpcnct_out;
1110 	struct be_dma_mem nonemb_cmd;
1111 	unsigned int tag;
1112 	int ret = -ENOMEM;
1113 
1114 	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1115 		    "BS_%d : In beiscsi_open_conn\n");
1116 
1117 	beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
1118 	if (beiscsi_ep->ep_cid == 0xFFFF) {
1119 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1120 			    "BS_%d : No free cid available\n");
1121 		return ret;
1122 	}
1123 
1124 	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1125 		    "BS_%d : In beiscsi_open_conn, ep_cid=%d\n",
1126 		    beiscsi_ep->ep_cid);
1127 
1128 	phba->ep_array[BE_GET_CRI_FROM_CID
1129 		       (beiscsi_ep->ep_cid)] = ep;
1130 
1131 	beiscsi_ep->cid_vld = 0;
1132 	nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
1133 				sizeof(struct tcp_connect_and_offload_in),
1134 				&nonemb_cmd.dma);
1135 	if (nonemb_cmd.va == NULL) {
1136 
1137 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1138 			    "BS_%d : Failed to allocate memory for"
1139 			    " mgmt_open_connection\n");
1140 
1141 		beiscsi_free_ep(beiscsi_ep);
1142 		return -ENOMEM;
1143 	}
1144 	nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in);
1145 	memset(nonemb_cmd.va, 0, nonemb_cmd.size);
1146 	tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd);
1147 	if (tag <= 0) {
1148 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1149 			    "BS_%d : mgmt_open_connection Failed for cid=%d\n",
1150 			    beiscsi_ep->ep_cid);
1151 
1152 		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
1153 				    nonemb_cmd.va, nonemb_cmd.dma);
1154 		beiscsi_free_ep(beiscsi_ep);
1155 		return -EAGAIN;
1156 	}
1157 
1158 	ret = beiscsi_mccq_compl(phba, tag, NULL, nonemb_cmd.va);
1159 	if (ret) {
1160 		beiscsi_log(phba, KERN_ERR,
1161 			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
1162 			    "BS_%d : mgmt_open_connection Failed");
1163 
1164 		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
1165 			    nonemb_cmd.va, nonemb_cmd.dma);
1166 		beiscsi_free_ep(beiscsi_ep);
1167 		return -EBUSY;
1168 	}
1169 
1170 	ptcpcnct_out = (struct tcp_connect_and_offload_out *)nonemb_cmd.va;
1171 	beiscsi_ep = ep->dd_data;
1172 	beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
1173 	beiscsi_ep->cid_vld = 1;
1174 	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1175 		    "BS_%d : mgmt_open_connection Success\n");
1176 
1177 	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
1178 			    nonemb_cmd.va, nonemb_cmd.dma);
1179 	return 0;
1180 }
1181 
1182 /**
1183  * beiscsi_ep_connect - Ask chip to create TCP Conn
1184  * @scsi_host: Pointer to scsi_host structure
1185  * @dst_addr: The IP address of Target
1186  * @non_blocking: blocking or non-blocking call
1187  *
1188  * This routines first asks chip to create a connection and then allocates an EP
1189  */
1190 struct iscsi_endpoint *
1191 beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
1192 		   int non_blocking)
1193 {
1194 	struct beiscsi_hba *phba;
1195 	struct beiscsi_endpoint *beiscsi_ep;
1196 	struct iscsi_endpoint *ep;
1197 	int ret;
1198 
1199 	if (shost)
1200 		phba = iscsi_host_priv(shost);
1201 	else {
1202 		ret = -ENXIO;
1203 		printk(KERN_ERR
1204 		       "beiscsi_ep_connect shost is NULL\n");
1205 		return ERR_PTR(ret);
1206 	}
1207 
1208 	if (beiscsi_error(phba)) {
1209 		ret = -EIO;
1210 		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
1211 			    "BS_%d : The FW state Not Stable!!!\n");
1212 		return ERR_PTR(ret);
1213 	}
1214 
1215 	if (phba->state & BE_ADAPTER_PCI_ERR) {
1216 		ret = -EBUSY;
1217 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1218 			    "BS_%d : In PCI_ERROR Recovery\n");
1219 		return ERR_PTR(ret);
1220 	} else if (phba->state & BE_ADAPTER_LINK_DOWN) {
1221 		ret = -EBUSY;
1222 		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG,
1223 			    "BS_%d : The Adapter Port state is Down!!!\n");
1224 		return ERR_PTR(ret);
1225 	}
1226 
1227 	ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint));
1228 	if (!ep) {
1229 		ret = -ENOMEM;
1230 		return ERR_PTR(ret);
1231 	}
1232 
1233 	beiscsi_ep = ep->dd_data;
1234 	beiscsi_ep->phba = phba;
1235 	beiscsi_ep->openiscsi_ep = ep;
1236 	ret = beiscsi_open_conn(ep, NULL, dst_addr, non_blocking);
1237 	if (ret) {
1238 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1239 			    "BS_%d : Failed in beiscsi_open_conn\n");
1240 		goto free_ep;
1241 	}
1242 
1243 	return ep;
1244 
1245 free_ep:
1246 	iscsi_destroy_endpoint(ep);
1247 	return ERR_PTR(ret);
1248 }
1249 
1250 /**
1251  * beiscsi_ep_poll - Poll to see if connection is established
1252  * @ep:	endpoint to be used
1253  * @timeout_ms: timeout specified in millisecs
1254  *
1255  * Poll to see if TCP connection established
1256  */
1257 int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
1258 {
1259 	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
1260 
1261 	beiscsi_log(beiscsi_ep->phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1262 		    "BS_%d : In  beiscsi_ep_poll\n");
1263 
1264 	if (beiscsi_ep->cid_vld == 1)
1265 		return 1;
1266 	else
1267 		return 0;
1268 }
1269 
1270 /**
1271  * beiscsi_close_conn - Upload the  connection
1272  * @ep: The iscsi endpoint
1273  * @flag: The type of connection closure
1274  */
1275 static int beiscsi_close_conn(struct  beiscsi_endpoint *beiscsi_ep, int flag)
1276 {
1277 	int ret = 0;
1278 	unsigned int tag;
1279 	struct beiscsi_hba *phba = beiscsi_ep->phba;
1280 
1281 	tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag);
1282 	if (!tag) {
1283 		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1284 			    "BS_%d : upload failed for cid 0x%x\n",
1285 			    beiscsi_ep->ep_cid);
1286 
1287 		ret = -EAGAIN;
1288 	}
1289 
1290 	ret = beiscsi_mccq_compl(phba, tag, NULL, NULL);
1291 	return ret;
1292 }
1293 
1294 /**
1295  * beiscsi_unbind_conn_to_cid - Unbind the beiscsi_conn from phba conn table
1296  * @phba: The phba instance
1297  * @cid: The cid to free
1298  */
1299 static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba,
1300 				      unsigned int cid)
1301 {
1302 	uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);
1303 
1304 	if (phba->conn_table[cri_index])
1305 		phba->conn_table[cri_index] = NULL;
1306 	else {
1307 		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1308 			    "BS_%d : Connection table Not occupied.\n");
1309 		return -EINVAL;
1310 	}
1311 	return 0;
1312 }
1313 
1314 /**
1315  * beiscsi_ep_disconnect - Tears down the TCP connection
1316  * @ep:	endpoint to be used
1317  *
1318  * Tears down the TCP connection
1319  */
1320 void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
1321 {
1322 	struct beiscsi_conn *beiscsi_conn;
1323 	struct beiscsi_endpoint *beiscsi_ep;
1324 	struct beiscsi_hba *phba;
1325 	unsigned int tag;
1326 	uint8_t mgmt_invalidate_flag, tcp_upload_flag;
1327 	unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
1328 
1329 	beiscsi_ep = ep->dd_data;
1330 	phba = beiscsi_ep->phba;
1331 	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG,
1332 		    "BS_%d : In beiscsi_ep_disconnect for ep_cid = %d\n",
1333 		    beiscsi_ep->ep_cid);
1334 
1335 	if (beiscsi_ep->conn) {
1336 		beiscsi_conn = beiscsi_ep->conn;
1337 		iscsi_suspend_queue(beiscsi_conn->conn);
1338 		mgmt_invalidate_flag = ~BEISCSI_NO_RST_ISSUE;
1339 		tcp_upload_flag = CONNECTION_UPLOAD_GRACEFUL;
1340 	} else {
1341 		mgmt_invalidate_flag = BEISCSI_NO_RST_ISSUE;
1342 		tcp_upload_flag = CONNECTION_UPLOAD_ABORT;
1343 	}
1344 
1345 	if (phba->state & BE_ADAPTER_PCI_ERR) {
1346 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1347 			    "BS_%d : PCI_ERROR Recovery\n");
1348 		goto free_ep;
1349 	}
1350 
1351 	tag = mgmt_invalidate_connection(phba, beiscsi_ep,
1352 					  beiscsi_ep->ep_cid,
1353 					  mgmt_invalidate_flag,
1354 					  savecfg_flag);
1355 	if (!tag) {
1356 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
1357 			    "BS_%d : mgmt_invalidate_connection Failed for cid=%d\n",
1358 			    beiscsi_ep->ep_cid);
1359 	}
1360 
1361 	beiscsi_mccq_compl(phba, tag, NULL, NULL);
1362 	beiscsi_close_conn(beiscsi_ep, tcp_upload_flag);
1363 free_ep:
1364 	beiscsi_free_ep(beiscsi_ep);
1365 	beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
1366 	iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
1367 }
1368 
1369 umode_t be2iscsi_attr_is_visible(int param_type, int param)
1370 {
1371 	switch (param_type) {
1372 	case ISCSI_NET_PARAM:
1373 		switch (param) {
1374 		case ISCSI_NET_PARAM_IFACE_ENABLE:
1375 		case ISCSI_NET_PARAM_IPV4_ADDR:
1376 		case ISCSI_NET_PARAM_IPV4_SUBNET:
1377 		case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
1378 		case ISCSI_NET_PARAM_IPV4_GW:
1379 		case ISCSI_NET_PARAM_IPV6_ADDR:
1380 		case ISCSI_NET_PARAM_VLAN_ID:
1381 		case ISCSI_NET_PARAM_VLAN_PRIORITY:
1382 		case ISCSI_NET_PARAM_VLAN_ENABLED:
1383 			return S_IRUGO;
1384 		default:
1385 			return 0;
1386 		}
1387 	case ISCSI_HOST_PARAM:
1388 		switch (param) {
1389 		case ISCSI_HOST_PARAM_HWADDRESS:
1390 		case ISCSI_HOST_PARAM_INITIATOR_NAME:
1391 		case ISCSI_HOST_PARAM_PORT_STATE:
1392 		case ISCSI_HOST_PARAM_PORT_SPEED:
1393 			return S_IRUGO;
1394 		default:
1395 			return 0;
1396 		}
1397 	case ISCSI_PARAM:
1398 		switch (param) {
1399 		case ISCSI_PARAM_MAX_RECV_DLENGTH:
1400 		case ISCSI_PARAM_MAX_XMIT_DLENGTH:
1401 		case ISCSI_PARAM_HDRDGST_EN:
1402 		case ISCSI_PARAM_DATADGST_EN:
1403 		case ISCSI_PARAM_CONN_ADDRESS:
1404 		case ISCSI_PARAM_CONN_PORT:
1405 		case ISCSI_PARAM_EXP_STATSN:
1406 		case ISCSI_PARAM_PERSISTENT_ADDRESS:
1407 		case ISCSI_PARAM_PERSISTENT_PORT:
1408 		case ISCSI_PARAM_PING_TMO:
1409 		case ISCSI_PARAM_RECV_TMO:
1410 		case ISCSI_PARAM_INITIAL_R2T_EN:
1411 		case ISCSI_PARAM_MAX_R2T:
1412 		case ISCSI_PARAM_IMM_DATA_EN:
1413 		case ISCSI_PARAM_FIRST_BURST:
1414 		case ISCSI_PARAM_MAX_BURST:
1415 		case ISCSI_PARAM_PDU_INORDER_EN:
1416 		case ISCSI_PARAM_DATASEQ_INORDER_EN:
1417 		case ISCSI_PARAM_ERL:
1418 		case ISCSI_PARAM_TARGET_NAME:
1419 		case ISCSI_PARAM_TPGT:
1420 		case ISCSI_PARAM_USERNAME:
1421 		case ISCSI_PARAM_PASSWORD:
1422 		case ISCSI_PARAM_USERNAME_IN:
1423 		case ISCSI_PARAM_PASSWORD_IN:
1424 		case ISCSI_PARAM_FAST_ABORT:
1425 		case ISCSI_PARAM_ABORT_TMO:
1426 		case ISCSI_PARAM_LU_RESET_TMO:
1427 		case ISCSI_PARAM_IFACE_NAME:
1428 		case ISCSI_PARAM_INITIATOR_NAME:
1429 			return S_IRUGO;
1430 		default:
1431 			return 0;
1432 		}
1433 	}
1434 
1435 	return 0;
1436 }
1437