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);
}