1 /* 2 * Copyright (c) 2010 Cisco Systems, Inc. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License along with 14 * this program; if not, write to the Free Software Foundation, Inc., 15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 */ 17 18 /* XXX TBD some includes may be extraneous */ 19 20 #include <linux/module.h> 21 #include <linux/moduleparam.h> 22 #include <linux/utsname.h> 23 #include <linux/init.h> 24 #include <linux/slab.h> 25 #include <linux/kthread.h> 26 #include <linux/types.h> 27 #include <linux/string.h> 28 #include <linux/configfs.h> 29 #include <linux/ctype.h> 30 #include <linux/hash.h> 31 #include <linux/rcupdate.h> 32 #include <linux/rculist.h> 33 #include <linux/kref.h> 34 #include <asm/unaligned.h> 35 #include <scsi/libfc.h> 36 37 #include <target/target_core_base.h> 38 #include <target/target_core_fabric.h> 39 40 #include "tcm_fc.h" 41 42 #define TFC_SESS_DBG(lport, fmt, args...) \ 43 pr_debug("host%u: rport %6.6x: " fmt, \ 44 (lport)->host->host_no, \ 45 (lport)->port_id, ##args ) 46 47 static void ft_sess_delete_all(struct ft_tport *); 48 49 /* 50 * Lookup or allocate target local port. 51 * Caller holds ft_lport_lock. 52 */ 53 static struct ft_tport *ft_tport_get(struct fc_lport *lport) 54 { 55 struct ft_tpg *tpg; 56 struct ft_tport *tport; 57 int i; 58 59 tport = rcu_dereference_protected(lport->prov[FC_TYPE_FCP], 60 lockdep_is_held(&ft_lport_lock)); 61 if (tport && tport->tpg) 62 return tport; 63 64 tpg = ft_lport_find_tpg(lport); 65 if (!tpg) 66 return NULL; 67 68 if (tport) { 69 tport->tpg = tpg; 70 tpg->tport = tport; 71 return tport; 72 } 73 74 tport = kzalloc(sizeof(*tport), GFP_KERNEL); 75 if (!tport) 76 return NULL; 77 78 tport->lport = lport; 79 tport->tpg = tpg; 80 tpg->tport = tport; 81 for (i = 0; i < FT_SESS_HASH_SIZE; i++) 82 INIT_HLIST_HEAD(&tport->hash[i]); 83 84 rcu_assign_pointer(lport->prov[FC_TYPE_FCP], tport); 85 return tport; 86 } 87 88 /* 89 * Delete a target local port. 90 * Caller holds ft_lport_lock. 91 */ 92 static void ft_tport_delete(struct ft_tport *tport) 93 { 94 struct fc_lport *lport; 95 struct ft_tpg *tpg; 96 97 ft_sess_delete_all(tport); 98 lport = tport->lport; 99 lport->service_params &= ~FCP_SPPF_TARG_FCN; 100 BUG_ON(tport != lport->prov[FC_TYPE_FCP]); 101 RCU_INIT_POINTER(lport->prov[FC_TYPE_FCP], NULL); 102 103 tpg = tport->tpg; 104 if (tpg) { 105 tpg->tport = NULL; 106 tport->tpg = NULL; 107 } 108 kfree_rcu(tport, rcu); 109 } 110 111 /* 112 * Add local port. 113 * Called thru fc_lport_iterate(). 114 */ 115 void ft_lport_add(struct fc_lport *lport, void *arg) 116 { 117 mutex_lock(&ft_lport_lock); 118 ft_tport_get(lport); 119 lport->service_params |= FCP_SPPF_TARG_FCN; 120 mutex_unlock(&ft_lport_lock); 121 } 122 123 /* 124 * Delete local port. 125 * Called thru fc_lport_iterate(). 126 */ 127 void ft_lport_del(struct fc_lport *lport, void *arg) 128 { 129 struct ft_tport *tport; 130 131 mutex_lock(&ft_lport_lock); 132 tport = lport->prov[FC_TYPE_FCP]; 133 if (tport) 134 ft_tport_delete(tport); 135 mutex_unlock(&ft_lport_lock); 136 } 137 138 /* 139 * Notification of local port change from libfc. 140 * Create or delete local port and associated tport. 141 */ 142 int ft_lport_notify(struct notifier_block *nb, unsigned long event, void *arg) 143 { 144 struct fc_lport *lport = arg; 145 146 switch (event) { 147 case FC_LPORT_EV_ADD: 148 ft_lport_add(lport, NULL); 149 break; 150 case FC_LPORT_EV_DEL: 151 ft_lport_del(lport, NULL); 152 break; 153 } 154 return NOTIFY_DONE; 155 } 156 157 /* 158 * Hash function for FC_IDs. 159 */ 160 static u32 ft_sess_hash(u32 port_id) 161 { 162 return hash_32(port_id, FT_SESS_HASH_BITS); 163 } 164 165 /* 166 * Find session in local port. 167 * Sessions and hash lists are RCU-protected. 168 * A reference is taken which must be eventually freed. 169 */ 170 static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id) 171 { 172 struct ft_tport *tport; 173 struct hlist_head *head; 174 struct ft_sess *sess; 175 char *reason = "no session created"; 176 177 rcu_read_lock(); 178 tport = rcu_dereference(lport->prov[FC_TYPE_FCP]); 179 if (!tport) { 180 reason = "not an FCP port"; 181 goto out; 182 } 183 184 head = &tport->hash[ft_sess_hash(port_id)]; 185 hlist_for_each_entry_rcu(sess, head, hash) { 186 if (sess->port_id == port_id) { 187 kref_get(&sess->kref); 188 rcu_read_unlock(); 189 TFC_SESS_DBG(lport, "port_id %x found %p\n", 190 port_id, sess); 191 return sess; 192 } 193 } 194 out: 195 rcu_read_unlock(); 196 TFC_SESS_DBG(lport, "port_id %x not found, %s\n", 197 port_id, reason); 198 return NULL; 199 } 200 201 static int ft_sess_alloc_cb(struct se_portal_group *se_tpg, 202 struct se_session *se_sess, void *p) 203 { 204 struct ft_sess *sess = p; 205 struct ft_tport *tport = sess->tport; 206 struct hlist_head *head = &tport->hash[ft_sess_hash(sess->port_id)]; 207 208 TFC_SESS_DBG(tport->lport, "port_id %x sess %p\n", sess->port_id, sess); 209 hlist_add_head_rcu(&sess->hash, head); 210 tport->sess_count++; 211 212 return 0; 213 } 214 215 /* 216 * Allocate session and enter it in the hash for the local port. 217 * Caller holds ft_lport_lock. 218 */ 219 static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, 220 struct fc_rport_priv *rdata) 221 { 222 struct se_portal_group *se_tpg = &tport->tpg->se_tpg; 223 struct ft_sess *sess; 224 struct hlist_head *head; 225 unsigned char initiatorname[TRANSPORT_IQN_LEN]; 226 227 ft_format_wwn(&initiatorname[0], TRANSPORT_IQN_LEN, rdata->ids.port_name); 228 229 head = &tport->hash[ft_sess_hash(port_id)]; 230 hlist_for_each_entry_rcu(sess, head, hash) 231 if (sess->port_id == port_id) 232 return sess; 233 234 sess = kzalloc(sizeof(*sess), GFP_KERNEL); 235 if (!sess) 236 return ERR_PTR(-ENOMEM); 237 238 kref_init(&sess->kref); /* ref for table entry */ 239 sess->tport = tport; 240 sess->port_id = port_id; 241 242 sess->se_sess = target_alloc_session(se_tpg, TCM_FC_DEFAULT_TAGS, 243 sizeof(struct ft_cmd), 244 TARGET_PROT_NORMAL, &initiatorname[0], 245 sess, ft_sess_alloc_cb); 246 if (IS_ERR(sess->se_sess)) { 247 int rc = PTR_ERR(sess->se_sess); 248 kfree(sess); 249 sess = ERR_PTR(rc); 250 } 251 return sess; 252 } 253 254 /* 255 * Unhash the session. 256 * Caller holds ft_lport_lock. 257 */ 258 static void ft_sess_unhash(struct ft_sess *sess) 259 { 260 struct ft_tport *tport = sess->tport; 261 262 hlist_del_rcu(&sess->hash); 263 BUG_ON(!tport->sess_count); 264 tport->sess_count--; 265 sess->port_id = -1; 266 sess->params = 0; 267 } 268 269 /* 270 * Delete session from hash. 271 * Caller holds ft_lport_lock. 272 */ 273 static struct ft_sess *ft_sess_delete(struct ft_tport *tport, u32 port_id) 274 { 275 struct hlist_head *head; 276 struct ft_sess *sess; 277 278 head = &tport->hash[ft_sess_hash(port_id)]; 279 hlist_for_each_entry_rcu(sess, head, hash) { 280 if (sess->port_id == port_id) { 281 ft_sess_unhash(sess); 282 return sess; 283 } 284 } 285 return NULL; 286 } 287 288 static void ft_close_sess(struct ft_sess *sess) 289 { 290 transport_deregister_session_configfs(sess->se_sess); 291 target_sess_cmd_list_set_waiting(sess->se_sess); 292 target_wait_for_sess_cmds(sess->se_sess); 293 ft_sess_put(sess); 294 } 295 296 /* 297 * Delete all sessions from tport. 298 * Caller holds ft_lport_lock. 299 */ 300 static void ft_sess_delete_all(struct ft_tport *tport) 301 { 302 struct hlist_head *head; 303 struct ft_sess *sess; 304 305 for (head = tport->hash; 306 head < &tport->hash[FT_SESS_HASH_SIZE]; head++) { 307 hlist_for_each_entry_rcu(sess, head, hash) { 308 ft_sess_unhash(sess); 309 ft_close_sess(sess); /* release from table */ 310 } 311 } 312 } 313 314 /* 315 * TCM ops for sessions. 316 */ 317 318 /* 319 * Remove session and send PRLO. 320 * This is called when the ACL is being deleted or queue depth is changing. 321 */ 322 void ft_sess_close(struct se_session *se_sess) 323 { 324 struct ft_sess *sess = se_sess->fabric_sess_ptr; 325 u32 port_id; 326 327 mutex_lock(&ft_lport_lock); 328 port_id = sess->port_id; 329 if (port_id == -1) { 330 mutex_unlock(&ft_lport_lock); 331 return; 332 } 333 TFC_SESS_DBG(sess->tport->lport, "port_id %x close session\n", port_id); 334 ft_sess_unhash(sess); 335 mutex_unlock(&ft_lport_lock); 336 ft_close_sess(sess); 337 /* XXX Send LOGO or PRLO */ 338 synchronize_rcu(); /* let transport deregister happen */ 339 } 340 341 u32 ft_sess_get_index(struct se_session *se_sess) 342 { 343 struct ft_sess *sess = se_sess->fabric_sess_ptr; 344 345 return sess->port_id; /* XXX TBD probably not what is needed */ 346 } 347 348 u32 ft_sess_get_port_name(struct se_session *se_sess, 349 unsigned char *buf, u32 len) 350 { 351 struct ft_sess *sess = se_sess->fabric_sess_ptr; 352 353 return ft_format_wwn(buf, len, sess->port_name); 354 } 355 356 /* 357 * libfc ops involving sessions. 358 */ 359 360 static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, 361 const struct fc_els_spp *rspp, struct fc_els_spp *spp) 362 { 363 struct ft_tport *tport; 364 struct ft_sess *sess; 365 u32 fcp_parm; 366 367 tport = ft_tport_get(rdata->local_port); 368 if (!tport) 369 goto not_target; /* not a target for this local port */ 370 371 if (!rspp) 372 goto fill; 373 374 if (rspp->spp_flags & (FC_SPP_OPA_VAL | FC_SPP_RPA_VAL)) 375 return FC_SPP_RESP_NO_PA; 376 377 /* 378 * If both target and initiator bits are off, the SPP is invalid. 379 */ 380 fcp_parm = ntohl(rspp->spp_params); 381 if (!(fcp_parm & (FCP_SPPF_INIT_FCN | FCP_SPPF_TARG_FCN))) 382 return FC_SPP_RESP_INVL; 383 384 /* 385 * Create session (image pair) only if requested by 386 * EST_IMG_PAIR flag and if the requestor is an initiator. 387 */ 388 if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR) { 389 spp->spp_flags |= FC_SPP_EST_IMG_PAIR; 390 if (!(fcp_parm & FCP_SPPF_INIT_FCN)) 391 return FC_SPP_RESP_CONF; 392 sess = ft_sess_create(tport, rdata->ids.port_id, rdata); 393 if (IS_ERR(sess)) { 394 if (PTR_ERR(sess) == -EACCES) { 395 spp->spp_flags &= ~FC_SPP_EST_IMG_PAIR; 396 return FC_SPP_RESP_CONF; 397 } else 398 return FC_SPP_RESP_RES; 399 } 400 if (!sess->params) 401 rdata->prli_count++; 402 sess->params = fcp_parm; 403 sess->port_name = rdata->ids.port_name; 404 sess->max_frame = rdata->maxframe_size; 405 406 /* XXX TBD - clearing actions. unit attn, see 4.10 */ 407 } 408 409 /* 410 * OR in our service parameters with other provider (initiator), if any. 411 */ 412 fill: 413 fcp_parm = ntohl(spp->spp_params); 414 fcp_parm &= ~FCP_SPPF_RETRY; 415 spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); 416 return FC_SPP_RESP_ACK; 417 418 not_target: 419 fcp_parm = ntohl(spp->spp_params); 420 fcp_parm &= ~FCP_SPPF_TARG_FCN; 421 spp->spp_params = htonl(fcp_parm); 422 return 0; 423 } 424 425 /** 426 * tcm_fcp_prli() - Handle incoming or outgoing PRLI for the FCP target 427 * @rdata: remote port private 428 * @spp_len: service parameter page length 429 * @rspp: received service parameter page (NULL for outgoing PRLI) 430 * @spp: response service parameter page 431 * 432 * Returns spp response code. 433 */ 434 static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len, 435 const struct fc_els_spp *rspp, struct fc_els_spp *spp) 436 { 437 int ret; 438 439 mutex_lock(&ft_lport_lock); 440 ret = ft_prli_locked(rdata, spp_len, rspp, spp); 441 mutex_unlock(&ft_lport_lock); 442 TFC_SESS_DBG(rdata->local_port, "port_id %x flags %x ret %x\n", 443 rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret); 444 return ret; 445 } 446 447 static void ft_sess_free(struct kref *kref) 448 { 449 struct ft_sess *sess = container_of(kref, struct ft_sess, kref); 450 451 transport_deregister_session(sess->se_sess); 452 kfree_rcu(sess, rcu); 453 } 454 455 void ft_sess_put(struct ft_sess *sess) 456 { 457 int sess_held = kref_read(&sess->kref); 458 459 BUG_ON(!sess_held); 460 kref_put(&sess->kref, ft_sess_free); 461 } 462 463 static void ft_prlo(struct fc_rport_priv *rdata) 464 { 465 struct ft_sess *sess; 466 struct ft_tport *tport; 467 468 mutex_lock(&ft_lport_lock); 469 tport = rcu_dereference_protected(rdata->local_port->prov[FC_TYPE_FCP], 470 lockdep_is_held(&ft_lport_lock)); 471 472 if (!tport) { 473 mutex_unlock(&ft_lport_lock); 474 return; 475 } 476 sess = ft_sess_delete(tport, rdata->ids.port_id); 477 if (!sess) { 478 mutex_unlock(&ft_lport_lock); 479 return; 480 } 481 mutex_unlock(&ft_lport_lock); 482 ft_close_sess(sess); /* release from table */ 483 rdata->prli_count--; 484 /* XXX TBD - clearing actions. unit attn, see 4.10 */ 485 } 486 487 /* 488 * Handle incoming FCP request. 489 * Caller has verified that the frame is type FCP. 490 */ 491 static void ft_recv(struct fc_lport *lport, struct fc_frame *fp) 492 { 493 struct ft_sess *sess; 494 u32 sid = fc_frame_sid(fp); 495 496 TFC_SESS_DBG(lport, "recv sid %x\n", sid); 497 498 sess = ft_sess_get(lport, sid); 499 if (!sess) { 500 TFC_SESS_DBG(lport, "sid %x sess lookup failed\n", sid); 501 /* TBD XXX - if FCP_CMND, send PRLO */ 502 fc_frame_free(fp); 503 return; 504 } 505 ft_recv_req(sess, fp); /* must do ft_sess_put() */ 506 } 507 508 /* 509 * Provider ops for libfc. 510 */ 511 struct fc4_prov ft_prov = { 512 .prli = ft_prli, 513 .prlo = ft_prlo, 514 .recv = ft_recv, 515 .module = THIS_MODULE, 516 }; 517