49 #define SCSI_IOFMT "[%04x][i:%0*x t:%0*x h:%04x]"
50 #define SCSI_ITT_SIZE(ocs) ((ocs->ocs_xport == OCS_XPORT_FC) ? 4 : 8)
52 #define SCSI_IOFMT_ARGS(io) io->instance_index, SCSI_ITT_SIZE(io->ocs), io->init_task_tag, SCSI_ITT_SIZE(io->ocs), io->tgt_task_tag, io->hw_tag
54 #define scsi_io_printf(io, fmt, ...) ocs_log_debug(io->ocs, "[%s]" SCSI_IOFMT fmt, \
55 io->node->display_name, SCSI_IOFMT_ARGS(io), ##__VA_ARGS__)
61 int ocs_mgmt_node_exec(
char *parent,
char *action,
void *arg_in, uint32_t arg_in_length,
62 void *arg_out, uint32_t arg_out_length,
void *node);
87 ocs_node_cb_t cbdata = {0};
90 ocs_lock(&node->active_ios_lock);
92 ocs_log_debug(node->ocs,
"[%s] initiate ELS abort %s\n", node->display_name, els->display_name);
93 ocs_unlock(&node->active_ios_lock);
96 ocs_lock(&node->active_ios_lock);
98 ocs_unlock(&node->active_ios_lock);
119 ocs_remote_node_t *rnode = data;
120 ocs_node_t *node = rnode->node;
140 ocs_log_test(ocs,
"unhandled event %#x\n", event);
145 if ((node->node_group != NULL) &&
147 ocs_node_t *n = NULL;
157 if ((!n->rnode.attached) && (node->node_group == n->node_group)) {
158 n->rnode.attached = attach_ok;
159 node_printf(n,
"rpi[%d] deferred HLM node attach %s posted\n",
160 n->rnode.index, attach_ok ?
"ok" :
"fail");
162 if (!n->rnode.attached) {
163 ocs_atomic_sub_return(&ocs->hal.rpi_ref[n->rnode.index].rpi_count, 1);
165 if (0 == ocs_atomic_read(&ocs->hal.rpi_ref[n->rnode.index].rpi_count)) {
166 ocs_atomic_set(&ocs->hal.rpi_ref[n->rnode.index].rpi_attached, 0);
180 ocs_atomic_sub_return(&ocs->hal.rpi_ref[node->rnode.index].rpi_count, 1);
182 if (0 == ocs_atomic_read(&ocs->hal.rpi_ref[node->rnode.index].rpi_count)) {
183 ocs_atomic_set(&ocs->hal.rpi_ref[node->rnode.index].rpi_attached, 0);
208 node =
spv_get(sport->lookup, port_id);
225 ocs_node_t *node = NULL;;
252 ocs_node_t *node = NULL;;
283 ocs_xport_t *xport = ocs->xport;
288 uint64_t max_xfer_size;
291 xport->nodes_count = node_count;
293 xport->nodes = ocs_malloc(ocs, node_count *
sizeof(ocs_node_t *), OCS_M_ZERO | OCS_M_NOWAIT);
294 if (xport->nodes == NULL) {
295 ocs_log_err(ocs,
"node ptrs allocation failed");
301 max_xfer_size = (max_sge * (uint64_t)num_sgl);
303 max_xfer_size = 65536;
309 for (i = 0; i < node_count; i ++) {
310 node = ocs_malloc(ocs,
sizeof(ocs_node_t), OCS_M_ZERO | OCS_M_NOWAIT);
312 ocs_log_err(ocs,
"node allocation failed");
317 node->instance_index = i;
318 node->max_wr_xfer_size = max_xfer_size;
319 node->rnode.indicator = UINT32_MAX;
321 rc = ocs_dma_alloc(ocs, &node->sparm_dma_buf, 256, 16);
323 ocs_free(ocs, node,
sizeof(ocs_node_t));
324 ocs_log_err(ocs,
"ocs_dma_alloc failed: %d\n", rc);
328 xport->nodes[i] = node;
352 ocs_xport_t *xport = ocs->xport;
361 for (i = 0; i < xport->nodes_count; i ++) {
362 node = xport->nodes[i];
365 ocs_dma_free(ocs, &node->sparm_dma_buf);
366 ocs_free(ocs, node,
sizeof(ocs_node_t));
368 xport->nodes[i] = NULL;
371 ocs_free(ocs, xport->nodes, (xport->nodes_count *
sizeof(ocs_node_t *)));
391 ocs_xport_t *xport = ocs->xport;
392 ocs_node_t *node = NULL;
394 if (index >= (xport->nodes_count)) {
395 ocs_log_test(ocs,
"invalid index: %d\n", index);
398 node = xport->nodes[index];
399 return node->attached ? node : NULL;
418 ocs_node_t *node = NULL;
419 uint32_t instance_index;
420 uint64_t max_wr_xfer_size;
421 ocs_t *ocs = sport->ocs;
422 ocs_xport_t *xport = ocs->xport;
423 ocs_dma_t sparm_dma_buf;
427 if (sport->shutting_down) {
428 ocs_log_debug(ocs,
"node allocation when shutting down %06x", port_id);
436 ocs_log_err(ocs,
"node allocation failed %06x", port_id);
441 instance_index = node->instance_index;
442 max_wr_xfer_size = node->max_wr_xfer_size;
443 sparm_dma_buf = node->sparm_dma_buf;
445 ocs_memset(node, 0,
sizeof(*node));
446 node->instance_index = instance_index;
447 node->max_wr_xfer_size = max_wr_xfer_size;
448 node->sparm_dma_buf = sparm_dma_buf;
449 node->rnode.indicator = UINT32_MAX;
460 ocs_log_err(ocs,
"ocs_hal_node_alloc failed: %d\n", rc);
473 ocs_lock_init(ocs, &node->pend_frames_lock,
"pend_frames_lock[%d]", node->instance_index);
475 ocs_lock_init(ocs, &node->active_ios_lock,
"active_ios[%d]", node->instance_index);
482 ocs_memset(node->sparm_dma_buf.virt, 0, node->sparm_dma_buf.size);
484 node->rnode.node = node;
487 node->unreg_rpi = FALSE;
491 spv_set(sport->lookup, port_id, node);
516 ocs_node_t *ns = NULL;
517 int post_all_free = FALSE;
544 ocs_log_test(ocs,
"ocs_hal_node_free failed: %d\n", rc);
549 if (ocs_timer_pending(&node->gidpt_delay_timer)) {
550 ocs_del_timer(&node->gidpt_delay_timer);
554 if (sport->lookup == NULL) {
555 ocs_log_test(node->ocs,
"assertion failed: sport lookup is NULL\n");
560 spv_set(sport->lookup, node->rnode.fc_id, NULL);
567 post_all_free = TRUE;
577 node->sm.current_state = NULL;
580 ocs_lock_free(&node->pend_frames_lock);
581 ocs_lock_free(&node->active_ios_lock);
617 ocs_strncpy(node->prev_state_name, node->current_state_name,
sizeof(node->prev_state_name));
618 ocs_strncpy(node->current_state_name,
"disabled",
sizeof(node->current_state_name));
623 ocs_lock(&node->active_ios_lock);
628 ocs_unlock(&node->active_ios_lock);
631 ocs_lock(&node->active_ios_lock);
636 ocs_dma_free(els->ocs, &els->els_rsp);
637 ocs_dma_free(els->ocs, &els->els_req);
641 ocs_unlock(&node->active_ios_lock);
644 ocs_lock(&node->active_ios_lock);
649 ocs_dma_free(els->ocs, &els->els_rsp);
650 ocs_dma_free(els->ocs, &els->els_req);
654 ocs_unlock(&node->active_ios_lock);
674 ocs_sport_t *sport = node->sport;
675 ocs_domain_t *domain = sport->domain;
676 ocs_t *ocs = node->ocs;
678 if (!domain->attached) {
679 ocs_log_test(ocs,
"Warning: ocs_node_attach with unattached domain\n");
687 if (ocs->enable_hlm) {
691 ocs_dma_copy_in(&node->sparm_dma_buf, node->service_params+4,
sizeof(node->service_params)-4);
697 ocs_log_test(ocs,
"ocs_hal_node_attach failed: %d\n", rc);
723 ocs_snprintf(buffer, buffer_length,
"fabric");
726 ocs_snprintf(buffer, buffer_length,
"fabctl");
729 ocs_snprintf(buffer, buffer_length,
"nserve");
733 ocs_snprintf(buffer, buffer_length,
"dctl%02x",
736 ocs_snprintf(buffer, buffer_length,
"%06x", fc_id);
757 uint32_t port_id = node->rnode.fc_id;
758 ocs_sport_t *sport = node->sport;
759 char portid_display[16];
765 ocs_snprintf(node->display_name,
sizeof(node->display_name),
"%s.%s", sport->display_name, portid_display);
781 ocs_t *ocs = node->ocs;
785 ocs_log_debug(ocs,
"[%s] cleaning up LS_ACC oxid=0x%x\n",
786 node->display_name, node->ls_acc_oxid);
788 node->ls_acc_io->hio = NULL;
791 node->ls_acc_io = NULL;
803 frame =
ocs_frame_next(&node->pend_frames, &node->pend_frames_lock);
857 switch (node->shutdown_reason) {
870 node_printf(node,
"Shutdown reason: implicit logout, re-authenticate\n");
873 if (node->rnode.indicator == UINT32_MAX) {
875 &node->rnode.indicator, &node->rnode.index)) {
876 ocs_log_err(node->ocs,
"FCOE_RPI allocation failure addr=%#x\n", node->rnode.fc_id);
884 node->unreg_rpi = FALSE;
893 int8_t pend_frames_empty;
899 ocs_lock(&node->pend_frames_lock);
901 ocs_unlock(&node->pend_frames_lock);
908 node_printf(node,
"Shutdown: explicit logo pend=%d sport.ini=%d node.tgt=%d\n",
909 !pend_frames_empty, node->sport->enable_ini, node->targ);
911 if((!pend_frames_empty) || (node->sport->enable_ini && node->targ)) {
912 uint8_t send_plogi = FALSE;
913 if (node->sport->enable_ini && node->targ) {
921 if (node->rnode.indicator == UINT32_MAX) {
923 &node->rnode.indicator, &node->rnode.index)) {
924 ocs_log_err(node->ocs,
"FCOE_RPI allocation failure addr=%#x\n", node->rnode.fc_id);
931 node->unreg_rpi = FALSE;
948 goto restart_node_attach;
959 node_printf(node,
"Shutdown reason: default, purge pending\n");
995 if ((node->els_req_cnt == 0) && (node->els_cmpl_cnt == 0) &&
997 if (!node->attached) {
1034 ocs_lock(&node->active_ios_lock);
1039 (els == node->ls_acc_io)) {
1043 node_printf(node,
"Freeing pending els %s\n", els->display_name);
1046 ocs_dma_free(els->ocs, &els->els_rsp);
1047 ocs_dma_free(els->ocs, &els->els_req);
1051 ocs_unlock(&node->active_ios_lock);
1053 if (node->ls_acc_io && node->ls_acc_io->hio != NULL) {
1063 node_printf(node,
"invalidating ls_acc_io due to implicit logo\n");
1069 node->ls_acc_io->hio = NULL;
1104 uint8_t check_quiesce = FALSE;
1115 check_quiesce = TRUE;
1128 node->els_req_cnt--;
1129 check_quiesce = TRUE;
1135 node->els_cmpl_cnt--;
1136 check_quiesce = TRUE;
1143 check_quiesce = TRUE;
1167 if (check_quiesce) {
1207 node->attached = FALSE;
1279 node->els_req_cnt--;
1319 ocs_node_t *node = NULL;
1321 ocs_node_cb_t *cbdata = arg;
1344 node->attached = TRUE;
1349 node->attached = FALSE;
1358 node->els_cmpl_cnt--;
1369 node->els_req_cnt--;
1376 ocs_log_debug(ocs,
"[%s] (%s) ELS x%02x, LS_RJT not supported\n",
1377 node->display_name, funcname, ((uint8_t*)cbdata->payload->dma.virt)[0]);
1395 ocs_log_debug(ocs,
"[%s] (%s) %s sending ELS_RJT\n",
1410 ocs_log_debug(ocs,
"[%s] (%s) %s sending CT_REJECT\n",
1417 ocs_log_debug(ocs,
"[%s] (%s) %s sending CT_ACCEPT\n",
1425 ocs_log_debug(ocs,
"[%s] (%s) %s sending BA_ACC\n",
1433 int send_empty_event;
1435 ocs_lock(&node->active_ios_lock);
1437 send_empty_event = (!node->io_alloc_enabled) &&
ocs_list_empty(&node->active_ios);
1438 ocs_unlock(&node->active_ios_lock);
1439 if (send_empty_event) {
1446 ocs_log_test(node->ocs,
"[%s] %-20s %-20s not handled\n", node->display_name, funcname,
1471 ocs_memcpy(node->service_params, payload,
sizeof(node->service_params));
1475 node->suppress_rsp = 0;
1500 int free_node = FALSE;
1512 if (!node->hold_frames && (node->evtdepth == 1)) {
1520 if ((node->evtdepth == 0) && node->req_free) {
1549 ocs_sm_ctx_t *ctx = &node->sm;
1552 if (ctx->current_state == state) {
1556 ctx->current_state = state;
1579 ocs_memset(buffer, 0, buffer_len);
1581 ocs_snprintf(buffer, buffer_len,
"eui.%016" PRIX64, eui_name);
1644 ocs_ddump_value(textbuf,
"current_state",
"%s", node->current_state_name);
1654 ocs_ddump_value(textbuf,
"io_alloc_enabled",
"%d", node->io_alloc_enabled);
1655 ocs_ddump_value(textbuf,
"shutdown_reason",
"%d", node->shutdown_reason);
1668 ocs_ddump_value(textbuf,
"chained_io_count",
"%d", node->chained_io_count);
1673 ocs_lock(&node->pend_frames_lock);
1682 ocs_snprintf(buf,
sizeof(buf),
"%02x/%06x/%02x/%02x/%04x/%04x len %ld",
1684 ocs_be16toh(hdr->
ox_id), ocs_be16toh(hdr->
rx_id),
1690 ocs_unlock(&node->pend_frames_lock);
1695 ocs_lock(&node->active_ios_lock);
1713 ocs_unlock(&node->active_ios_lock);
1740 ocs_node_t *node = NULL;
1742 ocs_node_cb_t *cbdata = arg;
1757 ocs_log_debug(node->ocs,
"[%s] %-20s expecting ELS cmd=x%x received type=%d\n",
1758 node->display_name, funcname, cmd, cbdata->els->hio_type);
1760 ocs_log_debug(node->ocs,
"[%s] %-20s expecting ELS cmd=x%x received cmd=x%x\n",
1761 node->display_name, funcname, cmd, els_gen->
command_code);
1764 node_common_func(funcname, ctx, evt, arg);
1790 ocs_node_t *node = NULL;
1792 ocs_node_cb_t *cbdata = arg;
1807 ocs_log_debug(node->ocs,
"[%s] %-20s expecting CT cmd=x%x received type=%d\n",
1808 node->display_name, funcname, cmd, cbdata->els->hio_type);
1810 ocs_log_debug(node->ocs,
"[%s] %-20s expecting CT cmd=x%x received cmd=x%x\n",
1811 node->display_name, funcname, cmd, fcct->
cmd_rsp_code);
1814 node_common_func(funcname, ctx, evt, arg);
1823 ocs_node_cb_t *cbdata = arg;
1840 ocs_node_t *node = (ocs_node_t *)
object;
1865 ocs_lock(&node->active_ios_lock);
1867 if ((io->mgmt_functions) && (io->mgmt_functions->get_list_handler)) {
1868 io->mgmt_functions->get_list_handler(textbuf, io);
1871 ocs_unlock(&node->active_ios_lock);
1880 ocs_node_t *node = (ocs_node_t *)
object;
1886 ocs_snprintf(qualifier,
sizeof(qualifier),
"%s/node[%d]", parent, node->instance_index);
1889 if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
1890 char *unqualified_name = name + strlen(qualifier) +1;
1893 if (ocs_strcmp(unqualified_name,
"display_name") == 0) {
1896 }
else if (ocs_strcmp(unqualified_name,
"indicator") == 0) {
1899 }
else if (ocs_strcmp(unqualified_name,
"fc_id") == 0) {
1902 }
else if (ocs_strcmp(unqualified_name,
"attached") == 0) {
1905 }
else if (ocs_strcmp(unqualified_name,
"hold_frames") == 0) {
1908 }
else if (ocs_strcmp(unqualified_name,
"io_alloc_enabled") == 0) {
1911 }
else if (ocs_strcmp(unqualified_name,
"req_free") == 0) {
1914 }
else if (ocs_strcmp(unqualified_name,
"ls_acc_oxid") == 0) {
1917 }
else if (ocs_strcmp(unqualified_name,
"ls_acc_did") == 0) {
1920 }
else if (ocs_strcmp(unqualified_name,
"abort_cnt") == 0) {
1923 }
else if (ocs_strcmp(unqualified_name,
"targ") == 0) {
1926 }
else if (ocs_strcmp(unqualified_name,
"init") == 0) {
1929 }
else if (ocs_strcmp(unqualified_name,
"wwpn") == 0) {
1932 }
else if (ocs_strcmp(unqualified_name,
"wwnn") == 0) {
1935 }
else if (ocs_strcmp(unqualified_name,
"current_state") == 0) {
1938 }
else if (ocs_strcmp(unqualified_name,
"login_state") == 0) {
1941 }
else if (ocs_strcmp(unqualified_name,
"pend_frames") == 0) {
1943 ocs_lock(&node->pend_frames_lock);
1949 ocs_snprintf(buf,
sizeof(buf),
"%02x/%04x/%04x len %ld", hdr->
r_ctl,
1950 ocs_be16toh(hdr->
ox_id), ocs_be16toh(hdr->
rx_id),
1954 ocs_unlock(&node->pend_frames_lock);
1956 }
else if (ocs_strcmp(unqualified_name,
"chained_io_count") == 0) {
1961 ocs_lock(&node->active_ios_lock);
1963 if ((io->mgmt_functions) && (io->mgmt_functions->get_handler)) {
1964 retval = io->mgmt_functions->get_handler(textbuf, qualifier, name, io);
1971 ocs_unlock(&node->active_ios_lock);
1984 ocs_node_t *node = (ocs_node_t *)
object;
2004 ocs_lock(&node->pend_frames_lock);
2010 ocs_snprintf(buf,
sizeof(buf),
"%02x/%04x/%04x len %ld", hdr->
r_ctl,
2011 ocs_be16toh(hdr->
ox_id), ocs_be16toh(hdr->
rx_id),
2015 ocs_unlock(&node->pend_frames_lock);
2022 ocs_lock(&node->active_ios_lock);
2024 if ((io->mgmt_functions) && (io->mgmt_functions->get_all_handler)) {
2025 io->mgmt_functions->get_all_handler(textbuf,io);
2028 ocs_unlock(&node->active_ios_lock);
2037 ocs_node_t *node = (ocs_node_t *)
object;
2041 ocs_snprintf(qualifier,
sizeof(qualifier),
"%s/node[%d]", parent, node->instance_index);
2044 if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
2046 ocs_lock(&node->active_ios_lock);
2048 if ((io->mgmt_functions) && (io->mgmt_functions->set_handler)) {
2049 retval = io->mgmt_functions->set_handler(qualifier, name, value, io);
2057 ocs_unlock(&node->active_ios_lock);
2066 void *arg_out, uint32_t arg_out_length,
void *
object)
2069 ocs_node_t *node = (ocs_node_t *)
object;
2073 ocs_snprintf(qualifier,
sizeof(qualifier),
"%s.node%d", parent, node->instance_index);
2076 if (ocs_strncmp(action, qualifier, strlen(qualifier)) == 0) {
2077 char *unqualified_name = action + strlen(qualifier) +1;
2079 if (ocs_strcmp(unqualified_name,
"resume") == 0) {
2085 ocs_lock(&node->active_ios_lock);
2087 if ((io->mgmt_functions) && (io->mgmt_functions->exec_handler)) {
2088 retval = io->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length,
2089 arg_out, arg_out_length, io);
2097 ocs_unlock(&node->active_ios_lock);
2121 ocs_lock(&node->active_ios_lock);
2123 ocs_unlock(&node->active_ios_lock);
2142 node->nodedb_state = state;
2174 node->nodedb_state = NULL;
2236 uint32_t payload_size;
2237 } els_cmd_list[] = {
2250 ocs_t *ocs = node->ocs;
2251 ocs_node_cb_t cbdata;
2258 ocs_memset(&cbdata, 0,
sizeof(cbdata));
2259 cbdata.header = seq->
header;
2260 cbdata.payload = seq->
payload;
2263 for (i = 0; i < ARRAY_SIZE(els_cmd_list); i ++) {
2264 if (els_cmd_list[i].cmd == buf[0]) {
2265 evt = els_cmd_list[i].evt;
2266 payload_size = els_cmd_list[i].payload_size;
2281 case OCS_EVT_FLOGI_RCVD:
2287 case OCS_EVT_PLOGI_RCVD: {
2290 ocs_log_info(ocs,
"ELS PLOGI (0x%x) REQ rcvd; OX_ID: %04x, S_ID: %06x, WWPN: %016" PRIX64
"\n",
2296 case OCS_EVT_PRLI_RCVD:
2297 ocs_log_info(ocs,
"ELS PRLI (0x%x) REQ rcvd; OX_ID: %04x, S_ID: %06x, WWPN: %016" PRIX64
"\n",
2306 ocs->xport->fc_stats.stats.fcp_stats.control_requests++;
2311 if (cbdata.io != NULL) {
2312 cbdata.io->hal_priv = seq->
hal_priv;
2314 cbdata.io->seq_init = 1;
2318 node_printf(node,
"failure to allocate SCSI IO for ELS s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
2344 ocs_t *ocs = node->ocs;
2345 ocs_xport_t *xport = ocs->xport;
2347 uint16_t ox_id = ocs_be16toh(hdr->
ox_id);
2348 uint16_t rx_id = ocs_be16toh(hdr->
rx_id);
2349 ocs_node_cb_t cbdata;
2359 uint32_t send_frame_capable;
2361 ocs_log_debug(ocs,
"IO not found (ox_id %04x)\n", ox_id);
2365 if ((rc == 0) && send_frame_capable) {
2368 ocs_log_test(ocs,
"ocs_bls_acc_send_frame failed\n");
2375 ocs_memset(&cbdata, 0,
sizeof(cbdata));
2376 cbdata.header = seq->
header;
2377 cbdata.payload = seq->
payload;
2380 if (cbdata.io != NULL) {
2381 cbdata.io->hal_priv = seq->
hal_priv;
2383 cbdata.io->seq_init = 1;
2386 cbdata.io->ocs = ocs;
2387 cbdata.io->node = node;
2388 cbdata.io->cmd_tgt = TRUE;
2392 ocs_atomic_add_return(&xport->io_alloc_failed_count, 1);
2393 node_printf(node,
"SCSI IO allocation failed for ABTS received s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
2422 ocs_t *ocs = node->ocs;
2428 uint16_t gstype = iu->
gs_type;
2429 ocs_node_cb_t cbdata;
2434 uint32_t payload_size;
2454 ocs_memset(&cbdata, 0,
sizeof(cbdata));
2455 cbdata.header = seq->
header;
2456 cbdata.payload = seq->
payload;
2459 ocs_io_t *els_loopback_io = NULL;
2460 uint16_t ox_id = ocs_be16toh(hdr->
ox_id);
2463 if (els_loopback_io && els_loopback_io->loopback_evt_data.is_loopback_frame) {
2464 cbdata.els = els_loopback_io;
2466 if (els_loopback_io->loopback_evt_data.loopback_rx_data) {
2467 ocs_memcpy(els_loopback_io->loopback_evt_data.loopback_rx_data,
2469 els_loopback_io->loopback_evt_data.loopback_rx_data_len);
2471 ocs_sem_v(&els_loopback_io->loopback_evt_data.wait_io_sem);
2474 ocs_log_err(node->ocs,
"Unable to find loopback frame\n");
2479 for (i = 0; i < ARRAY_SIZE(ct_cmd_list); i ++) {
2480 if (ct_cmd_list[i].cmd == gscmd) {
2481 evt = ct_cmd_list[i].evt;
2482 payload_size = ct_cmd_list[i].payload_size;
2490 ocs->xport->fc_stats.stats.fcp_stats.control_requests++;
2494 if (cbdata.io == NULL) {
2495 node_printf(node,
"GS IO failed for s_id %06x d_id %06x ox_id %04x rx_id %04x\n",
2497 ocs_be16toh(hdr->
ox_id), ocs_be16toh(hdr->
rx_id));
2500 cbdata.io->hal_priv = seq->
hal_priv;
2524 ocs_node_cb_t cbdata;
2525 ocs_t *ocs = node->ocs;
2527 ocs_memset(&cbdata, 0,
sizeof(cbdata));
2528 cbdata.header = seq->
header;
2529 cbdata.payload = seq->
payload;
2553 node_printf(node,
"Dropping frame hdr = %08x %08x %08x %08x %08x %08x\n",
2554 ocs_htobe32(((uint32_t *)hdr)[0]),
2555 ocs_htobe32(((uint32_t *)hdr)[1]),
2556 ocs_htobe32(((uint32_t *)hdr)[2]),
2557 ocs_htobe32(((uint32_t *)hdr)[3]),
2558 ocs_htobe32(((uint32_t *)hdr)[4]),
2559 ocs_htobe32(((uint32_t *)hdr)[5]));
2586 ocs_node_t *node = (ocs_node_t *)rnode->node;
2589 return node->suppress_rsp;
int32_t ocs_node_suppress_resp(ocs_remote_node_t *rnode)
Return node suppress_rsp state.
#define FC_GS_NAMESERVER_GA_NXT
int32_t ocs_hal_io_free(ocs_hal_t *hal, ocs_hal_io_t *io)
Free a previously-allocated HAL IO object.
#define FC_GS_NAMESERVER_GFF_ID
ocs_hal_rtn_e ocs_hal_node_alloc(ocs_hal_t *hal, ocs_remote_node_t *rnode, uint32_t fc_addr, ocs_sli_port_t *sport)
Allocate a remote node object.
int32_t ocs_node_recv_bls_no_sit(ocs_node_t *node, ocs_hal_sequence_t *seq)
Stub handler for non-ABTS BLS frames.
#define FC_GS_NAMESERVER_RCS_ID
#define FC_GS_NAMESERVER_RFT_ID
int32_t ocs_node_recv_abts_frame(ocs_node_t *node, ocs_hal_sequence_t *seq)
Dispatch a ABTS frame (RQ Pair/sequence coalescing).
void * __ocs_node_paused(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Paused node state.
#define FC_GS_NAMESERVER_RPA
ocs_io_t * ocs_els_io_alloc(ocs_node_t *node, uint32_t reqlen, ocs_els_role_e role)
Allocate an IO structure for an ELS IO context.
ocs_hal_rq_buffer_t * header
#define FC_ADDR_CONTROLLER
static int32_t ocs_list_empty(ocs_list_t *list)
Test if a list is empty.
static void ocs_node_lock_free(ocs_node_t *node)
int32_t ocs_node_recv_ct_frame(ocs_node_t *node, ocs_hal_sequence_t *seq)
Dispatch a CT frame.
void ocs_mgmt_emit_int(ocs_textbuf_t *textbuf, int mode, const char *name, const char *fmt,...)
Generate a property with an integer value in a management XML document.
void ocs_ddump_els(ocs_textbuf_t *textbuf, ocs_io_t *els)
Generate ELS context ddump data.
#define FCCT_HDR_CMDRSP_ACCEPT
int32_t node_check_ct_req(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg, uint32_t cmd, ocs_node_common_func_t node_common_func, const char *funcname)
check CT request completion
int ocs_mgmt_node_set(char *parent, char *name, char *value, void *node)
void ocs_node_force_free(ocs_node_t *node)
free memory resources of a node object
#define FCCT_COMMAND_NOT_SUPPORTED
#define FC_GS_NAMESERVER_GID_PT
void * __ocs_node_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
state: shutdown a node
void ocs_node_post_event(ocs_node_t *node, ocs_sm_event_t evt, void *arg)
Post event to node state machine context.
int ocs_mgmt_node_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *node)
void ocs_mgmt_node_list(ocs_textbuf_t *textbuf, void *node)
static void ocs_node_accept_frames(ocs_node_t *node)
accept frames
void ocs_node_transition(ocs_node_t *node, ocs_sm_function_t state, void *data)
transition state of a node
ocs_io_t * ocs_send_ls_rjt(ocs_io_t *io, uint32_t ox_id, uint32_t reason_code, uint32_t reason_code_expl, uint32_t vendor_unique, els_cb_t cb, void *cbarg)
Send an LS_RJT ELS response.
int32_t sli_resource_alloc(sli4_t *sli4, sli4_resource_e rtype, uint32_t *rid, uint32_t *index)
Allocate SLI Port resources.
void ocs_els_post_event(ocs_io_t *els, ocs_sm_event_t evt, void *data)
ELS state machine post event wrapper.
#define FC_GS_NAMESERVER_RPN_ID
static void ocs_device_lock(ocs_t *ocs)
int32_t ocs_node_attach(ocs_node_t *node)
Perform HAL call to attach a remote node.
int32_t ocs_node_purge_pending(ocs_node_t *node)
Purge node's pending (queued) frames.
ocs_hal_sequence_t * ocs_frame_next(ocs_list_t *pend_list, ocs_lock_t *list_lock)
Return next FC frame on node->pend_frames list.
void ocs_display_sparams(const char *prelabel, const char *reqlabel, int dest, void *textbuf, void *sparams)
Display service parameters.
ocs_io_t * ocs_io_find_init_els_io(ocs_t *ocs, ocs_node_t *node, uint16_t ox_id)
Find an els I/O given it's node and ox_id.
ocs_node_t * ocs_node_find(ocs_sport_t *sport, uint32_t port_id)
Find an FC node structure given the FC port ID.
void ocs_node_fcid_display(uint32_t fc_id, char *buffer, uint32_t buffer_length)
Generate text for a node's fc_id.
#define FC_GS_NAMESERVER_RHBA
ocs_node_t * ocs_node_get_instance(ocs_t *ocs, uint32_t index)
return pointer to node object given instance index
void ocs_ddump_section(ocs_textbuf_t *textbuf, const char *name, uint32_t instance)
Generate driver dump section start data.
int ocs_node_active_ios_empty(ocs_node_t *node)
Return TRUE if active ios list is empty.
void *(* ocs_node_common_func_t)(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
int32_t ocs_els_io_list_empty(ocs_node_t *node, ocs_list_t *list)
return TRUE if given ELS list is empty (while taking proper locks)
void ocs_mgmt_start_section(ocs_textbuf_t *textbuf, const char *name, int index)
Generate the beginning of a numbered section in a management XML document.
int const char const char void ocs_mgmt_emit_boolean(ocs_textbuf_t *textbuf, int access, const char *name, const int value)
Generate a property with a boolean value in a management XML document.
void ocs_node_init_device(ocs_node_t *node, int send_plogi)
Initialize device node.
void ocs_els_io_free(ocs_io_t *els)
Free IO structure for an ELS IO context.
#define FC_GS_NAMESERVER_RFF_ID
#define FC_FCTL_END_SEQUENCE
static void * ocs_list_remove(ocs_list_t *list, void *item)
Remove an item from the list.
#define FC_GS_NAMESERVER_GID_FT
static ocs_hal_rtn_e ocs_hal_sequence_free(ocs_hal_t *hal, ocs_hal_sequence_t *seq)
#define FC_REASON_COMMAND_NOT_SUPPORTED
void ocs_node_send_ls_io_cleanup(ocs_node_t *node)
cleans up an XRI for the pending link services accept by aborting the XRI if required.
const char * ocs_sm_event_name(ocs_sm_event_t evt)
#define FC_GS_NAMESERVER_RSNN_NN
#define FC_PLOGI_CSP_W1_VALID_VENDOR_VER_LEVEL
#define ocs_list_init(head, type, link)
static void ocs_node_lock_init(ocs_node_t *node)
#define FC_GS_NAMESERVER_GFPN_ID
void ocs_node_update_display_name(ocs_node_t *node)
update the node's display name
static ocs_mgmt_functions_t node_mgmt_functions
#define FC_ADDR_IS_DOMAIN_CTRL(x)
int32_t ocs_node_free(ocs_node_t *node)
free a node structure
void *(* ocs_sm_function_t)(ocs_sm_ctx_t *, ocs_sm_event_t, void *)
#define ocs_list_foreach_safe(list, item, nxt)
Iterate a linked list safely.
int32_t ocs_node_create_pool(ocs_t *ocs, uint32_t node_count)
allocate node object pool
static void ocs_device_unlock(ocs_t *ocs)
int32_t ocs_remote_node_cb(void *arg, ocs_hal_remote_node_event_e event, void *data)
Handle remote node events from HAL.
#define FC_GS_NAMESERVER_RNN_ID
ocs_hal_rtn_e ocs_hal_get(ocs_hal_t *hal, ocs_hal_property_e prop, uint32_t *value)
ocs_node_t * ocs_node_find_wwnn(ocs_sport_t *sport, uint64_t wwnn)
Find an FC node structure given the WWNN.
ocs_hal_rtn_e ocs_hal_node_attach(ocs_hal_t *hal, ocs_remote_node_t *rnode, ocs_dma_t *sparms)
Update a remote node object with the remote port's service parameters.
void ocs_mgmt_end_section(ocs_textbuf_t *textbuf, const char *name, int index)
Generate the indexed end of a section in a management XML document.
void ocs_node_initiate_cleanup(ocs_node_t *node)
Initiate node IO cleanup.
int ocs_mgmt_node_exec(char *parent, char *action, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length, void *node)
#define FC_REASON_UNABLE_TO_PERFORM
ocs_node_t * ocs_node_find_wwpn(ocs_sport_t *sport, uint64_t wwpn)
Find an FC node structure given the WWPN.
uint64_t ocs_node_get_wwnn(ocs_node_t *node)
return nodes' WWNN as a uint64_t
static void ocs_sport_lock(ocs_sport_t *sport)
ocs_node_t * ocs_node_alloc(ocs_sport_t *sport, uint32_t port_id, uint8_t init, uint8_t targ)
Allocate an fc node structure and add to node list.
void ocs_node_pause(ocs_node_t *node, ocs_sm_function_t state)
Pause a node.
void ocs_ddump_endsection(ocs_textbuf_t *textbuf, const char *name, uint32_t instance)
Generate driver dump section end data.
int32_t ocs_send_ct_rsp(ocs_io_t *io, uint32_t ox_id, fcct_iu_header_t *ct_hdr, uint32_t cmd_rsp_code, uint32_t reason_code, uint32_t reason_code_explanation)
Send CT response.
ocs_mgmt_get_list_handler get_list_handler
void ocs_node_build_eui_name(char *buffer, uint32_t buffer_len, uint64_t eui_name)
build EUI formatted WWN
int32_t ocs_node_recv_els_frame(ocs_node_t *node, ocs_hal_sequence_t *seq)
Dispatch a ELS frame.
#define MAX_ACC_REJECT_PAYLOAD
void * __ocs_node_wait_ios_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
state: initiate node shutdown
ocs_hal_rtn_e ocs_hal_node_free_resources(ocs_hal_t *hal, ocs_remote_node_t *rnode)
Free a remote node resource.
void ocs_scsi_io_alloc_enable(ocs_node_t *node)
Enable IO allocation.
int ocs_sm_post_event(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *data)
Post an event to a context.
static void ocs_node_lock(ocs_node_t *node)
static void ocs_list_add_tail(ocs_list_t *list, void *item)
Add an item to the tail of the list.
int32_t node_check_ct_resp(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
#define OCS_HAL_RTN_IS_ERROR(e)
int32_t ocs_node_resume(ocs_node_t *node)
Resume a paused state.
#define FC_ADDR_GET_DOMAIN_CTRL(x)
#define ocs_list_remove_head(list)
Remove and return an item from the head of the list.
int32_t ocs_sframe_send_bls_acc(ocs_node_t *node, ocs_hal_sequence_t *seq)
Send BA_ACC using sent frame.
void ocs_scsi_tgt_ddump(ocs_textbuf_t *textbuf, ocs_scsi_ddump_type_e type, void *obj)
void * spv_get(sparse_vector_t sv, uint32_t idx)
Return the sparse vector cell value.
#define FCCT_HDR_CMDRSP_REJECT
#define FC_ADDR_NAMESERVER
uint32_t vendor_version_level[4]
int32_t ocs_node_is_remote_node(ocs_remote_node_t *rnode)
int ocs_ddump_node(ocs_textbuf_t *textbuf, ocs_node_t *node)
Generate node ddump data.
void ocs_ddump_io(ocs_textbuf_t *textbuf, ocs_io_t *io)
Generate IO context ddump data.
Defines a general FC sequence object, consisting of a header, payload buffers and a HAL IO in the cas...
ocs_io_t * ocs_bls_send_acc_hdr(ocs_io_t *io, fc_header_t *hdr)
Send a BA_ACC given the request's FC header.
void * __ocs_node_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
state: common node event handler
#define std_node_state_decl(...)
static void ocs_node_hold_frames(ocs_node_t *node)
hold frames in pending frame list
static int ocs_node_check_els_quiesced(ocs_node_t *node)
Checks to see if ELS's have been quiesced.
void * __ocs_d_device_ready(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Device node state machine: Device is ready.
int32_t ocs_process_node_pending(ocs_node_t *node)
Process pending frames queued to the given node.
#define node_printf(node, fmt,...)
void * __ocs_d_wait_node_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Device node state machine: Wait for a node attach when found by a remote node.
void ocs_node_free_pool(ocs_t *ocs)
free node object pool
ocs_hal_remote_node_event_e
#define ocs_assert(cond,...)
static int ocs_node_process_plogi_frame(ocs_node_t *node)
#define FC_GS_TYPE_LOOPBACK
static void ocs_io_free(ocs_t *ocs, ocs_io_t *io)
void * __ocs_node_wait_node_free(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Node state machine: Wait for a HAL node free event to complete.
void * __ocs_node_wait_els_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
Node state machine: Wait for all ELSs to complete.
static uint32_t fc_be24toh(uint32_t x)
static void ocs_scsi_notify_node_force_free(ocs_node_t *node)
Notification from base driver that node is in force-free path.
#define FC_GS_NAMESERVER_RSPN_ID
void ocs_mgmt_emit_string(ocs_textbuf_t *textbuf, int access, const char *name, const char *value)
Generate a property with a string value in a management XML document.
ocs_io_t * ocs_io_find_tgt_io(ocs_t *ocs, ocs_node_t *node, uint16_t ox_id, uint16_t rx_id)
Find an I/O given it's node and ox_id.
ocs_io_t * ocs_scsi_io_alloc(ocs_node_t *node, ocs_scsi_io_role_e role)
Allocate a SCSI IO context.
#define ocs_list_foreach(list, item)
Iterate a linked list.
void ocs_node_abort_all_els(ocs_node_t *node)
Device node state machine wait for all ELS's to complete.
int32_t node_check_els_req(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg, uint8_t cmd, ocs_node_common_func_t node_common_func, const char *funcname)
check ELS request completion
#define FC_EXPL_NO_ADDITIONAL
#define OCS_FC_PLOGI_VENDOR_VERSION_EMLX_ID
#define FC_GS_NAMESERVER_GPN_ID
int32_t ocs_node_recv_fcp_cmd(ocs_node_t *node, ocs_hal_sequence_t *seq)
Dispatch a FCP command frame when the node is not ready.
static void ocs_node_unlock(ocs_node_t *node)
int ocs_node_group_init(ocs_node_t *node)
Initialize a node for high login mode.
#define FC_GS_NAMESERVER_GNN_ID
void ocs_sm_disable(ocs_sm_ctx_t *ctx)
Disable further state machine processing.
static void ocs_sport_unlock(ocs_sport_t *sport)
void ocs_mgmt_emit_property_name(ocs_textbuf_t *textbuf, int access, const char *name)
Generate a property, with no value, in a management XML document.
void ocs_node_save_sparms(ocs_node_t *node, void *payload)
save node service parameters
void ocs_ddump_value(ocs_textbuf_t *textbuf, const char *name, const char *fmt,...)
Generate driver dump data for a given value.
ocs_hal_rq_buffer_t * payload
uint64_t ocs_node_get_wwpn(ocs_node_t *node)
return nodes' WWPN as a uint64_t
void spv_set(sparse_vector_t sv, uint32_t idx, void *value)
Set the sparse vector cell value.
uint32_t common_service_parameters[4]
void ocs_scsi_ini_ddump(ocs_textbuf_t *textbuf, ocs_scsi_ddump_type_e type, void *obj)
void ocs_mgmt_node_get_all(ocs_textbuf_t *textbuf, void *node)
void ocs_send_ls_acc_after_attach(ocs_io_t *io, fc_header_t *hdr, ocs_node_send_ls_acc_e ls)
Save the OX_ID for sending LS_ACC sometime later.