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