Lines Matching +full:lock +full:- +full:status

1 // SPDX-License-Identifier: GPL-2.0-or-later
20 #include <linux/firewire-constants.h>
40 0x390104d8, /* command_set: SPC-2 */
58 ret = sbp_run_transaction(req->card, TCODE_READ_QUADLET_REQUEST, in read_peer_guid()
59 req->node_addr, req->generation, req->speed, in read_peer_guid()
65 ret = sbp_run_transaction(req->card, TCODE_READ_QUADLET_REQUEST, in read_peer_guid()
66 req->node_addr, req->generation, req->speed, in read_peer_guid()
83 spin_lock_bh(&tpg->se_tpg.session_lock); in sbp_session_find_by_guid()
84 list_for_each_entry(se_sess, &tpg->se_tpg.tpg_sess_list, sess_list) { in sbp_session_find_by_guid()
85 sess = se_sess->fabric_sess_ptr; in sbp_session_find_by_guid()
86 if (sess->guid == guid) in sbp_session_find_by_guid()
89 spin_unlock_bh(&tpg->se_tpg.session_lock); in sbp_session_find_by_guid()
99 spin_lock_bh(&session->lock); in sbp_login_find_by_lun()
100 list_for_each_entry(login, &session->login_list, link) { in sbp_login_find_by_lun()
101 if (login->login_lun == unpacked_lun) in sbp_login_find_by_lun()
104 spin_unlock_bh(&session->lock); in sbp_login_find_by_lun()
119 spin_lock_bh(&tpg->se_tpg.session_lock); in sbp_login_count_all_by_lun()
120 list_for_each_entry(se_sess, &tpg->se_tpg.tpg_sess_list, sess_list) { in sbp_login_count_all_by_lun()
121 sess = se_sess->fabric_sess_ptr; in sbp_login_count_all_by_lun()
123 spin_lock_bh(&sess->lock); in sbp_login_count_all_by_lun()
124 list_for_each_entry(login, &sess->login_list, link) { in sbp_login_count_all_by_lun()
125 if (login->login_lun != unpacked_lun) in sbp_login_count_all_by_lun()
128 if (!exclusive || login->exclusive) in sbp_login_count_all_by_lun()
131 spin_unlock_bh(&sess->lock); in sbp_login_count_all_by_lun()
133 spin_unlock_bh(&tpg->se_tpg.session_lock); in sbp_login_count_all_by_lun()
145 spin_lock_bh(&tpg->se_tpg.session_lock); in sbp_login_find_by_id()
146 list_for_each_entry(se_sess, &tpg->se_tpg.tpg_sess_list, sess_list) { in sbp_login_find_by_id()
147 sess = se_sess->fabric_sess_ptr; in sbp_login_find_by_id()
149 spin_lock_bh(&sess->lock); in sbp_login_find_by_id()
150 list_for_each_entry(login, &sess->login_list, link) { in sbp_login_find_by_id()
151 if (login->login_id == login_id) in sbp_login_find_by_id()
154 spin_unlock_bh(&sess->lock); in sbp_login_find_by_id()
156 spin_unlock_bh(&tpg->se_tpg.session_lock); in sbp_login_find_by_id()
163 struct se_portal_group *se_tpg = &tpg->se_tpg; in sbp_get_lun_from_tpg()
167 hlist_for_each_entry_rcu(se_lun, &se_tpg->tpg_lun_hlist, link) { in sbp_get_lun_from_tpg()
168 if (se_lun->unpacked_lun == login_lun) { in sbp_get_lun_from_tpg()
176 *err = -ENODEV; in sbp_get_lun_from_tpg()
192 return ERR_PTR(-ENOMEM); in sbp_session_create()
194 spin_lock_init(&sess->lock); in sbp_session_create()
195 INIT_LIST_HEAD(&sess->login_list); in sbp_session_create()
196 INIT_DELAYED_WORK(&sess->maint_work, session_maintenance_work); in sbp_session_create()
197 sess->guid = guid; in sbp_session_create()
199 sess->se_sess = target_setup_session(&tpg->se_tpg, 128, in sbp_session_create()
203 if (IS_ERR(sess->se_sess)) { in sbp_session_create()
205 ret = PTR_ERR(sess->se_sess); in sbp_session_create()
215 spin_lock_bh(&sess->lock); in sbp_session_release()
216 if (!list_empty(&sess->login_list)) { in sbp_session_release()
217 spin_unlock_bh(&sess->lock); in sbp_session_release()
220 spin_unlock_bh(&sess->lock); in sbp_session_release()
223 cancel_delayed_work_sync(&sess->maint_work); in sbp_session_release()
225 target_remove_session(sess->se_sess); in sbp_session_release()
227 if (sess->card) in sbp_session_release()
228 fw_card_put(sess->card); in sbp_session_release()
238 struct sbp_session *sess = login->sess; in sbp_login_release()
242 sbp_target_agent_unregister(login->tgt_agt); in sbp_login_release()
245 spin_lock_bh(&sess->lock); in sbp_login_release()
246 list_del(&login->link); in sbp_login_release()
247 spin_unlock_bh(&sess->lock); in sbp_login_release()
262 struct sbp_tport *tport = agent->tport; in sbp_management_request_login()
263 struct sbp_tpg *tpg = tport->tpg; in sbp_management_request_login()
272 LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc)), &ret); in sbp_management_request_login()
275 LOGIN_ORB_LUN(be32_to_cpu(req->orb.misc))); in sbp_management_request_login()
277 req->status.status = cpu_to_be32( in sbp_management_request_login()
287 req->status.status = cpu_to_be32( in sbp_management_request_login()
300 pr_notice("initiator already logged-in\n"); in sbp_management_request_login()
303 * SBP-2 R4 says we should return access denied, but in sbp_management_request_login()
325 if (LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc)) && in sbp_management_request_login()
329 req->status.status = cpu_to_be32( in sbp_management_request_login()
342 req->status.status = cpu_to_be32( in sbp_management_request_login()
353 tport->max_logins_per_lun) { in sbp_management_request_login()
356 req->status.status = cpu_to_be32( in sbp_management_request_login()
366 case -EPERM: in sbp_management_request_login()
374 req->status.status = cpu_to_be32( in sbp_management_request_login()
381 sess->node_id = req->node_addr; in sbp_management_request_login()
382 sess->card = fw_card_get(req->card); in sbp_management_request_login()
383 sess->generation = req->generation; in sbp_management_request_login()
384 sess->speed = req->speed; in sbp_management_request_login()
386 schedule_delayed_work(&sess->maint_work, in sbp_management_request_login()
391 sess->reconnect_hold = min( in sbp_management_request_login()
392 1 << LOGIN_ORB_RECONNECT(be32_to_cpu(req->orb.misc)), in sbp_management_request_login()
393 tport->max_reconnect_timeout) - 1; in sbp_management_request_login()
401 req->status.status = cpu_to_be32( in sbp_management_request_login()
407 login->sess = sess; in sbp_management_request_login()
408 login->login_lun = unpacked_lun; in sbp_management_request_login()
409 login->status_fifo_addr = sbp2_pointer_to_addr(&req->orb.status_fifo); in sbp_management_request_login()
410 login->exclusive = LOGIN_ORB_EXCLUSIVE(be32_to_cpu(req->orb.misc)); in sbp_management_request_login()
411 login->login_id = atomic_inc_return(&login_id); in sbp_management_request_login()
413 login->tgt_agt = sbp_target_agent_register(login); in sbp_management_request_login()
414 if (IS_ERR(login->tgt_agt)) { in sbp_management_request_login()
415 ret = PTR_ERR(login->tgt_agt); in sbp_management_request_login()
421 req->status.status = cpu_to_be32( in sbp_management_request_login()
427 spin_lock_bh(&sess->lock); in sbp_management_request_login()
428 list_add_tail(&login->link, &sess->login_list); in sbp_management_request_login()
429 spin_unlock_bh(&sess->lock); in sbp_management_request_login()
438 req->status.status = cpu_to_be32( in sbp_management_request_login()
445 LOGIN_ORB_RESPONSE_LENGTH(be32_to_cpu(req->orb.length)), in sbp_management_request_login()
447 response->misc = cpu_to_be32( in sbp_management_request_login()
449 (login->login_id & 0xffff)); in sbp_management_request_login()
450 response->reconnect_hold = cpu_to_be32(sess->reconnect_hold & 0xffff); in sbp_management_request_login()
451 addr_to_sbp2_pointer(login->tgt_agt->handler.offset, in sbp_management_request_login()
452 &response->command_block_agent); in sbp_management_request_login()
454 ret = sbp_run_transaction(sess->card, TCODE_WRITE_BLOCK_REQUEST, in sbp_management_request_login()
455 sess->node_id, sess->generation, sess->speed, in sbp_management_request_login()
456 sbp2_pointer_to_addr(&req->orb.ptr2), response, in sbp_management_request_login()
464 req->status.status = cpu_to_be32( in sbp_management_request_login()
472 req->status.status = cpu_to_be32( in sbp_management_request_login()
484 req->status.status = cpu_to_be32( in sbp_management_request_query_logins()
493 struct sbp_tport *tport = agent->tport; in sbp_management_request_reconnect()
494 struct sbp_tpg *tpg = tport->tpg; in sbp_management_request_reconnect()
503 req->status.status = cpu_to_be32( in sbp_management_request_reconnect()
512 RECONNECT_ORB_LOGIN_ID(be32_to_cpu(req->orb.misc))); in sbp_management_request_reconnect()
517 req->status.status = cpu_to_be32( in sbp_management_request_reconnect()
523 if (login->sess->guid != guid) { in sbp_management_request_reconnect()
526 req->status.status = cpu_to_be32( in sbp_management_request_reconnect()
532 spin_lock_bh(&login->sess->lock); in sbp_management_request_reconnect()
533 if (login->sess->card) in sbp_management_request_reconnect()
534 fw_card_put(login->sess->card); in sbp_management_request_reconnect()
537 login->sess->generation = req->generation; in sbp_management_request_reconnect()
538 login->sess->node_id = req->node_addr; in sbp_management_request_reconnect()
539 login->sess->card = fw_card_get(req->card); in sbp_management_request_reconnect()
540 login->sess->speed = req->speed; in sbp_management_request_reconnect()
541 spin_unlock_bh(&login->sess->lock); in sbp_management_request_reconnect()
543 req->status.status = cpu_to_be32( in sbp_management_request_reconnect()
552 struct sbp_tport *tport = agent->tport; in sbp_management_request_logout()
553 struct sbp_tpg *tpg = tport->tpg; in sbp_management_request_logout()
557 id = LOGOUT_ORB_LOGIN_ID(be32_to_cpu(req->orb.misc)); in sbp_management_request_logout()
563 req->status.status = cpu_to_be32( in sbp_management_request_logout()
570 login->login_lun, login->login_id); in sbp_management_request_logout()
572 if (req->node_addr != login->sess->node_id) { in sbp_management_request_logout()
575 req->status.status = cpu_to_be32( in sbp_management_request_logout()
583 req->status.status = cpu_to_be32( in sbp_management_request_logout()
592 spin_lock_bh(&sess->lock); in session_check_for_reset()
594 if (sess->card) { in session_check_for_reset()
595 spin_lock_irq(&sess->card->lock); in session_check_for_reset()
596 card_valid = (sess->card->local_node != NULL); in session_check_for_reset()
597 spin_unlock_irq(&sess->card->lock); in session_check_for_reset()
600 fw_card_put(sess->card); in session_check_for_reset()
601 sess->card = NULL; in session_check_for_reset()
605 if (!card_valid || (sess->generation != sess->card->generation)) { in session_check_for_reset()
607 sess->guid); in session_check_for_reset()
609 sess->node_id = -1; in session_check_for_reset()
610 sess->reconnect_expires = get_jiffies_64() + in session_check_for_reset()
611 ((sess->reconnect_hold + 1) * HZ); in session_check_for_reset()
614 spin_unlock_bh(&sess->lock); in session_check_for_reset()
622 pr_info("Reconnect timer expired for node: %016llx\n", sess->guid); in session_reconnect_expired()
624 spin_lock_bh(&sess->lock); in session_reconnect_expired()
625 list_for_each_entry_safe(login, temp, &sess->login_list, link) { in session_reconnect_expired()
626 login->sess = NULL; in session_reconnect_expired()
627 list_move_tail(&login->link, &login_list); in session_reconnect_expired()
629 spin_unlock_bh(&sess->lock); in session_reconnect_expired()
632 list_del(&login->link); in session_reconnect_expired()
645 spin_lock_bh(&sess->lock); in session_maintenance_work()
646 if (list_empty(&sess->login_list)) { in session_maintenance_work()
647 spin_unlock_bh(&sess->lock); in session_maintenance_work()
650 spin_unlock_bh(&sess->lock); in session_maintenance_work()
652 if (sess->node_id != -1) { in session_maintenance_work()
656 schedule_delayed_work(&sess->maint_work, in session_maintenance_work()
658 } else if (!time_after64(get_jiffies_64(), sess->reconnect_expires)) { in session_maintenance_work()
660 schedule_delayed_work(&sess->maint_work, in session_maintenance_work()
677 spin_lock_bh(&agent->lock); in tgt_agent_rw_agent_state()
678 state = agent->state; in tgt_agent_rw_agent_state()
679 spin_unlock_bh(&agent->lock); in tgt_agent_rw_agent_state()
700 spin_lock_bh(&agent->lock); in tgt_agent_rw_agent_reset()
701 agent->state = AGENT_STATE_RESET; in tgt_agent_rw_agent_reset()
702 spin_unlock_bh(&agent->lock); in tgt_agent_rw_agent_reset()
717 spin_lock_bh(&agent->lock); in tgt_agent_rw_orb_pointer()
718 if (agent->state != AGENT_STATE_SUSPENDED && in tgt_agent_rw_orb_pointer()
719 agent->state != AGENT_STATE_RESET) { in tgt_agent_rw_orb_pointer()
720 spin_unlock_bh(&agent->lock); in tgt_agent_rw_orb_pointer()
724 agent->state = AGENT_STATE_ACTIVE; in tgt_agent_rw_orb_pointer()
725 spin_unlock_bh(&agent->lock); in tgt_agent_rw_orb_pointer()
727 agent->orb_pointer = sbp2_pointer_to_addr(ptr); in tgt_agent_rw_orb_pointer()
728 agent->doorbell = false; in tgt_agent_rw_orb_pointer()
731 agent->orb_pointer); in tgt_agent_rw_orb_pointer()
733 queue_work(system_unbound_wq, &agent->work); in tgt_agent_rw_orb_pointer()
739 spin_lock_bh(&agent->lock); in tgt_agent_rw_orb_pointer()
740 addr_to_sbp2_pointer(agent->orb_pointer, ptr); in tgt_agent_rw_orb_pointer()
741 spin_unlock_bh(&agent->lock); in tgt_agent_rw_orb_pointer()
754 spin_lock_bh(&agent->lock); in tgt_agent_rw_doorbell()
755 if (agent->state != AGENT_STATE_SUSPENDED) { in tgt_agent_rw_doorbell()
756 spin_unlock_bh(&agent->lock); in tgt_agent_rw_doorbell()
760 agent->state = AGENT_STATE_ACTIVE; in tgt_agent_rw_doorbell()
761 spin_unlock_bh(&agent->lock); in tgt_agent_rw_doorbell()
763 agent->doorbell = true; in tgt_agent_rw_doorbell()
767 queue_work(system_unbound_wq, &agent->work); in tgt_agent_rw_doorbell()
785 /* ignored as we don't send unsolicited status */ in tgt_agent_rw_unsolicited_status_enable()
802 struct sbp_session *sess = agent->login->sess; in tgt_agent_rw()
805 spin_lock_bh(&sess->lock); in tgt_agent_rw()
806 sess_gen = sess->generation; in tgt_agent_rw()
807 sess_node = sess->node_id; in tgt_agent_rw()
808 spin_unlock_bh(&sess->lock); in tgt_agent_rw()
824 offset -= agent->handler.offset; in tgt_agent_rw()
860 req->orb_pointer, in tgt_agent_process_work()
861 sbp2_pointer_to_addr(&req->orb.next_orb), in tgt_agent_process_work()
862 sbp2_pointer_to_addr(&req->orb.data_descriptor), in tgt_agent_process_work()
863 be32_to_cpu(req->orb.misc)); in tgt_agent_process_work()
865 if (req->orb_pointer >> 32) in tgt_agent_process_work()
868 switch (ORB_REQUEST_FORMAT(be32_to_cpu(req->orb.misc))) { in tgt_agent_process_work()
873 case 2: /* Vendor-dependent */ in tgt_agent_process_work()
874 req->status.status |= cpu_to_be32( in tgt_agent_process_work()
884 req->status.status |= cpu_to_be32( in tgt_agent_process_work()
898 /* used to double-check we haven't been issued an AGENT_RESET */
903 spin_lock_bh(&agent->lock); in tgt_agent_check_active()
904 active = (agent->state == AGENT_STATE_ACTIVE); in tgt_agent_check_active()
905 spin_unlock_bh(&agent->lock); in tgt_agent_check_active()
913 struct se_session *se_sess = sess->se_sess; in sbp_mgt_get_req()
917 tag = sbitmap_queue_get(&se_sess->sess_tag_pool, &cpu); in sbp_mgt_get_req()
919 return ERR_PTR(-ENOMEM); in sbp_mgt_get_req()
921 req = &((struct sbp_target_request *)se_sess->sess_cmd_map)[tag]; in sbp_mgt_get_req()
923 req->se_cmd.map_tag = tag; in sbp_mgt_get_req()
924 req->se_cmd.map_cpu = cpu; in sbp_mgt_get_req()
925 req->se_cmd.tag = next_orb; in sbp_mgt_get_req()
934 struct sbp_session *sess = agent->login->sess; in tgt_agent_fetch_work()
937 bool doorbell = agent->doorbell; in tgt_agent_fetch_work()
938 u64 next_orb = agent->orb_pointer; in tgt_agent_fetch_work()
941 req = sbp_mgt_get_req(sess, sess->card, next_orb); in tgt_agent_fetch_work()
943 spin_lock_bh(&agent->lock); in tgt_agent_fetch_work()
944 agent->state = AGENT_STATE_DEAD; in tgt_agent_fetch_work()
945 spin_unlock_bh(&agent->lock); in tgt_agent_fetch_work()
949 req->login = agent->login; in tgt_agent_fetch_work()
950 req->orb_pointer = next_orb; in tgt_agent_fetch_work()
952 req->status.status = cpu_to_be32(STATUS_BLOCK_ORB_OFFSET_HIGH( in tgt_agent_fetch_work()
953 req->orb_pointer >> 32)); in tgt_agent_fetch_work()
954 req->status.orb_low = cpu_to_be32( in tgt_agent_fetch_work()
955 req->orb_pointer & 0xfffffffc); in tgt_agent_fetch_work()
958 ret = sbp_run_transaction(sess->card, TCODE_READ_BLOCK_REQUEST, in tgt_agent_fetch_work()
959 sess->node_id, sess->generation, sess->speed, in tgt_agent_fetch_work()
960 req->orb_pointer, &req->orb, sizeof(req->orb)); in tgt_agent_fetch_work()
963 req->status.status |= cpu_to_be32( in tgt_agent_fetch_work()
972 spin_lock_bh(&agent->lock); in tgt_agent_fetch_work()
973 agent->state = AGENT_STATE_DEAD; in tgt_agent_fetch_work()
974 spin_unlock_bh(&agent->lock); in tgt_agent_fetch_work()
981 if (be32_to_cpu(req->orb.next_orb.high) & 0x80000000) { in tgt_agent_fetch_work()
983 req->status.status |= cpu_to_be32(STATUS_BLOCK_SRC( in tgt_agent_fetch_work()
986 next_orb = sbp2_pointer_to_addr(&req->orb.next_orb); in tgt_agent_fetch_work()
987 req->status.status |= cpu_to_be32(STATUS_BLOCK_SRC( in tgt_agent_fetch_work()
992 INIT_WORK(&req->work, tgt_agent_process_work); in tgt_agent_fetch_work()
993 queue_work(system_unbound_wq, &req->work); in tgt_agent_fetch_work()
999 spin_lock_bh(&agent->lock); in tgt_agent_fetch_work()
1000 doorbell = agent->doorbell = false; in tgt_agent_fetch_work()
1004 agent->orb_pointer = next_orb; in tgt_agent_fetch_work()
1006 agent->state = AGENT_STATE_SUSPENDED; in tgt_agent_fetch_work()
1008 spin_unlock_bh(&agent->lock); in tgt_agent_fetch_work()
1020 return ERR_PTR(-ENOMEM); in sbp_target_agent_register()
1022 spin_lock_init(&agent->lock); in sbp_target_agent_register()
1024 agent->handler.length = 0x20; in sbp_target_agent_register()
1025 agent->handler.address_callback = tgt_agent_rw; in sbp_target_agent_register()
1026 agent->handler.callback_data = agent; in sbp_target_agent_register()
1028 agent->login = login; in sbp_target_agent_register()
1029 agent->state = AGENT_STATE_RESET; in sbp_target_agent_register()
1030 INIT_WORK(&agent->work, tgt_agent_fetch_work); in sbp_target_agent_register()
1031 agent->orb_pointer = 0; in sbp_target_agent_register()
1032 agent->doorbell = false; in sbp_target_agent_register()
1034 ret = fw_core_add_address_handler(&agent->handler, in sbp_target_agent_register()
1046 fw_core_remove_address_handler(&agent->handler); in sbp_target_agent_unregister()
1047 cancel_work_sync(&agent->work); in sbp_target_agent_unregister()
1089 struct sbp_login_descriptor *login = req->login; in sbp_run_request_transaction()
1090 struct sbp_session *sess = login->sess; in sbp_run_request_transaction()
1094 spin_lock_bh(&sess->lock); in sbp_run_request_transaction()
1095 card = fw_card_get(sess->card); in sbp_run_request_transaction()
1096 node_id = sess->node_id; in sbp_run_request_transaction()
1097 generation = sess->generation; in sbp_run_request_transaction()
1098 speed = sess->speed; in sbp_run_request_transaction()
1099 spin_unlock_bh(&sess->lock); in sbp_run_request_transaction()
1113 cmd_len = scsi_command_size(req->orb.command_block); in sbp_fetch_command()
1115 req->cmd_buf = kmalloc(cmd_len, GFP_KERNEL); in sbp_fetch_command()
1116 if (!req->cmd_buf) in sbp_fetch_command()
1117 return -ENOMEM; in sbp_fetch_command()
1119 memcpy(req->cmd_buf, req->orb.command_block, in sbp_fetch_command()
1120 min_t(int, cmd_len, sizeof(req->orb.command_block))); in sbp_fetch_command()
1122 if (cmd_len > sizeof(req->orb.command_block)) { in sbp_fetch_command()
1124 copy_len = cmd_len - sizeof(req->orb.command_block); in sbp_fetch_command()
1128 req->orb_pointer + sizeof(req->orb), in sbp_fetch_command()
1129 req->cmd_buf + sizeof(req->orb.command_block), in sbp_fetch_command()
1132 return -EIO; in sbp_fetch_command()
1143 if (!CMDBLK_ORB_PG_TBL_PRESENT(be32_to_cpu(req->orb.misc))) in sbp_fetch_page_table()
1146 pg_tbl_sz = CMDBLK_ORB_DATA_SIZE(be32_to_cpu(req->orb.misc)) * in sbp_fetch_page_table()
1151 return -ENOMEM; in sbp_fetch_page_table()
1154 sbp2_pointer_to_addr(&req->orb.data_descriptor), in sbp_fetch_page_table()
1158 return -EIO; in sbp_fetch_page_table()
1161 req->pg_tbl = pg_tbl; in sbp_fetch_page_table()
1170 data_size = CMDBLK_ORB_DATA_SIZE(be32_to_cpu(req->orb.misc)); in sbp_calc_data_length_direction()
1171 direction = CMDBLK_ORB_DIRECTION(be32_to_cpu(req->orb.misc)); in sbp_calc_data_length_direction()
1181 if (req->pg_tbl) { in sbp_calc_data_length_direction()
1185 req->pg_tbl[idx].segment_length); in sbp_calc_data_length_direction()
1194 struct sbp_login_descriptor *login = req->login; in sbp_handle_command()
1195 struct sbp_session *sess = login->sess; in sbp_handle_command()
1213 unpacked_lun = req->login->login_lun; in sbp_handle_command()
1217 req->orb_pointer, unpacked_lun, data_length, data_dir); in sbp_handle_command()
1220 req->se_cmd.tag = req->orb_pointer; in sbp_handle_command()
1221 target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf, in sbp_handle_command()
1222 req->sense_buf, unpacked_lun, data_length, in sbp_handle_command()
1227 req->status.status |= cpu_to_be32( in sbp_handle_command()
1241 struct sbp_session *sess = req->login->sess; in sbp_rw_data()
1250 if (req->se_cmd.data_direction == DMA_FROM_DEVICE) { in sbp_rw_data()
1258 max_payload = 4 << CMDBLK_ORB_MAX_PAYLOAD(be32_to_cpu(req->orb.misc)); in sbp_rw_data()
1259 speed = CMDBLK_ORB_SPEED(be32_to_cpu(req->orb.misc)); in sbp_rw_data()
1261 pg_size = CMDBLK_ORB_PG_SIZE(be32_to_cpu(req->orb.misc)); in sbp_rw_data()
1266 spin_lock_bh(&sess->lock); in sbp_rw_data()
1267 card = fw_card_get(sess->card); in sbp_rw_data()
1268 node_id = sess->node_id; in sbp_rw_data()
1269 generation = sess->generation; in sbp_rw_data()
1270 spin_unlock_bh(&sess->lock); in sbp_rw_data()
1272 if (req->pg_tbl) { in sbp_rw_data()
1273 pte = req->pg_tbl; in sbp_rw_data()
1274 num_pte = CMDBLK_ORB_DATA_SIZE(be32_to_cpu(req->orb.misc)); in sbp_rw_data()
1282 offset = sbp2_pointer_to_addr(&req->orb.data_descriptor); in sbp_rw_data()
1283 length = req->se_cmd.data_length; in sbp_rw_data()
1286 sg_miter_start(&iter, req->se_cmd.t_data_sg, req->se_cmd.t_data_nents, in sbp_rw_data()
1291 offset = (u64)be16_to_cpu(pte->segment_base_hi) << 32 | in sbp_rw_data()
1292 be32_to_cpu(pte->segment_base_lo); in sbp_rw_data()
1293 length = be16_to_cpu(pte->segment_length); in sbp_rw_data()
1296 num_pte--; in sbp_rw_data()
1312 length -= tfr_length; in sbp_rw_data()
1324 return -EIO; in sbp_rw_data()
1331 struct sbp_login_descriptor *login = req->login; in sbp_send_status()
1333 length = (((be32_to_cpu(req->status.status) >> 24) & 0x07) + 1) * 4; in sbp_send_status()
1336 login->status_fifo_addr, &req->status, length); in sbp_send_status()
1339 ret = -EIO; in sbp_send_status()
1343 pr_debug("sbp_send_status: status write complete for ORB: 0x%llx\n", in sbp_send_status()
1344 req->orb_pointer); in sbp_send_status()
1347 * ahead of sbp_check_stop_free() -> transport_generic_free_cmd() in sbp_send_status()
1348 * final se_cmd->cmd_kref put. in sbp_send_status()
1351 target_put_sess_cmd(&req->se_cmd); in sbp_send_status()
1357 struct se_cmd *se_cmd = &req->se_cmd; in sbp_sense_mangle()
1358 u8 *sense = req->sense_buf; in sbp_sense_mangle()
1359 u8 *status = req->status.data; in sbp_sense_mangle() local
1361 WARN_ON(se_cmd->scsi_sense_length < 18); in sbp_sense_mangle()
1365 status[0] = 0 << 6; in sbp_sense_mangle()
1368 status[0] = 1 << 6; in sbp_sense_mangle()
1374 * TODO: SBP-3 specifies what we should do with descriptor in sbp_sense_mangle()
1379 req->status.status |= cpu_to_be32( in sbp_sense_mangle()
1387 status[0] |= se_cmd->scsi_status & 0x3f;/* status */ in sbp_sense_mangle()
1388 status[1] = in sbp_sense_mangle()
1392 status[2] = 0; /* XXX sense_code */ in sbp_sense_mangle()
1393 status[3] = 0; /* XXX sense_qualifier */ in sbp_sense_mangle()
1396 status[4] = sense[3]; in sbp_sense_mangle()
1397 status[5] = sense[4]; in sbp_sense_mangle()
1398 status[6] = sense[5]; in sbp_sense_mangle()
1399 status[7] = sense[6]; in sbp_sense_mangle()
1401 /* CDB-dependent */ in sbp_sense_mangle()
1402 status[8] = sense[8]; in sbp_sense_mangle()
1403 status[9] = sense[9]; in sbp_sense_mangle()
1404 status[10] = sense[10]; in sbp_sense_mangle()
1405 status[11] = sense[11]; in sbp_sense_mangle()
1408 status[12] = sense[14]; in sbp_sense_mangle()
1410 /* sense_key-dependent */ in sbp_sense_mangle()
1411 status[13] = sense[15]; in sbp_sense_mangle()
1412 status[14] = sense[16]; in sbp_sense_mangle()
1413 status[15] = sense[17]; in sbp_sense_mangle()
1415 req->status.status |= cpu_to_be32( in sbp_sense_mangle()
1424 struct se_cmd *se_cmd = &req->se_cmd; in sbp_send_sense()
1426 if (se_cmd->scsi_sense_length) { in sbp_send_sense()
1429 req->status.status |= cpu_to_be32( in sbp_send_sense()
1441 struct se_cmd *se_cmd = &req->se_cmd; in sbp_free_request()
1442 struct se_session *se_sess = se_cmd->se_sess; in sbp_free_request()
1444 kfree(req->pg_tbl); in sbp_free_request()
1445 kfree(req->cmd_buf); in sbp_free_request()
1454 struct sbp_management_request *req = agent->request; in sbp_mgt_agent_process()
1459 ret = sbp_run_transaction(req->card, TCODE_READ_BLOCK_REQUEST, in sbp_mgt_agent_process()
1460 req->node_addr, req->generation, req->speed, in sbp_mgt_agent_process()
1461 agent->orb_offset, &req->orb, sizeof(req->orb)); in sbp_mgt_agent_process()
1468 sbp2_pointer_to_addr(&req->orb.ptr1), in sbp_mgt_agent_process()
1469 sbp2_pointer_to_addr(&req->orb.ptr2), in sbp_mgt_agent_process()
1470 be32_to_cpu(req->orb.misc), be32_to_cpu(req->orb.length), in sbp_mgt_agent_process()
1471 sbp2_pointer_to_addr(&req->orb.status_fifo)); in sbp_mgt_agent_process()
1473 if (!ORB_NOTIFY(be32_to_cpu(req->orb.misc)) || in sbp_mgt_agent_process()
1474 ORB_REQUEST_FORMAT(be32_to_cpu(req->orb.misc)) != 0) { in sbp_mgt_agent_process()
1479 switch (MANAGEMENT_ORB_FUNCTION(be32_to_cpu(req->orb.misc))) { in sbp_mgt_agent_process()
1496 req->status.status = cpu_to_be32( in sbp_mgt_agent_process()
1509 req->status.status = cpu_to_be32( in sbp_mgt_agent_process()
1518 req->status.status = cpu_to_be32( in sbp_mgt_agent_process()
1527 req->status.status = cpu_to_be32( in sbp_mgt_agent_process()
1536 req->status.status = cpu_to_be32( in sbp_mgt_agent_process()
1544 MANAGEMENT_ORB_FUNCTION(be32_to_cpu(req->orb.misc))); in sbp_mgt_agent_process()
1546 req->status.status = cpu_to_be32( in sbp_mgt_agent_process()
1553 req->status.status |= cpu_to_be32( in sbp_mgt_agent_process()
1556 STATUS_BLOCK_ORB_OFFSET_HIGH(agent->orb_offset >> 32)); in sbp_mgt_agent_process()
1557 req->status.orb_low = cpu_to_be32(agent->orb_offset); in sbp_mgt_agent_process()
1559 /* write the status block back to the initiator */ in sbp_mgt_agent_process()
1560 ret = sbp_run_transaction(req->card, TCODE_WRITE_BLOCK_REQUEST, in sbp_mgt_agent_process()
1561 req->node_addr, req->generation, req->speed, in sbp_mgt_agent_process()
1562 sbp2_pointer_to_addr(&req->orb.status_fifo), in sbp_mgt_agent_process()
1563 &req->status, 8 + status_data_len); in sbp_mgt_agent_process()
1565 pr_debug("mgt_orb status write failed: %x\n", ret); in sbp_mgt_agent_process()
1570 fw_card_put(req->card); in sbp_mgt_agent_process()
1573 spin_lock_bh(&agent->lock); in sbp_mgt_agent_process()
1574 agent->state = MANAGEMENT_AGENT_STATE_IDLE; in sbp_mgt_agent_process()
1575 spin_unlock_bh(&agent->lock); in sbp_mgt_agent_process()
1587 if (!agent->tport->enable) in sbp_mgt_agent_rw()
1590 if ((offset != agent->handler.offset) || (length != 8)) in sbp_mgt_agent_rw()
1597 spin_lock_bh(&agent->lock); in sbp_mgt_agent_rw()
1598 prev_state = agent->state; in sbp_mgt_agent_rw()
1599 agent->state = MANAGEMENT_AGENT_STATE_BUSY; in sbp_mgt_agent_rw()
1600 spin_unlock_bh(&agent->lock); in sbp_mgt_agent_rw()
1613 req->card = fw_card_get(card); in sbp_mgt_agent_rw()
1614 req->generation = generation; in sbp_mgt_agent_rw()
1615 req->node_addr = source; in sbp_mgt_agent_rw()
1616 req->speed = fw_get_request_speed(request); in sbp_mgt_agent_rw()
1618 agent->orb_offset = sbp2_pointer_to_addr(ptr); in sbp_mgt_agent_rw()
1619 agent->request = req; in sbp_mgt_agent_rw()
1621 queue_work(system_unbound_wq, &agent->work); in sbp_mgt_agent_rw()
1624 addr_to_sbp2_pointer(agent->orb_offset, ptr); in sbp_mgt_agent_rw()
1642 return ERR_PTR(-ENOMEM); in sbp_management_agent_register()
1644 spin_lock_init(&agent->lock); in sbp_management_agent_register()
1645 agent->tport = tport; in sbp_management_agent_register()
1646 agent->handler.length = 0x08; in sbp_management_agent_register()
1647 agent->handler.address_callback = sbp_mgt_agent_rw; in sbp_management_agent_register()
1648 agent->handler.callback_data = agent; in sbp_management_agent_register()
1649 agent->state = MANAGEMENT_AGENT_STATE_IDLE; in sbp_management_agent_register()
1650 INIT_WORK(&agent->work, sbp_mgt_agent_process); in sbp_management_agent_register()
1651 agent->orb_offset = 0; in sbp_management_agent_register()
1652 agent->request = NULL; in sbp_management_agent_register()
1654 ret = fw_core_add_address_handler(&agent->handler, in sbp_management_agent_register()
1666 fw_core_remove_address_handler(&agent->handler); in sbp_management_agent_unregister()
1667 cancel_work_sync(&agent->work); in sbp_management_agent_unregister()
1679 struct sbp_tport *tport = tpg->tport; in sbp_get_fabric_wwn()
1681 return &tport->tport_name[0]; in sbp_get_fabric_wwn()
1687 return tpg->tport_tpgt; in sbp_get_tag()
1706 req->status.status |= cpu_to_be32( in sbp_write_pending()
1729 req->status.status |= cpu_to_be32( in sbp_queue_data_in()
1767 return transport_generic_free_cmd(&req->se_cmd, 0); in sbp_check_stop_free()
1776 hlist_for_each_entry_rcu(lun, &tpg->tpg_lun_hlist, link) in sbp_count_se_tpg_luns()
1789 if (tport->unit_directory.data) { in sbp_update_unit_directory()
1790 fw_core_remove_descriptor(&tport->unit_directory); in sbp_update_unit_directory()
1791 kfree(tport->unit_directory.data); in sbp_update_unit_directory()
1792 tport->unit_directory.data = NULL; in sbp_update_unit_directory()
1795 if (!tport->enable || !tport->tpg) in sbp_update_unit_directory()
1798 num_luns = sbp_count_se_tpg_luns(&tport->tpg->se_tpg); in sbp_update_unit_directory()
1802 * - all of those in the template in sbp_update_unit_directory()
1803 * - management_agent in sbp_update_unit_directory()
1804 * - unit_characteristics in sbp_update_unit_directory()
1805 * - reconnect_timeout in sbp_update_unit_directory()
1806 * - unit unique ID in sbp_update_unit_directory()
1807 * - one for each LUN in sbp_update_unit_directory()
1809 * MUST NOT include leaf or sub-directory entries in sbp_update_unit_directory()
1813 if (tport->directory_id != -1) in sbp_update_unit_directory()
1819 return -ENOMEM; in sbp_update_unit_directory()
1825 if (tport->directory_id != -1) in sbp_update_unit_directory()
1826 data[idx++] = (CSR_DIRECTORY_ID << 24) | tport->directory_id; in sbp_update_unit_directory()
1834 mgt_agt_addr = (tport->mgt_agt->handler.offset - CSR_REGISTER_BASE) / 4; in sbp_update_unit_directory()
1839 (((tport->mgt_orb_timeout * 2) << 8) & 0xff00) | in sbp_update_unit_directory()
1843 data[idx++] = 0x3d000000 | (tport->max_reconnect_timeout & 0xffff); in sbp_update_unit_directory()
1849 hlist_for_each_entry_rcu(lun, &tport->tpg->se_tpg.tpg_lun_hlist, link) { in sbp_update_unit_directory()
1853 * rcu_dereference_raw protected by se_lun->lun_group symlink in sbp_update_unit_directory()
1854 * reference to se_device->dev_group. in sbp_update_unit_directory()
1856 dev = rcu_dereference_raw(lun->lun_se_dev); in sbp_update_unit_directory()
1857 type = dev->transport->get_device_type(dev); in sbp_update_unit_directory()
1862 (lun->unpacked_lun & 0xffff); in sbp_update_unit_directory()
1868 data[idx++] = tport->guid >> 32; in sbp_update_unit_directory()
1869 data[idx++] = tport->guid; in sbp_update_unit_directory()
1871 tport->unit_directory.length = idx; in sbp_update_unit_directory()
1872 tport->unit_directory.key = (CSR_DIRECTORY | CSR_UNIT) << 24; in sbp_update_unit_directory()
1873 tport->unit_directory.data = data; in sbp_update_unit_directory()
1875 ret = fw_core_add_descriptor(&tport->unit_directory); in sbp_update_unit_directory()
1877 kfree(tport->unit_directory.data); in sbp_update_unit_directory()
1878 tport->unit_directory.data = NULL; in sbp_update_unit_directory()
1891 for (cp = name; cp < &name[SBP_NAMELEN - 1]; cp++) { in sbp_parse_wwn()
1899 return cp - name; in sbp_parse_wwn()
1903 nibble = c - '0'; in sbp_parse_wwn()
1905 nibble = tolower(c) - 'a' + 10; in sbp_parse_wwn()
1914 err, cp - name, pos); in sbp_parse_wwn()
1915 return -1; in sbp_parse_wwn()
1928 return -EINVAL; in sbp_init_nodeacl()
1938 return sbp_update_unit_directory(tpg->tport); in sbp_post_link_lun()
1946 struct sbp_tport *tport = tpg->tport; in sbp_pre_unlink_lun()
1949 if (sbp_count_se_tpg_luns(&tpg->se_tpg) == 0) in sbp_pre_unlink_lun()
1950 tport->enable = 0; in sbp_pre_unlink_lun()
1968 return ERR_PTR(-EINVAL); in sbp_make_tpg()
1970 return ERR_PTR(-EINVAL); in sbp_make_tpg()
1972 if (tport->tpg) { in sbp_make_tpg()
1974 return ERR_PTR(-EBUSY); in sbp_make_tpg()
1979 return ERR_PTR(-ENOMEM); in sbp_make_tpg()
1981 tpg->tport = tport; in sbp_make_tpg()
1982 tpg->tport_tpgt = tpgt; in sbp_make_tpg()
1983 tport->tpg = tpg; in sbp_make_tpg()
1986 tport->enable = 0; in sbp_make_tpg()
1987 tport->directory_id = -1; in sbp_make_tpg()
1988 tport->mgt_orb_timeout = 15; in sbp_make_tpg()
1989 tport->max_reconnect_timeout = 5; in sbp_make_tpg()
1990 tport->max_logins_per_lun = 1; in sbp_make_tpg()
1992 tport->mgt_agt = sbp_management_agent_register(tport); in sbp_make_tpg()
1993 if (IS_ERR(tport->mgt_agt)) { in sbp_make_tpg()
1994 ret = PTR_ERR(tport->mgt_agt); in sbp_make_tpg()
1998 ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SBP); in sbp_make_tpg()
2002 return &tpg->se_tpg; in sbp_make_tpg()
2005 sbp_management_agent_unregister(tport->mgt_agt); in sbp_make_tpg()
2007 tport->tpg = NULL; in sbp_make_tpg()
2015 struct sbp_tport *tport = tpg->tport; in sbp_drop_tpg()
2018 sbp_management_agent_unregister(tport->mgt_agt); in sbp_drop_tpg()
2019 tport->tpg = NULL; in sbp_drop_tpg()
2032 return ERR_PTR(-EINVAL); in sbp_make_tport()
2036 return ERR_PTR(-ENOMEM); in sbp_make_tport()
2038 tport->guid = guid; in sbp_make_tport()
2039 sbp_format_wwn(tport->tport_name, SBP_NAMELEN, guid); in sbp_make_tport()
2041 return &tport->tport_wwn; in sbp_make_tport()
2068 struct sbp_tport *tport = tpg->tport; in sbp_tpg_directory_id_show()
2070 if (tport->directory_id == -1) in sbp_tpg_directory_id_show()
2073 return sprintf(page, "%06x\n", tport->directory_id); in sbp_tpg_directory_id_show()
2081 struct sbp_tport *tport = tpg->tport; in sbp_tpg_directory_id_store()
2084 if (tport->enable) { in sbp_tpg_directory_id_store()
2086 return -EBUSY; in sbp_tpg_directory_id_store()
2090 tport->directory_id = -1; in sbp_tpg_directory_id_store()
2093 return -EINVAL; in sbp_tpg_directory_id_store()
2095 return -EINVAL; in sbp_tpg_directory_id_store()
2097 tport->directory_id = val; in sbp_tpg_directory_id_store()
2106 struct sbp_tport *tport = tpg->tport; in sbp_enable_tpg()
2110 if (sbp_count_se_tpg_luns(&tpg->se_tpg) == 0) { in sbp_enable_tpg()
2112 return -EINVAL; in sbp_enable_tpg()
2115 /* XXX: force-shutdown sessions instead? */ in sbp_enable_tpg()
2116 spin_lock_bh(&se_tpg->session_lock); in sbp_enable_tpg()
2117 if (!list_empty(&se_tpg->tpg_sess_list)) { in sbp_enable_tpg()
2118 spin_unlock_bh(&se_tpg->session_lock); in sbp_enable_tpg()
2119 return -EBUSY; in sbp_enable_tpg()
2121 spin_unlock_bh(&se_tpg->session_lock); in sbp_enable_tpg()
2124 tport->enable = enable; in sbp_enable_tpg()
2147 struct sbp_tport *tport = tpg->tport; in sbp_tpg_attrib_mgt_orb_timeout_show()
2148 return sprintf(page, "%d\n", tport->mgt_orb_timeout); in sbp_tpg_attrib_mgt_orb_timeout_show()
2156 struct sbp_tport *tport = tpg->tport; in sbp_tpg_attrib_mgt_orb_timeout_store()
2161 return -EINVAL; in sbp_tpg_attrib_mgt_orb_timeout_store()
2163 return -EINVAL; in sbp_tpg_attrib_mgt_orb_timeout_store()
2165 if (tport->mgt_orb_timeout == val) in sbp_tpg_attrib_mgt_orb_timeout_store()
2168 tport->mgt_orb_timeout = val; in sbp_tpg_attrib_mgt_orb_timeout_store()
2182 struct sbp_tport *tport = tpg->tport; in sbp_tpg_attrib_max_reconnect_timeout_show()
2183 return sprintf(page, "%d\n", tport->max_reconnect_timeout); in sbp_tpg_attrib_max_reconnect_timeout_show()
2191 struct sbp_tport *tport = tpg->tport; in sbp_tpg_attrib_max_reconnect_timeout_store()
2196 return -EINVAL; in sbp_tpg_attrib_max_reconnect_timeout_store()
2198 return -EINVAL; in sbp_tpg_attrib_max_reconnect_timeout_store()
2200 if (tport->max_reconnect_timeout == val) in sbp_tpg_attrib_max_reconnect_timeout_store()
2203 tport->max_reconnect_timeout = val; in sbp_tpg_attrib_max_reconnect_timeout_store()
2217 struct sbp_tport *tport = tpg->tport; in sbp_tpg_attrib_max_logins_per_lun_show()
2218 return sprintf(page, "%d\n", tport->max_logins_per_lun); in sbp_tpg_attrib_max_logins_per_lun_show()
2226 struct sbp_tport *tport = tpg->tport; in sbp_tpg_attrib_max_logins_per_lun_store()
2230 return -EINVAL; in sbp_tpg_attrib_max_logins_per_lun_store()
2232 return -EINVAL; in sbp_tpg_attrib_max_logins_per_lun_store()
2236 tport->max_logins_per_lun = val; in sbp_tpg_attrib_max_logins_per_lun_store()