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