Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
be_iscsi.c
Go to the documentation of this file.
1 
20 #include <scsi/libiscsi.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 
33 
41  u16 cmds_max,
42  u16 qdepth,
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) {
56  "beiscsi_session_create: invalid ep\n");
57  return NULL;
58  }
59  beiscsi_ep = ep->dd_data;
60  phba = beiscsi_ep->phba;
61  shost = phba->shost;
62 
64  "BS_%d : In beiscsi_session_create\n");
65 
66  if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) {
68  "BS_%d : Cannot handle %d cmds."
69  "Max cmds per session supported is %d. Using %d."
70  "\n", cmds_max,
71  beiscsi_ep->phba->params.wrbs_per_cxn,
72  beiscsi_ep->phba->params.wrbs_per_cxn);
73 
74  cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn;
75  }
76 
78  shost, cmds_max,
79  sizeof(*beiscsi_sess),
80  sizeof(*io_task),
81  initial_cmdsn, ISCSI_MAX_TARGET);
82  if (!cls_session)
83  return NULL;
84  sess = cls_session->dd_data;
85  beiscsi_sess = sess->dd_data;
86  beiscsi_sess->bhs_pool = pci_pool_create("beiscsi_bhs_pool",
87  phba->pcidev,
88  sizeof(struct be_cmd_bhs),
89  64, 0);
90  if (!beiscsi_sess->bhs_pool)
91  goto destroy_sess;
92 
93  return cls_session;
94 destroy_sess:
95  iscsi_session_teardown(cls_session);
96  return NULL;
97 }
98 
107 {
108  struct iscsi_session *sess = cls_session->dd_data;
109  struct beiscsi_session *beiscsi_sess = sess->dd_data;
110 
111  printk(KERN_INFO "In beiscsi_session_destroy\n");
112  pci_pool_destroy(beiscsi_sess->bhs_pool);
113  iscsi_session_teardown(cls_session);
114 }
115 
121 struct iscsi_cls_conn *
123 {
124  struct beiscsi_hba *phba;
125  struct Scsi_Host *shost;
126  struct iscsi_cls_conn *cls_conn;
127  struct beiscsi_conn *beiscsi_conn;
128  struct iscsi_conn *conn;
129  struct iscsi_session *sess;
130  struct beiscsi_session *beiscsi_sess;
131 
132  shost = iscsi_session_to_shost(cls_session);
133  phba = iscsi_host_priv(shost);
134 
136  "BS_%d : In beiscsi_conn_create ,cid"
137  "from iscsi layer=%d\n", cid);
138 
139  cls_conn = iscsi_conn_setup(cls_session, sizeof(*beiscsi_conn), cid);
140  if (!cls_conn)
141  return NULL;
142 
143  conn = cls_conn->dd_data;
144  beiscsi_conn = conn->dd_data;
145  beiscsi_conn->ep = NULL;
146  beiscsi_conn->phba = phba;
147  beiscsi_conn->conn = conn;
148  sess = cls_session->dd_data;
149  beiscsi_sess = sess->dd_data;
150  beiscsi_conn->beiscsi_sess = beiscsi_sess;
151  return cls_conn;
152 }
153 
160 static int beiscsi_bindconn_cid(struct beiscsi_hba *phba,
161  struct beiscsi_conn *beiscsi_conn,
162  unsigned int cid)
163 {
164  if (phba->conn_table[cid]) {
166  "BS_%d : Connection table already occupied. Detected clash\n");
167 
168  return -EINVAL;
169  } else {
171  "BS_%d : phba->conn_table[%d]=%p(beiscsi_conn)\n",
172  cid, beiscsi_conn);
173 
174  phba->conn_table[cid] = beiscsi_conn;
175  }
176  return 0;
177 }
178 
187 int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
188  struct iscsi_cls_conn *cls_conn,
189  u64 transport_fd, int is_leading)
190 {
191  struct iscsi_conn *conn = cls_conn->dd_data;
192  struct beiscsi_conn *beiscsi_conn = conn->dd_data;
193  struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
194  struct beiscsi_hba *phba = iscsi_host_priv(shost);
195  struct beiscsi_endpoint *beiscsi_ep;
196  struct iscsi_endpoint *ep;
197 
198  ep = iscsi_lookup_endpoint(transport_fd);
199  if (!ep)
200  return -EINVAL;
201 
202  beiscsi_ep = ep->dd_data;
203 
204  if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
205  return -EINVAL;
206 
207  if (beiscsi_ep->phba != phba) {
209  "BS_%d : beiscsi_ep->hba=%p not equal to phba=%p\n",
210  beiscsi_ep->phba, phba);
211 
212  return -EEXIST;
213  }
214 
215  beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid;
216  beiscsi_conn->ep = beiscsi_ep;
217  beiscsi_ep->conn = beiscsi_conn;
218 
220  "BS_%d : beiscsi_conn=%p conn=%p ep_cid=%d\n",
221  beiscsi_conn, conn, beiscsi_ep->ep_cid);
222 
223  return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid);
224 }
225 
226 static int beiscsi_create_ipv4_iface(struct beiscsi_hba *phba)
227 {
228  if (phba->ipv4_iface)
229  return 0;
230 
231  phba->ipv4_iface = iscsi_create_iface(phba->shost,
234  0, 0);
235  if (!phba->ipv4_iface) {
237  "BS_%d : Could not "
238  "create default IPv4 address.\n");
239  return -ENODEV;
240  }
241 
242  return 0;
243 }
244 
245 static int beiscsi_create_ipv6_iface(struct beiscsi_hba *phba)
246 {
247  if (phba->ipv6_iface)
248  return 0;
249 
250  phba->ipv6_iface = iscsi_create_iface(phba->shost,
253  0, 0);
254  if (!phba->ipv6_iface) {
256  "BS_%d : Could not "
257  "create default IPv6 address.\n");
258  return -ENODEV;
259  }
260 
261  return 0;
262 }
263 
265 {
266  struct be_cmd_get_if_info_resp if_info;
267 
268  if (!mgmt_get_if_info(phba, BE2_IPV4, &if_info))
269  beiscsi_create_ipv4_iface(phba);
270 
271  if (!mgmt_get_if_info(phba, BE2_IPV6, &if_info))
272  beiscsi_create_ipv6_iface(phba);
273 }
274 
276 {
277  if (phba->ipv6_iface)
279  if (phba->ipv4_iface)
281 }
282 
283 static int
284 beiscsi_set_static_ip(struct Scsi_Host *shost,
285  struct iscsi_iface_param_info *iface_param,
286  void *data, uint32_t dt_len)
287 {
288  struct beiscsi_hba *phba = iscsi_host_priv(shost);
289  struct iscsi_iface_param_info *iface_ip = NULL;
290  struct iscsi_iface_param_info *iface_subnet = NULL;
291  struct nlattr *nla;
292  int ret;
293 
294 
295  switch (iface_param->param) {
297  nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
298  if (nla)
299  iface_ip = nla_data(nla);
300 
301  nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
302  if (nla)
303  iface_subnet = nla_data(nla);
304  break;
306  iface_ip = iface_param;
307  nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_SUBNET);
308  if (nla)
309  iface_subnet = nla_data(nla);
310  break;
312  iface_subnet = iface_param;
313  nla = nla_find(data, dt_len, ISCSI_NET_PARAM_IPV4_ADDR);
314  if (nla)
315  iface_ip = nla_data(nla);
316  break;
317  default:
319  "BS_%d : Unsupported param %d\n",
320  iface_param->param);
321  }
322 
323  if (!iface_ip || !iface_subnet) {
325  "BS_%d : IP and Subnet Mask required\n");
326  return -EINVAL;
327  }
328 
329  ret = mgmt_set_ip(phba, iface_ip, iface_subnet,
331 
332  return ret;
333 }
334 
347 static int
348 beiscsi_set_vlan_tag(struct Scsi_Host *shost,
349  struct iscsi_iface_param_info *iface_param)
350 {
351  struct beiscsi_hba *phba = iscsi_host_priv(shost);
352  int ret = 0;
353 
354  /* Get the Interface Handle */
355  if (mgmt_get_all_if_id(phba)) {
357  "BS_%d : Getting Interface Handle Failed\n");
358  return -EIO;
359  }
360 
361  switch (iface_param->param) {
363  if (iface_param->value[0] != ISCSI_VLAN_ENABLE)
364  ret = mgmt_set_vlan(phba, BEISCSI_VLAN_DISABLE);
365  break;
367  ret = mgmt_set_vlan(phba,
368  *((uint16_t *)iface_param->value));
369  break;
370  default:
372  "BS_%d : Unkown Param Type : %d\n",
373  iface_param->param);
374  return -ENOSYS;
375  }
376  return ret;
377 }
378 
379 
380 static int
381 beiscsi_set_ipv4(struct Scsi_Host *shost,
382  struct iscsi_iface_param_info *iface_param,
383  void *data, uint32_t dt_len)
384 {
385  struct beiscsi_hba *phba = iscsi_host_priv(shost);
386  int ret = 0;
387 
388  /* Check the param */
389  switch (iface_param->param) {
391  ret = mgmt_set_gateway(phba, iface_param);
392  break;
394  if (iface_param->value[0] == ISCSI_BOOTPROTO_DHCP)
395  ret = mgmt_set_ip(phba, iface_param,
397  else if (iface_param->value[0] == ISCSI_BOOTPROTO_STATIC)
398  ret = beiscsi_set_static_ip(shost, iface_param,
399  data, dt_len);
400  else
402  "BS_%d : Invalid BOOTPROTO: %d\n",
403  iface_param->value[0]);
404  break;
406  if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
407  ret = beiscsi_create_ipv4_iface(phba);
408  else
410  break;
413  ret = beiscsi_set_static_ip(shost, iface_param,
414  data, dt_len);
415  break;
418  ret = beiscsi_set_vlan_tag(shost, iface_param);
419  break;
420  default:
422  "BS_%d : Param %d not supported\n",
423  iface_param->param);
424  }
425 
426  return ret;
427 }
428 
429 static int
430 beiscsi_set_ipv6(struct Scsi_Host *shost,
431  struct iscsi_iface_param_info *iface_param,
432  void *data, uint32_t dt_len)
433 {
434  struct beiscsi_hba *phba = iscsi_host_priv(shost);
435  int ret = 0;
436 
437  switch (iface_param->param) {
439  if (iface_param->value[0] == ISCSI_IFACE_ENABLE)
440  ret = beiscsi_create_ipv6_iface(phba);
441  else {
443  ret = 0;
444  }
445  break;
447  ret = mgmt_set_ip(phba, iface_param, NULL,
449  break;
450  default:
452  "BS_%d : Param %d not supported\n",
453  iface_param->param);
454  }
455 
456  return ret;
457 }
458 
460  void *data, uint32_t dt_len)
461 {
462  struct iscsi_iface_param_info *iface_param = NULL;
463  struct beiscsi_hba *phba = iscsi_host_priv(shost);
464  struct nlattr *attrib;
465  uint32_t rm_len = dt_len;
466  int ret = 0 ;
467 
468  nla_for_each_attr(attrib, data, dt_len, rm_len) {
469  iface_param = nla_data(attrib);
470 
471  if (iface_param->param_type != ISCSI_NET_PARAM)
472  continue;
473 
474  /*
475  * BE2ISCSI only supports 1 interface
476  */
477  if (iface_param->iface_num) {
479  "BS_%d : Invalid iface_num %d."
480  "Only iface_num 0 is supported.\n",
481  iface_param->iface_num);
482 
483  return -EINVAL;
484  }
485 
486  switch (iface_param->iface_type) {
488  ret = beiscsi_set_ipv4(shost, iface_param,
489  data, dt_len);
490  break;
492  ret = beiscsi_set_ipv6(shost, iface_param,
493  data, dt_len);
494  break;
495  default:
497  "BS_%d : Invalid iface type :%d passed\n",
498  iface_param->iface_type);
499  break;
500  }
501 
502  if (ret)
503  return ret;
504  }
505 
506  return ret;
507 }
508 
509 static int be2iscsi_get_if_param(struct beiscsi_hba *phba,
510  struct iscsi_iface *iface, int param,
511  char *buf)
512 {
513  struct be_cmd_get_if_info_resp if_info;
514  int len, ip_type = BE2_IPV4;
515 
516  memset(&if_info, 0, sizeof(if_info));
517 
518  if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
519  ip_type = BE2_IPV6;
520 
521  len = mgmt_get_if_info(phba, ip_type, &if_info);
522  if (len)
523  return len;
524 
525  switch (param) {
527  len = sprintf(buf, "%pI4\n", &if_info.ip_addr.addr);
528  break;
530  len = sprintf(buf, "%pI6\n", &if_info.ip_addr.addr);
531  break;
533  if (!if_info.dhcp_state)
534  len = sprintf(buf, "static");
535  else
536  len = sprintf(buf, "dhcp");
537  break;
539  len = sprintf(buf, "%pI4\n", &if_info.ip_addr.subnet_mask);
540  break;
542  len = sprintf(buf, "%s\n",
543  (if_info.vlan_priority == BEISCSI_VLAN_DISABLE)
544  ? "Disabled" : "Enabled");
545  break;
547  if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE)
548  return -EINVAL;
549  else
550  len = sprintf(buf, "%d\n",
551  (if_info.vlan_priority &
553  break;
555  if (if_info.vlan_priority == BEISCSI_VLAN_DISABLE)
556  return -EINVAL;
557  else
558  len = sprintf(buf, "%d\n",
559  ((if_info.vlan_priority >> 13) &
561  break;
562  default:
563  WARN_ON(1);
564  }
565 
566  return len;
567 }
568 
571  int param, char *buf)
572 {
573  struct Scsi_Host *shost = iscsi_iface_to_shost(iface);
574  struct beiscsi_hba *phba = iscsi_host_priv(shost);
575  struct be_cmd_get_def_gateway_resp gateway;
576  int len = -ENOSYS;
577 
578  switch (param) {
586  len = be2iscsi_get_if_param(phba, iface, param, buf);
587  break;
589  len = sprintf(buf, "enabled");
590  break;
592  memset(&gateway, 0, sizeof(gateway));
593  len = mgmt_get_gateway(phba, BE2_IPV4, &gateway);
594  if (!len)
595  len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr);
596  break;
597  default:
598  len = -ENOSYS;
599  }
600 
601  return len;
602 }
603 
613  enum iscsi_param param, char *buf)
614 {
615  struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
616  int len = 0;
617 
618  beiscsi_log(beiscsi_ep->phba, KERN_INFO,
620  "BS_%d : In beiscsi_ep_get_param,"
621  " param= %d\n", param);
622 
623  switch (param) {
625  len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport);
626  break;
628  if (beiscsi_ep->ip_type == BE2_IPV4)
629  len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr);
630  else
631  len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
632  break;
633  default:
634  return -ENOSYS;
635  }
636  return len;
637 }
638 
639 int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
640  enum iscsi_param param, char *buf, int buflen)
641 {
642  struct iscsi_conn *conn = cls_conn->dd_data;
643  struct iscsi_session *session = conn->session;
644  struct beiscsi_hba *phba = NULL;
645  int ret;
646 
647  phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
649  "BS_%d : In beiscsi_conn_set_param,"
650  " param= %d\n", param);
651 
652  ret = iscsi_set_param(cls_conn, param, buf, buflen);
653  if (ret)
654  return ret;
655  /*
656  * If userspace tried to set the value to higher than we can
657  * support override here.
658  */
659  switch (param) {
661  if (session->first_burst > 8192)
662  session->first_burst = 8192;
663  break;
665  if (conn->max_recv_dlength > 65536)
666  conn->max_recv_dlength = 65536;
667  break;
669  if (session->max_burst > 262144)
670  session->max_burst = 262144;
671  break;
673  if ((conn->max_xmit_dlength > 65536) ||
674  (conn->max_xmit_dlength == 0))
675  conn->max_xmit_dlength = 65536;
676  default:
677  return 0;
678  }
679 
680  return 0;
681 }
682 
690 static int beiscsi_get_initname(char *buf, struct beiscsi_hba *phba)
691 {
692  int rc;
693  unsigned int tag, wrb_num;
694  unsigned short status, extd_status;
695  struct be_mcc_wrb *wrb;
696  struct be_cmd_hba_name *resp;
697  struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
698 
699  tag = be_cmd_get_initname(phba);
700  if (!tag) {
702  "BS_%d : Getting Initiator Name Failed\n");
703 
704  return -EBUSY;
705  } else
706  wait_event_interruptible(phba->ctrl.mcc_wait[tag],
707  phba->ctrl.mcc_numtag[tag]);
708 
709  wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
710  extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
711  status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
712 
713  if (status || extd_status) {
714  beiscsi_log(phba, KERN_ERR,
716  "BS_%d : MailBox Command Failed with "
717  "status = %d extd_status = %d\n",
718  status, extd_status);
719 
720  free_mcc_tag(&phba->ctrl, tag);
721  return -EAGAIN;
722  }
723  wrb = queue_get_wrb(mccq, wrb_num);
724  free_mcc_tag(&phba->ctrl, tag);
725  resp = embedded_payload(wrb);
726  rc = sprintf(buf, "%s\n", resp->initiator_name);
727  return rc;
728 }
729 
736 static void beiscsi_get_port_state(struct Scsi_Host *shost)
737 {
738  struct beiscsi_hba *phba = iscsi_host_priv(shost);
739  struct iscsi_cls_host *ihost = shost->shost_data;
740 
741  ihost->port_state = (phba->state == BE_ADAPTER_UP) ?
743 }
744 
751 static int beiscsi_get_port_speed(struct Scsi_Host *shost)
752 {
753  unsigned int tag, wrb_num;
754  unsigned short status, extd_status;
755  struct be_mcc_wrb *wrb;
757  struct beiscsi_hba *phba = iscsi_host_priv(shost);
758  struct iscsi_cls_host *ihost = shost->shost_data;
759  struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
760 
761  tag = be_cmd_get_port_speed(phba);
762  if (!tag) {
764  "BS_%d : Getting Port Speed Failed\n");
765 
766  return -EBUSY;
767  } else
768  wait_event_interruptible(phba->ctrl.mcc_wait[tag],
769  phba->ctrl.mcc_numtag[tag]);
770 
771  wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
772  extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
773  status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
774 
775  if (status || extd_status) {
776  beiscsi_log(phba, KERN_ERR,
778  "BS_%d : MailBox Command Failed with "
779  "status = %d extd_status = %d\n",
780  status, extd_status);
781 
782  free_mcc_tag(&phba->ctrl, tag);
783  return -EAGAIN;
784  }
785  wrb = queue_get_wrb(mccq, wrb_num);
786  free_mcc_tag(&phba->ctrl, tag);
787  resp = embedded_payload(wrb);
788 
789  switch (resp->mac_speed) {
792  break;
795  break;
798  break;
801  break;
802  default:
804  }
805  return 0;
806 }
807 
817  enum iscsi_host_param param, char *buf)
818 {
819  struct beiscsi_hba *phba = iscsi_host_priv(shost);
820  int status = 0;
821 
823  "BS_%d : In beiscsi_get_host_param,"
824  " param= %d\n", param);
825 
826  switch (param) {
828  status = beiscsi_get_macaddr(buf, phba);
829  if (status < 0) {
831  "BS_%d : beiscsi_get_macaddr Failed\n");
832  return status;
833  }
834  break;
836  status = beiscsi_get_initname(buf, phba);
837  if (status < 0) {
839  "BS_%d : Retreiving Initiator Name Failed\n");
840  return status;
841  }
842  break;
844  beiscsi_get_port_state(shost);
845  status = sprintf(buf, "%s\n", iscsi_get_port_state_name(shost));
846  break;
848  status = beiscsi_get_port_speed(shost);
849  if (status) {
851  "BS_%d : Retreiving Port Speed Failed\n");
852  return status;
853  }
854  status = sprintf(buf, "%s\n", iscsi_get_port_speed_name(shost));
855  break;
856  default:
857  return iscsi_host_get_param(shost, param, buf);
858  }
859  return status;
860 }
861 
862 int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba)
863 {
864  struct be_cmd_get_nic_conf_resp resp;
865  int rc;
866 
867  if (strlen(phba->mac_address))
868  return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
869 
870  memset(&resp, 0, sizeof(resp));
871  rc = mgmt_get_nic_conf(phba, &resp);
872  if (rc)
873  return rc;
874 
875  memcpy(phba->mac_address, resp.mac_address, ETH_ALEN);
876  return sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
877 }
878 
887  struct iscsi_stats *stats)
888 {
889  struct iscsi_conn *conn = cls_conn->dd_data;
890  struct beiscsi_hba *phba = NULL;
891 
892  phba = ((struct beiscsi_conn *)conn->dd_data)->phba;
894  "BS_%d : In beiscsi_conn_get_stats\n");
895 
896  stats->txdata_octets = conn->txdata_octets;
897  stats->rxdata_octets = conn->rxdata_octets;
898  stats->dataout_pdus = conn->dataout_pdus_cnt;
899  stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
900  stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
901  stats->datain_pdus = conn->datain_pdus_cnt;
902  stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
903  stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
904  stats->r2t_pdus = conn->r2t_pdus_cnt;
905  stats->digest_err = 0;
906  stats->timeout_err = 0;
907  stats->custom_length = 0;
908  strcpy(stats->custom[0].desc, "eh_abort_cnt");
909  stats->custom[0].value = conn->eh_abort_cnt;
910 }
911 
917 static void beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn,
919 {
920  struct iscsi_conn *conn = beiscsi_conn->conn;
921  struct iscsi_session *session = conn->session;
922 
923  AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length,
924  params, session->max_burst);
926  max_send_data_segment_length, params,
927  conn->max_xmit_dlength);
928  AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length,
929  params, session->first_burst);
931  session->erl);
932  AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params,
933  conn->datadgst_en);
934  AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params,
935  conn->hdrdgst_en);
936  AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params,
937  session->initial_r2t_en);
938  AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params,
939  session->imm_data_en);
940  AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params,
941  (conn->exp_statsn - 1));
942 }
943 
948 int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
949 {
950  struct iscsi_conn *conn = cls_conn->dd_data;
951  struct beiscsi_conn *beiscsi_conn = conn->dd_data;
952  struct beiscsi_endpoint *beiscsi_ep;
953  struct beiscsi_offload_params params;
954 
955  beiscsi_log(beiscsi_conn->phba, KERN_INFO,
957  "BS_%d : In beiscsi_conn_start\n");
958 
959  memset(&params, 0, sizeof(struct beiscsi_offload_params));
960  beiscsi_ep = beiscsi_conn->ep;
961  if (!beiscsi_ep)
962  beiscsi_log(beiscsi_conn->phba, KERN_ERR,
964  "BS_%d : In beiscsi_conn_start , no beiscsi_ep\n");
965 
966  beiscsi_conn->login_in_progress = 0;
967  beiscsi_set_params_for_offld(beiscsi_conn, &params);
968  beiscsi_offload_connection(beiscsi_conn, &params);
969  iscsi_conn_start(cls_conn);
970  return 0;
971 }
972 
977 static int beiscsi_get_cid(struct beiscsi_hba *phba)
978 {
979  unsigned short cid = 0xFFFF;
980 
981  if (!phba->avlbl_cids)
982  return cid;
983 
984  cid = phba->cid_array[phba->cid_alloc++];
985  if (phba->cid_alloc == phba->params.cxns_per_ctrl)
986  phba->cid_alloc = 0;
987  phba->avlbl_cids--;
988  return cid;
989 }
990 
996 static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
997 {
998  phba->avlbl_cids++;
999  phba->cid_array[phba->cid_free++] = cid;
1000  if (phba->cid_free == phba->params.cxns_per_ctrl)
1001  phba->cid_free = 0;
1002 }
1003 
1008 static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep)
1009 {
1010  struct beiscsi_hba *phba = beiscsi_ep->phba;
1011 
1012  beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
1013  beiscsi_ep->phba = NULL;
1014 }
1015 
1024 static int beiscsi_open_conn(struct iscsi_endpoint *ep,
1025  struct sockaddr *src_addr,
1026  struct sockaddr *dst_addr, int non_blocking)
1027 {
1028  struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
1029  struct beiscsi_hba *phba = beiscsi_ep->phba;
1030  struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
1031  struct be_mcc_wrb *wrb;
1032  struct tcp_connect_and_offload_out *ptcpcnct_out;
1033  unsigned short status, extd_status;
1034  struct be_dma_mem nonemb_cmd;
1035  unsigned int tag, wrb_num;
1036  int ret = -ENOMEM;
1037 
1039  "BS_%d : In beiscsi_open_conn\n");
1040 
1041  beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
1042  if (beiscsi_ep->ep_cid == 0xFFFF) {
1044  "BS_%d : No free cid available\n");
1045  return ret;
1046  }
1047 
1049  "BS_%d : In beiscsi_open_conn, ep_cid=%d\n",
1050  beiscsi_ep->ep_cid);
1051 
1052  phba->ep_array[beiscsi_ep->ep_cid -
1053  phba->fw_config.iscsi_cid_start] = ep;
1054  if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
1055  phba->params.cxns_per_ctrl * 2)) {
1056 
1058  "BS_%d : Failed in allocate iscsi cid\n");
1059  goto free_ep;
1060  }
1061 
1062  beiscsi_ep->cid_vld = 0;
1063  nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
1064  sizeof(struct tcp_connect_and_offload_in),
1065  &nonemb_cmd.dma);
1066  if (nonemb_cmd.va == NULL) {
1067 
1069  "BS_%d : Failed to allocate memory for"
1070  " mgmt_open_connection\n");
1071 
1072  beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
1073  return -ENOMEM;
1074  }
1075  nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in);
1076  memset(nonemb_cmd.va, 0, nonemb_cmd.size);
1077  tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd);
1078  if (!tag) {
1080  "BS_%d : mgmt_open_connection Failed for cid=%d\n",
1081  beiscsi_ep->ep_cid);
1082 
1083  beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
1084  pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
1085  nonemb_cmd.va, nonemb_cmd.dma);
1086  return -EAGAIN;
1087  } else {
1088  wait_event_interruptible(phba->ctrl.mcc_wait[tag],
1089  phba->ctrl.mcc_numtag[tag]);
1090  }
1091  wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16;
1092  extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8;
1093  status = phba->ctrl.mcc_numtag[tag] & 0x000000FF;
1094  if (status || extd_status) {
1095  beiscsi_log(phba, KERN_ERR,
1097  "BS_%d : mgmt_open_connection Failed"
1098  " status = %d extd_status = %d\n",
1099  status, extd_status);
1100 
1101  free_mcc_tag(&phba->ctrl, tag);
1102  pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
1103  nonemb_cmd.va, nonemb_cmd.dma);
1104  goto free_ep;
1105  } else {
1106  wrb = queue_get_wrb(mccq, wrb_num);
1107  free_mcc_tag(&phba->ctrl, tag);
1108 
1109  ptcpcnct_out = embedded_payload(wrb);
1110  beiscsi_ep = ep->dd_data;
1111  beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
1112  beiscsi_ep->cid_vld = 1;
1114  "BS_%d : mgmt_open_connection Success\n");
1115  }
1116  pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
1117  nonemb_cmd.va, nonemb_cmd.dma);
1118  return 0;
1119 
1120 free_ep:
1121  beiscsi_free_ep(beiscsi_ep);
1122  return -EBUSY;
1123 }
1124 
1133 struct iscsi_endpoint *
1134 beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
1135  int non_blocking)
1136 {
1137  struct beiscsi_hba *phba;
1138  struct beiscsi_endpoint *beiscsi_ep;
1139  struct iscsi_endpoint *ep;
1140  int ret;
1141 
1142  if (shost)
1143  phba = iscsi_host_priv(shost);
1144  else {
1145  ret = -ENXIO;
1147  "beiscsi_ep_connect shost is NULL\n");
1148  return ERR_PTR(ret);
1149  }
1150 
1151  if (phba->state != BE_ADAPTER_UP) {
1152  ret = -EBUSY;
1154  "BS_%d : The Adapter state is Not UP\n");
1155  return ERR_PTR(ret);
1156  }
1157 
1158  ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint));
1159  if (!ep) {
1160  ret = -ENOMEM;
1161  return ERR_PTR(ret);
1162  }
1163 
1164  beiscsi_ep = ep->dd_data;
1165  beiscsi_ep->phba = phba;
1166  beiscsi_ep->openiscsi_ep = ep;
1167  ret = beiscsi_open_conn(ep, NULL, dst_addr, non_blocking);
1168  if (ret) {
1170  "BS_%d : Failed in beiscsi_open_conn\n");
1171  goto free_ep;
1172  }
1173 
1174  return ep;
1175 
1176 free_ep:
1178  return ERR_PTR(ret);
1179 }
1180 
1189 {
1190  struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
1191 
1193  "BS_%d : In beiscsi_ep_poll\n");
1194 
1195  if (beiscsi_ep->cid_vld == 1)
1196  return 1;
1197  else
1198  return 0;
1199 }
1200 
1206 static int beiscsi_close_conn(struct beiscsi_endpoint *beiscsi_ep, int flag)
1207 {
1208  int ret = 0;
1209  unsigned int tag;
1210  struct beiscsi_hba *phba = beiscsi_ep->phba;
1211 
1212  tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag);
1213  if (!tag) {
1215  "BS_%d : upload failed for cid 0x%x\n",
1216  beiscsi_ep->ep_cid);
1217 
1218  ret = -EAGAIN;
1219  } else {
1220  wait_event_interruptible(phba->ctrl.mcc_wait[tag],
1221  phba->ctrl.mcc_numtag[tag]);
1222  free_mcc_tag(&phba->ctrl, tag);
1223  }
1224  return ret;
1225 }
1226 
1232 static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba,
1233  unsigned int cid)
1234 {
1235  if (phba->conn_table[cid])
1236  phba->conn_table[cid] = NULL;
1237  else {
1239  "BS_%d : Connection table Not occupied.\n");
1240  return -EINVAL;
1241  }
1242  return 0;
1243 }
1244 
1252 {
1253  struct beiscsi_conn *beiscsi_conn;
1254  struct beiscsi_endpoint *beiscsi_ep;
1255  struct beiscsi_hba *phba;
1256  unsigned int tag;
1257  uint8_t mgmt_invalidate_flag, tcp_upload_flag;
1258  unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
1259 
1260  beiscsi_ep = ep->dd_data;
1261  phba = beiscsi_ep->phba;
1263  "BS_%d : In beiscsi_ep_disconnect for ep_cid = %d\n",
1264  beiscsi_ep->ep_cid);
1265 
1266  if (beiscsi_ep->conn) {
1267  beiscsi_conn = beiscsi_ep->conn;
1268  iscsi_suspend_queue(beiscsi_conn->conn);
1269  mgmt_invalidate_flag = ~BEISCSI_NO_RST_ISSUE;
1270  tcp_upload_flag = CONNECTION_UPLOAD_GRACEFUL;
1271  } else {
1272  mgmt_invalidate_flag = BEISCSI_NO_RST_ISSUE;
1273  tcp_upload_flag = CONNECTION_UPLOAD_ABORT;
1274  }
1275 
1276  tag = mgmt_invalidate_connection(phba, beiscsi_ep,
1277  beiscsi_ep->ep_cid,
1278  mgmt_invalidate_flag,
1279  savecfg_flag);
1280  if (!tag) {
1282  "BS_%d : mgmt_invalidate_connection Failed for cid=%d\n",
1283  beiscsi_ep->ep_cid);
1284  } else {
1285  wait_event_interruptible(phba->ctrl.mcc_wait[tag],
1286  phba->ctrl.mcc_numtag[tag]);
1287  free_mcc_tag(&phba->ctrl, tag);
1288  }
1289 
1290  beiscsi_close_conn(beiscsi_ep, tcp_upload_flag);
1291  beiscsi_free_ep(beiscsi_ep);
1292  beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
1293  iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
1294 }
1295 
1297 {
1298  switch (param_type) {
1299  case ISCSI_NET_PARAM:
1300  switch (param) {
1310  return S_IRUGO;
1311  default:
1312  return 0;
1313  }
1314  case ISCSI_HOST_PARAM:
1315  switch (param) {
1320  return S_IRUGO;
1321  default:
1322  return 0;
1323  }
1324  case ISCSI_PARAM:
1325  switch (param) {
1331  case ISCSI_PARAM_CONN_PORT:
1335  case ISCSI_PARAM_PING_TMO:
1336  case ISCSI_PARAM_RECV_TMO:
1338  case ISCSI_PARAM_MAX_R2T:
1341  case ISCSI_PARAM_MAX_BURST:
1344  case ISCSI_PARAM_ERL:
1346  case ISCSI_PARAM_TPGT:
1347  case ISCSI_PARAM_USERNAME:
1348  case ISCSI_PARAM_PASSWORD:
1352  case ISCSI_PARAM_ABORT_TMO:
1356  return S_IRUGO;
1357  default:
1358  return 0;
1359  }
1360  }
1361 
1362  return 0;
1363 }