f18e643f358961987e2297cc13eb43d62f51124a
[linux-2.6.git] / drivers / scsi / be2iscsi / be_iscsi.c
1 /**
2  * Copyright (C) 2005 - 2009 ServerEngines
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 (jayamohank@serverengines.com)
11  *
12  * Contact Information:
13  * linux-drivers@serverengines.com
14  *
15  * ServerEngines
16  * 209 N. Fair Oaks Ave
17  * Sunnyvale, CA 94085
18  *
19  */
20
21 #include <scsi/libiscsi.h>
22 #include <scsi/scsi_transport_iscsi.h>
23 #include <scsi/scsi_transport.h>
24 #include <scsi/scsi_cmnd.h>
25 #include <scsi/scsi_device.h>
26 #include <scsi/scsi_host.h>
27 #include <scsi/scsi.h>
28
29 #include "be_iscsi.h"
30
31 extern struct iscsi_transport beiscsi_iscsi_transport;
32
33 /**
34  * beiscsi_session_create - creates a new iscsi session
35  * @cmds_max: max commands supported
36  * @qdepth: max queue depth supported
37  * @initial_cmdsn: initial iscsi CMDSN
38  */
39 struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep,
40                                                  u16 cmds_max,
41                                                  u16 qdepth,
42                                                  u32 initial_cmdsn)
43 {
44         struct Scsi_Host *shost;
45         struct beiscsi_endpoint *beiscsi_ep;
46         struct iscsi_cls_session *cls_session;
47         struct beiscsi_hba *phba;
48         struct iscsi_task *task;
49         struct iscsi_session *sess;
50         struct beiscsi_session *beiscsi_sess;
51         struct beiscsi_io_task *io_task;
52         unsigned int max_size, num_cmd;
53         dma_addr_t bus_add;
54         u64 pa_addr;
55         void *vaddr;
56
57         SE_DEBUG(DBG_LVL_8, "In beiscsi_session_create\n");
58
59         if (!ep) {
60                 SE_DEBUG(DBG_LVL_1, "beiscsi_session_create: invalid ep \n");
61                 return NULL;
62         }
63         beiscsi_ep = ep->dd_data;
64         phba = beiscsi_ep->phba;
65         shost = phba->shost;
66         if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) {
67                 shost_printk(KERN_ERR, shost, "Cannot handle %d cmds."
68                              "Max cmds per session supported is %d. Using %d. "
69                              "\n", cmds_max,
70                               beiscsi_ep->phba->params.wrbs_per_cxn,
71                               beiscsi_ep->phba->params.wrbs_per_cxn);
72                 cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn;
73         }
74
75          cls_session = iscsi_session_setup(&beiscsi_iscsi_transport,
76                                            shost, cmds_max,
77                                            sizeof(*beiscsi_sess),
78                                            sizeof(*io_task),
79                                            initial_cmdsn, ISCSI_MAX_TARGET);
80         if (!cls_session)
81                 return NULL;
82         sess = cls_session->dd_data;
83         max_size = ALIGN(sizeof(struct be_cmd_bhs), 64) * sess->cmds_max;
84         vaddr = pci_alloc_consistent(phba->pcidev, max_size, &bus_add);
85         pa_addr = (__u64) bus_add;
86
87         for (num_cmd = 0; num_cmd < sess->cmds_max; num_cmd++) {
88                 task = sess->cmds[num_cmd];
89                 io_task = task->dd_data;
90                 io_task->cmd_bhs = vaddr;
91                 io_task->bhs_pa.u.a64.address = pa_addr;
92                 io_task->alloc_size = max_size;
93                 vaddr += ALIGN(sizeof(struct be_cmd_bhs), 64);
94                 pa_addr += ALIGN(sizeof(struct be_cmd_bhs), 64);
95         }
96         return cls_session;
97 }
98
99 /**
100  * beiscsi_session_destroy - destroys iscsi session
101  * @cls_session:        pointer to iscsi cls session
102  *
103  * Destroys iSCSI session instance and releases
104  * resources allocated for it.
105  */
106 void beiscsi_session_destroy(struct iscsi_cls_session *cls_session)
107 {
108         struct iscsi_task *task;
109         struct beiscsi_io_task *io_task;
110         struct iscsi_session *sess = cls_session->dd_data;
111         struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
112         struct beiscsi_hba *phba = iscsi_host_priv(shost);
113
114         task = sess->cmds[0];
115         io_task = task->dd_data;
116         pci_free_consistent(phba->pcidev,
117                             io_task->alloc_size,
118                             io_task->cmd_bhs,
119                             io_task->bhs_pa.u.a64.address);
120         iscsi_session_teardown(cls_session);
121 }
122
123 /**
124  * beiscsi_conn_create - create an instance of iscsi connection
125  * @cls_session: ptr to iscsi_cls_session
126  * @cid: iscsi cid
127  */
128 struct iscsi_cls_conn *
129 beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid)
130 {
131         struct beiscsi_hba *phba;
132         struct Scsi_Host *shost;
133         struct iscsi_cls_conn *cls_conn;
134         struct beiscsi_conn *beiscsi_conn;
135         struct iscsi_conn *conn;
136
137         SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_create ,cid"
138                  "from iscsi layer=%d\n", cid);
139         shost = iscsi_session_to_shost(cls_session);
140         phba = iscsi_host_priv(shost);
141
142         cls_conn = iscsi_conn_setup(cls_session, sizeof(*beiscsi_conn), cid);
143         if (!cls_conn)
144                 return NULL;
145
146         conn = cls_conn->dd_data;
147         beiscsi_conn = conn->dd_data;
148         beiscsi_conn->ep = NULL;
149         beiscsi_conn->phba = phba;
150         beiscsi_conn->conn = conn;
151         return cls_conn;
152 }
153
154 /**
155  * beiscsi_bindconn_cid - Bind the beiscsi_conn with phba connection table
156  * @beiscsi_conn: The pointer to  beiscsi_conn structure
157  * @phba: The phba instance
158  * @cid: The cid to free
159  */
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]) {
165                 SE_DEBUG(DBG_LVL_1,
166                          "Connection table already occupied. Detected clash\n");
167                 return -EINVAL;
168         } else {
169                 SE_DEBUG(DBG_LVL_8, "phba->conn_table[%d]=%p(beiscsi_conn) \n",
170                          cid, beiscsi_conn);
171                 phba->conn_table[cid] = beiscsi_conn;
172         }
173         return 0;
174 }
175
176 /**
177  * beiscsi_conn_bind - Binds iscsi session/connection with TCP connection
178  * @cls_session: pointer to iscsi cls session
179  * @cls_conn: pointer to iscsi cls conn
180  * @transport_fd: EP handle(64 bit)
181  *
182  * This function binds the TCP Conn with iSCSI Connection and Session.
183  */
184 int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
185                       struct iscsi_cls_conn *cls_conn,
186                       u64 transport_fd, int is_leading)
187 {
188         struct iscsi_conn *conn = cls_conn->dd_data;
189         struct beiscsi_conn *beiscsi_conn = conn->dd_data;
190         struct Scsi_Host *shost =
191                 (struct Scsi_Host *)iscsi_session_to_shost(cls_session);
192         struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
193         struct beiscsi_endpoint *beiscsi_ep;
194         struct iscsi_endpoint *ep;
195
196         SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_bind\n");
197         ep = iscsi_lookup_endpoint(transport_fd);
198         if (!ep)
199                 return -EINVAL;
200
201         beiscsi_ep = ep->dd_data;
202
203         if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
204                 return -EINVAL;
205
206         if (beiscsi_ep->phba != phba) {
207                 SE_DEBUG(DBG_LVL_8,
208                          "beiscsi_ep->hba=%p not equal to phba=%p \n",
209                          beiscsi_ep->phba, phba);
210                 return -EEXIST;
211         }
212
213         beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid;
214         beiscsi_conn->ep = beiscsi_ep;
215         beiscsi_ep->conn = beiscsi_conn;
216         SE_DEBUG(DBG_LVL_8, "beiscsi_conn=%p conn=%p ep_cid=%d \n",
217                  beiscsi_conn, conn, beiscsi_ep->ep_cid);
218         return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid);
219 }
220
221 /**
222  * beiscsi_conn_get_param - get the iscsi parameter
223  * @cls_conn: pointer to iscsi cls conn
224  * @param: parameter type identifier
225  * @buf: buffer pointer
226  *
227  * returns iscsi parameter
228  */
229 int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
230                            enum iscsi_param param, char *buf)
231 {
232         struct beiscsi_endpoint *beiscsi_ep;
233         struct iscsi_conn *conn = cls_conn->dd_data;
234         struct beiscsi_conn *beiscsi_conn = conn->dd_data;
235         int len = 0;
236
237         beiscsi_ep = beiscsi_conn->ep;
238         if (!beiscsi_ep) {
239                 SE_DEBUG(DBG_LVL_1,
240                          "In beiscsi_conn_get_param , no beiscsi_ep\n");
241                 return -1;
242         }
243
244         switch (param) {
245         case ISCSI_PARAM_CONN_PORT:
246                 len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport);
247                 break;
248         case ISCSI_PARAM_CONN_ADDRESS:
249                 if (beiscsi_ep->ip_type == BE2_IPV4)
250                         len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr);
251                 else
252                         len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
253                 break;
254         default:
255                 return iscsi_conn_get_param(cls_conn, param, buf);
256         }
257         return len;
258 }
259
260 int beiscsi_set_param(struct iscsi_cls_conn *cls_conn,
261                       enum iscsi_param param, char *buf, int buflen)
262 {
263         struct iscsi_conn *conn = cls_conn->dd_data;
264         struct iscsi_session *session = conn->session;
265         int ret;
266
267         ret = iscsi_set_param(cls_conn, param, buf, buflen);
268         if (ret)
269                 return ret;
270         /*
271          * If userspace tried to set the value to higher than we can
272          * support override here.
273          */
274         switch (param) {
275         case ISCSI_PARAM_FIRST_BURST:
276                 if (session->first_burst > 8192)
277                         session->first_burst = 8192;
278                 break;
279         case ISCSI_PARAM_MAX_RECV_DLENGTH:
280                 if (conn->max_recv_dlength > 65536)
281                         conn->max_recv_dlength = 65536;
282                 break;
283         case ISCSI_PARAM_MAX_BURST:
284                 if (session->first_burst > 262144)
285                         session->first_burst = 262144;
286                 break;
287         default:
288                 return 0;
289         }
290
291         return 0;
292 }
293
294 /**
295  * beiscsi_get_host_param - get the iscsi parameter
296  * @shost: pointer to scsi_host structure
297  * @param: parameter type identifier
298  * @buf: buffer pointer
299  *
300  * returns host parameter
301  */
302 int beiscsi_get_host_param(struct Scsi_Host *shost,
303                            enum iscsi_host_param param, char *buf)
304 {
305         struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost);
306         int len = 0;
307
308         switch (param) {
309         case ISCSI_HOST_PARAM_HWADDRESS:
310                 be_cmd_get_mac_addr(&phba->ctrl, phba->mac_address);
311                 len = sysfs_format_mac(buf, phba->mac_address, ETH_ALEN);
312                 break;
313         default:
314                 return iscsi_host_get_param(shost, param, buf);
315         }
316         return len;
317 }
318
319 /**
320  * beiscsi_conn_get_stats - get the iscsi stats
321  * @cls_conn: pointer to iscsi cls conn
322  * @stats: pointer to iscsi_stats structure
323  *
324  * returns iscsi stats
325  */
326 void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn,
327                             struct iscsi_stats *stats)
328 {
329         struct iscsi_conn *conn = cls_conn->dd_data;
330
331         SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_stats\n");
332         stats->txdata_octets = conn->txdata_octets;
333         stats->rxdata_octets = conn->rxdata_octets;
334         stats->dataout_pdus = conn->dataout_pdus_cnt;
335         stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
336         stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
337         stats->datain_pdus = conn->datain_pdus_cnt;
338         stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
339         stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
340         stats->r2t_pdus = conn->r2t_pdus_cnt;
341         stats->digest_err = 0;
342         stats->timeout_err = 0;
343         stats->custom_length = 0;
344         strcpy(stats->custom[0].desc, "eh_abort_cnt");
345         stats->custom[0].value = conn->eh_abort_cnt;
346 }
347
348 /**
349  * beiscsi_set_params_for_offld - get the parameters for offload
350  * @beiscsi_conn: pointer to beiscsi_conn
351  * @params: pointer to offload_params structure
352  */
353 static void  beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn,
354                                           struct beiscsi_offload_params *params)
355 {
356         struct iscsi_conn *conn = beiscsi_conn->conn;
357         struct iscsi_session *session = conn->session;
358
359         AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length,
360                       params, session->max_burst);
361         AMAP_SET_BITS(struct amap_beiscsi_offload_params,
362                       max_send_data_segment_length, params,
363                       conn->max_xmit_dlength);
364         AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length,
365                       params, session->first_burst);
366         AMAP_SET_BITS(struct amap_beiscsi_offload_params, erl, params,
367                       session->erl);
368         AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params,
369                       conn->datadgst_en);
370         AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params,
371                       conn->hdrdgst_en);
372         AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params,
373                       session->initial_r2t_en);
374         AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params,
375                       session->imm_data_en);
376         AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params,
377                       (conn->exp_statsn - 1));
378 }
379
380 /**
381  * beiscsi_conn_start - offload of session to chip
382  * @cls_conn: pointer to beiscsi_conn
383  */
384 int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn)
385 {
386         struct iscsi_conn *conn = cls_conn->dd_data;
387         struct beiscsi_conn *beiscsi_conn = conn->dd_data;
388         struct beiscsi_endpoint *beiscsi_ep;
389         struct beiscsi_offload_params params;
390         struct iscsi_session *session = conn->session;
391         struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
392         struct beiscsi_hba *phba = iscsi_host_priv(shost);
393
394         memset(&params, 0, sizeof(struct beiscsi_offload_params));
395         beiscsi_ep = beiscsi_conn->ep;
396         if (!beiscsi_ep)
397                 SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_start , no beiscsi_ep\n");
398
399         free_mgmt_sgl_handle(phba, beiscsi_conn->plogin_sgl_handle);
400         beiscsi_conn->login_in_progress = 0;
401         beiscsi_set_params_for_offld(beiscsi_conn, &params);
402         beiscsi_offload_connection(beiscsi_conn, &params);
403         iscsi_conn_start(cls_conn);
404         return 0;
405 }
406
407 /**
408  * beiscsi_get_cid - Allocate a cid
409  * @phba: The phba instance
410  */
411 static int beiscsi_get_cid(struct beiscsi_hba *phba)
412 {
413         unsigned short cid = 0xFFFF;
414
415         if (!phba->avlbl_cids)
416                 return cid;
417
418         cid = phba->cid_array[phba->cid_alloc++];
419         if (phba->cid_alloc == phba->params.cxns_per_ctrl)
420                 phba->cid_alloc = 0;
421         phba->avlbl_cids--;
422         return cid;
423 }
424
425 /**
426  * beiscsi_open_conn - Ask FW to open a TCP connection
427  * @ep: endpoint to be used
428  * @src_addr: The source IP address
429  * @dst_addr: The Destination  IP address
430  *
431  * Asks the FW to open a TCP connection
432  */
433 static int beiscsi_open_conn(struct iscsi_endpoint *ep,
434                              struct sockaddr *src_addr,
435                              struct sockaddr *dst_addr, int non_blocking)
436 {
437         struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
438         struct beiscsi_hba *phba = beiscsi_ep->phba;
439         int ret = -1;
440
441         beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
442         if (beiscsi_ep->ep_cid == 0xFFFF) {
443                 SE_DEBUG(DBG_LVL_1, "No free cid available\n");
444                 return ret;
445         }
446         SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d ",
447                  beiscsi_ep->ep_cid);
448         phba->ep_array[beiscsi_ep->ep_cid] = ep;
449         if (beiscsi_ep->ep_cid >
450             (phba->fw_config.iscsi_cid_start + phba->params.cxns_per_ctrl)) {
451                 SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
452                 return ret;
453         }
454
455         beiscsi_ep->cid_vld = 0;
456         return mgmt_open_connection(phba, dst_addr, beiscsi_ep);
457 }
458
459 /**
460  * beiscsi_put_cid - Free the cid
461  * @phba: The phba for which the cid is being freed
462  * @cid: The cid to free
463  */
464 static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid)
465 {
466         phba->avlbl_cids++;
467         phba->cid_array[phba->cid_free++] = cid;
468         if (phba->cid_free == phba->params.cxns_per_ctrl)
469                 phba->cid_free = 0;
470 }
471
472 /**
473  * beiscsi_free_ep - free endpoint
474  * @ep: pointer to iscsi endpoint structure
475  */
476 static void beiscsi_free_ep(struct iscsi_endpoint *ep)
477 {
478         struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
479         struct beiscsi_hba *phba = beiscsi_ep->phba;
480
481         beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
482         beiscsi_ep->phba = NULL;
483         iscsi_destroy_endpoint(ep);
484 }
485
486 /**
487  * beiscsi_ep_connect - Ask chip to create TCP Conn
488  * @scsi_host: Pointer to scsi_host structure
489  * @dst_addr: The IP address of Target
490  * @non_blocking: blocking or non-blocking call
491  *
492  * This routines first asks chip to create a connection and then allocates an EP
493  */
494 struct iscsi_endpoint *
495 beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
496                    int non_blocking)
497 {
498         struct beiscsi_hba *phba;
499         struct beiscsi_endpoint *beiscsi_ep;
500         struct iscsi_endpoint *ep;
501         int ret;
502
503         SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_connect \n");
504         if (shost)
505                 phba = iscsi_host_priv(shost);
506         else {
507                 ret = -ENXIO;
508                 SE_DEBUG(DBG_LVL_1, "shost is NULL \n");
509                 return ERR_PTR(ret);
510         }
511         ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint));
512         if (!ep) {
513                 ret = -ENOMEM;
514                 return ERR_PTR(ret);
515         }
516
517         beiscsi_ep = ep->dd_data;
518         beiscsi_ep->phba = phba;
519
520         if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) {
521                 SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
522                 ret = -ENOMEM;
523                 goto free_ep;
524         }
525
526         return ep;
527
528 free_ep:
529         beiscsi_free_ep(ep);
530         return ERR_PTR(ret);
531 }
532
533 /**
534  * beiscsi_ep_poll - Poll to see if connection is established
535  * @ep: endpoint to be used
536  * @timeout_ms: timeout specified in millisecs
537  *
538  * Poll to see if TCP connection established
539  */
540 int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
541 {
542         struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
543
544         SE_DEBUG(DBG_LVL_8, "In  beiscsi_ep_poll\n");
545         if (beiscsi_ep->cid_vld == 1)
546                 return 1;
547         else
548                 return 0;
549 }
550
551 /**
552  * beiscsi_close_conn - Upload the  connection
553  * @ep: The iscsi endpoint
554  * @flag: The type of connection closure
555  */
556 static int beiscsi_close_conn(struct iscsi_endpoint *ep, int flag)
557 {
558         int ret = 0;
559         struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
560         struct beiscsi_hba *phba = beiscsi_ep->phba;
561
562         if (MGMT_STATUS_SUCCESS !=
563             mgmt_upload_connection(phba, beiscsi_ep->ep_cid,
564                 CONNECTION_UPLOAD_GRACEFUL)) {
565                 SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x",
566                          beiscsi_ep->ep_cid);
567                 ret = -1;
568         }
569
570         return ret;
571 }
572
573 /**
574  * beiscsi_ep_disconnect - Tears down the TCP connection
575  * @ep: endpoint to be used
576  *
577  * Tears down the TCP connection
578  */
579 void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
580 {
581         struct beiscsi_conn *beiscsi_conn;
582         struct beiscsi_endpoint *beiscsi_ep;
583         struct beiscsi_hba *phba;
584         int flag = 0;
585
586         beiscsi_ep = ep->dd_data;
587         phba = beiscsi_ep->phba;
588         SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect\n");
589
590         if (beiscsi_ep->conn) {
591                 beiscsi_conn = beiscsi_ep->conn;
592                 iscsi_suspend_queue(beiscsi_conn->conn);
593                 beiscsi_close_conn(ep, flag);
594         }
595
596         beiscsi_free_ep(ep);
597 }
598
599 /**
600  * beiscsi_unbind_conn_to_cid - Unbind the beiscsi_conn from phba conn table
601  * @phba: The phba instance
602  * @cid: The cid to free
603  */
604 static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba,
605                                       unsigned int cid)
606 {
607         if (phba->conn_table[cid])
608                 phba->conn_table[cid] = NULL;
609         else {
610                 SE_DEBUG(DBG_LVL_8, "Connection table Not occupied. \n");
611                 return -EINVAL;
612         }
613         return 0;
614 }
615
616 /**
617  * beiscsi_conn_stop - Invalidate and stop the connection
618  * @cls_conn: pointer to get iscsi_conn
619  * @flag: The type of connection closure
620  */
621 void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
622 {
623         struct iscsi_conn *conn = cls_conn->dd_data;
624         struct beiscsi_conn *beiscsi_conn = conn->dd_data;
625         struct beiscsi_endpoint *beiscsi_ep;
626         struct iscsi_session *session = conn->session;
627         struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
628         struct beiscsi_hba *phba = iscsi_host_priv(shost);
629         unsigned int status;
630         unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;
631
632         SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop\n");
633         beiscsi_ep = beiscsi_conn->ep;
634         if (!beiscsi_ep) {
635                 SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n");
636                 return;
637         }
638         status = mgmt_invalidate_connection(phba, beiscsi_ep,
639                                             beiscsi_ep->ep_cid, 1,
640                                             savecfg_flag);
641         if (status != MGMT_STATUS_SUCCESS) {
642                 SE_DEBUG(DBG_LVL_1,
643                          "mgmt_invalidate_connection Failed for cid=%d \n",
644                          beiscsi_ep->ep_cid);
645         }
646         beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
647         iscsi_conn_stop(cls_conn, flag);
648 }