static void sbp_mgt_agent_process()

in sbp/sbp_target.c [1450:1576]


static void sbp_mgt_agent_process(struct work_struct *work)
{
	struct sbp_management_agent *agent =
		container_of(work, struct sbp_management_agent, work);
	struct sbp_management_request *req = agent->request;
	int ret;
	int status_data_len = 0;

	/* fetch the ORB from the initiator */
	ret = sbp_run_transaction(req->card, TCODE_READ_BLOCK_REQUEST,
		req->node_addr, req->generation, req->speed,
		agent->orb_offset, &req->orb, sizeof(req->orb));
	if (ret != RCODE_COMPLETE) {
		pr_debug("mgt_orb fetch failed: %x\n", ret);
		goto out;
	}

	pr_debug("mgt_orb ptr1:0x%llx ptr2:0x%llx misc:0x%x len:0x%x status_fifo:0x%llx\n",
		sbp2_pointer_to_addr(&req->orb.ptr1),
		sbp2_pointer_to_addr(&req->orb.ptr2),
		be32_to_cpu(req->orb.misc), be32_to_cpu(req->orb.length),
		sbp2_pointer_to_addr(&req->orb.status_fifo));

	if (!ORB_NOTIFY(be32_to_cpu(req->orb.misc)) ||
		ORB_REQUEST_FORMAT(be32_to_cpu(req->orb.misc)) != 0) {
		pr_err("mgt_orb bad request\n");
		goto out;
	}

	switch (MANAGEMENT_ORB_FUNCTION(be32_to_cpu(req->orb.misc))) {
	case MANAGEMENT_ORB_FUNCTION_LOGIN:
		sbp_management_request_login(agent, req, &status_data_len);
		break;

	case MANAGEMENT_ORB_FUNCTION_QUERY_LOGINS:
		sbp_management_request_query_logins(agent, req,
				&status_data_len);
		break;

	case MANAGEMENT_ORB_FUNCTION_RECONNECT:
		sbp_management_request_reconnect(agent, req, &status_data_len);
		break;

	case MANAGEMENT_ORB_FUNCTION_SET_PASSWORD:
		pr_notice("SET PASSWORD not implemented\n");

		req->status.status = cpu_to_be32(
			STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
			STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));

		break;

	case MANAGEMENT_ORB_FUNCTION_LOGOUT:
		sbp_management_request_logout(agent, req, &status_data_len);
		break;

	case MANAGEMENT_ORB_FUNCTION_ABORT_TASK:
		pr_notice("ABORT TASK not implemented\n");

		req->status.status = cpu_to_be32(
			STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
			STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));

		break;

	case MANAGEMENT_ORB_FUNCTION_ABORT_TASK_SET:
		pr_notice("ABORT TASK SET not implemented\n");

		req->status.status = cpu_to_be32(
			STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
			STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));

		break;

	case MANAGEMENT_ORB_FUNCTION_LOGICAL_UNIT_RESET:
		pr_notice("LOGICAL UNIT RESET not implemented\n");

		req->status.status = cpu_to_be32(
			STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
			STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));

		break;

	case MANAGEMENT_ORB_FUNCTION_TARGET_RESET:
		pr_notice("TARGET RESET not implemented\n");

		req->status.status = cpu_to_be32(
			STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
			STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));

		break;

	default:
		pr_notice("unknown management function 0x%x\n",
			MANAGEMENT_ORB_FUNCTION(be32_to_cpu(req->orb.misc)));

		req->status.status = cpu_to_be32(
			STATUS_BLOCK_RESP(STATUS_RESP_REQUEST_COMPLETE) |
			STATUS_BLOCK_SBP_STATUS(SBP_STATUS_REQ_TYPE_NOTSUPP));

		break;
	}

	req->status.status |= cpu_to_be32(
		STATUS_BLOCK_SRC(1) | /* Response to ORB, next_ORB absent */
		STATUS_BLOCK_LEN(DIV_ROUND_UP(status_data_len, 4) + 1) |
		STATUS_BLOCK_ORB_OFFSET_HIGH(agent->orb_offset >> 32));
	req->status.orb_low = cpu_to_be32(agent->orb_offset);

	/* write the status block back to the initiator */
	ret = sbp_run_transaction(req->card, TCODE_WRITE_BLOCK_REQUEST,
		req->node_addr, req->generation, req->speed,
		sbp2_pointer_to_addr(&req->orb.status_fifo),
		&req->status, 8 + status_data_len);
	if (ret != RCODE_COMPLETE) {
		pr_debug("mgt_orb status write failed: %x\n", ret);
		goto out;
	}

out:
	fw_card_put(req->card);
	kfree(req);

	spin_lock_bh(&agent->lock);
	agent->state = MANAGEMENT_AGENT_STATE_IDLE;
	spin_unlock_bh(&agent->lock);
}