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 <generated/utsrelease.h> 23 #include <linux/utsname.h> 24 #include <linux/init.h> 25 #include <linux/slab.h> 26 #include <linux/kthread.h> 27 #include <linux/types.h> 28 #include <linux/string.h> 29 #include <linux/configfs.h> 30 #include <linux/ctype.h> 31 #include <linux/hash.h> 32 #include <linux/rcupdate.h> 33 #include <linux/rculist.h> 34 #include <linux/kref.h> 35 #include <asm/unaligned.h> 36 #include <scsi/scsi.h> 37 #include <scsi/scsi_host.h> 38 #include <scsi/scsi_device.h> 39 #include <scsi/scsi_cmnd.h> 40 #include <scsi/libfc.h> 41 42 #include <target/target_core_base.h> 43 #include <target/target_core_transport.h> 44 #include <target/target_core_fabric_ops.h> 45 #include <target/target_core_device.h> 46 #include <target/target_core_tpg.h> 47 #include <target/target_core_configfs.h> 48 #include <target/configfs_macros.h> 49 50 #include "tcm_fc.h" 51 52 static void ft_sess_delete_all(struct ft_tport *); 53 54 /* 55 * Lookup or allocate target local port. 56 * Caller holds ft_lport_lock. 57 */ 58 static struct ft_tport *ft_tport_create(struct fc_lport *lport) 59 { 60 struct ft_tpg *tpg; 61 struct ft_tport *tport; 62 int i; 63 64 tport = rcu_dereference(lport->prov[FC_TYPE_FCP]); 65 if (tport && tport->tpg) 66 return tport; 67 68 tpg = ft_lport_find_tpg(lport); 69 if (!tpg) 70 return NULL; 71 72 if (tport) { 73 tport->tpg = tpg; 74 return tport; 75 } 76 77 tport = kzalloc(sizeof(*tport), GFP_KERNEL); 78 if (!tport) 79 return NULL; 80 81 tport->lport = lport; 82 tport->tpg = tpg; 83 tpg->tport = tport; 84 for (i = 0; i < FT_SESS_HASH_SIZE; i++) 85 INIT_HLIST_HEAD(&tport->hash[i]); 86 87 rcu_assign_pointer(lport->prov[FC_TYPE_FCP], tport); 88 return tport; 89 } 90 91 /* 92 * Free tport via RCU. 93 */ 94 static void ft_tport_rcu_free(struct rcu_head *rcu) 95 { 96 struct ft_tport *tport = container_of(rcu, struct ft_tport, rcu); 97 98 kfree(tport); 99 } 100 101 /* 102 * Delete a target local port. 103 * Caller holds ft_lport_lock. 104 */ 105 static void ft_tport_delete(struct ft_tport *tport) 106 { 107 struct fc_lport *lport; 108 struct ft_tpg *tpg; 109 110 ft_sess_delete_all(tport); 111 lport = tport->lport; 112 BUG_ON(tport != lport->prov[FC_TYPE_FCP]); 113 rcu_assign_pointer(lport->prov[FC_TYPE_FCP], NULL); 114 115 tpg = tport->tpg; 116 if (tpg) { 117 tpg->tport = NULL; 118 tport->tpg = NULL; 119 } 120 call_rcu(&tport->rcu, ft_tport_rcu_free); 121 } 122 123 /* 124 * Add local port. 125 * Called thru fc_lport_iterate(). 126 */ 127 void ft_lport_add(struct fc_lport *lport, void *arg) 128 { 129 mutex_lock(&ft_lport_lock); 130 ft_tport_create(lport); 131 mutex_unlock(&ft_lport_lock); 132 } 133 134 /* 135 * Delete local port. 136 * Called thru fc_lport_iterate(). 137 */ 138 void ft_lport_del(struct fc_lport *lport, void *arg) 139 { 140 struct ft_tport *tport; 141 142 mutex_lock(&ft_lport_lock); 143 tport = lport->prov[FC_TYPE_FCP]; 144 if (tport) 145 ft_tport_delete(tport); 146 mutex_unlock(&ft_lport_lock); 147 } 148 149 /* 150 * Notification of local port change from libfc. 151 * Create or delete local port and associated tport. 152 */ 153 int ft_lport_notify(struct notifier_block *nb, unsigned long event, void *arg) 154 { 155 struct fc_lport *lport = arg; 156 157 switch (event) { 158 case FC_LPORT_EV_ADD: 159 ft_lport_add(lport, NULL); 160 break; 161 case FC_LPORT_EV_DEL: 162 ft_lport_del(lport, NULL); 163 break; 164 } 165 return NOTIFY_DONE; 166 } 167 168 /* 169 * Hash function for FC_IDs. 170 */ 171 static u32 ft_sess_hash(u32 port_id) 172 { 173 return hash_32(port_id, FT_SESS_HASH_BITS); 174 } 175 176 /* 177 * Find session in local port. 178 * Sessions and hash lists are RCU-protected. 179 * A reference is taken which must be eventually freed. 180 */ 181 static struct ft_sess *ft_sess_get(struct fc_lport *lport, u32 port_id) 182 { 183 struct ft_tport *tport; 184 struct hlist_head *head; 185 struct hlist_node *pos; 186 struct ft_sess *sess; 187 188 rcu_read_lock(); 189 tport = rcu_dereference(lport->prov[FC_TYPE_FCP]); 190 if (!tport) 191 goto out; 192 193 head = &tport->hash[ft_sess_hash(port_id)]; 194 hlist_for_each_entry_rcu(sess, pos, head, hash) { 195 if (sess->port_id == port_id) { 196 kref_get(&sess->kref); 197 rcu_read_unlock(); 198 pr_debug("port_id %x found %p\n", port_id, sess); 199 return sess; 200 } 201 } 202 out: 203 rcu_read_unlock(); 204 pr_debug("port_id %x not found\n", port_id); 205 return NULL; 206 } 207 208 /* 209 * Allocate session and enter it in the hash for the local port. 210 * Caller holds ft_lport_lock. 211 */ 212 static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id, 213 struct ft_node_acl *acl) 214 { 215 struct ft_sess *sess; 216 struct hlist_head *head; 217 struct hlist_node *pos; 218 219 head = &tport->hash[ft_sess_hash(port_id)]; 220 hlist_for_each_entry_rcu(sess, pos, head, hash) 221 if (sess->port_id == port_id) 222 return sess; 223 224 sess = kzalloc(sizeof(*sess), GFP_KERNEL); 225 if (!sess) 226 return NULL; 227 228 sess->se_sess = transport_init_session(); 229 if (IS_ERR(sess->se_sess)) { 230 kfree(sess); 231 return NULL; 232 } 233 sess->se_sess->se_node_acl = &acl->se_node_acl; 234 sess->tport = tport; 235 sess->port_id = port_id; 236 kref_init(&sess->kref); /* ref for table entry */ 237 hlist_add_head_rcu(&sess->hash, head); 238 tport->sess_count++; 239 240 pr_debug("port_id %x sess %p\n", port_id, sess); 241 242 transport_register_session(&tport->tpg->se_tpg, &acl->se_node_acl, 243 sess->se_sess, sess); 244 return sess; 245 } 246 247 /* 248 * Unhash the session. 249 * Caller holds ft_lport_lock. 250 */ 251 static void ft_sess_unhash(struct ft_sess *sess) 252 { 253 struct ft_tport *tport = sess->tport; 254 255 hlist_del_rcu(&sess->hash); 256 BUG_ON(!tport->sess_count); 257 tport->sess_count--; 258 sess->port_id = -1; 259 sess->params = 0; 260 } 261 262 /* 263 * Delete session from hash. 264 * Caller holds ft_lport_lock. 265 */ 266 static struct ft_sess *ft_sess_delete(struct ft_tport *tport, u32 port_id) 267 { 268 struct hlist_head *head; 269 struct hlist_node *pos; 270 struct ft_sess *sess; 271 272 head = &tport->hash[ft_sess_hash(port_id)]; 273 hlist_for_each_entry_rcu(sess, pos, head, hash) { 274 if (sess->port_id == port_id) { 275 ft_sess_unhash(sess); 276 return sess; 277 } 278 } 279 return NULL; 280 } 281 282 /* 283 * Delete all sessions from tport. 284 * Caller holds ft_lport_lock. 285 */ 286 static void ft_sess_delete_all(struct ft_tport *tport) 287 { 288 struct hlist_head *head; 289 struct hlist_node *pos; 290 struct ft_sess *sess; 291 292 for (head = tport->hash; 293 head < &tport->hash[FT_SESS_HASH_SIZE]; head++) { 294 hlist_for_each_entry_rcu(sess, pos, head, hash) { 295 ft_sess_unhash(sess); 296 transport_deregister_session_configfs(sess->se_sess); 297 ft_sess_put(sess); /* release from table */ 298 } 299 } 300 } 301 302 /* 303 * TCM ops for sessions. 304 */ 305 306 /* 307 * Determine whether session is allowed to be shutdown in the current context. 308 * Returns non-zero if the session should be shutdown. 309 */ 310 int ft_sess_shutdown(struct se_session *se_sess) 311 { 312 struct ft_sess *sess = se_sess->fabric_sess_ptr; 313 314 pr_debug("port_id %x\n", sess->port_id); 315 return 1; 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 struct fc_lport *lport; 326 u32 port_id; 327 328 mutex_lock(&ft_lport_lock); 329 lport = sess->tport->lport; 330 port_id = sess->port_id; 331 if (port_id == -1) { 332 mutex_unlock(&ft_lport_lock); 333 return; 334 } 335 pr_debug("port_id %x\n", port_id); 336 ft_sess_unhash(sess); 337 mutex_unlock(&ft_lport_lock); 338 transport_deregister_session_configfs(se_sess); 339 ft_sess_put(sess); 340 /* XXX Send LOGO or PRLO */ 341 synchronize_rcu(); /* let transport deregister happen */ 342 } 343 344 void ft_sess_stop(struct se_session *se_sess, int sess_sleep, int conn_sleep) 345 { 346 struct ft_sess *sess = se_sess->fabric_sess_ptr; 347 348 pr_debug("port_id %x\n", sess->port_id); 349 } 350 351 int ft_sess_logged_in(struct se_session *se_sess) 352 { 353 struct ft_sess *sess = se_sess->fabric_sess_ptr; 354 355 return sess->port_id != -1; 356 } 357 358 u32 ft_sess_get_index(struct se_session *se_sess) 359 { 360 struct ft_sess *sess = se_sess->fabric_sess_ptr; 361 362 return sess->port_id; /* XXX TBD probably not what is needed */ 363 } 364 365 u32 ft_sess_get_port_name(struct se_session *se_sess, 366 unsigned char *buf, u32 len) 367 { 368 struct ft_sess *sess = se_sess->fabric_sess_ptr; 369 370 return ft_format_wwn(buf, len, sess->port_name); 371 } 372 373 void ft_sess_set_erl0(struct se_session *se_sess) 374 { 375 /* XXX TBD called when out of memory */ 376 } 377 378 /* 379 * libfc ops involving sessions. 380 */ 381 382 static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, 383 const struct fc_els_spp *rspp, struct fc_els_spp *spp) 384 { 385 struct ft_tport *tport; 386 struct ft_sess *sess; 387 struct ft_node_acl *acl; 388 u32 fcp_parm; 389 390 tport = ft_tport_create(rdata->local_port); 391 if (!tport) 392 return 0; /* not a target for this local port */ 393 394 acl = ft_acl_get(tport->tpg, rdata); 395 if (!acl) 396 return 0; 397 398 if (!rspp) 399 goto fill; 400 401 if (rspp->spp_flags & (FC_SPP_OPA_VAL | FC_SPP_RPA_VAL)) 402 return FC_SPP_RESP_NO_PA; 403 404 /* 405 * If both target and initiator bits are off, the SPP is invalid. 406 */ 407 fcp_parm = ntohl(rspp->spp_params); 408 if (!(fcp_parm & (FCP_SPPF_INIT_FCN | FCP_SPPF_TARG_FCN))) 409 return FC_SPP_RESP_INVL; 410 411 /* 412 * Create session (image pair) only if requested by 413 * EST_IMG_PAIR flag and if the requestor is an initiator. 414 */ 415 if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR) { 416 spp->spp_flags |= FC_SPP_EST_IMG_PAIR; 417 if (!(fcp_parm & FCP_SPPF_INIT_FCN)) 418 return FC_SPP_RESP_CONF; 419 sess = ft_sess_create(tport, rdata->ids.port_id, acl); 420 if (!sess) 421 return FC_SPP_RESP_RES; 422 if (!sess->params) 423 rdata->prli_count++; 424 sess->params = fcp_parm; 425 sess->port_name = rdata->ids.port_name; 426 sess->max_frame = rdata->maxframe_size; 427 428 /* XXX TBD - clearing actions. unit attn, see 4.10 */ 429 } 430 431 /* 432 * OR in our service parameters with other provider (initiator), if any. 433 * TBD XXX - indicate RETRY capability? 434 */ 435 fill: 436 fcp_parm = ntohl(spp->spp_params); 437 spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); 438 return FC_SPP_RESP_ACK; 439 } 440 441 /** 442 * tcm_fcp_prli() - Handle incoming or outgoing PRLI for the FCP target 443 * @rdata: remote port private 444 * @spp_len: service parameter page length 445 * @rspp: received service parameter page (NULL for outgoing PRLI) 446 * @spp: response service parameter page 447 * 448 * Returns spp response code. 449 */ 450 static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len, 451 const struct fc_els_spp *rspp, struct fc_els_spp *spp) 452 { 453 int ret; 454 455 mutex_lock(&ft_lport_lock); 456 ret = ft_prli_locked(rdata, spp_len, rspp, spp); 457 mutex_unlock(&ft_lport_lock); 458 pr_debug("port_id %x flags %x ret %x\n", 459 rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret); 460 return ret; 461 } 462 463 static void ft_sess_rcu_free(struct rcu_head *rcu) 464 { 465 struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu); 466 467 transport_deregister_session(sess->se_sess); 468 kfree(sess); 469 } 470 471 static void ft_sess_free(struct kref *kref) 472 { 473 struct ft_sess *sess = container_of(kref, struct ft_sess, kref); 474 475 call_rcu(&sess->rcu, ft_sess_rcu_free); 476 } 477 478 void ft_sess_put(struct ft_sess *sess) 479 { 480 int sess_held = atomic_read(&sess->kref.refcount); 481 482 BUG_ON(!sess_held); 483 kref_put(&sess->kref, ft_sess_free); 484 } 485 486 static void ft_prlo(struct fc_rport_priv *rdata) 487 { 488 struct ft_sess *sess; 489 struct ft_tport *tport; 490 491 mutex_lock(&ft_lport_lock); 492 tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]); 493 if (!tport) { 494 mutex_unlock(&ft_lport_lock); 495 return; 496 } 497 sess = ft_sess_delete(tport, rdata->ids.port_id); 498 if (!sess) { 499 mutex_unlock(&ft_lport_lock); 500 return; 501 } 502 mutex_unlock(&ft_lport_lock); 503 transport_deregister_session_configfs(sess->se_sess); 504 ft_sess_put(sess); /* release from table */ 505 rdata->prli_count--; 506 /* XXX TBD - clearing actions. unit attn, see 4.10 */ 507 } 508 509 /* 510 * Handle incoming FCP request. 511 * Caller has verified that the frame is type FCP. 512 */ 513 static void ft_recv(struct fc_lport *lport, struct fc_frame *fp) 514 { 515 struct ft_sess *sess; 516 u32 sid = fc_frame_sid(fp); 517 518 pr_debug("sid %x\n", sid); 519 520 sess = ft_sess_get(lport, sid); 521 if (!sess) { 522 pr_debug("sid %x sess lookup failed\n", sid); 523 /* TBD XXX - if FCP_CMND, send PRLO */ 524 fc_frame_free(fp); 525 return; 526 } 527 ft_recv_req(sess, fp); /* must do ft_sess_put() */ 528 } 529 530 /* 531 * Provider ops for libfc. 532 */ 533 struct fc4_prov ft_prov = { 534 .prli = ft_prli, 535 .prlo = ft_prlo, 536 .recv = ft_recv, 537 .module = THIS_MODULE, 538 }; 539