Merge tag 'fbdev-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / be2iscsi / be_iscsi.c
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 }