46 #if defined(OCS_ENABLE_VPD_SUPPORT)
51 #define SCSI_IOFMT "[%04x][i:%0*x t:%0*x h:%04x]"
52 #define SCSI_ITT_SIZE(ocs) ((ocs->ocs_xport == OCS_XPORT_FC) ? 4 : 8)
54 #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
56 #define enable_tsend_auto_resp(ocs) ((ocs->ctrlmask & OCS_CTRLMASK_XPORT_DISABLE_AUTORSP_TSEND) == 0)
57 #define enable_treceive_auto_resp(ocs) ((ocs->ctrlmask & OCS_CTRLMASK_XPORT_DISABLE_AUTORSP_TRECEIVE) == 0)
59 #define scsi_io_printf(io, fmt, ...) ocs_log_info(io->ocs, "[%s]" SCSI_IOFMT fmt, \
60 io->node->display_name, SCSI_IOFMT_ARGS(io), ##__VA_ARGS__)
62 #define scsi_io_trace(io, fmt, ...) \
64 if (OCS_LOG_ENABLE_SCSI_TRACE(io->ocs)) \
65 scsi_io_printf(io, fmt, ##__VA_ARGS__); \
68 #define scsi_log(ocs, fmt, ...) \
70 if (OCS_LOG_ENABLE_SCSI_TRACE(ocs)) \
71 ocs_log_info(ocs, fmt, ##__VA_ARGS__); \
76 uint32_t ext,
void *arg);
83 uint32_t addrlen_count,
ocs_dif_t *dif,
int is_crc);
102 static inline uint32_t
105 return ocs_be32toh(*((uint32_t*)p));
125 ocs_lock(&node->active_ios_lock);
126 node->io_alloc_enabled = TRUE;
127 ocs_unlock(&node->active_ios_lock);
147 ocs_lock(&node->active_ios_lock);
148 node->io_alloc_enabled = FALSE;
149 ocs_unlock(&node->active_ios_lock);
165 ocs_lock(&node->active_ios_lock);
166 state = node->io_alloc_enabled;
167 ocs_unlock(&node->active_ios_lock);
205 ocs_lock(&node->active_ios_lock);
207 if (!node->io_alloc_enabled) {
208 ocs_unlock(&node->active_ios_lock);
214 ocs_atomic_add_return(&xport->io_alloc_failed_count, 1);
215 ocs_unlock(&node->active_ios_lock);
222 if (io->hio != NULL) {
223 ocs_log_err(node->ocs,
"assertion failed: io->hio is not NULL\n");
224 ocs_unlock(&node->active_ios_lock);
234 io->display_name =
"scsi_io";
250 ocs_unlock(&node->active_ios_lock);
271 ocs_io_t *io = (ocs_io_t *)arg;
272 ocs_t *ocs = io->ocs;
273 ocs_node_t *node = io->node;
278 scsi_io_trace(io,
"freeing io 0x%p %s\n", io, io->display_name);
282 ocs_lock(&node->active_ios_lock);
284 ocs_unlock(&node->active_ios_lock);
287 ocs_node_cb_t cb_data;
289 ocs_memset(&cb_data, 0,
sizeof(ocs_node_cb_t));
293 ocs_lock(&node->active_ios_lock);
295 ocs_unlock(&node->active_ios_lock);
299 #if defined(OCS_INCLUDE_SCST)
300 io->tgt_io.iostate = 0;
319 scsi_io_trace(io,
"freeing io 0x%p %s\n", io, io->display_name);
321 ocs_ref_put(&io->ref);
330 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, uint32_t first_burst,
351 int32_t status, uint32_t ext_status,
void *app)
356 uint16_t additional_length;
364 scsi_io_trace(io,
"status x%x ext_status x%x\n", status, ext_status);
371 io->transferred += length;
374 if (io->scsi_tgt_cb) {
379 io->scsi_tgt_cb = NULL;
384 if ((status == 0) && (io->auto_resp))
401 additional_length = ((ext_status >> 16) & 0xFFFF);
421 if ((additional_length != 0) && (tdpv != 0) &&
432 switch (ext_status) {
453 ocs_log_info(io->ocs,
454 "IO timed out tag %04x (%d) ox_id=%x xri=%#x\n",
455 io->tag, io->tag, io->iparam.fcp_tgt.ox_id, hio->indicator);
468 cb(io, scsi_status, flags, io->scsi_tgt_cb_arg);
541 ocs_t *ocs = io->ocs;
545 uint64_t first_check_block;
546 uint64_t last_check_block;
547 uint32_t check_count;
549 int32_t addrlen_count = 0;
554 first_check_block = length / blocksize;
555 last_check_block = ((length + check_length) / blocksize);
556 check_count = last_check_block - first_check_block;
558 ocs_log_debug(ocs,
"blocksize %d first check_block %" PRId64
" last_check_block %" PRId64
" check_count %d\n",
559 blocksize, first_check_block, last_check_block, check_count);
561 for (i = first_check_block; i < last_check_block; i++) {
563 if (addrlen_count < 0) {
564 ocs_log_test(ocs,
"ocs_scsi_get_block_vaddr() failed: %d\n", addrlen_count);
570 ocs_log_debug(ocs,
"block guard check error, lba %" PRId64
"\n", scsi_dif_info.
lba + i);
575 ocs_log_debug(ocs,
"app tag check error, lba %" PRId64
"\n", scsi_dif_info.
lba + i);
580 ocs_log_debug(ocs,
"ref tag check error, lba %" PRId64
"\n", scsi_dif_info.
lba + i);
616 for (i = 0; i < addrlen_count; i++) {
619 return (crc == ocs_be16toh(dif->
crc));
623 return (checksum == dif->
crc);
647 ocs_log_debug(ocs,
"expected app tag 0x%x, actual 0x%x\n",
648 exp_app_tag, ocs_be16toh(dif->
app_tag));
650 return (exp_app_tag == ocs_be16toh(dif->
app_tag));
673 if (exp_ref_tag != ocs_be32toh(dif->
ref_tag)) {
674 ocs_log_debug(ocs,
"expected ref tag 0x%x, actual 0x%x\n",
675 exp_ref_tag, ocs_be32toh(dif->
ref_tag));
708 for (i = 0; i < sgl_count; i++) {
727 ocs_t *ocs = hal->os;
728 uint32_t blocksize = 0;
736 ocs_log_err(ocs,
"ocs_hal_io_init_sges failed: %d\n", rc);
764 ocs_log_test(hal->os,
"Inavlid hal_dif blocksize %d\n", hal_dif->
blk_size);
767 for (i = 0; i < sgl_count; i++) {
768 if ((sgl[i].len % blocksize) != 0) {
769 ocs_log_test(hal->os,
"sgl[%d] len of %ld is not multiple of blocksize\n",
776 for (i = 0; i < sgl_count; i++) {
791 blockcount = sgl[i].
len / blocksize;
802 ocs_log_err(ocs,
"ocs_hal_io_add_sge failed: count=%d rc=%d\n",
808 for (i = 0; i < sgl_count; i++) {
815 ocs_log_err(ocs,
"ocs_hal_io_add_sge failed: count=%d rc=%d\n",
842 if (scsi_dif_info == NULL) {
887 ocs_log_test(ocs,
"unhandled SCSI DIF operation %d\n",
912 ocs_log_test(ocs,
"unhandled SCSI DIF block size %d\n",
949 ocs_hal_io_t *hio = io->hio;
951 uint32_t *dword = NULL;
956 ocs_addr32_hi(hio->def_sgl.phys),
957 ocs_addr32_lo(hio->def_sgl.phys));
958 n_sge = (hio->sgl == &hio->def_sgl ? hio->n_sge : hio->def_sgl_count);
959 for (i = 0, data = hio->def_sgl.virt; i < n_sge; i++, data++) {
960 dword = (uint32_t*)data;
963 i, dword[0], dword[1], dword[2], dword[3]);
965 if (dword[2] & (1U << 31)) {
970 if (hio->ovfl_sgl != NULL &&
971 hio->sgl == hio->ovfl_sgl) {
973 ocs_addr32_hi(hio->ovfl_sgl->phys),
974 ocs_addr32_lo(hio->ovfl_sgl->phys));
975 for (i = 0, data = hio->ovfl_sgl->virt; i < hio->n_sge; i++, data++) {
976 dword = (uint32_t*)data;
979 i, dword[0], dword[1], dword[2], dword[3]);
980 if (dword[2] & (1U << 31)) {
1009 if (io->hal_cb != NULL) {
1034 ocs_xport_t *xport = ocs->xport;
1042 if (ocs_atomic_add_return(&xport->io_pending_recursing, 1)) {
1044 ocs_atomic_sub_return(&xport->io_pending_recursing, 1);
1049 ocs_lock(&xport->io_pending_lock);
1066 hio->eq = io->hal_priv;
1071 ocs_unlock(&xport->io_pending_lock);
1080 ocs_atomic_sub_return(&xport->io_pending_count, 1);
1093 ocs_log_test(ocs,
"call to ocs_hal_async_call() failed\n");
1097 }
while (io != NULL);
1109 ocs_lock(&xport->io_pending_lock);
1112 if (io->io_to_abort->hio != NULL) {
1122 ocs_atomic_sub_return(&xport->io_pending_count, 1);
1126 ocs_unlock(&xport->io_pending_lock);
1132 ocs_log_test(ocs,
"call to ocs_hal_async_call() failed\n");
1138 ocs_atomic_sub_return(&xport->io_pending_recursing, 1);
1165 ocs_t *ocs = io->ocs;
1166 ocs_xport_t *xport = ocs->xport;
1176 if (io->hio != NULL) {
1185 ocs_lock(&xport->io_pending_lock);
1191 if (io->low_latency) {
1196 ocs_unlock(&xport->io_pending_lock);
1197 ocs_atomic_add_return(&xport->io_pending_count, 1);
1198 ocs_atomic_add_return(&xport->io_total_pending, 1);
1204 ocs_unlock(&xport->io_pending_lock);
1214 ocs_lock(&xport->io_pending_lock);
1216 ocs_unlock(&xport->io_pending_lock);
1218 ocs_atomic_add_return(&xport->io_total_pending, 1);
1219 ocs_atomic_add_return(&xport->io_pending_count, 1);
1245 ocs_t *ocs = io->ocs;
1246 ocs_xport_t *xport = ocs->xport;
1256 ocs_lock(&xport->io_pending_lock);
1259 ocs_unlock(&xport->io_pending_lock);
1260 ocs_atomic_add_return(&xport->io_pending_count, 1);
1261 ocs_atomic_add_return(&xport->io_total_pending, 1);
1267 ocs_unlock(&xport->io_pending_lock);
1291 ocs_t *ocs = io->ocs;
1297 io->tgt_task_tag = hio->indicator;
1298 }
else if (io->cmd_ini) {
1299 io->init_task_tag = hio->indicator;
1301 io->hw_tag = hio->reqtag;
1303 hio->eq = io->hal_priv;
1306 switch(io->wq_steering) {
1319 switch (io->io_type) {
1322 uint32_t total_count;
1323 uint32_t host_allocated;
1338 if (host_allocated && total_count > max_sgl) {
1340 uint32_t count = total_count - max_sgl + 1;
1341 rc = ocs_dma_alloc(ocs, &io->ovfl_sgl, count*
sizeof(
sli4_sge_t), 64);
1343 ocs_log_err(ocs,
"ocs_dma_alloc overflow sgl failed\n");
1349 ocs_log_err(ocs,
"ocs_hal_io_register_sgl() failed\n");
1353 io->node->chained_io_count++;
1356 rc =
ocs_scsi_build_sgls(&ocs->hal, io->hio, &io->hal_dif, io->sgl, io->sgl_count, io->hio_type);
1367 io->iparam.fcp_tgt.app_id = io->app_id;
1370 rc =
ocs_hal_io_send(&io->ocs->hal, io->hio_type, io->hio, io->wire_len, &io->iparam, &io->node->rnode,
1377 &io->els_req, io->wire_len,
1378 &io->els_rsp, &io->node->rnode, &io->iparam,
1384 &io->els_rsp, io->wire_len,
1385 NULL, &io->node->rnode, &io->iparam,
1393 NULL, 0, NULL, &io->node->rnode, &io->iparam, io->hal_cb, io);
1420 switch (io->io_type) {
1422 ocs_hal_io_t *hio_to_abort = NULL;
1424 hio_to_abort = io->io_to_abort->hio;
1426 if (hio_to_abort == NULL) {
1501 static inline int32_t
1510 uint32_t disable_ar_tgt_dif = FALSE;
1511 size_t residual = 0;
1519 if (dif_info != NULL) {
1521 if (disable_ar_tgt_dif) {
1526 io->sgl_count = sgl_count;
1529 if (sgl && (sgl != io->sgl)) {
1530 ocs_assert(sgl_count <= io->sgl_allocated, -1);
1531 ocs_memcpy(io->sgl, sgl, sgl_count*
sizeof(*io->sgl));
1542 ocs_assert(io->exp_xfer_len > io->transferred, -1);
1544 io->hio_type = type;
1546 io->scsi_tgt_cb = cb;
1547 io->scsi_tgt_cb_arg = arg;
1556 io->scsi_dif_info = *dif_info;
1559 io->wire_len = MIN(xwire_len, io->exp_xfer_len - io->transferred);
1560 residual = (xwire_len - io->wire_len);
1562 ocs_memset(&io->iparam, 0,
sizeof(io->iparam));
1563 io->iparam.fcp_tgt.ox_id = io->init_task_tag;
1564 io->iparam.fcp_tgt.offset = io->transferred;
1565 io->iparam.fcp_tgt.dif_oper = io->hal_dif.dif;
1566 io->iparam.fcp_tgt.blk_size = io->hal_dif.blk_size;
1567 io->iparam.fcp_tgt.cs_ctl = io->cs_ctl;
1568 io->iparam.fcp_tgt.timeout = io->timeout;
1569 io->iparam.fcp_tgt.wqe_timer = io->trecv_wqe_timer;
1577 io->auto_resp = TRUE;
1579 io->auto_resp = FALSE;
1583 io->xfer_req = io->wire_len;
1588 io->transferred += residual;
1596 size_t len = sgl_ptr->
len;
1597 if ( len > residual) {
1598 sgl_ptr->
len = len - residual;
1617 ocs->xport->fc_stats.stats.fcp_stats.input_requests++;
1618 ocs->xport->fc_stats.stats.fcp_stats.input_bytes += xwire_len;
1620 ocs->xport->fc_stats.stats.fcp_stats.output_requests++;
1621 ocs->xport->fc_stats.stats.fcp_stats.output_bytes += xwire_len;
1661 if (io->ovfl_sgl.size) {
1662 ocs_dma_free(io->ocs, &io->ovfl_sgl);
1692 int auto_resp = TRUE;
1693 uint8_t scsi_status = 0;
1694 uint16_t scsi_status_qualifier = 0;
1695 uint8_t *sense_data = NULL;
1696 uint32_t sense_data_length = 0;
1709 ocs_log_test(io->ocs,
"Got completion while the link is down or invalid RPI/XRI or sequence timeout, tag 0x%x\n", io->tag);
1722 residual = io->exp_xfer_len - io->transferred;
1728 io->scsi_tgt_cb = cb;
1729 io->scsi_tgt_cb_arg = arg;
1731 ocs_memset(&io->iparam, 0,
sizeof(io->iparam));
1732 io->iparam.fcp_tgt.ox_id = io->init_task_tag;
1733 io->iparam.fcp_tgt.offset = 0;
1734 io->iparam.fcp_tgt.cs_ctl = io->cs_ctl;
1735 io->iparam.fcp_tgt.timeout = io->timeout;
1736 io->iparam.fcp_tgt.wqe_timer = io->trecv_wqe_timer;
1747 ocs_log_err(ocs,
"NULL response buffer\n");
1753 ocs_memset(fcprsp, 0,
sizeof(*fcprsp));
1755 io->wire_len += (
sizeof(*fcprsp) -
sizeof(fcprsp->
data));
1758 *((uint16_t*)fcprsp->
status_qualifier) = ocs_htobe16(scsi_status_qualifier);
1761 if (residual != 0) {
1768 *((uint32_t *)fcprsp->
fcp_resid) = ocs_htobe32(residual);
1771 *((uint32_t *)fcprsp->
fcp_resid) = ocs_htobe32(-residual);
1778 ocs_memcpy(fcprsp->
data, sense_data, sense_data_length);
1779 *((uint32_t*)fcprsp->
fcp_sns_len) = ocs_htobe32(sense_data_length);
1780 io->wire_len += sense_data_length;
1783 io->sgl[0].addr = io->rspbuf.phys;
1784 io->sgl[0].dif_addr = 0;
1785 io->sgl[0].len = io->wire_len;
1822 uint8_t fcp_rspcode;
1857 io->scsi_tgt_cb = cb;
1858 io->scsi_tgt_cb_arg = arg;
1866 fcprsp = io->rspbuf.virt;
1867 ocs_memset(fcprsp, 0,
sizeof(*fcprsp));
1872 if (addl_rsp_info != NULL) {
1877 io->wire_len =
sizeof(*fcprsp) -
sizeof(fcprsp->
data) +
sizeof(*rspinfo);
1879 *((uint32_t*)fcprsp->
fcp_rsp_len) = ocs_htobe32(
sizeof(*rspinfo));
1881 io->sgl[0].addr = io->rspbuf.phys;
1882 io->sgl[0].dif_addr = 0;
1883 io->sgl[0].len = io->wire_len;
1886 ocs_memset(&io->iparam, 0,
sizeof(io->iparam));
1887 io->iparam.fcp_tgt.ox_id = io->init_task_tag;
1888 io->iparam.fcp_tgt.offset = 0;
1889 io->iparam.fcp_tgt.cs_ctl = io->cs_ctl;
1890 io->iparam.fcp_tgt.timeout = io->timeout;
1915 ocs_target_abort_cb(ocs_hal_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status,
void *app)
1928 void *abort_cb_arg = io->abort_cb_arg;
1930 io->abort_cb = NULL;
1931 io->abort_cb_arg = NULL;
1938 switch (ext_status) {
1959 abort_cb(io->io_to_abort, scsi_status, 0, abort_cb_arg);
1965 ocs_ref_put(&io->io_to_abort->ref);
1995 ocs_io_t *abort_io = NULL;
2004 if ((ocs_ref_get_unless_zero(&io->ref) == 0)) {
2016 if (abort_io == NULL) {
2017 ocs_atomic_add_return(&xport->io_alloc_failed_count, 1);
2018 ocs_ref_put(&io->ref);
2026 abort_io->cmd_tgt = TRUE;
2027 abort_io->node = io->node;
2031 abort_io->display_name =
"tgt_abort";
2032 abort_io->io_to_abort = io;
2033 abort_io->send_abts = send_abts;
2034 abort_io->abort_cb = cb;
2035 abort_io->abort_cb_arg = arg;
2040 ocs_ref_put(&io->ref);
2062 ocs_target_bls_resp_cb(ocs_hal_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status,
void *app)
2083 void *bls_cb_arg = io->bls_cb_arg;
2086 io->bls_cb_arg = NULL;
2089 bls_cb(io, bls_status, 0, bls_cb_arg);
2118 ocs_memset(&io->iparam, 0,
sizeof(io->iparam));
2119 io->iparam.bls.ox_id = io->init_task_tag;
2120 io->iparam.bls.rx_id = io->abort_rx_id;
2122 acc = (
void *)io->iparam.bls.payload;
2124 ocs_memset(io->iparam.bls.payload, 0,
sizeof(io->iparam.bls.payload));
2125 acc->
ox_id = io->iparam.bls.ox_id;
2126 acc->
rx_id = io->iparam.bls.rx_id;
2133 io->display_name =
"bls_rsp";
2136 io->bls_cb_arg = arg;
2163 ocs_log_test(io->ocs,
"Got completion for non-busy io with tag 0x%x\n", io->tag);
2167 scsi_io_trace(io,
"freeing io 0x%p %s\n", io, io->display_name);
2168 ocs_assert(ocs_ref_read_count(&io->ref) > 0);
2169 ocs_ref_put(&io->ref);
2191 int32_t status, uint32_t ext_status,
void *app)
2200 scsi_io_trace(io,
"status x%x ext_status x%x\n", status, ext_status);
2208 if (io->scsi_ini_cb) {
2213 uint8_t *pd = fcprsp->
data;
2216 io->scsi_ini_cb = NULL;
2218 ocs_memset(&rsp, 0,
sizeof(rsp));
2256 if (length != io->wire_len) {
2257 uint32_t rsp_len = ext_status;
2258 uint8_t *rsp_bytes = io->rspbuf.virt;
2260 uint8_t all_zeroes = (rsp_len > 0);
2262 for (i = 0; i < rsp_len; i++) {
2263 if (rsp_bytes[i] != 0) {
2270 ocs_log_test(io->ocs,
"[%s]" SCSI_IOFMT "local reject=0x%02x\n",
2284 if (ext_status & 0x01) {
2286 }
else if (ext_status & 0x02) {
2288 }
else if (ext_status & 0x04) {
2299 cb(io, scsi_status, &rsp, flags, io->scsi_ini_cb_arg);
2339 rc =
ocs_scsi_send_io(
OCS_HAL_IO_INITIATOR_READ, node, io, lun, 0, cdb, cdb_len, dif_info, sgl, sgl_count,
2340 wire_len, 0, cb, arg);
2378 rc =
ocs_scsi_send_io(
OCS_HAL_IO_INITIATOR_WRITE, node, io, lun, 0, cdb, cdb_len, dif_info, sgl, sgl_count,
2379 wire_len, 0, cb, arg);
2414 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, uint32_t first_burst,
2419 rc =
ocs_scsi_send_io(
OCS_HAL_IO_INITIATOR_WRITE, node, io, lun, 0, cdb, cdb_len, dif_info, sgl, sgl_count,
2420 wire_len, 0, cb, arg);
2450 rc =
ocs_scsi_send_io(
OCS_HAL_IO_INITIATOR_NODATA, node, io, lun, 0, cdb, cdb_len, NULL, NULL, 0, 0, 0, cb, arg);
2492 if ((ocs_ref_get_unless_zero(&io_to_abort->ref) == 0)) {
2501 io->display_name =
"abort_task";
2502 io->io_to_abort = io_to_abort;
2503 io->send_abts = TRUE;
2504 io->scsi_ini_cb = cb;
2505 io->scsi_ini_cb_arg = arg;
2511 ocs_ref_put(&io->ref);
2514 io->display_name =
"tmf";
2516 sgl, sgl_count, len, 0, cb, arg);
2552 ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, uint32_t first_burst,
2558 uint32_t cmnd_bytes = 0;
2559 uint8_t abort_test_bits;
2561 uint8_t tmf_flags = 0;
2569 io->sgl_count = sgl_count;
2572 if (sgl != io->sgl) {
2573 ocs_assert(sgl_count <= io->sgl_allocated, -1);
2574 ocs_memcpy(io->sgl, sgl,
sizeof(*io->sgl) * sgl_count);
2578 io->tgt_task_tag = 0xffff;
2580 io->wire_len = wire_len;
2581 io->hio_type = type;
2591 for (i = 0; i < cdb_len; i ++) {
2602 cmnd = io->cmdbuf.virt;
2604 ocs_assert(
sizeof(*cmnd) <= io->cmdbuf.size, -1);
2606 ocs_memset(cmnd, 0,
sizeof(*cmnd));
2614 if (cdb_len <= 16) {
2615 ocs_memcpy(cmnd->
fcp_cdb, cdb, cdb_len);
2617 uint32_t addl_cdb_bytes;
2619 ocs_memcpy(cmnd->
fcp_cdb, cdb, 16);
2620 addl_cdb_bytes = cdb_len - 16;
2627 cmnd_bytes += (addl_cdb_bytes + 3) & ~0x3;
2632 abort_test_bits = (lun >> 24);
2636 cmnd->
fcp_lun[1] = lun & 0xff;
2643 cmnd->
fcp_lun[1] = lun & 0xff;
2645 ocs_log_test(ocs,
"unsupported LU %08X\n", lun);
2649 cmnd->
fcp_lun[2] = abort_test_bits;
2678 *fcp_dl = ocs_htobe32(io->wire_len);
2680 switch (io->hio_type) {
2691 ocs_log_test(ocs,
"bad IO type %d\n", io->hio_type);
2700 io->scsi_ini_cb = cb;
2701 io->scsi_ini_cb_arg = arg;
2704 io->iparam.fcp_ini.cmnd = &io->cmdbuf;
2705 io->iparam.fcp_ini.cmnd_size = cmnd_bytes;
2706 io->iparam.fcp_ini.rsp = &io->rspbuf;
2707 io->iparam.fcp_ini.flags = 0;
2708 io->iparam.fcp_ini.dif_oper = io->hal_dif.dif;
2709 io->iparam.fcp_ini.blk_size = io->hal_dif.blk_size;
2710 io->iparam.fcp_ini.timeout = io->timeout;
2711 io->iparam.fcp_ini.first_burst = first_burst;
2735 uint32_t ext_status,
void *arg)
2747 ocs_log_debug(ocs,
"status %d ext %d\n", status, ext_status);
2750 ocs_ref_put(&io->io_to_abort->ref);
2766 ocs_log_test(ocs,
"Unhandled local reject 0x%x/0x%x\n", status, ext_status);
2775 if (io->scsi_ini_cb) {
2776 (*io->scsi_ini_cb)(io, scsi_status, NULL, 0, io->scsi_ini_cb_arg);
2801 ocs_xport_t *xport = ocs->xport;
2854 ocs_log_debug(ocs,
"invalid property request %d\n", prop);
2888 #if defined(OCS_ENABLE_VPD_SUPPORT)
2895 ocs_log_test(ocs,
"Can't get VPD length\n");
2896 rc =
"\012sn-unknown";
2906 ocs_strlen(rc) == 0) {
2908 scsi_log(ocs,
"Note: VPD is missing, using wwnn for serial number\n");
2910 if ((ocs == NULL) || (ocs->domain == NULL) || (ocs->domain->sport == NULL)) {
2911 rc =
"\011(Unknown)";
2913 rc = &ocs->domain->sport->wwnn_str[8];
2924 ocs_log_test(ocs,
"Can't get VPD length\n");
2925 rc =
"\012pn-unknown";
2932 rc =
"\012pn-unknown";
2935 rc =
"\012pn-unknown";
2945 ocs_log_debug(ocs,
"invalid property request %d\n", prop);
3008 io->transferred = transferred;
3030 ocs_log_test(ocs,
"ocs_hal_callback(OCS_HAL_CB_BOUNCE) failed: %d\n", rc);
uint8_t additional_fcp_cdb_length
static int32_t ocs_target_send_bls_resp(ocs_io_t *io, ocs_scsi_io_cb_t cb, void *arg)
Complete abort request.
static void ocs_initiator_io_cb(ocs_hal_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app)
Handle initiator IO completion.
#define FCP_RSP_LEN_VALID
static int32_t ocs_scsi_build_sgls(ocs_hal_t *hal, ocs_hal_io_t *hio, ocs_hal_dif_info_t *hal_dif, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, ocs_hal_io_type_e type)
uint32_t disable_app_ffff
ocs_hal_rtn_e ocs_hal_srrs_send(ocs_hal_t *hal, ocs_hal_io_type_e type, ocs_hal_io_t *io, ocs_dma_t *send, uint32_t len, ocs_dma_t *receive, ocs_remote_node_t *rnode, ocs_hal_io_param_t *iparam, ocs_hal_srrs_cb_t cb, void *arg)
Send a Single Request/Response Sequence (SRRS).
static int32_t ocs_io_busy(ocs_io_t *io)
Test if IO object is busy.
static uint32_t ocs_scsi_dif_check_guard(ocs_hal_dif_info_t *dif_info, ocs_scsi_vaddr_len_t addrlen[], uint32_t addrlen_count, ocs_dif_t *dif, int is_crc)
Check the block guard of block data.
static void _ocs_scsi_io_free(void *arg)
Free a SCSI IO context (internal).
static int32_t ocs_scsi_check_pending_async_cb(ocs_hal_t *hal, int32_t status, uint8_t *mqe, void *arg)
Check pending error asynchronous callback function.
#define SLI4_FC_LOCAL_REJECT_ABORT_IN_PROGRESS
static int ocs_scsi_dif_guard_is_crc(uint8_t direction, ocs_hal_dif_info_t *dif_info)
Determine if an IO is using CRC for DIF guard format.
#define SLI4_FC_WCQE_STATUS_SHUTDOWN
static void ocs_scsi_io_free_ovfl(ocs_io_t *io)
Free overflow SGL.
static int32_t ocs_list_empty(ocs_list_t *list)
Test if a list is empty.
T10 DIF information passed to the transport.
static int32_t ocs_scsi_io_dispatch_no_hal_io(ocs_io_t *io)
Dispatch IO.
T10 DIF information passed to the transport.
#define OCS_SCSI_WQ_STEERING_REQUEST
int32_t ocs_scsi_io_dispatch_abort(ocs_io_t *io, void *cb)
Attempt to dispatch an Abort IO.
static void ocs_target_io_cb(ocs_hal_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app)
Target response completion callback.
static ocs_scsi_io_status_e ocs_scsi_dif_check_unknown(ocs_io_t *io, uint32_t length, uint32_t check_length, int is_crc)
Check a block and DIF data, computing the appropriate SCSI status.
#define SLI4_FC_WCQE_STATUS_LOCAL_REJECT
#define SLI4_FC_DI_ERROR_GE
DI_ERROR Extended Status.
static uint32_t ocs_scsi_dif_check_ref_tag(ocs_t *ocs, ocs_hal_dif_info_t *dif_info, uint32_t exp_ref_tag, ocs_dif_t *dif)
Check the ref tag of dif data.
ocs_hal_rtn_e ocs_hal_io_abort(ocs_hal_t *hal, ocs_hal_io_t *io_to_abort, uint32_t send_abts, void *cb, void *arg)
Abort a previously-started IO.
#define FCP_CLEAR_TASK_SET
void ocs_node_post_event(ocs_node_t *node, ocs_sm_event_t evt, void *arg)
Post event to node state machine context.
uint32_t sense_data_length
#define SLI4_FC_DI_ERROR_AE
ocs_hal_rtn_e ocs_hal_io_add_seed_sge(ocs_hal_t *hal, ocs_hal_io_t *io, ocs_hal_dif_info_t *dif_info)
Add a T10 PI seed scatter gather list entry.
#define OCS_FC_MAX_SGL
Defines the number of SGLs allocated on each IO object.
#define SCSI_IOFMT_ARGS(io)
#define SLI4_FC_DI_ERROR_TDPV
static int32_t ocs_list_is_singular(ocs_list_t *list)
Test if a list has single entry.
int32_t ocs_scsi_io_dispatch(ocs_io_t *io, void *cb)
Attempt to dispatch a non-abort IO.
#define SLI4_FC_LOCAL_REJECT_ABORT_REQUESTED
#define OCS_SCSI_WQ_CLASS_MASK
#define OCS_LOG_ENABLE_SCSI_TRACE(ocs)
uint8_t * ocs_textbuf_get_buffer(ocs_textbuf_t *textbuf)
#define OCS_SCSI_LOW_LATENCY
#define FCP_LUN_ADDRESS_METHOD_MASK
ocs_hal_rtn_e ocs_hal_io_add_sge(ocs_hal_t *hal, ocs_hal_io_t *io, uintptr_t addr, uint32_t length)
Add a scatter gather list entry to an IO.
generic scatter-gather list structure
static void ocs_log_sgl(ocs_io_t *io)
This function logs the SGLs for an IO.
#define FCP_SNS_LEN_VALID
ocs_hal_rtn_e ocs_hal_callback(ocs_hal_t *hal, ocs_hal_callback_e which, void *func, void *arg)
Register a callback for the given event.
static uint8_t * ocs_find_vpd(uint8_t *vpddata, uint32_t vpddata_length, const char *key)
find a VPD entry
int32_t(* ocs_scsi_rsp_io_cb_t)(ocs_io_t *io, ocs_scsi_io_status_e status, ocs_scsi_cmd_resp_t *rsp, uint32_t flags, void *arg)
void ocs_scsi_io_free(ocs_io_t *io)
Free a SCSI IO context.
int32_t ocs_scsi_send_wr_io_first_burst(ocs_node_t *node, ocs_io_t *io, uint32_t lun, void *cdb, uint32_t cdb_len, ocs_scsi_dif_info_t *dif_info, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, uint32_t first_burst, ocs_scsi_rsp_io_cb_t cb, void *arg)
Initiate initiator write IO.
#define OCS_SCSI_NO_AUTO_RESPONSE
#define SLI4_FC_WCQE_STATUS_SUCCESS
FC/FCoE Completion Status Codes.
static void * ocs_list_remove(ocs_list_t *list, void *item)
Remove an item from the list.
#define enable_tsend_auto_resp(ocs)
int ocs_hal_can_accept_wqes(struct ocs_hal_io_s *hio)
Validate HAL IO state to make sure HAL can accept and post wqe to SLI.
#define FCP_TMF_SUCCEEDED
int32_t ocs_scsi_recv_wr_data(ocs_io_t *io, uint32_t flags, ocs_scsi_dif_info_t *dif_info, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint64_t wire_len, ocs_scsi_io_cb_t cb, void *arg)
#define SLI4_FC_WCQE_STATUS_TARGET_WQE_TIMEOUT
#define FCP_QUERY_ASYNCHRONOUS_EVENT
#define SLI4_FC_LOCAL_REJECT_SEQUENCE_TIMEOUT
void ocs_scsi_io_alloc_disable(ocs_node_t *node)
Disable IO allocation.
ocs_hal_io_t * ocs_hal_io_alloc(ocs_hal_t *hal)
Allocate a HAL IO object.
#define SLI4_FC_LOCAL_REJECT_NO_XRI
int32_t ocs_scsi_send_rd_data(ocs_io_t *io, uint32_t flags, ocs_scsi_dif_info_t *dif_info, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint64_t wire_len, ocs_scsi_io_cb_t cb, void *arg)
uint32_t ocs_io_pool_allocated(ocs_io_pool_t *io_pool)
ocs_hal_rtn_e ocs_hal_io_register_sgl(ocs_hal_t *hal, ocs_hal_io_t *io, ocs_dma_t *sgl, uint32_t sgl_count)
#define OCS_SCSI_IO_CMPL_RSP_SENT
int32_t ocs_scsi_get_block_vaddr(ocs_io_t *io, uint64_t blocknumber, ocs_scsi_vaddr_len_t addrlen[], uint32_t max_addrlen, void **dif_vaddr)
Return address of data and DIF data given a block in the target.
void ocs_scsi_update_first_burst_transferred(ocs_io_t *io, uint32_t transferred)
Update transferred count.
#define SLI4_FC_LOCAL_REJECT_INVALID_RELOFFSET
ocs_scsi_dif_blk_size_e blk_size
void ocs_scsi_register_bounce(ocs_t *ocs, void(*fctn)(void(*fctn)(void *arg), void *arg, uint32_t s_id, uint32_t d_id, uint32_t ox_id))
Register bounce callback for multi-threading.
#define SLI4_FC_DI_ERROR_EDIR
#define OCS_SCSI_WQ_STEERING_CPU
static uint32_t ocs_scsi_count_sgls(ocs_hal_dif_info_t *hal_dif, ocs_scsi_sgl_t *sgl, uint32_t sgl_count)
Return count of SGE's required for request.
#define FCP_ABORT_TASK_SET
#define scsi_io_trace(io, fmt,...)
#define FCP_QUERY_TASK_SET
#define OCS_SCSI_LAST_DATAPHASE
ocs_hal_rtn_e ocs_hal_io_add_dif_sge(ocs_hal_t *hal, ocs_hal_io_t *io, uintptr_t addr)
Add a T10 DIF scatter gather list entry to an IO.
ocs_hal_rtn_e ocs_hal_get(ocs_hal_t *hal, ocs_hal_property_e prop, uint32_t *value)
uint32_t disable_app_ffff
uint8_t data[FCP_MAX_RSP_INFO_LEN]
#define OCS_SCSI_WQ_STEERING_MASK
uint16_t ocs_scsi_dif_calc_checksum(ocs_scsi_vaddr_len_t addrlen[], uint32_t addrlen_count)
Calculate the IP-checksum guard value for a block.
static int32_t ocs_scsi_abort_io_cb(struct ocs_hal_io_s *hio, ocs_remote_node_t *rnode, uint32_t len, int32_t status, uint32_t ext, void *arg)
Callback for an aborted IO.
#define OCS_SCSI_SNS_BUF_VALID(sense)
uint32_t response_data_length
int32_t(* ocs_hal_done_t)(struct ocs_hal_io_s *, ocs_remote_node_t *, uint32_t len, int32_t status, uint32_t ext, void *ul_arg)
HAL callback type.
int32_t ocs_scsi_send_rd_io(ocs_node_t *node, ocs_io_t *io, uint32_t lun, void *cdb, uint32_t cdb_len, ocs_scsi_dif_info_t *dif_info, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, ocs_scsi_rsp_io_cb_t cb, void *arg)
Initiate initiator read IO.
#define io_error_log(io, fmt,...)
#define OCS_SCSI_WQ_CLASS_SHIFT
uint32_t disable_app_ref_ffff
static int32_t ocs_target_abort_cb(ocs_hal_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app)
Process target abort callback.
int32_t ocs_hal_dif_mem_blocksize(ocs_hal_dif_info_t *dif_info, int wiretomem)
Return memory block size given HAL DIF API.
#define FCP_LUN_ADDR_FLAT_MAX
int32_t ocs_textbuf_init(ocs_t *ocs, ocs_textbuf_t *textbuf, void *buffer, uint32_t length)
#define SLI4_FC_DI_ERROR_RE
#define OCS_HAL_DIF_OPER_INSERT
int32_t(* ocs_scsi_io_cb_t)(ocs_io_t *io, ocs_scsi_io_status_e status, uint32_t flags, void *arg)
uint8_t fcp_cdb_and_dl[20]
void ocs_scsi_io_alloc_enable(ocs_node_t *node)
Enable IO allocation.
#define scsi_io_printf(io, fmt,...)
int32_t ocs_scsi_send_nodata_io(ocs_node_t *node, ocs_io_t *io, uint32_t lun, void *cdb, uint32_t cdb_len, ocs_scsi_rsp_io_cb_t cb, void *arg)
Initiate initiator SCSI command with no data.
#define FCP_LUN_ADDR_SIMPLE_MAX
ocs_hal_rtn_e ocs_hal_io_send(ocs_hal_t *hal, ocs_hal_io_type_e type, ocs_hal_io_t *io, uint32_t len, ocs_hal_io_param_t *iparam, ocs_remote_node_t *rnode, void *cb, void *arg)
Send a read, write, or response IO.
static void ocs_list_add_tail(ocs_list_t *list, void *item)
Add an item to the tail of the list.
ocs_scsi_property_e
property names for ocs_scsi_get_property() functions
uint32_t auto_incr_ref_tag
#define enable_treceive_auto_resp(ocs)
ocs_hal_dif_oper_e dif_oper
static int32_t ocs_target_bls_resp_cb(ocs_hal_io_t *hio, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *app)
Process target BLS response callback.
#define SLI4_FC_LOCAL_REJECT_OUT_OF_ORDER_DATA
#define ocs_list_remove_head(list)
Remove and return an item from the head of the list.
static void ocs_list_add_head(ocs_list_t *list, void *item)
Add an item to the head of the list.
uint8_t status_qualifier[2]
uint32_t uint16_t dif_seed
int32_t ocs_scsi_send_tmf(ocs_node_t *node, ocs_io_t *io, ocs_io_t *io_to_abort, uint32_t lun, ocs_scsi_tmf_cmd_e tmf, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t len, ocs_scsi_rsp_io_cb_t cb, void *arg)
Initiate initiator task management operation.
#define SLI4_DIF_PASS_THROUGH
void ocs_scsi_check_pending(ocs_t *ocs)
Check for pending IOs to dispatch.
#define FCP_TMF_INCORRECT_LUN
static uint32_t ocs_fc_getbe32(void *p)
Returns a big-endian 32-bit value given a pointer.
#define SLI4_FC_WCQE_STATUS_FCP_RSP_FAILURE
int32_t ocs_scsi_tgt_abort_io(ocs_io_t *io, bool send_abts, ocs_scsi_io_cb_t cb, void *arg)
Abort a target IO.
int32_t ocs_scsi_send_wr_io(ocs_node_t *node, ocs_io_t *io, uint32_t lun, void *cdb, uint32_t cdb_len, ocs_scsi_dif_info_t *dif_info, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, ocs_scsi_rsp_io_cb_t cb, void *arg)
Initiate initiator write IO.
#define FCP_LUN_ADDR_METHOD_FLAT
#define SLI4_IO_AUTO_GOOD_RESPONSE
void ocs_textbuf_printf(ocs_textbuf_t *textbuf, const char *fmt,...)
Helper function to dump message.
#define FCP_LOGICAL_UNIT_RESET
#define SLI4_FC_LOCAL_REJECT_INVALID_RPI
ocs_hal_rtn_e ocs_hal_io_init_sges(ocs_hal_t *hal, ocs_hal_io_t *io, ocs_hal_io_type_e type)
Initialize the scatter gather list entries of an IO.
uint16_t scsi_status_qualifier
int32_t ocs_scsi_send_resp(ocs_io_t *io, uint32_t flags, ocs_scsi_cmd_resp_t *rsp, ocs_scsi_io_cb_t cb, void *arg)
Send response data.
int32_t ocs_hal_async_call(ocs_hal_t *hal, ocs_hal_async_cb_t callback, void *arg)
Make an async callback using NOP mailbox command.
#define ocs_assert(cond,...)
Scatter-Gather Entry (SGE)
void ocs_scsi_del_initiator_complete(ocs_node_t *node)
Notify that delete initiator is complete.
uint32_t response_wire_length
static void ocs_io_free(ocs_t *ocs, ocs_io_t *io)
void * ocs_hal_get_ptr(ocs_hal_t *hal, ocs_hal_property_e prop)
static int32_t ocs_scsi_convert_dif_info(ocs_t *ocs, ocs_scsi_dif_info_t *scsi_dif_info, ocs_hal_dif_info_t *hal_dif_info)
Convert SCSI API T10 DIF information into the FC HAL format.
uint16_t ocs_scsi_dif_calc_crc(const uint8_t *buffer, uint32_t size, uint16_t crc)
Calculate the T10 PI CRC guard value for a block.
int32_t ocs_scsi_send_tmf_resp(ocs_io_t *io, ocs_scsi_tmf_resp_e rspcode, uint8_t addl_rsp_info[3], ocs_scsi_io_cb_t cb, void *arg)
Send TMF response data.
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.
#define OCS_SCSI_WQ_STEERING_CLASS
#define scsi_log(ocs, fmt,...)
ocs_hal_dif_blk_size_e blk_size
static uint32_t ocs_scsi_dif_check_app_tag(ocs_t *ocs, ocs_hal_dif_info_t *dif_info, uint16_t exp_app_tag, ocs_dif_t *dif)
Check the app tag of dif data.
void * ocs_scsi_get_property_ptr(ocs_t *ocs, ocs_scsi_property_e prop)
Return a property pointer.
uint32_t disable_app_ref_ffff
uint8_t uint8_t task_management_flags
static int32_t ocs_scsi_xfer_data(ocs_io_t *io, uint32_t flags, ocs_scsi_dif_info_t *dif_info, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint64_t xwire_len, ocs_hal_io_type_e type, int enable_ar, ocs_scsi_io_cb_t cb, void *arg)
Send read/write data.
void ocs_scsi_del_target_complete(ocs_node_t *node)
Notify that delete target is complete.
ocs_scsi_dif_oper_e dif_oper
int32_t ocs_scsi_io_alloc_enabled(ocs_node_t *node)
Get state of IO allocation.
static ocs_io_t * ocs_io_alloc(ocs_t *ocs)
static int32_t ocs_scsi_send_io(ocs_hal_io_type_e type, ocs_node_t *node, ocs_io_t *io, uint32_t lun, ocs_scsi_tmf_cmd_e tmf, uint8_t *cdb, uint32_t cdb_len, ocs_scsi_dif_info_t *dif_info, ocs_scsi_sgl_t *sgl, uint32_t sgl_count, uint32_t wire_len, uint32_t first_burst, ocs_scsi_rsp_io_cb_t cb, void *arg)
Send an FCP IO.
static int32_t ocs_scsi_io_dispatch_hal_io(ocs_io_t *io, ocs_hal_io_t *hio)
Dispatch IO.
#define FCP_LUN_ADDRESS_METHOD_SHIFT
uint32_t ocs_scsi_get_property(ocs_t *ocs, ocs_scsi_property_e prop)
Return SCSI API integer valued property.
void ocs_scsi_io_complete(ocs_io_t *io)
Notify the base driver that the IO is complete.
#define SLI4_FC_WCQE_STATUS_DISPATCH_ERROR
#define OCS_CTRLMASK_TEST_CHAINED_SGLS
#define SLI4_FC_WCQE_STATUS_DI_ERROR
#define OCS_SCSI_WQ_STEERING_SHIFT