| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 1 | /** | 
| Jayamohan Kallickal | d2eeb1a | 2010-01-23 05:35:15 +0530 | [diff] [blame] | 2 |  * Copyright (C) 2005 - 2010 ServerEngines | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 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; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 47 | 	struct beiscsi_hba *phba; | 
| Jayamohan Kallickal | b8b9e1b8 | 2009-09-22 08:21:22 +0530 | [diff] [blame] | 48 | 	struct iscsi_session *sess; | 
 | 49 | 	struct beiscsi_session *beiscsi_sess; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 50 | 	struct beiscsi_io_task *io_task; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 51 |  | 
 | 52 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_session_create\n"); | 
 | 53 |  | 
 | 54 | 	if (!ep) { | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 55 | 		SE_DEBUG(DBG_LVL_1, "beiscsi_session_create: invalid ep\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 56 | 		return NULL; | 
 | 57 | 	} | 
 | 58 | 	beiscsi_ep = ep->dd_data; | 
 | 59 | 	phba = beiscsi_ep->phba; | 
 | 60 | 	shost = phba->shost; | 
 | 61 | 	if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { | 
 | 62 | 		shost_printk(KERN_ERR, shost, "Cannot handle %d cmds." | 
 | 63 | 			     "Max cmds per session supported is %d. Using %d. " | 
 | 64 | 			     "\n", cmds_max, | 
 | 65 | 			      beiscsi_ep->phba->params.wrbs_per_cxn, | 
 | 66 | 			      beiscsi_ep->phba->params.wrbs_per_cxn); | 
 | 67 | 		cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; | 
 | 68 | 	} | 
 | 69 |  | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 70 | 	cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, | 
 | 71 | 					  shost, cmds_max, | 
 | 72 | 					  sizeof(*beiscsi_sess), | 
 | 73 | 					  sizeof(*io_task), | 
 | 74 | 					  initial_cmdsn, ISCSI_MAX_TARGET); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 75 | 	if (!cls_session) | 
 | 76 | 		return NULL; | 
 | 77 | 	sess = cls_session->dd_data; | 
| Jayamohan Kallickal | 2afc95b | 2009-09-22 08:22:26 +0530 | [diff] [blame] | 78 | 	beiscsi_sess = sess->dd_data; | 
 | 79 | 	beiscsi_sess->bhs_pool =  pci_pool_create("beiscsi_bhs_pool", | 
 | 80 | 						   phba->pcidev, | 
 | 81 | 						   sizeof(struct be_cmd_bhs), | 
 | 82 | 						   64, 0); | 
 | 83 | 	if (!beiscsi_sess->bhs_pool) | 
 | 84 | 		goto destroy_sess; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 85 |  | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 86 | 	return cls_session; | 
| Jayamohan Kallickal | 2afc95b | 2009-09-22 08:22:26 +0530 | [diff] [blame] | 87 | destroy_sess: | 
 | 88 | 	iscsi_session_teardown(cls_session); | 
 | 89 | 	return NULL; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 90 | } | 
 | 91 |  | 
 | 92 | /** | 
 | 93 |  * beiscsi_session_destroy - destroys iscsi session | 
 | 94 |  * @cls_session:	pointer to iscsi cls session | 
 | 95 |  * | 
 | 96 |  * Destroys iSCSI session instance and releases | 
 | 97 |  * resources allocated for it. | 
 | 98 |  */ | 
 | 99 | void beiscsi_session_destroy(struct iscsi_cls_session *cls_session) | 
 | 100 | { | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 101 | 	struct iscsi_session *sess = cls_session->dd_data; | 
| Jayamohan Kallickal | 2afc95b | 2009-09-22 08:22:26 +0530 | [diff] [blame] | 102 | 	struct beiscsi_session *beiscsi_sess = sess->dd_data; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 103 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 104 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_session_destroy\n"); | 
| Jayamohan Kallickal | 2afc95b | 2009-09-22 08:22:26 +0530 | [diff] [blame] | 105 | 	pci_pool_destroy(beiscsi_sess->bhs_pool); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 106 | 	iscsi_session_teardown(cls_session); | 
 | 107 | } | 
 | 108 |  | 
 | 109 | /** | 
 | 110 |  * beiscsi_conn_create - create an instance of iscsi connection | 
 | 111 |  * @cls_session: ptr to iscsi_cls_session | 
 | 112 |  * @cid: iscsi cid | 
 | 113 |  */ | 
 | 114 | struct iscsi_cls_conn * | 
 | 115 | beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid) | 
 | 116 | { | 
 | 117 | 	struct beiscsi_hba *phba; | 
 | 118 | 	struct Scsi_Host *shost; | 
 | 119 | 	struct iscsi_cls_conn *cls_conn; | 
 | 120 | 	struct beiscsi_conn *beiscsi_conn; | 
 | 121 | 	struct iscsi_conn *conn; | 
| Jayamohan Kallickal | 2afc95b | 2009-09-22 08:22:26 +0530 | [diff] [blame] | 122 | 	struct iscsi_session *sess; | 
 | 123 | 	struct beiscsi_session *beiscsi_sess; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 124 |  | 
 | 125 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_create ,cid" | 
 | 126 | 		 "from iscsi layer=%d\n", cid); | 
 | 127 | 	shost = iscsi_session_to_shost(cls_session); | 
 | 128 | 	phba = iscsi_host_priv(shost); | 
 | 129 |  | 
 | 130 | 	cls_conn = iscsi_conn_setup(cls_session, sizeof(*beiscsi_conn), cid); | 
 | 131 | 	if (!cls_conn) | 
 | 132 | 		return NULL; | 
 | 133 |  | 
 | 134 | 	conn = cls_conn->dd_data; | 
 | 135 | 	beiscsi_conn = conn->dd_data; | 
 | 136 | 	beiscsi_conn->ep = NULL; | 
 | 137 | 	beiscsi_conn->phba = phba; | 
 | 138 | 	beiscsi_conn->conn = conn; | 
| Jayamohan Kallickal | 2afc95b | 2009-09-22 08:22:26 +0530 | [diff] [blame] | 139 | 	sess = cls_session->dd_data; | 
 | 140 | 	beiscsi_sess = sess->dd_data; | 
 | 141 | 	beiscsi_conn->beiscsi_sess = beiscsi_sess; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 142 | 	return cls_conn; | 
 | 143 | } | 
 | 144 |  | 
 | 145 | /** | 
 | 146 |  * beiscsi_bindconn_cid - Bind the beiscsi_conn with phba connection table | 
 | 147 |  * @beiscsi_conn: The pointer to  beiscsi_conn structure | 
 | 148 |  * @phba: The phba instance | 
 | 149 |  * @cid: The cid to free | 
 | 150 |  */ | 
 | 151 | static int beiscsi_bindconn_cid(struct beiscsi_hba *phba, | 
 | 152 | 				struct beiscsi_conn *beiscsi_conn, | 
 | 153 | 				unsigned int cid) | 
 | 154 | { | 
 | 155 | 	if (phba->conn_table[cid]) { | 
 | 156 | 		SE_DEBUG(DBG_LVL_1, | 
 | 157 | 			 "Connection table already occupied. Detected clash\n"); | 
 | 158 | 		return -EINVAL; | 
 | 159 | 	} else { | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 160 | 		SE_DEBUG(DBG_LVL_8, "phba->conn_table[%d]=%p(beiscsi_conn)\n", | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 161 | 			 cid, beiscsi_conn); | 
 | 162 | 		phba->conn_table[cid] = beiscsi_conn; | 
 | 163 | 	} | 
 | 164 | 	return 0; | 
 | 165 | } | 
 | 166 |  | 
 | 167 | /** | 
 | 168 |  * beiscsi_conn_bind - Binds iscsi session/connection with TCP connection | 
 | 169 |  * @cls_session: pointer to iscsi cls session | 
 | 170 |  * @cls_conn: pointer to iscsi cls conn | 
 | 171 |  * @transport_fd: EP handle(64 bit) | 
 | 172 |  * | 
 | 173 |  * This function binds the TCP Conn with iSCSI Connection and Session. | 
 | 174 |  */ | 
 | 175 | int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, | 
 | 176 | 		      struct iscsi_cls_conn *cls_conn, | 
 | 177 | 		      u64 transport_fd, int is_leading) | 
 | 178 | { | 
 | 179 | 	struct iscsi_conn *conn = cls_conn->dd_data; | 
 | 180 | 	struct beiscsi_conn *beiscsi_conn = conn->dd_data; | 
 | 181 | 	struct Scsi_Host *shost = | 
 | 182 | 		(struct Scsi_Host *)iscsi_session_to_shost(cls_session); | 
 | 183 | 	struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); | 
 | 184 | 	struct beiscsi_endpoint *beiscsi_ep; | 
 | 185 | 	struct iscsi_endpoint *ep; | 
 | 186 |  | 
 | 187 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_bind\n"); | 
 | 188 | 	ep = iscsi_lookup_endpoint(transport_fd); | 
 | 189 | 	if (!ep) | 
 | 190 | 		return -EINVAL; | 
 | 191 |  | 
 | 192 | 	beiscsi_ep = ep->dd_data; | 
 | 193 |  | 
 | 194 | 	if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) | 
 | 195 | 		return -EINVAL; | 
 | 196 |  | 
 | 197 | 	if (beiscsi_ep->phba != phba) { | 
 | 198 | 		SE_DEBUG(DBG_LVL_8, | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 199 | 			 "beiscsi_ep->hba=%p not equal to phba=%p\n", | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 200 | 			 beiscsi_ep->phba, phba); | 
 | 201 | 		return -EEXIST; | 
 | 202 | 	} | 
 | 203 |  | 
 | 204 | 	beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid; | 
 | 205 | 	beiscsi_conn->ep = beiscsi_ep; | 
 | 206 | 	beiscsi_ep->conn = beiscsi_conn; | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 207 | 	SE_DEBUG(DBG_LVL_8, "beiscsi_conn=%p conn=%p ep_cid=%d\n", | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 208 | 		 beiscsi_conn, conn, beiscsi_ep->ep_cid); | 
 | 209 | 	return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid); | 
 | 210 | } | 
 | 211 |  | 
 | 212 | /** | 
 | 213 |  * beiscsi_conn_get_param - get the iscsi parameter | 
 | 214 |  * @cls_conn: pointer to iscsi cls conn | 
 | 215 |  * @param: parameter type identifier | 
 | 216 |  * @buf: buffer pointer | 
 | 217 |  * | 
 | 218 |  * returns iscsi parameter | 
 | 219 |  */ | 
 | 220 | int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, | 
 | 221 | 			   enum iscsi_param param, char *buf) | 
 | 222 | { | 
 | 223 | 	struct beiscsi_endpoint *beiscsi_ep; | 
 | 224 | 	struct iscsi_conn *conn = cls_conn->dd_data; | 
 | 225 | 	struct beiscsi_conn *beiscsi_conn = conn->dd_data; | 
 | 226 | 	int len = 0; | 
 | 227 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 228 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_param, param= %d\n", param); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 229 | 	beiscsi_ep = beiscsi_conn->ep; | 
 | 230 | 	if (!beiscsi_ep) { | 
 | 231 | 		SE_DEBUG(DBG_LVL_1, | 
 | 232 | 			 "In beiscsi_conn_get_param , no beiscsi_ep\n"); | 
| Jayamohan Kallickal | d3ad2bb | 2010-07-22 04:16:38 +0530 | [diff] [blame] | 233 | 		return -ENODEV; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 234 | 	} | 
 | 235 |  | 
 | 236 | 	switch (param) { | 
 | 237 | 	case ISCSI_PARAM_CONN_PORT: | 
 | 238 | 		len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport); | 
 | 239 | 		break; | 
 | 240 | 	case ISCSI_PARAM_CONN_ADDRESS: | 
 | 241 | 		if (beiscsi_ep->ip_type == BE2_IPV4) | 
 | 242 | 			len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr); | 
 | 243 | 		else | 
 | 244 | 			len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr); | 
 | 245 | 		break; | 
 | 246 | 	default: | 
 | 247 | 		return iscsi_conn_get_param(cls_conn, param, buf); | 
 | 248 | 	} | 
 | 249 | 	return len; | 
 | 250 | } | 
 | 251 |  | 
 | 252 | int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, | 
 | 253 | 		      enum iscsi_param param, char *buf, int buflen) | 
 | 254 | { | 
 | 255 | 	struct iscsi_conn *conn = cls_conn->dd_data; | 
 | 256 | 	struct iscsi_session *session = conn->session; | 
 | 257 | 	int ret; | 
 | 258 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 259 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_set_param, param= %d\n", param); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 260 | 	ret = iscsi_set_param(cls_conn, param, buf, buflen); | 
 | 261 | 	if (ret) | 
 | 262 | 		return ret; | 
 | 263 | 	/* | 
 | 264 | 	 * If userspace tried to set the value to higher than we can | 
 | 265 | 	 * support override here. | 
 | 266 | 	 */ | 
 | 267 | 	switch (param) { | 
 | 268 | 	case ISCSI_PARAM_FIRST_BURST: | 
 | 269 | 		if (session->first_burst > 8192) | 
 | 270 | 			session->first_burst = 8192; | 
 | 271 | 		break; | 
 | 272 | 	case ISCSI_PARAM_MAX_RECV_DLENGTH: | 
 | 273 | 		if (conn->max_recv_dlength > 65536) | 
 | 274 | 			conn->max_recv_dlength = 65536; | 
 | 275 | 		break; | 
 | 276 | 	case ISCSI_PARAM_MAX_BURST: | 
| Jayamohan Kallickal | 230dceb | 2010-01-23 05:36:10 +0530 | [diff] [blame] | 277 | 		if (session->max_burst > 262144) | 
 | 278 | 			session->max_burst = 262144; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 279 | 		break; | 
| Jayamohan Kallickal | 42f43c4 | 2010-07-22 04:26:45 +0530 | [diff] [blame] | 280 | 	case ISCSI_PARAM_MAX_XMIT_DLENGTH: | 
 | 281 | 		if ((conn->max_xmit_dlength > 65536) || | 
 | 282 | 		    (conn->max_xmit_dlength == 0)) | 
 | 283 | 			conn->max_xmit_dlength = 65536; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 284 | 	default: | 
 | 285 | 		return 0; | 
 | 286 | 	} | 
 | 287 |  | 
 | 288 | 	return 0; | 
 | 289 | } | 
 | 290 |  | 
 | 291 | /** | 
 | 292 |  * beiscsi_get_host_param - get the iscsi parameter | 
 | 293 |  * @shost: pointer to scsi_host structure | 
 | 294 |  * @param: parameter type identifier | 
 | 295 |  * @buf: buffer pointer | 
 | 296 |  * | 
 | 297 |  * returns host parameter | 
 | 298 |  */ | 
 | 299 | int beiscsi_get_host_param(struct Scsi_Host *shost, | 
 | 300 | 			   enum iscsi_host_param param, char *buf) | 
 | 301 | { | 
 | 302 | 	struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); | 
| Jayamohan Kallickal | b15d05b | 2010-08-12 23:36:06 +0530 | [diff] [blame] | 303 | 	int status = 0; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 304 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 305 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 306 | 	switch (param) { | 
 | 307 | 	case ISCSI_HOST_PARAM_HWADDRESS: | 
| Jayamohan Kallickal | c7acc5b | 2010-07-22 04:29:18 +0530 | [diff] [blame] | 308 | 		status = beiscsi_get_macaddr(buf, phba); | 
 | 309 | 		if (status < 0) { | 
 | 310 | 			SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n"); | 
 | 311 | 			return status; | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 312 | 		} | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 313 | 		break; | 
 | 314 | 	default: | 
 | 315 | 		return iscsi_host_get_param(shost, param, buf); | 
 | 316 | 	} | 
| Jayamohan Kallickal | b15d05b | 2010-08-12 23:36:06 +0530 | [diff] [blame] | 317 | 	return status; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 318 | } | 
 | 319 |  | 
| Jayamohan Kallickal | c7acc5b | 2010-07-22 04:29:18 +0530 | [diff] [blame] | 320 | int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) | 
 | 321 | { | 
 | 322 | 	struct be_cmd_resp_get_mac_addr *resp; | 
 | 323 | 	struct be_mcc_wrb *wrb; | 
 | 324 | 	unsigned int tag, wrb_num; | 
 | 325 | 	unsigned short status, extd_status; | 
 | 326 | 	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | 
 | 327 | 	int rc; | 
 | 328 |  | 
 | 329 | 	if (phba->read_mac_address) | 
 | 330 | 		return sysfs_format_mac(buf, phba->mac_address, | 
 | 331 | 					ETH_ALEN); | 
 | 332 |  | 
 | 333 | 	tag = be_cmd_get_mac_addr(phba); | 
 | 334 | 	if (!tag) { | 
 | 335 | 		SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); | 
 | 336 | 		return -EBUSY; | 
 | 337 | 	} else | 
 | 338 | 		wait_event_interruptible(phba->ctrl.mcc_wait[tag], | 
 | 339 | 					 phba->ctrl.mcc_numtag[tag]); | 
 | 340 |  | 
 | 341 | 	wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | 
 | 342 | 	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | 
 | 343 | 	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | 
 | 344 | 	if (status || extd_status) { | 
 | 345 | 		SE_DEBUG(DBG_LVL_1, "Failed to get be_cmd_get_mac_addr" | 
 | 346 | 				    " status = %d extd_status = %d\n", | 
 | 347 | 				    status, extd_status); | 
 | 348 | 		free_mcc_tag(&phba->ctrl, tag); | 
 | 349 | 		return -EAGAIN; | 
 | 350 | 	} | 
 | 351 | 	wrb = queue_get_wrb(mccq, wrb_num); | 
 | 352 | 	free_mcc_tag(&phba->ctrl, tag); | 
 | 353 | 	resp = embedded_payload(wrb); | 
 | 354 | 	memcpy(phba->mac_address, resp->mac_address, ETH_ALEN); | 
 | 355 | 	rc = sysfs_format_mac(buf, phba->mac_address, | 
 | 356 | 			       ETH_ALEN); | 
 | 357 | 	phba->read_mac_address = 1; | 
 | 358 | 	return rc; | 
 | 359 | } | 
 | 360 |  | 
 | 361 |  | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 362 | /** | 
 | 363 |  * beiscsi_conn_get_stats - get the iscsi stats | 
 | 364 |  * @cls_conn: pointer to iscsi cls conn | 
 | 365 |  * @stats: pointer to iscsi_stats structure | 
 | 366 |  * | 
 | 367 |  * returns iscsi stats | 
 | 368 |  */ | 
 | 369 | void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, | 
 | 370 | 			    struct iscsi_stats *stats) | 
 | 371 | { | 
 | 372 | 	struct iscsi_conn *conn = cls_conn->dd_data; | 
 | 373 |  | 
 | 374 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_stats\n"); | 
 | 375 | 	stats->txdata_octets = conn->txdata_octets; | 
 | 376 | 	stats->rxdata_octets = conn->rxdata_octets; | 
 | 377 | 	stats->dataout_pdus = conn->dataout_pdus_cnt; | 
 | 378 | 	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt; | 
 | 379 | 	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt; | 
 | 380 | 	stats->datain_pdus = conn->datain_pdus_cnt; | 
 | 381 | 	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; | 
 | 382 | 	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt; | 
 | 383 | 	stats->r2t_pdus = conn->r2t_pdus_cnt; | 
 | 384 | 	stats->digest_err = 0; | 
 | 385 | 	stats->timeout_err = 0; | 
 | 386 | 	stats->custom_length = 0; | 
 | 387 | 	strcpy(stats->custom[0].desc, "eh_abort_cnt"); | 
 | 388 | 	stats->custom[0].value = conn->eh_abort_cnt; | 
 | 389 | } | 
 | 390 |  | 
 | 391 | /** | 
 | 392 |  * beiscsi_set_params_for_offld - get the parameters for offload | 
 | 393 |  * @beiscsi_conn: pointer to beiscsi_conn | 
 | 394 |  * @params: pointer to offload_params structure | 
 | 395 |  */ | 
 | 396 | static void  beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn, | 
 | 397 | 					  struct beiscsi_offload_params *params) | 
 | 398 | { | 
 | 399 | 	struct iscsi_conn *conn = beiscsi_conn->conn; | 
 | 400 | 	struct iscsi_session *session = conn->session; | 
 | 401 |  | 
 | 402 | 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length, | 
 | 403 | 		      params, session->max_burst); | 
 | 404 | 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, | 
 | 405 | 		      max_send_data_segment_length, params, | 
 | 406 | 		      conn->max_xmit_dlength); | 
 | 407 | 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length, | 
 | 408 | 		      params, session->first_burst); | 
 | 409 | 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, erl, params, | 
 | 410 | 		      session->erl); | 
 | 411 | 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params, | 
 | 412 | 		      conn->datadgst_en); | 
 | 413 | 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params, | 
 | 414 | 		      conn->hdrdgst_en); | 
 | 415 | 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params, | 
 | 416 | 		      session->initial_r2t_en); | 
 | 417 | 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params, | 
 | 418 | 		      session->imm_data_en); | 
 | 419 | 	AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params, | 
 | 420 | 		      (conn->exp_statsn - 1)); | 
 | 421 | } | 
 | 422 |  | 
 | 423 | /** | 
 | 424 |  * beiscsi_conn_start - offload of session to chip | 
 | 425 |  * @cls_conn: pointer to beiscsi_conn | 
 | 426 |  */ | 
 | 427 | int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) | 
 | 428 | { | 
 | 429 | 	struct iscsi_conn *conn = cls_conn->dd_data; | 
 | 430 | 	struct beiscsi_conn *beiscsi_conn = conn->dd_data; | 
 | 431 | 	struct beiscsi_endpoint *beiscsi_ep; | 
 | 432 | 	struct beiscsi_offload_params params; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 433 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 434 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_start\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 435 | 	memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); | 
 | 436 | 	beiscsi_ep = beiscsi_conn->ep; | 
 | 437 | 	if (!beiscsi_ep) | 
 | 438 | 		SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_start , no beiscsi_ep\n"); | 
 | 439 |  | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 440 | 	beiscsi_conn->login_in_progress = 0; | 
 | 441 | 	beiscsi_set_params_for_offld(beiscsi_conn, ¶ms); | 
 | 442 | 	beiscsi_offload_connection(beiscsi_conn, ¶ms); | 
 | 443 | 	iscsi_conn_start(cls_conn); | 
 | 444 | 	return 0; | 
 | 445 | } | 
 | 446 |  | 
 | 447 | /** | 
 | 448 |  * beiscsi_get_cid - Allocate a cid | 
 | 449 |  * @phba: The phba instance | 
 | 450 |  */ | 
 | 451 | static int beiscsi_get_cid(struct beiscsi_hba *phba) | 
 | 452 | { | 
 | 453 | 	unsigned short cid = 0xFFFF; | 
 | 454 |  | 
 | 455 | 	if (!phba->avlbl_cids) | 
 | 456 | 		return cid; | 
 | 457 |  | 
 | 458 | 	cid = phba->cid_array[phba->cid_alloc++]; | 
 | 459 | 	if (phba->cid_alloc == phba->params.cxns_per_ctrl) | 
 | 460 | 		phba->cid_alloc = 0; | 
 | 461 | 	phba->avlbl_cids--; | 
 | 462 | 	return cid; | 
 | 463 | } | 
 | 464 |  | 
 | 465 | /** | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 466 |  * beiscsi_put_cid - Free the cid | 
 | 467 |  * @phba: The phba for which the cid is being freed | 
 | 468 |  * @cid: The cid to free | 
 | 469 |  */ | 
 | 470 | static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) | 
 | 471 | { | 
 | 472 | 	phba->avlbl_cids++; | 
 | 473 | 	phba->cid_array[phba->cid_free++] = cid; | 
 | 474 | 	if (phba->cid_free == phba->params.cxns_per_ctrl) | 
 | 475 | 		phba->cid_free = 0; | 
 | 476 | } | 
 | 477 |  | 
 | 478 | /** | 
 | 479 |  * beiscsi_free_ep - free endpoint | 
 | 480 |  * @ep:	pointer to iscsi endpoint structure | 
 | 481 |  */ | 
 | 482 | static void beiscsi_free_ep(struct beiscsi_endpoint *beiscsi_ep) | 
 | 483 | { | 
 | 484 | 	struct beiscsi_hba *phba = beiscsi_ep->phba; | 
 | 485 |  | 
 | 486 | 	beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | 
 | 487 | 	beiscsi_ep->phba = NULL; | 
 | 488 | } | 
 | 489 |  | 
 | 490 | /** | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 491 |  * beiscsi_open_conn - Ask FW to open a TCP connection | 
 | 492 |  * @ep:	endpoint to be used | 
 | 493 |  * @src_addr: The source IP address | 
 | 494 |  * @dst_addr: The Destination  IP address | 
 | 495 |  * | 
 | 496 |  * Asks the FW to open a TCP connection | 
 | 497 |  */ | 
 | 498 | static int beiscsi_open_conn(struct iscsi_endpoint *ep, | 
 | 499 | 			     struct sockaddr *src_addr, | 
 | 500 | 			     struct sockaddr *dst_addr, int non_blocking) | 
 | 501 | { | 
 | 502 | 	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | 
 | 503 | 	struct beiscsi_hba *phba = beiscsi_ep->phba; | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 504 | 	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | 
 | 505 | 	struct be_mcc_wrb *wrb; | 
 | 506 | 	struct tcp_connect_and_offload_out *ptcpcnct_out; | 
 | 507 | 	unsigned short status, extd_status; | 
| Jayamohan Kallickal | 3cbb7a7 | 2010-07-22 04:27:47 +0530 | [diff] [blame] | 508 | 	struct be_dma_mem nonemb_cmd; | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 509 | 	unsigned int tag, wrb_num; | 
| Jayamohan Kallickal | d3ad2bb | 2010-07-22 04:16:38 +0530 | [diff] [blame] | 510 | 	int ret = -ENOMEM; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 511 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 512 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 513 | 	beiscsi_ep->ep_cid = beiscsi_get_cid(phba); | 
 | 514 | 	if (beiscsi_ep->ep_cid == 0xFFFF) { | 
 | 515 | 		SE_DEBUG(DBG_LVL_1, "No free cid available\n"); | 
 | 516 | 		return ret; | 
 | 517 | 	} | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 518 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d\n", | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 519 | 		 beiscsi_ep->ep_cid); | 
| Jayamohan Kallickal | 7da5087 | 2010-01-05 05:04:12 +0530 | [diff] [blame] | 520 | 	phba->ep_array[beiscsi_ep->ep_cid - | 
 | 521 | 		       phba->fw_config.iscsi_cid_start] = ep; | 
 | 522 | 	if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start + | 
 | 523 | 				  phba->params.cxns_per_ctrl * 2)) { | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 524 | 		SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); | 
| Jayamohan Kallickal | 3cbb7a7 | 2010-07-22 04:27:47 +0530 | [diff] [blame] | 525 | 		beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 526 | 		goto free_ep; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 527 | 	} | 
 | 528 |  | 
 | 529 | 	beiscsi_ep->cid_vld = 0; | 
| Jayamohan Kallickal | 3cbb7a7 | 2010-07-22 04:27:47 +0530 | [diff] [blame] | 530 | 	nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, | 
 | 531 | 				sizeof(struct tcp_connect_and_offload_in), | 
 | 532 | 				&nonemb_cmd.dma); | 
 | 533 | 	if (nonemb_cmd.va == NULL) { | 
 | 534 | 		SE_DEBUG(DBG_LVL_1, | 
 | 535 | 			 "Failed to allocate memory for mgmt_open_connection" | 
 | 536 | 			 "\n"); | 
 | 537 | 		beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | 
 | 538 | 		return -ENOMEM; | 
 | 539 | 	} | 
 | 540 | 	nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in); | 
 | 541 | 	memset(nonemb_cmd.va, 0, nonemb_cmd.size); | 
 | 542 | 	tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd); | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 543 | 	if (!tag) { | 
 | 544 | 		SE_DEBUG(DBG_LVL_1, | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 545 | 			 "mgmt_open_connection Failed for cid=%d\n", | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 546 | 			 beiscsi_ep->ep_cid); | 
| Jayamohan Kallickal | 1f92638 | 2010-07-22 04:22:27 +0530 | [diff] [blame] | 547 | 		beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | 
| Jayamohan Kallickal | 3cbb7a7 | 2010-07-22 04:27:47 +0530 | [diff] [blame] | 548 | 		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | 
 | 549 | 				    nonemb_cmd.va, nonemb_cmd.dma); | 
| Jayamohan Kallickal | 1f92638 | 2010-07-22 04:22:27 +0530 | [diff] [blame] | 550 | 		return -EAGAIN; | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 551 | 	} else { | 
 | 552 | 		wait_event_interruptible(phba->ctrl.mcc_wait[tag], | 
 | 553 | 					 phba->ctrl.mcc_numtag[tag]); | 
 | 554 | 	} | 
 | 555 | 	wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | 
 | 556 | 	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | 
 | 557 | 	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | 
 | 558 | 	if (status || extd_status) { | 
 | 559 | 		SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed" | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 560 | 				    " status = %d extd_status = %d\n", | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 561 | 				    status, extd_status); | 
| Jayamohan Kallickal | 3cbb7a7 | 2010-07-22 04:27:47 +0530 | [diff] [blame] | 562 | 		beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 563 | 		free_mcc_tag(&phba->ctrl, tag); | 
| Jayamohan Kallickal | 3cbb7a7 | 2010-07-22 04:27:47 +0530 | [diff] [blame] | 564 | 		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | 
 | 565 | 			    nonemb_cmd.va, nonemb_cmd.dma); | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 566 | 		goto free_ep; | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 567 | 	} else { | 
 | 568 | 		wrb = queue_get_wrb(mccq, wrb_num); | 
 | 569 | 		free_mcc_tag(&phba->ctrl, tag); | 
 | 570 |  | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 571 | 		ptcpcnct_out = embedded_payload(wrb); | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 572 | 		beiscsi_ep = ep->dd_data; | 
 | 573 | 		beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle; | 
 | 574 | 		beiscsi_ep->cid_vld = 1; | 
 | 575 | 		SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n"); | 
 | 576 | 	} | 
| Jayamohan Kallickal | 3cbb7a7 | 2010-07-22 04:27:47 +0530 | [diff] [blame] | 577 | 	beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | 
 | 578 | 	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | 
 | 579 | 			    nonemb_cmd.va, nonemb_cmd.dma); | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 580 | 	return 0; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 581 |  | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 582 | free_ep: | 
 | 583 | 	beiscsi_free_ep(beiscsi_ep); | 
| Jayamohan Kallickal | d3ad2bb | 2010-07-22 04:16:38 +0530 | [diff] [blame] | 584 | 	return -EBUSY; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 585 | } | 
 | 586 |  | 
 | 587 | /** | 
 | 588 |  * beiscsi_ep_connect - Ask chip to create TCP Conn | 
 | 589 |  * @scsi_host: Pointer to scsi_host structure | 
 | 590 |  * @dst_addr: The IP address of Target | 
 | 591 |  * @non_blocking: blocking or non-blocking call | 
 | 592 |  * | 
 | 593 |  * This routines first asks chip to create a connection and then allocates an EP | 
 | 594 |  */ | 
 | 595 | struct iscsi_endpoint * | 
 | 596 | beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, | 
 | 597 | 		   int non_blocking) | 
 | 598 | { | 
 | 599 | 	struct beiscsi_hba *phba; | 
 | 600 | 	struct beiscsi_endpoint *beiscsi_ep; | 
 | 601 | 	struct iscsi_endpoint *ep; | 
 | 602 | 	int ret; | 
 | 603 |  | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 604 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_connect\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 605 | 	if (shost) | 
 | 606 | 		phba = iscsi_host_priv(shost); | 
 | 607 | 	else { | 
 | 608 | 		ret = -ENXIO; | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 609 | 		SE_DEBUG(DBG_LVL_1, "shost is NULL\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 610 | 		return ERR_PTR(ret); | 
 | 611 | 	} | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 612 |  | 
| Jayamohan Kallickal | 5dc1c41 | 2010-01-23 05:36:52 +0530 | [diff] [blame] | 613 | 	if (phba->state != BE_ADAPTER_UP) { | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 614 | 		ret = -EBUSY; | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 615 | 		SE_DEBUG(DBG_LVL_1, "The Adapter state is Not UP\n"); | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 616 | 		return ERR_PTR(ret); | 
 | 617 | 	} | 
 | 618 |  | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 619 | 	ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint)); | 
 | 620 | 	if (!ep) { | 
 | 621 | 		ret = -ENOMEM; | 
 | 622 | 		return ERR_PTR(ret); | 
 | 623 | 	} | 
 | 624 |  | 
 | 625 | 	beiscsi_ep = ep->dd_data; | 
 | 626 | 	beiscsi_ep->phba = phba; | 
| Jayamohan Kallickal | c246228 | 2010-01-05 05:05:34 +0530 | [diff] [blame] | 627 | 	beiscsi_ep->openiscsi_ep = ep; | 
| Jayamohan Kallickal | f5ed7bd | 2010-07-22 04:18:01 +0530 | [diff] [blame] | 628 | 	ret = beiscsi_open_conn(ep, NULL, dst_addr, non_blocking); | 
 | 629 | 	if (ret) { | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 630 | 		SE_DEBUG(DBG_LVL_1, "Failed in beiscsi_open_conn\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 631 | 		goto free_ep; | 
 | 632 | 	} | 
 | 633 |  | 
 | 634 | 	return ep; | 
 | 635 |  | 
 | 636 | free_ep: | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 637 | 	iscsi_destroy_endpoint(ep); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 638 | 	return ERR_PTR(ret); | 
 | 639 | } | 
 | 640 |  | 
 | 641 | /** | 
 | 642 |  * beiscsi_ep_poll - Poll to see if connection is established | 
 | 643 |  * @ep:	endpoint to be used | 
 | 644 |  * @timeout_ms: timeout specified in millisecs | 
 | 645 |  * | 
 | 646 |  * Poll to see if TCP connection established | 
 | 647 |  */ | 
 | 648 | int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) | 
 | 649 | { | 
 | 650 | 	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | 
 | 651 |  | 
 | 652 | 	SE_DEBUG(DBG_LVL_8, "In  beiscsi_ep_poll\n"); | 
 | 653 | 	if (beiscsi_ep->cid_vld == 1) | 
 | 654 | 		return 1; | 
 | 655 | 	else | 
 | 656 | 		return 0; | 
 | 657 | } | 
 | 658 |  | 
 | 659 | /** | 
 | 660 |  * beiscsi_close_conn - Upload the  connection | 
 | 661 |  * @ep: The iscsi endpoint | 
 | 662 |  * @flag: The type of connection closure | 
 | 663 |  */ | 
| Jayamohan Kallickal | c246228 | 2010-01-05 05:05:34 +0530 | [diff] [blame] | 664 | static int beiscsi_close_conn(struct  beiscsi_endpoint *beiscsi_ep, int flag) | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 665 | { | 
 | 666 | 	int ret = 0; | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 667 | 	unsigned int tag; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 668 | 	struct beiscsi_hba *phba = beiscsi_ep->phba; | 
 | 669 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 670 | 	tag = mgmt_upload_connection(phba, beiscsi_ep->ep_cid, flag); | 
 | 671 | 	if (!tag) { | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 672 | 		SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x\n", | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 673 | 			 beiscsi_ep->ep_cid); | 
| Jayamohan Kallickal | d3ad2bb | 2010-07-22 04:16:38 +0530 | [diff] [blame] | 674 | 		ret = -EAGAIN; | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 675 | 	} else { | 
 | 676 | 		wait_event_interruptible(phba->ctrl.mcc_wait[tag], | 
 | 677 | 					 phba->ctrl.mcc_numtag[tag]); | 
 | 678 | 		free_mcc_tag(&phba->ctrl, tag); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 679 | 	} | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 680 | 	return ret; | 
 | 681 | } | 
 | 682 |  | 
 | 683 | /** | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 684 |  * beiscsi_unbind_conn_to_cid - Unbind the beiscsi_conn from phba conn table | 
 | 685 |  * @phba: The phba instance | 
 | 686 |  * @cid: The cid to free | 
 | 687 |  */ | 
 | 688 | static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba, | 
 | 689 | 				      unsigned int cid) | 
 | 690 | { | 
 | 691 | 	if (phba->conn_table[cid]) | 
 | 692 | 		phba->conn_table[cid] = NULL; | 
 | 693 | 	else { | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 694 | 		SE_DEBUG(DBG_LVL_8, "Connection table Not occupied.\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 695 | 		return -EINVAL; | 
 | 696 | 	} | 
 | 697 | 	return 0; | 
 | 698 | } | 
 | 699 |  | 
 | 700 | /** | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 701 |  * beiscsi_ep_disconnect - Tears down the TCP connection | 
 | 702 |  * @ep:	endpoint to be used | 
 | 703 |  * | 
 | 704 |  * Tears down the TCP connection | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 705 |  */ | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 706 | void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 707 | { | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 708 | 	struct beiscsi_conn *beiscsi_conn; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 709 | 	struct beiscsi_endpoint *beiscsi_ep; | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 710 | 	struct beiscsi_hba *phba; | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 711 | 	unsigned int tag; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 712 | 	unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; | 
 | 713 |  | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 714 | 	beiscsi_ep = ep->dd_data; | 
 | 715 | 	phba = beiscsi_ep->phba; | 
 | 716 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect for ep_cid = %d\n", | 
 | 717 | 			     beiscsi_ep->ep_cid); | 
 | 718 |  | 
 | 719 | 	if (!beiscsi_ep->conn) { | 
 | 720 | 		SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect, no " | 
 | 721 | 			 "beiscsi_ep\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 722 | 		return; | 
 | 723 | 	} | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 724 | 	beiscsi_conn = beiscsi_ep->conn; | 
 | 725 | 	iscsi_suspend_queue(beiscsi_conn->conn); | 
 | 726 |  | 
 | 727 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect ep_cid = %d\n", | 
 | 728 | 		 beiscsi_ep->ep_cid); | 
 | 729 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 730 | 	tag = mgmt_invalidate_connection(phba, beiscsi_ep, | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 731 | 					    beiscsi_ep->ep_cid, 1, | 
 | 732 | 					    savecfg_flag); | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 733 | 	if (!tag) { | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 734 | 		SE_DEBUG(DBG_LVL_1, | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 735 | 			 "mgmt_invalidate_connection Failed for cid=%d\n", | 
| Jayamohan Kallickal | 90a289e | 2010-02-20 08:04:28 +0530 | [diff] [blame] | 736 | 			  beiscsi_ep->ep_cid); | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 737 | 	} else { | 
 | 738 | 		wait_event_interruptible(phba->ctrl.mcc_wait[tag], | 
 | 739 | 					 phba->ctrl.mcc_numtag[tag]); | 
 | 740 | 		free_mcc_tag(&phba->ctrl, tag); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 741 | 	} | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 742 |  | 
| Jayamohan Kallickal | c246228 | 2010-01-05 05:05:34 +0530 | [diff] [blame] | 743 | 	beiscsi_close_conn(beiscsi_ep, CONNECTION_UPLOAD_GRACEFUL); | 
 | 744 | 	beiscsi_free_ep(beiscsi_ep); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 745 | 	beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); | 
| Mike Christie | fa95d20 | 2010-06-09 03:30:08 -0500 | [diff] [blame] | 746 | 	iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 747 | } |