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_setup_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 target_sess_cmd_list_set_waiting(sess->se_sess); 291 target_wait_for_sess_cmds(sess->se_sess); 292 ft_sess_put(sess); 293 } 294 295 /* 296 * Delete all sessions from tport. 297 * Caller holds ft_lport_lock. 298 */ 299 static void ft_sess_delete_all(struct ft_tport *tport) 300 { 301 struct hlist_head *head; 302 struct ft_sess *sess; 303 304 for (head = tport->hash; 305 head < &tport->hash[FT_SESS_HASH_SIZE]; head++) { 306 hlist_for_each_entry_rcu(sess, head, hash) { 307 ft_sess_unhash(sess); 308 ft_close_sess(sess); /* release from table */ 309 } 310 } 311 } 312 313 /* 314 * TCM ops for sessions. 315 */ 316 317 /* 318 * Remove session and send PRLO. 319 * This is called when the ACL is being deleted or queue depth is changing. 320 */ 321 void ft_sess_close(struct se_session *se_sess) 322 { 323 struct ft_sess *sess = se_sess->fabric_sess_ptr; 324 u32 port_id; 325 326 mutex_lock(&ft_lport_lock); 327 port_id = sess->port_id; 328 if (port_id == -1) { 329 mutex_unlock(&ft_lport_lock); 330 return; 331 } 332 TFC_SESS_DBG(sess->tport->lport, "port_id %x close session\n", port_id); 333 ft_sess_unhash(sess); 334 mutex_unlock(&ft_lport_lock); 335 ft_close_sess(sess); 336 /* XXX Send LOGO or PRLO */ 337 synchronize_rcu(); /* let transport deregister happen */ 338 } 339 340 u32 ft_sess_get_index(struct se_session *se_sess) 341 { 342 struct ft_sess *sess = se_sess->fabric_sess_ptr; 343 344 return sess->port_id; /* XXX TBD probably not what is needed */ 345 } 346 347 u32 ft_sess_get_port_name(struct se_session *se_sess, 348 unsigned char *buf, u32 len) 349 { 350 struct ft_sess *sess = se_sess->fabric_sess_ptr; 351 352 return ft_format_wwn(buf, len, sess->port_name); 353 } 354 355 /* 356 * libfc ops involving sessions. 357 */ 358 359 static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, 360 const struct fc_els_spp *rspp, struct fc_els_spp *spp) 361 { 362 struct ft_tport *tport; 363 struct ft_sess *sess; 364 u32 fcp_parm; 365 366 tport = ft_tport_get(rdata->local_port); 367 if (!tport) 368 goto not_target; /* not a target for this local port */ 369 370 if (!rspp) 371 goto fill; 372 373 if (rspp->spp_flags & (FC_SPP_OPA_VAL | FC_SPP_RPA_VAL)) 374 return FC_SPP_RESP_NO_PA; 375 376 /* 377 * If both target and initiator bits are off, the SPP is invalid. 378 */ 379 fcp_parm = ntohl(rspp->spp_params); 380 if (!(fcp_parm & (FCP_SPPF_INIT_FCN | FCP_SPPF_TARG_FCN))) 381 return FC_SPP_RESP_INVL; 382 383 /* 384 * Create session (image pair) only if requested by 385 * EST_IMG_PAIR flag and if the requestor is an initiator. 386 */ 387 if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR) { 388 spp->spp_flags |= FC_SPP_EST_IMG_PAIR; 389 if (!(fcp_parm & FCP_SPPF_INIT_FCN)) 390 return FC_SPP_RESP_CONF; 391 sess = ft_sess_create(tport, rdata->ids.port_id, rdata); 392 if (IS_ERR(sess)) { 393 if (PTR_ERR(sess) == -EACCES) { 394 spp->spp_flags &= ~FC_SPP_EST_IMG_PAIR; 395 return FC_SPP_RESP_CONF; 396 } else 397 return FC_SPP_RESP_RES; 398 } 399 if (!sess->params) 400 rdata->prli_count++; 401 sess->params = fcp_parm; 402 sess->port_name = rdata->ids.port_name; 403 sess->max_frame = rdata->maxframe_size; 404 405 /* XXX TBD - clearing actions. unit attn, see 4.10 */ 406 } 407 408 /* 409 * OR in our service parameters with other provider (initiator), if any. 410 */ 411 fill: 412 fcp_parm = ntohl(spp->spp_params); 413 fcp_parm &= ~FCP_SPPF_RETRY; 414 spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); 415 return FC_SPP_RESP_ACK; 416 417 not_target: 418 fcp_parm = ntohl(spp->spp_params); 419 fcp_parm &= ~FCP_SPPF_TARG_FCN; 420 spp->spp_params = htonl(fcp_parm); 421 return 0; 422 } 423 424 /** 425 * tcm_fcp_prli() - Handle incoming or outgoing PRLI for the FCP target 426 * @rdata: remote port private 427 * @spp_len: service parameter page length 428 * @rspp: received service parameter page (NULL for outgoing PRLI) 429 * @spp: response service parameter page 430 * 431 * Returns spp response code. 432 */ 433 static int ft_prli(struct fc_rport_priv *rdata, u32 spp_len, 434 const struct fc_els_spp *rspp, struct fc_els_spp *spp) 435 { 436 int ret; 437 438 mutex_lock(&ft_lport_lock); 439 ret = ft_prli_locked(rdata, spp_len, rspp, spp); 440 mutex_unlock(&ft_lport_lock); 441 TFC_SESS_DBG(rdata->local_port, "port_id %x flags %x ret %x\n", 442 rdata->ids.port_id, rspp ? rspp->spp_flags : 0, ret); 443 return ret; 444 } 445 446 static void ft_sess_free(struct kref *kref) 447 { 448 struct ft_sess *sess = container_of(kref, struct ft_sess, kref); 449 450 target_remove_session(sess->se_sess); 451 kfree_rcu(sess, rcu); 452 } 453 454 void ft_sess_put(struct ft_sess *sess) 455 { 456 int sess_held = kref_read(&sess->kref); 457 458 BUG_ON(!sess_held); 459 kref_put(&sess->kref, ft_sess_free); 460 } 461 462 static void ft_prlo(struct fc_rport_priv *rdata) 463 { 464 struct ft_sess *sess; 465 struct ft_tport *tport; 466 467 mutex_lock(&ft_lport_lock); 468 tport = rcu_dereference_protected(rdata->local_port->prov[FC_TYPE_FCP], 469 lockdep_is_held(&ft_lport_lock)); 470 471 if (!tport) { 472 mutex_unlock(&ft_lport_lock); 473 return; 474 } 475 sess = ft_sess_delete(tport, rdata->ids.port_id); 476 if (!sess) { 477 mutex_unlock(&ft_lport_lock); 478 return; 479 } 480 mutex_unlock(&ft_lport_lock); 481 ft_close_sess(sess); /* release from table */ 482 rdata->prli_count--; 483 /* XXX TBD - clearing actions. unit attn, see 4.10 */ 484 } 485 486 /* 487 * Handle incoming FCP request. 488 * Caller has verified that the frame is type FCP. 489 */ 490 static void ft_recv(struct fc_lport *lport, struct fc_frame *fp) 491 { 492 struct ft_sess *sess; 493 u32 sid = fc_frame_sid(fp); 494 495 TFC_SESS_DBG(lport, "recv sid %x\n", sid); 496 497 sess = ft_sess_get(lport, sid); 498 if (!sess) { 499 TFC_SESS_DBG(lport, "sid %x sess lookup failed\n", sid); 500 /* TBD XXX - if FCP_CMND, send PRLO */ 501 fc_frame_free(fp); 502 return; 503 } 504 ft_recv_req(sess, fp); /* must do ft_sess_put() */ 505 } 506 507 /* 508 * Provider ops for libfc. 509 */ 510 struct fc4_prov ft_prov = { 511 .prli = ft_prli, 512 .prlo = ft_prlo, 513 .recv = ft_recv, 514 .module = THIS_MODULE, 515 }; 516