11e66f787SSean Bruno /*-
27ea28254SJohn Hall * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries.
31e66f787SSean Bruno *
41e66f787SSean Bruno * Redistribution and use in source and binary forms, with or without
51e66f787SSean Bruno * modification, are permitted provided that the following conditions
61e66f787SSean Bruno * are met:
71e66f787SSean Bruno * 1. Redistributions of source code must retain the above copyright
81e66f787SSean Bruno * notice, this list of conditions and the following disclaimer.
91e66f787SSean Bruno * 2. Redistributions in binary form must reproduce the above copyright
101e66f787SSean Bruno * notice, this list of conditions and the following disclaimer in the
111e66f787SSean Bruno * documentation and/or other materials provided with the distribution.
121e66f787SSean Bruno *
131e66f787SSean Bruno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
141e66f787SSean Bruno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
151e66f787SSean Bruno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
161e66f787SSean Bruno * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
171e66f787SSean Bruno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
181e66f787SSean Bruno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
191e66f787SSean Bruno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
201e66f787SSean Bruno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
211e66f787SSean Bruno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
221e66f787SSean Bruno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
231e66f787SSean Bruno * SUCH DAMAGE.
241e66f787SSean Bruno */
251e66f787SSean Bruno
261e66f787SSean Bruno
271e66f787SSean Bruno #include "smartpqi_includes.h"
281e66f787SSean Bruno
297ea28254SJohn Hall /* Change this if need to debug why AIO is not being used */
307ea28254SJohn Hall #define DBG_AIO DBG_IO
319fac68fcSPAPANI SRIKANTH
321e66f787SSean Bruno #define SG_FLAG_LAST 0x40000000
331e66f787SSean Bruno #define SG_FLAG_CHAIN 0x80000000
341e66f787SSean Bruno
357ea28254SJohn Hall /* Local Prototypes */
367ea28254SJohn Hall static void pqisrc_increment_io_counters(pqisrc_softstate_t *softs, rcb_t *rcb);
377ea28254SJohn Hall static int fill_lba_for_scsi_rw(pqisrc_softstate_t *softs, uint8_t *cdb, aio_req_locator_t *l);
387ea28254SJohn Hall
397ea28254SJohn Hall
401e66f787SSean Bruno /* Subroutine to find out embedded sgl count in IU */
419fac68fcSPAPANI SRIKANTH static inline uint32_t
pqisrc_embedded_sgl_count(uint32_t elem_alloted,uint8_t iu_type)427ea28254SJohn Hall pqisrc_embedded_sgl_count(uint32_t elem_alloted, uint8_t iu_type)
431e66f787SSean Bruno {
447ea28254SJohn Hall uint32_t embedded_sgl_count = MAX_EMBEDDED_SG_IN_FIRST_IU_DEFAULT;
457ea28254SJohn Hall
467ea28254SJohn Hall DBG_FUNC("IN\n");
477ea28254SJohn Hall
487ea28254SJohn Hall if (iu_type == PQI_IU_TYPE_RAID5_WRITE_BYPASS_REQUEST ||
497ea28254SJohn Hall iu_type == PQI_IU_TYPE_RAID6_WRITE_BYPASS_REQUEST)
507ea28254SJohn Hall embedded_sgl_count = MAX_EMBEDDED_SG_IN_FIRST_IU_RAID56_AIO;
517ea28254SJohn Hall
521e66f787SSean Bruno /**
531e66f787SSean Bruno calculate embedded sgl count using num_elem_alloted for IO
541e66f787SSean Bruno **/
551e66f787SSean Bruno if(elem_alloted - 1)
561e66f787SSean Bruno embedded_sgl_count += ((elem_alloted - 1) * MAX_EMBEDDED_SG_IN_IU);
577ea28254SJohn Hall /* DBG_IO("embedded_sgl_count :%d\n", embedded_sgl_count); */
581e66f787SSean Bruno
597ea28254SJohn Hall DBG_FUNC("OUT\n");
601e66f787SSean Bruno
611e66f787SSean Bruno return embedded_sgl_count;
621e66f787SSean Bruno
631e66f787SSean Bruno }
641e66f787SSean Bruno
651e66f787SSean Bruno /* Subroutine to find out contiguous free elem in IU */
669fac68fcSPAPANI SRIKANTH static inline uint32_t
pqisrc_contiguous_free_elem(uint32_t pi,uint32_t ci,uint32_t elem_in_q)679fac68fcSPAPANI SRIKANTH pqisrc_contiguous_free_elem(uint32_t pi, uint32_t ci, uint32_t elem_in_q)
681e66f787SSean Bruno {
691e66f787SSean Bruno uint32_t contiguous_free_elem = 0;
701e66f787SSean Bruno
717ea28254SJohn Hall DBG_FUNC("IN\n");
721e66f787SSean Bruno
731e66f787SSean Bruno if(pi >= ci) {
741e66f787SSean Bruno contiguous_free_elem = (elem_in_q - pi);
751e66f787SSean Bruno if(ci == 0)
761e66f787SSean Bruno contiguous_free_elem -= 1;
771e66f787SSean Bruno } else {
781e66f787SSean Bruno contiguous_free_elem = (ci - pi - 1);
791e66f787SSean Bruno }
801e66f787SSean Bruno
817ea28254SJohn Hall DBG_FUNC("OUT\n");
821e66f787SSean Bruno
831e66f787SSean Bruno return contiguous_free_elem;
841e66f787SSean Bruno }
851e66f787SSean Bruno
861e66f787SSean Bruno /* Subroutine to find out num of elements need for the request */
871e66f787SSean Bruno static uint32_t
pqisrc_num_elem_needed(pqisrc_softstate_t * softs,uint32_t SG_Count,pqi_scsi_dev_t * devp,boolean_t is_write,IO_PATH_T io_path)887ea28254SJohn Hall pqisrc_num_elem_needed(pqisrc_softstate_t *softs, uint32_t SG_Count,
897ea28254SJohn Hall pqi_scsi_dev_t *devp, boolean_t is_write, IO_PATH_T io_path)
901e66f787SSean Bruno {
911e66f787SSean Bruno uint32_t num_sg;
921e66f787SSean Bruno uint32_t num_elem_required = 1;
937ea28254SJohn Hall uint32_t sg_in_first_iu = MAX_EMBEDDED_SG_IN_FIRST_IU_DEFAULT;
947ea28254SJohn Hall
957ea28254SJohn Hall DBG_FUNC("IN\n");
967ea28254SJohn Hall DBG_IO("SGL_Count :%u\n",SG_Count);
977ea28254SJohn Hall
987ea28254SJohn Hall if ((devp->raid_level == SA_RAID_5 || devp->raid_level == SA_RAID_6)
997ea28254SJohn Hall && is_write && (io_path == AIO_PATH))
1007ea28254SJohn Hall sg_in_first_iu = MAX_EMBEDDED_SG_IN_FIRST_IU_RAID56_AIO;
1011e66f787SSean Bruno /********
1021e66f787SSean Bruno If SG_Count greater than max sg per IU i.e 4 or 68
1031e66f787SSean Bruno (4 is with out spanning or 68 is with spanning) chaining is required.
1047ea28254SJohn Hall OR, If SG_Count <= MAX_EMBEDDED_SG_IN_FIRST_IU_* then,
1051e66f787SSean Bruno on these two cases one element is enough.
1061e66f787SSean Bruno ********/
1077ea28254SJohn Hall if(SG_Count > softs->max_sg_per_spanning_cmd ||
1087ea28254SJohn Hall SG_Count <= sg_in_first_iu)
1091e66f787SSean Bruno return num_elem_required;
1101e66f787SSean Bruno /*
1111e66f787SSean Bruno SGL Count Other Than First IU
1121e66f787SSean Bruno */
1137ea28254SJohn Hall num_sg = SG_Count - sg_in_first_iu;
1141e66f787SSean Bruno num_elem_required += PQISRC_DIV_ROUND_UP(num_sg, MAX_EMBEDDED_SG_IN_IU);
1157ea28254SJohn Hall DBG_FUNC("OUT\n");
1161e66f787SSean Bruno return num_elem_required;
1171e66f787SSean Bruno }
1181e66f787SSean Bruno
1191e66f787SSean Bruno /* Subroutine to build SG list for the IU submission*/
1209fac68fcSPAPANI SRIKANTH static boolean_t
pqisrc_build_sgl(sgt_t * sg_array,rcb_t * rcb,iu_header_t * iu_hdr,uint32_t num_elem_alloted)1219fac68fcSPAPANI SRIKANTH pqisrc_build_sgl(sgt_t *sg_array, rcb_t *rcb, iu_header_t *iu_hdr,
1221e66f787SSean Bruno uint32_t num_elem_alloted)
1231e66f787SSean Bruno {
1241e66f787SSean Bruno uint32_t i;
1251e66f787SSean Bruno uint32_t num_sg = OS_GET_IO_SG_COUNT(rcb);
1261e66f787SSean Bruno sgt_t *sgt = sg_array;
1271e66f787SSean Bruno sgt_t *sg_chain = NULL;
1281e66f787SSean Bruno boolean_t partial = false;
1291e66f787SSean Bruno
1307ea28254SJohn Hall DBG_FUNC("IN\n");
1311e66f787SSean Bruno
1327ea28254SJohn Hall /* DBG_IO("SGL_Count :%d",num_sg); */
1331e66f787SSean Bruno if (0 == num_sg) {
1341e66f787SSean Bruno goto out;
1351e66f787SSean Bruno }
1361e66f787SSean Bruno
1377ea28254SJohn Hall if (num_sg <= pqisrc_embedded_sgl_count(num_elem_alloted,
1387ea28254SJohn Hall iu_hdr->iu_type)) {
1397ea28254SJohn Hall
1401e66f787SSean Bruno for (i = 0; i < num_sg; i++, sgt++) {
1411e66f787SSean Bruno sgt->addr= OS_GET_IO_SG_ADDR(rcb,i);
1421e66f787SSean Bruno sgt->len= OS_GET_IO_SG_LEN(rcb,i);
1431e66f787SSean Bruno sgt->flags= 0;
1441e66f787SSean Bruno }
1451e66f787SSean Bruno
1461e66f787SSean Bruno sg_array[num_sg - 1].flags = SG_FLAG_LAST;
1471e66f787SSean Bruno } else {
1481e66f787SSean Bruno /**
1491e66f787SSean Bruno SGL Chaining
1501e66f787SSean Bruno **/
1511e66f787SSean Bruno sg_chain = rcb->sg_chain_virt;
1521e66f787SSean Bruno sgt->addr = rcb->sg_chain_dma;
1531e66f787SSean Bruno sgt->len = num_sg * sizeof(sgt_t);
1541e66f787SSean Bruno sgt->flags = SG_FLAG_CHAIN;
1551e66f787SSean Bruno
1561e66f787SSean Bruno sgt = sg_chain;
1571e66f787SSean Bruno for (i = 0; i < num_sg; i++, sgt++) {
1581e66f787SSean Bruno sgt->addr = OS_GET_IO_SG_ADDR(rcb,i);
1591e66f787SSean Bruno sgt->len = OS_GET_IO_SG_LEN(rcb,i);
1601e66f787SSean Bruno sgt->flags = 0;
1611e66f787SSean Bruno }
1621e66f787SSean Bruno
1631e66f787SSean Bruno sg_chain[num_sg - 1].flags = SG_FLAG_LAST;
1641e66f787SSean Bruno num_sg = 1;
1651e66f787SSean Bruno partial = true;
1669fac68fcSPAPANI SRIKANTH
1671e66f787SSean Bruno }
1681e66f787SSean Bruno out:
1691e66f787SSean Bruno iu_hdr->iu_length = num_sg * sizeof(sgt_t);
1707ea28254SJohn Hall DBG_FUNC("OUT\n");
1711e66f787SSean Bruno return partial;
1721e66f787SSean Bruno
1731e66f787SSean Bruno }
1741e66f787SSean Bruno
1757ea28254SJohn Hall #if 0
1767ea28254SJohn Hall static inline void
1777ea28254SJohn Hall pqisrc_show_raid_req(pqisrc_softstate_t *softs, pqisrc_raid_req_t *raid_req)
1787ea28254SJohn Hall {
1797ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "raid_req->header.iu_type",
1807ea28254SJohn Hall raid_req->header.iu_type);
1817ea28254SJohn Hall DBG_IO("%30s: 0x%d\n", "raid_req->response_queue_id",
1827ea28254SJohn Hall raid_req->response_queue_id);
1837ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "raid_req->request_id",
1847ea28254SJohn Hall raid_req->request_id);
1857ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "raid_req->buffer_length",
1867ea28254SJohn Hall raid_req->buffer_length);
1877ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "raid_req->task_attribute",
1887ea28254SJohn Hall raid_req->task_attribute);
1897ea28254SJohn Hall DBG_IO("%30s: 0x%llx\n", "raid_req->lun_number",
1907ea28254SJohn Hall *((long long unsigned int*)raid_req->lun_number));
1917ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "raid_req->error_index",
1927ea28254SJohn Hall raid_req->error_index);
1937ea28254SJohn Hall DBG_IO("%30s: 0x%p\n", "raid_req->sg_descriptors[0].addr",
1947ea28254SJohn Hall (void *)raid_req->sg_descriptors[0].addr);
1957ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "raid_req->sg_descriptors[0].len",
1967ea28254SJohn Hall raid_req->sg_descriptors[0].len);
1977ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "raid_req->sg_descriptors[0].flags",
1987ea28254SJohn Hall raid_req->sg_descriptors[0].flags);
1997ea28254SJohn Hall }
2007ea28254SJohn Hall #endif
2017ea28254SJohn Hall
2021e66f787SSean Bruno /*Subroutine used to Build the RAID request */
2031e66f787SSean Bruno static void
pqisrc_build_raid_io(pqisrc_softstate_t * softs,rcb_t * rcb,pqisrc_raid_req_t * raid_req,uint32_t num_elem_alloted)2041e66f787SSean Bruno pqisrc_build_raid_io(pqisrc_softstate_t *softs, rcb_t *rcb,
2051e66f787SSean Bruno pqisrc_raid_req_t *raid_req, uint32_t num_elem_alloted)
2061e66f787SSean Bruno {
2077ea28254SJohn Hall DBG_FUNC("IN\n");
2081e66f787SSean Bruno
2091e66f787SSean Bruno raid_req->header.iu_type = PQI_IU_TYPE_RAID_PATH_IO_REQUEST;
2101e66f787SSean Bruno raid_req->header.comp_feature = 0;
2111e66f787SSean Bruno raid_req->response_queue_id = OS_GET_IO_RESP_QID(softs, rcb);
2121e66f787SSean Bruno raid_req->work_area[0] = 0;
2131e66f787SSean Bruno raid_req->work_area[1] = 0;
2141e66f787SSean Bruno raid_req->request_id = rcb->tag;
2151e66f787SSean Bruno raid_req->nexus_id = 0;
2161e66f787SSean Bruno raid_req->buffer_length = GET_SCSI_BUFFLEN(rcb);
2171e66f787SSean Bruno memcpy(raid_req->lun_number, rcb->dvp->scsi3addr,
2181e66f787SSean Bruno sizeof(raid_req->lun_number));
2191e66f787SSean Bruno raid_req->protocol_spec = 0;
2201e66f787SSean Bruno raid_req->data_direction = rcb->data_dir;
2211e66f787SSean Bruno raid_req->reserved1 = 0;
2221e66f787SSean Bruno raid_req->fence = 0;
2231e66f787SSean Bruno raid_req->error_index = raid_req->request_id;
2241e66f787SSean Bruno raid_req->reserved2 = 0;
2251e66f787SSean Bruno raid_req->task_attribute = OS_GET_TASK_ATTR(rcb);
2261e66f787SSean Bruno raid_req->command_priority = 0;
2271e66f787SSean Bruno raid_req->reserved3 = 0;
2281e66f787SSean Bruno raid_req->reserved4 = 0;
2291e66f787SSean Bruno raid_req->reserved5 = 0;
2307ea28254SJohn Hall raid_req->ml_device_lun_number = (uint8_t)rcb->cm_ccb->ccb_h.target_lun;
2311e66f787SSean Bruno
2321e66f787SSean Bruno /* As cdb and additional_cdb_bytes are contiguous,
2331e66f787SSean Bruno update them in a single statement */
2347ea28254SJohn Hall memcpy(raid_req->cmd.cdb, rcb->cdbp, rcb->cmdlen);
2351e66f787SSean Bruno #if 0
2361e66f787SSean Bruno DBG_IO("CDB :");
2371e66f787SSean Bruno for(i = 0; i < rcb->cmdlen ; i++)
2381e66f787SSean Bruno DBG_IO(" 0x%x \n ",raid_req->cdb[i]);
2391e66f787SSean Bruno #endif
2401e66f787SSean Bruno
2411e66f787SSean Bruno switch (rcb->cmdlen) {
2421e66f787SSean Bruno case 6:
2431e66f787SSean Bruno case 10:
2441e66f787SSean Bruno case 12:
2451e66f787SSean Bruno case 16:
2461e66f787SSean Bruno raid_req->additional_cdb_bytes_usage =
2471e66f787SSean Bruno PQI_ADDITIONAL_CDB_BYTES_0;
2481e66f787SSean Bruno break;
2491e66f787SSean Bruno case 20:
2501e66f787SSean Bruno raid_req->additional_cdb_bytes_usage =
2511e66f787SSean Bruno PQI_ADDITIONAL_CDB_BYTES_4;
2521e66f787SSean Bruno break;
2531e66f787SSean Bruno case 24:
2541e66f787SSean Bruno raid_req->additional_cdb_bytes_usage =
2551e66f787SSean Bruno PQI_ADDITIONAL_CDB_BYTES_8;
2561e66f787SSean Bruno break;
2571e66f787SSean Bruno case 28:
2581e66f787SSean Bruno raid_req->additional_cdb_bytes_usage =
2591e66f787SSean Bruno PQI_ADDITIONAL_CDB_BYTES_12;
2601e66f787SSean Bruno break;
2611e66f787SSean Bruno case 32:
2621e66f787SSean Bruno default: /* todo:review again */
2631e66f787SSean Bruno raid_req->additional_cdb_bytes_usage =
2641e66f787SSean Bruno PQI_ADDITIONAL_CDB_BYTES_16;
2651e66f787SSean Bruno break;
2661e66f787SSean Bruno }
2671e66f787SSean Bruno
2681e66f787SSean Bruno /* Frame SGL Descriptor */
2691e66f787SSean Bruno raid_req->partial = pqisrc_build_sgl(&raid_req->sg_descriptors[0], rcb,
2701e66f787SSean Bruno &raid_req->header, num_elem_alloted);
2711e66f787SSean Bruno
2721e66f787SSean Bruno raid_req->header.iu_length +=
2731e66f787SSean Bruno offsetof(pqisrc_raid_req_t, sg_descriptors) - sizeof(iu_header_t);
2741e66f787SSean Bruno
2751e66f787SSean Bruno #if 0
2767ea28254SJohn Hall pqisrc_show_raid_req(softs, raid_req);
2771e66f787SSean Bruno #endif
2781e66f787SSean Bruno rcb->success_cmp_callback = pqisrc_process_io_response_success;
2791e66f787SSean Bruno rcb->error_cmp_callback = pqisrc_process_raid_response_error;
2801e66f787SSean Bruno rcb->resp_qid = raid_req->response_queue_id;
2811e66f787SSean Bruno
2827ea28254SJohn Hall DBG_FUNC("OUT\n");
2831e66f787SSean Bruno
2841e66f787SSean Bruno }
2851e66f787SSean Bruno
2867ea28254SJohn Hall /* We will need to expand this to handle different types of
2877ea28254SJohn Hall * aio request structures.
2887ea28254SJohn Hall */
2897ea28254SJohn Hall #if 0
2907ea28254SJohn Hall static inline void
2917ea28254SJohn Hall pqisrc_show_aio_req(pqisrc_softstate_t *softs, pqi_aio_req_t *aio_req)
2921e66f787SSean Bruno {
2937ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "aio_req->header.iu_type",
2947ea28254SJohn Hall aio_req->header.iu_type);
2957ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "aio_req->resp_qid",
2967ea28254SJohn Hall aio_req->response_queue_id);
2977ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "aio_req->req_id",
2987ea28254SJohn Hall aio_req->req_id);
2997ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "aio_req->nexus",
3007ea28254SJohn Hall aio_req->nexus);
3017ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "aio_req->buf_len",
3027ea28254SJohn Hall aio_req->buf_len);
3037ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "aio_req->cmd_flags.data_dir",
3047ea28254SJohn Hall aio_req->cmd_flags.data_dir);
3057ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "aio_req->attr_prio.task_attr",
3067ea28254SJohn Hall aio_req->attr_prio.task_attr);
3077ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "aio_req->err_idx",
3087ea28254SJohn Hall aio_req->err_idx);
3097ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "aio_req->num_sg",
3107ea28254SJohn Hall aio_req->num_sg);
3117ea28254SJohn Hall DBG_IO("%30s: 0x%p\n", "aio_req->sg_desc[0].addr",
3127ea28254SJohn Hall (void *)aio_req->sg_desc[0].addr);
3137ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "aio_req->sg_desc[0].len",
3147ea28254SJohn Hall aio_req->sg_desc[0].len);
3157ea28254SJohn Hall DBG_IO("%30s: 0x%x\n", "aio_req->sg_desc[0].flags",
3167ea28254SJohn Hall aio_req->sg_desc[0].flags);
3177ea28254SJohn Hall }
3187ea28254SJohn Hall #endif
3191e66f787SSean Bruno
3207ea28254SJohn Hall void
int_to_scsilun(uint64_t lun,uint8_t * scsi_lun)3217ea28254SJohn Hall int_to_scsilun(uint64_t lun, uint8_t *scsi_lun)
3227ea28254SJohn Hall {
3237ea28254SJohn Hall int i;
3247ea28254SJohn Hall
3257ea28254SJohn Hall memset(scsi_lun, 0, sizeof(lun));
3267ea28254SJohn Hall for (i = 0; i < sizeof(lun); i += 2) {
3277ea28254SJohn Hall scsi_lun[i] = (lun >> 8) & 0xFF;
3287ea28254SJohn Hall scsi_lun[i+1] = lun & 0xFF;
3297ea28254SJohn Hall lun = lun >> 16;
3307ea28254SJohn Hall }
3317ea28254SJohn Hall }
3327ea28254SJohn Hall
3337ea28254SJohn Hall
3347ea28254SJohn Hall /*Subroutine used to populate AIO IUs. */
3357ea28254SJohn Hall void
pqisrc_build_aio_common(pqisrc_softstate_t * softs,pqi_aio_req_t * aio_req,rcb_t * rcb,uint32_t num_elem_alloted)3367ea28254SJohn Hall pqisrc_build_aio_common(pqisrc_softstate_t *softs, pqi_aio_req_t *aio_req,
3377ea28254SJohn Hall rcb_t *rcb, uint32_t num_elem_alloted)
3387ea28254SJohn Hall {
3397ea28254SJohn Hall DBG_FUNC("IN\n");
3401e66f787SSean Bruno aio_req->header.iu_type = PQI_IU_TYPE_AIO_PATH_IO_REQUEST;
3411e66f787SSean Bruno aio_req->header.comp_feature = 0;
3421e66f787SSean Bruno aio_req->response_queue_id = OS_GET_IO_RESP_QID(softs, rcb);
3431e66f787SSean Bruno aio_req->work_area[0] = 0;
3441e66f787SSean Bruno aio_req->work_area[1] = 0;
3451e66f787SSean Bruno aio_req->req_id = rcb->tag;
3461e66f787SSean Bruno aio_req->res1[0] = 0;
3471e66f787SSean Bruno aio_req->res1[1] = 0;
3481e66f787SSean Bruno aio_req->nexus = rcb->ioaccel_handle;
3491e66f787SSean Bruno aio_req->buf_len = GET_SCSI_BUFFLEN(rcb);
3507ea28254SJohn Hall aio_req->cmd_flags.data_dir = rcb->data_dir;
3517ea28254SJohn Hall aio_req->cmd_flags.mem_type = 0;
3527ea28254SJohn Hall aio_req->cmd_flags.fence = 0;
3537ea28254SJohn Hall aio_req->cmd_flags.res2 = 0;
3547ea28254SJohn Hall aio_req->attr_prio.task_attr = OS_GET_TASK_ATTR(rcb);
3557ea28254SJohn Hall aio_req->attr_prio.cmd_prio = 0;
3567ea28254SJohn Hall aio_req->attr_prio.res3 = 0;
3571e66f787SSean Bruno aio_req->err_idx = aio_req->req_id;
3581e66f787SSean Bruno aio_req->cdb_len = rcb->cmdlen;
3599fac68fcSPAPANI SRIKANTH
360b17f4335SSean Bruno if (rcb->cmdlen > sizeof(aio_req->cdb))
361b17f4335SSean Bruno rcb->cmdlen = sizeof(aio_req->cdb);
3621e66f787SSean Bruno memcpy(aio_req->cdb, rcb->cdbp, rcb->cmdlen);
3631e66f787SSean Bruno memset(aio_req->res4, 0, sizeof(aio_req->res4));
3641e66f787SSean Bruno
3657ea28254SJohn Hall uint64_t lun = rcb->cm_ccb->ccb_h.target_lun;
3667ea28254SJohn Hall if (lun && (rcb->dvp->is_multi_lun)) {
3677ea28254SJohn Hall int_to_scsilun(lun, aio_req->lun);
3687ea28254SJohn Hall }
3697ea28254SJohn Hall else {
3707ea28254SJohn Hall memset(aio_req->lun, 0, sizeof(aio_req->lun));
3717ea28254SJohn Hall }
3727ea28254SJohn Hall
3737ea28254SJohn Hall /* handle encryption fields */
3741e66f787SSean Bruno if (rcb->encrypt_enable == true) {
3757ea28254SJohn Hall aio_req->cmd_flags.encrypt_enable = true;
3767ea28254SJohn Hall aio_req->encrypt_key_index =
3777ea28254SJohn Hall LE_16(rcb->enc_info.data_enc_key_index);
3787ea28254SJohn Hall aio_req->encrypt_twk_low =
3797ea28254SJohn Hall LE_32(rcb->enc_info.encrypt_tweak_lower);
3807ea28254SJohn Hall aio_req->encrypt_twk_high =
3817ea28254SJohn Hall LE_32(rcb->enc_info.encrypt_tweak_upper);
3821e66f787SSean Bruno } else {
3837ea28254SJohn Hall aio_req->cmd_flags.encrypt_enable = 0;
3841e66f787SSean Bruno aio_req->encrypt_key_index = 0;
3851e66f787SSean Bruno aio_req->encrypt_twk_high = 0;
3861e66f787SSean Bruno aio_req->encrypt_twk_low = 0;
3871e66f787SSean Bruno }
3881e66f787SSean Bruno /* Frame SGL Descriptor */
3897ea28254SJohn Hall aio_req->cmd_flags.partial = pqisrc_build_sgl(&aio_req->sg_desc[0], rcb,
3901e66f787SSean Bruno &aio_req->header, num_elem_alloted);
3911e66f787SSean Bruno
3921e66f787SSean Bruno aio_req->num_sg = aio_req->header.iu_length / sizeof(sgt_t);
3931e66f787SSean Bruno
3947ea28254SJohn Hall /* DBG_INFO("aio_req->num_sg :%d\n", aio_req->num_sg); */
3951e66f787SSean Bruno
3961e66f787SSean Bruno aio_req->header.iu_length += offsetof(pqi_aio_req_t, sg_desc) -
3971e66f787SSean Bruno sizeof(iu_header_t);
3987ea28254SJohn Hall /* set completion and error handlers. */
3991e66f787SSean Bruno rcb->success_cmp_callback = pqisrc_process_io_response_success;
4001e66f787SSean Bruno rcb->error_cmp_callback = pqisrc_process_aio_response_error;
4011e66f787SSean Bruno rcb->resp_qid = aio_req->response_queue_id;
4027ea28254SJohn Hall DBG_FUNC("OUT\n");
4031e66f787SSean Bruno
4047ea28254SJohn Hall }
4057ea28254SJohn Hall /*Subroutine used to show standard AIO IU fields */
4067ea28254SJohn Hall void
pqisrc_show_aio_common(pqisrc_softstate_t * softs,rcb_t * rcb,pqi_aio_req_t * aio_req)4077ea28254SJohn Hall pqisrc_show_aio_common(pqisrc_softstate_t *softs, rcb_t *rcb,
4087ea28254SJohn Hall pqi_aio_req_t *aio_req)
4097ea28254SJohn Hall {
4107ea28254SJohn Hall #ifdef DEBUG_AIO
4117ea28254SJohn Hall DBG_INFO("AIO IU Content, tag# 0x%08x", rcb->tag);
4127ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "iu_type", aio_req->header.iu_type);
4137ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "comp_feat", aio_req->header.comp_feature);
4147ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "length", aio_req->header.iu_length);
4157ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "resp_qid", aio_req->response_queue_id);
4167ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "req_id", aio_req->req_id);
4177ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "nexus", aio_req->nexus);
4187ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "buf_len", aio_req->buf_len);
4197ea28254SJohn Hall DBG_INFO("%15s:\n", "cmd_flags");
4207ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "data_dir", aio_req->cmd_flags.data_dir);
4217ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "partial", aio_req->cmd_flags.partial);
4227ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "mem_type", aio_req->cmd_flags.mem_type);
4237ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "fence", aio_req->cmd_flags.fence);
4247ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "encryption",
4257ea28254SJohn Hall aio_req->cmd_flags.encrypt_enable);
4267ea28254SJohn Hall DBG_INFO("%15s:\n", "attr_prio");
4277ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "task_attr", aio_req->attr_prio.task_attr);
4287ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "cmd_prio", aio_req->attr_prio.cmd_prio);
4297ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "dek_index", aio_req->encrypt_key_index);
4307ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "tweak_lower", aio_req->encrypt_twk_low);
4317ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "tweak_upper", aio_req->encrypt_twk_high);
4327ea28254SJohn Hall pqisrc_show_cdb(softs, "AIOC", rcb, aio_req->cdb);
4337ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "err_idx", aio_req->err_idx);
4347ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "num_sg", aio_req->num_sg);
4357ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "cdb_len", aio_req->cdb_len);
4367ea28254SJohn Hall #if 0
4377ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "lun", aio_req->lun);
4387ea28254SJohn Hall DBG_INFO("%15s: 0x%p\n", "sg_desc[0].addr",
4397ea28254SJohn Hall (void *)aio_req->sg_desc[0].addr);
4407ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "sg_desc[0].len",
4417ea28254SJohn Hall aio_req->sg_desc[0].len);
4427ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "sg_desc[0].flags",
4437ea28254SJohn Hall aio_req->sg_desc[0].flags);
4447ea28254SJohn Hall #endif
4457ea28254SJohn Hall #endif /* DEBUG_AIO */
4467ea28254SJohn Hall }
4471e66f787SSean Bruno
4487ea28254SJohn Hall /*Subroutine used to populate AIO RAID 1 write bypass IU. */
4497ea28254SJohn Hall void
pqisrc_build_aio_R1_write(pqisrc_softstate_t * softs,pqi_aio_raid1_write_req_t * aio_req,rcb_t * rcb,uint32_t num_elem_alloted)4507ea28254SJohn Hall pqisrc_build_aio_R1_write(pqisrc_softstate_t *softs,
4517ea28254SJohn Hall pqi_aio_raid1_write_req_t *aio_req, rcb_t *rcb,
4527ea28254SJohn Hall uint32_t num_elem_alloted)
4537ea28254SJohn Hall {
4547ea28254SJohn Hall DBG_FUNC("IN\n");
4557ea28254SJohn Hall if (!rcb->dvp) {
4567ea28254SJohn Hall DBG_WARN("%s: DEBUG: dev ptr is null", __func__);
4577ea28254SJohn Hall return;
4587ea28254SJohn Hall }
4597ea28254SJohn Hall if (!rcb->dvp->raid_map) {
4607ea28254SJohn Hall DBG_WARN("%s: DEBUG: raid_map is null", __func__);
4617ea28254SJohn Hall return;
4627ea28254SJohn Hall }
4637ea28254SJohn Hall
4647ea28254SJohn Hall aio_req->header.iu_type = PQI_IU_TYPE_RAID1_WRITE_BYPASS_REQUEST;
4657ea28254SJohn Hall aio_req->header.comp_feature = 0;
4667ea28254SJohn Hall aio_req->response_queue_id = OS_GET_IO_RESP_QID(softs, rcb);
4677ea28254SJohn Hall aio_req->work_area[0] = 0;
4687ea28254SJohn Hall aio_req->work_area[1] = 0;
4697ea28254SJohn Hall aio_req->req_id = rcb->tag;
4707ea28254SJohn Hall aio_req->volume_id = (LE_32(rcb->dvp->scsi3addr[0]) & 0x3FFF);
4717ea28254SJohn Hall aio_req->nexus_1 = rcb->it_nexus[0];
4727ea28254SJohn Hall aio_req->nexus_2 = rcb->it_nexus[1];
4737ea28254SJohn Hall aio_req->nexus_3 = rcb->it_nexus[2];
4747ea28254SJohn Hall aio_req->buf_len = GET_SCSI_BUFFLEN(rcb);
4757ea28254SJohn Hall aio_req->cmd_flags.data_dir = rcb->data_dir;
4767ea28254SJohn Hall aio_req->cmd_flags.mem_type = 0;
4777ea28254SJohn Hall aio_req->cmd_flags.fence = 0;
4787ea28254SJohn Hall aio_req->cmd_flags.res2 = 0;
4797ea28254SJohn Hall aio_req->attr_prio.task_attr = OS_GET_TASK_ATTR(rcb);
4807ea28254SJohn Hall aio_req->attr_prio.cmd_prio = 0;
4817ea28254SJohn Hall aio_req->attr_prio.res3 = 0;
4827ea28254SJohn Hall if(rcb->cmdlen > sizeof(aio_req->cdb))
4837ea28254SJohn Hall rcb->cmdlen = sizeof(aio_req->cdb);
4847ea28254SJohn Hall memcpy(aio_req->cdb, rcb->cdbp, rcb->cmdlen);
4857ea28254SJohn Hall aio_req->err_idx = aio_req->req_id;
4867ea28254SJohn Hall aio_req->cdb_len = rcb->cmdlen;
4877ea28254SJohn Hall aio_req->num_drives = LE_16(rcb->dvp->raid_map->layout_map_count);
4887ea28254SJohn Hall
4897ea28254SJohn Hall /* handle encryption fields */
4907ea28254SJohn Hall if (rcb->encrypt_enable == true) {
4917ea28254SJohn Hall aio_req->cmd_flags.encrypt_enable = true;
4927ea28254SJohn Hall aio_req->encrypt_key_index =
4937ea28254SJohn Hall LE_16(rcb->enc_info.data_enc_key_index);
4947ea28254SJohn Hall aio_req->encrypt_twk_low =
4957ea28254SJohn Hall LE_32(rcb->enc_info.encrypt_tweak_lower);
4967ea28254SJohn Hall aio_req->encrypt_twk_high =
4977ea28254SJohn Hall LE_32(rcb->enc_info.encrypt_tweak_upper);
4987ea28254SJohn Hall } else {
4997ea28254SJohn Hall aio_req->cmd_flags.encrypt_enable = 0;
5007ea28254SJohn Hall aio_req->encrypt_key_index = 0;
5017ea28254SJohn Hall aio_req->encrypt_twk_high = 0;
5027ea28254SJohn Hall aio_req->encrypt_twk_low = 0;
5037ea28254SJohn Hall }
5047ea28254SJohn Hall /* Frame SGL Descriptor */
5057ea28254SJohn Hall aio_req->cmd_flags.partial = pqisrc_build_sgl(&aio_req->sg_desc[0], rcb,
5067ea28254SJohn Hall &aio_req->header, num_elem_alloted);
5077ea28254SJohn Hall
5087ea28254SJohn Hall aio_req->num_sg = aio_req->header.iu_length / sizeof(sgt_t);
5097ea28254SJohn Hall
5107ea28254SJohn Hall /* DBG_INFO("aio_req->num_sg :%d\n", aio_req->num_sg); */
5117ea28254SJohn Hall
5127ea28254SJohn Hall aio_req->header.iu_length += offsetof(pqi_aio_raid1_write_req_t, sg_desc) -
5137ea28254SJohn Hall sizeof(iu_header_t);
5147ea28254SJohn Hall
5157ea28254SJohn Hall /* set completion and error handlers. */
5167ea28254SJohn Hall rcb->success_cmp_callback = pqisrc_process_io_response_success;
5177ea28254SJohn Hall rcb->error_cmp_callback = pqisrc_process_aio_response_error;
5187ea28254SJohn Hall rcb->resp_qid = aio_req->response_queue_id;
5197ea28254SJohn Hall DBG_FUNC("OUT\n");
5207ea28254SJohn Hall
5217ea28254SJohn Hall }
5227ea28254SJohn Hall
5237ea28254SJohn Hall /*Subroutine used to show AIO RAID1 Write bypass IU fields */
5247ea28254SJohn Hall void
pqisrc_show_aio_R1_write(pqisrc_softstate_t * softs,rcb_t * rcb,pqi_aio_raid1_write_req_t * aio_req)5257ea28254SJohn Hall pqisrc_show_aio_R1_write(pqisrc_softstate_t *softs, rcb_t *rcb,
5267ea28254SJohn Hall pqi_aio_raid1_write_req_t *aio_req)
5277ea28254SJohn Hall {
5287ea28254SJohn Hall
5297ea28254SJohn Hall #ifdef DEBUG_AIO
5307ea28254SJohn Hall DBG_INFO("AIO RAID1 Write IU Content, tag# 0x%08x", rcb->tag);
5317ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "iu_type", aio_req->header.iu_type);
5327ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "comp_feat", aio_req->header.comp_feature);
5337ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "length", aio_req->header.iu_length);
5347ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "resp_qid", aio_req->response_queue_id);
5357ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "req_id", aio_req->req_id);
5367ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "volume_id", aio_req->volume_id);
5377ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "nexus_1", aio_req->nexus_1);
5387ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "nexus_2", aio_req->nexus_2);
5397ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "nexus_3", aio_req->nexus_3);
5407ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "buf_len", aio_req->buf_len);
5417ea28254SJohn Hall DBG_INFO("%15s:\n", "cmd_flags");
5427ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "data_dir", aio_req->cmd_flags.data_dir);
5437ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "partial", aio_req->cmd_flags.partial);
5447ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "mem_type", aio_req->cmd_flags.mem_type);
5457ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "fence", aio_req->cmd_flags.fence);
5467ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "encryption",
5477ea28254SJohn Hall aio_req->cmd_flags.encrypt_enable);
5487ea28254SJohn Hall DBG_INFO("%15s:\n", "attr_prio");
5497ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "task_attr", aio_req->attr_prio.task_attr);
5507ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "cmd_prio", aio_req->attr_prio.cmd_prio);
5517ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "dek_index", aio_req->encrypt_key_index);
5527ea28254SJohn Hall pqisrc_show_cdb(softs, "AIOR1W", rcb, aio_req->cdb);
5537ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "err_idx", aio_req->err_idx);
5547ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "num_sg", aio_req->num_sg);
5557ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "cdb_len", aio_req->cdb_len);
5567ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "num_drives", aio_req->num_drives);
5577ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "tweak_lower", aio_req->encrypt_twk_low);
5587ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "tweak_upper", aio_req->encrypt_twk_high);
5597ea28254SJohn Hall #if 0
5607ea28254SJohn Hall DBG_INFO("%15s: 0x%p\n", "sg_desc[0].addr",
5617ea28254SJohn Hall (void *)aio_req->sg_desc[0].addr);
5627ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "sg_desc[0].len",
5637ea28254SJohn Hall aio_req->sg_desc[0].len);
5647ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "sg_desc[0].flags",
5657ea28254SJohn Hall aio_req->sg_desc[0].flags);
5667ea28254SJohn Hall #endif
5677ea28254SJohn Hall #endif /* DEBUG_AIO */
5687ea28254SJohn Hall }
5697ea28254SJohn Hall
5707ea28254SJohn Hall /*Subroutine used to populate AIO Raid5 or 6 write bypass IU */
5717ea28254SJohn Hall void
pqisrc_build_aio_R5or6_write(pqisrc_softstate_t * softs,pqi_aio_raid5or6_write_req_t * aio_req,rcb_t * rcb,uint32_t num_elem_alloted)5727ea28254SJohn Hall pqisrc_build_aio_R5or6_write(pqisrc_softstate_t *softs,
5737ea28254SJohn Hall pqi_aio_raid5or6_write_req_t *aio_req, rcb_t *rcb,
5747ea28254SJohn Hall uint32_t num_elem_alloted)
5757ea28254SJohn Hall {
5767ea28254SJohn Hall DBG_FUNC("IN\n");
5777ea28254SJohn Hall uint32_t index;
5787ea28254SJohn Hall unsigned num_data_disks;
5797ea28254SJohn Hall unsigned num_metadata_disks;
5807ea28254SJohn Hall unsigned total_disks;
5817ea28254SJohn Hall num_data_disks = LE_16(rcb->dvp->raid_map->data_disks_per_row);
5827ea28254SJohn Hall num_metadata_disks = LE_16(rcb->dvp->raid_map->metadata_disks_per_row);
5837ea28254SJohn Hall total_disks = num_data_disks + num_metadata_disks;
5847ea28254SJohn Hall
5857ea28254SJohn Hall index = PQISRC_DIV_ROUND_UP(rcb->raid_map_index + 1, total_disks);
5867ea28254SJohn Hall index *= total_disks;
5877ea28254SJohn Hall index -= num_metadata_disks;
5887ea28254SJohn Hall
5897ea28254SJohn Hall switch (rcb->dvp->raid_level) {
5907ea28254SJohn Hall case SA_RAID_5:
5917ea28254SJohn Hall aio_req->header.iu_type =
5927ea28254SJohn Hall PQI_IU_TYPE_RAID5_WRITE_BYPASS_REQUEST;
5937ea28254SJohn Hall break;
5947ea28254SJohn Hall case SA_RAID_6:
5957ea28254SJohn Hall aio_req->header.iu_type =
5967ea28254SJohn Hall PQI_IU_TYPE_RAID6_WRITE_BYPASS_REQUEST;
5977ea28254SJohn Hall break;
5987ea28254SJohn Hall default:
5997ea28254SJohn Hall DBG_ERR("WRONG RAID TYPE FOR FUNCTION\n");
6007ea28254SJohn Hall }
6017ea28254SJohn Hall aio_req->header.comp_feature = 0;
6027ea28254SJohn Hall aio_req->response_queue_id = OS_GET_IO_RESP_QID(softs, rcb);
6037ea28254SJohn Hall aio_req->work_area[0] = 0;
6047ea28254SJohn Hall aio_req->work_area[1] = 0;
6057ea28254SJohn Hall aio_req->req_id = rcb->tag;
6067ea28254SJohn Hall aio_req->volume_id = (LE_32(rcb->dvp->scsi3addr[0]) & 0x3FFF);
6077ea28254SJohn Hall aio_req->data_it_nexus = rcb->dvp->raid_map->dev_data[rcb->raid_map_index].ioaccel_handle;
6087ea28254SJohn Hall aio_req->p_parity_it_nexus =
6097ea28254SJohn Hall rcb->dvp->raid_map->dev_data[index].ioaccel_handle;
6107ea28254SJohn Hall if (aio_req->header.iu_type ==
6117ea28254SJohn Hall PQI_IU_TYPE_RAID6_WRITE_BYPASS_REQUEST) {
6127ea28254SJohn Hall aio_req->q_parity_it_nexus =
6137ea28254SJohn Hall rcb->dvp->raid_map->dev_data[index + 1].ioaccel_handle;
6147ea28254SJohn Hall }
6157ea28254SJohn Hall aio_req->xor_multiplier =
6167ea28254SJohn Hall rcb->dvp->raid_map->dev_data[rcb->raid_map_index].xor_mult[1];
6177ea28254SJohn Hall aio_req->row = rcb->row_num;
6187ea28254SJohn Hall /*aio_req->reserved = rcb->row_num * rcb->blocks_per_row +
6197ea28254SJohn Hall rcb->dvp->raid_map->disk_starting_blk;*/
6207ea28254SJohn Hall aio_req->buf_len = GET_SCSI_BUFFLEN(rcb);
6217ea28254SJohn Hall aio_req->cmd_flags.data_dir = rcb->data_dir;
6227ea28254SJohn Hall aio_req->cmd_flags.mem_type = 0;
6237ea28254SJohn Hall aio_req->cmd_flags.fence = 0;
6247ea28254SJohn Hall aio_req->cmd_flags.res2 = 0;
6257ea28254SJohn Hall aio_req->attr_prio.task_attr = OS_GET_TASK_ATTR(rcb);
6267ea28254SJohn Hall aio_req->attr_prio.cmd_prio = 0;
6277ea28254SJohn Hall aio_req->attr_prio.res3 = 0;
6287ea28254SJohn Hall if (rcb->cmdlen > sizeof(aio_req->cdb))
6297ea28254SJohn Hall rcb->cmdlen = sizeof(aio_req->cdb);
6307ea28254SJohn Hall memcpy(aio_req->cdb, rcb->cdbp, rcb->cmdlen);
6317ea28254SJohn Hall aio_req->err_idx = aio_req->req_id;
6327ea28254SJohn Hall aio_req->cdb_len = rcb->cmdlen;
6337ea28254SJohn Hall #if 0
6347ea28254SJohn Hall /* Stubbed out for later */
6357ea28254SJohn Hall aio_req->header.iu_type = iu_type;
6367ea28254SJohn Hall aio_req->data_it_nexus = ;
6377ea28254SJohn Hall aio_req->p_parity_it_nexus = ;
6387ea28254SJohn Hall aio_req->q_parity_it_nexus = ;
6397ea28254SJohn Hall aio_req->row = ;
6407ea28254SJohn Hall aio_req->stripe_lba = ;
6417ea28254SJohn Hall #endif
6427ea28254SJohn Hall /* handle encryption fields */
6437ea28254SJohn Hall if (rcb->encrypt_enable == true) {
6447ea28254SJohn Hall aio_req->cmd_flags.encrypt_enable = true;
6457ea28254SJohn Hall aio_req->encrypt_key_index =
6467ea28254SJohn Hall LE_16(rcb->enc_info.data_enc_key_index);
6477ea28254SJohn Hall aio_req->encrypt_twk_low =
6487ea28254SJohn Hall LE_32(rcb->enc_info.encrypt_tweak_lower);
6497ea28254SJohn Hall aio_req->encrypt_twk_high =
6507ea28254SJohn Hall LE_32(rcb->enc_info.encrypt_tweak_upper);
6517ea28254SJohn Hall } else {
6527ea28254SJohn Hall aio_req->cmd_flags.encrypt_enable = 0;
6537ea28254SJohn Hall aio_req->encrypt_key_index = 0;
6547ea28254SJohn Hall aio_req->encrypt_twk_high = 0;
6557ea28254SJohn Hall aio_req->encrypt_twk_low = 0;
6567ea28254SJohn Hall }
6577ea28254SJohn Hall /* Frame SGL Descriptor */
6587ea28254SJohn Hall aio_req->cmd_flags.partial = pqisrc_build_sgl(&aio_req->sg_desc[0], rcb,
6597ea28254SJohn Hall &aio_req->header, num_elem_alloted);
6607ea28254SJohn Hall
6617ea28254SJohn Hall aio_req->num_sg = aio_req->header.iu_length / sizeof(sgt_t);
6627ea28254SJohn Hall
6637ea28254SJohn Hall /* DBG_INFO("aio_req->num_sg :%d\n", aio_req->num_sg); */
6647ea28254SJohn Hall
6657ea28254SJohn Hall aio_req->header.iu_length += offsetof(pqi_aio_raid5or6_write_req_t, sg_desc) -
6667ea28254SJohn Hall sizeof(iu_header_t);
6677ea28254SJohn Hall /* set completion and error handlers. */
6687ea28254SJohn Hall rcb->success_cmp_callback = pqisrc_process_io_response_success;
6697ea28254SJohn Hall rcb->error_cmp_callback = pqisrc_process_aio_response_error;
6707ea28254SJohn Hall rcb->resp_qid = aio_req->response_queue_id;
6717ea28254SJohn Hall DBG_FUNC("OUT\n");
6727ea28254SJohn Hall
6737ea28254SJohn Hall }
6747ea28254SJohn Hall
6757ea28254SJohn Hall /*Subroutine used to show AIO RAID5/6 Write bypass IU fields */
6767ea28254SJohn Hall void
pqisrc_show_aio_R5or6_write(pqisrc_softstate_t * softs,rcb_t * rcb,pqi_aio_raid5or6_write_req_t * aio_req)6777ea28254SJohn Hall pqisrc_show_aio_R5or6_write(pqisrc_softstate_t *softs, rcb_t *rcb,
6787ea28254SJohn Hall pqi_aio_raid5or6_write_req_t *aio_req)
6797ea28254SJohn Hall {
6807ea28254SJohn Hall #ifdef DEBUG_AIO
6817ea28254SJohn Hall DBG_INFO("AIO RAID5or6 Write IU Content, tag# 0x%08x\n", rcb->tag);
6827ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "iu_type", aio_req->header.iu_type);
6837ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "comp_feat", aio_req->header.comp_feature);
6847ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "length", aio_req->header.iu_length);
6857ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "resp_qid", aio_req->response_queue_id);
6867ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "req_id", aio_req->req_id);
6877ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "volume_id", aio_req->volume_id);
6887ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "data_it_nexus",
6897ea28254SJohn Hall aio_req->data_it_nexus);
6907ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "p_parity_it_nexus",
6917ea28254SJohn Hall aio_req->p_parity_it_nexus);
6927ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "q_parity_it_nexus",
6937ea28254SJohn Hall aio_req->q_parity_it_nexus);
6947ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "buf_len", aio_req->buf_len);
6957ea28254SJohn Hall DBG_INFO("%15s:\n", "cmd_flags");
6967ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "data_dir", aio_req->cmd_flags.data_dir);
6977ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "partial", aio_req->cmd_flags.partial);
6987ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "mem_type", aio_req->cmd_flags.mem_type);
6997ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "fence", aio_req->cmd_flags.fence);
7007ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "encryption",
7017ea28254SJohn Hall aio_req->cmd_flags.encrypt_enable);
7027ea28254SJohn Hall DBG_INFO("%15s:\n", "attr_prio");
7037ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "task_attr", aio_req->attr_prio.task_attr);
7047ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "cmd_prio", aio_req->attr_prio.cmd_prio);
7057ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "dek_index", aio_req->encrypt_key_index);
7067ea28254SJohn Hall pqisrc_show_cdb(softs, "AIOR56W", rcb, aio_req->cdb);
7077ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "err_idx", aio_req->err_idx);
7087ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "num_sg", aio_req->num_sg);
7097ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "cdb_len", aio_req->cdb_len);
7107ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "tweak_lower", aio_req->encrypt_twk_low);
7117ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "tweak_upper", aio_req->encrypt_twk_high);
7127ea28254SJohn Hall DBG_INFO("%15s: 0x%lx\n", "row", aio_req->row);
7137ea28254SJohn Hall #if 0
7147ea28254SJohn Hall DBG_INFO("%15s: 0x%lx\n", "stripe_lba", aio_req->stripe_lba);
7157ea28254SJohn Hall DBG_INFO("%15s: 0x%p\n", "sg_desc[0].addr",
7167ea28254SJohn Hall (void *)aio_req->sg_desc[0].addr);
7177ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "sg_desc[0].len",
7187ea28254SJohn Hall aio_req->sg_desc[0].len);
7197ea28254SJohn Hall DBG_INFO("%15s: 0x%x\n", "sg_desc[0].flags",
7207ea28254SJohn Hall aio_req->sg_desc[0].flags);
7217ea28254SJohn Hall #endif
7227ea28254SJohn Hall #endif /* DEBUG_AIO */
7237ea28254SJohn Hall }
7247ea28254SJohn Hall
7257ea28254SJohn Hall /* Is the cdb a read command? */
7267ea28254SJohn Hall boolean_t
pqisrc_cdb_is_read(uint8_t * cdb)7277ea28254SJohn Hall pqisrc_cdb_is_read(uint8_t *cdb)
7287ea28254SJohn Hall {
7297ea28254SJohn Hall if (cdb[0] == SCMD_READ_6 || cdb[0] == SCMD_READ_10 ||
7307ea28254SJohn Hall cdb[0] == SCMD_READ_12 || cdb[0] == SCMD_READ_16)
7317ea28254SJohn Hall return true;
7327ea28254SJohn Hall return false;
7337ea28254SJohn Hall }
7347ea28254SJohn Hall
7357ea28254SJohn Hall /* Is the cdb a write command? */
7367ea28254SJohn Hall boolean_t
pqisrc_cdb_is_write(uint8_t * cdb)7377ea28254SJohn Hall pqisrc_cdb_is_write(uint8_t *cdb)
7387ea28254SJohn Hall {
7397ea28254SJohn Hall if (cdb == NULL)
7407ea28254SJohn Hall return false;
7417ea28254SJohn Hall
7427ea28254SJohn Hall if (cdb[0] == SCMD_WRITE_6 || cdb[0] == SCMD_WRITE_10 ||
7437ea28254SJohn Hall cdb[0] == SCMD_WRITE_12 || cdb[0] == SCMD_WRITE_16)
7447ea28254SJohn Hall return true;
7457ea28254SJohn Hall return false;
7467ea28254SJohn Hall }
7477ea28254SJohn Hall
7487ea28254SJohn Hall /*Subroutine used to show the AIO request */
7497ea28254SJohn Hall void
pqisrc_show_aio_io(pqisrc_softstate_t * softs,rcb_t * rcb,pqi_aio_req_t * aio_req,uint32_t num_elem_alloted)7507ea28254SJohn Hall pqisrc_show_aio_io(pqisrc_softstate_t *softs, rcb_t *rcb,
7517ea28254SJohn Hall pqi_aio_req_t *aio_req, uint32_t num_elem_alloted)
7527ea28254SJohn Hall {
7537ea28254SJohn Hall boolean_t is_write;
7547ea28254SJohn Hall DBG_FUNC("IN\n");
7557ea28254SJohn Hall
7567ea28254SJohn Hall is_write = pqisrc_cdb_is_write(rcb->cdbp);
7577ea28254SJohn Hall
7587ea28254SJohn Hall if (!is_write) {
7597ea28254SJohn Hall pqisrc_show_aio_common(softs, rcb, aio_req);
7607ea28254SJohn Hall goto out;
7617ea28254SJohn Hall }
7627ea28254SJohn Hall
7637ea28254SJohn Hall switch (rcb->dvp->raid_level) {
7647ea28254SJohn Hall case SA_RAID_0:
7657ea28254SJohn Hall pqisrc_show_aio_common(softs, rcb, aio_req);
7667ea28254SJohn Hall break;
7677ea28254SJohn Hall case SA_RAID_1:
7687ea28254SJohn Hall case SA_RAID_ADM:
7697ea28254SJohn Hall pqisrc_show_aio_R1_write(softs, rcb,
7707ea28254SJohn Hall (pqi_aio_raid1_write_req_t *)aio_req);
7717ea28254SJohn Hall break;
7727ea28254SJohn Hall case SA_RAID_5:
7737ea28254SJohn Hall case SA_RAID_6:
7747ea28254SJohn Hall pqisrc_show_aio_R5or6_write(softs, rcb,
7757ea28254SJohn Hall (pqi_aio_raid5or6_write_req_t *)aio_req);
7767ea28254SJohn Hall break;
7777ea28254SJohn Hall }
7787ea28254SJohn Hall
7797ea28254SJohn Hall out:
7807ea28254SJohn Hall DBG_FUNC("OUT\n");
7817ea28254SJohn Hall
7827ea28254SJohn Hall }
7837ea28254SJohn Hall
7847ea28254SJohn Hall
7857ea28254SJohn Hall void
pqisrc_build_aio_io(pqisrc_softstate_t * softs,rcb_t * rcb,pqi_aio_req_t * aio_req,uint32_t num_elem_alloted)7867ea28254SJohn Hall pqisrc_build_aio_io(pqisrc_softstate_t *softs, rcb_t *rcb,
7877ea28254SJohn Hall pqi_aio_req_t *aio_req, uint32_t num_elem_alloted)
7887ea28254SJohn Hall {
7897ea28254SJohn Hall boolean_t is_write;
7907ea28254SJohn Hall DBG_FUNC("IN\n");
7917ea28254SJohn Hall
7927ea28254SJohn Hall is_write = pqisrc_cdb_is_write(rcb->cdbp);
7937ea28254SJohn Hall
7947ea28254SJohn Hall if (is_write) {
7957ea28254SJohn Hall switch (rcb->dvp->raid_level) {
7967ea28254SJohn Hall case SA_RAID_0:
7977ea28254SJohn Hall pqisrc_build_aio_common(softs, aio_req,
7987ea28254SJohn Hall rcb, num_elem_alloted);
7997ea28254SJohn Hall break;
8007ea28254SJohn Hall case SA_RAID_1:
8017ea28254SJohn Hall case SA_RAID_ADM:
8027ea28254SJohn Hall pqisrc_build_aio_R1_write(softs,
8037ea28254SJohn Hall (pqi_aio_raid1_write_req_t *)aio_req,
8047ea28254SJohn Hall rcb, num_elem_alloted);
8057ea28254SJohn Hall
8067ea28254SJohn Hall break;
8077ea28254SJohn Hall case SA_RAID_5:
8087ea28254SJohn Hall case SA_RAID_6:
8097ea28254SJohn Hall pqisrc_build_aio_R5or6_write(softs,
8107ea28254SJohn Hall (pqi_aio_raid5or6_write_req_t *)aio_req,
8117ea28254SJohn Hall rcb, num_elem_alloted);
8127ea28254SJohn Hall break;
8137ea28254SJohn Hall }
8147ea28254SJohn Hall } else {
8157ea28254SJohn Hall pqisrc_build_aio_common(softs, aio_req, rcb, num_elem_alloted);
8167ea28254SJohn Hall }
8177ea28254SJohn Hall
8187ea28254SJohn Hall pqisrc_show_aio_io(softs, rcb, aio_req, num_elem_alloted);
8197ea28254SJohn Hall
8207ea28254SJohn Hall DBG_FUNC("OUT\n");
8217ea28254SJohn Hall }
8227ea28254SJohn Hall
8237ea28254SJohn Hall /*
8247ea28254SJohn Hall * Return true from this function to prevent AIO from handling this request.
8257ea28254SJohn Hall * True is returned if the request is determined to be part of a stream, or
8267ea28254SJohn Hall * if the controller does not handle AIO at the appropriate RAID level.
8277ea28254SJohn Hall */
8287ea28254SJohn Hall static boolean_t
pqisrc_is_parity_write_stream(pqisrc_softstate_t * softs,rcb_t * rcb)8297ea28254SJohn Hall pqisrc_is_parity_write_stream(pqisrc_softstate_t *softs, rcb_t *rcb)
8307ea28254SJohn Hall {
8317ea28254SJohn Hall os_ticks_t oldest_ticks;
8327ea28254SJohn Hall uint8_t lru_index;
8337ea28254SJohn Hall int i;
8347ea28254SJohn Hall int rc;
8357ea28254SJohn Hall pqi_scsi_dev_t *device;
8367ea28254SJohn Hall struct pqi_stream_data *pqi_stream_data;
8377ea28254SJohn Hall aio_req_locator_t loc;
8387ea28254SJohn Hall
8397ea28254SJohn Hall DBG_FUNC("IN\n");
8407ea28254SJohn Hall
8417ea28254SJohn Hall rc = fill_lba_for_scsi_rw(softs, rcb->cdbp , &loc);
8427ea28254SJohn Hall if (rc != PQI_STATUS_SUCCESS) {
8437ea28254SJohn Hall return false;
8447ea28254SJohn Hall }
8457ea28254SJohn Hall
8467ea28254SJohn Hall /* check writes only */
8477ea28254SJohn Hall if (!pqisrc_cdb_is_write(rcb->cdbp)) {
8487ea28254SJohn Hall return false;
8497ea28254SJohn Hall }
8507ea28254SJohn Hall
8517ea28254SJohn Hall if (!softs->enable_stream_detection) {
8527ea28254SJohn Hall return false;
8537ea28254SJohn Hall }
8547ea28254SJohn Hall
8557ea28254SJohn Hall device = rcb->dvp;
8567ea28254SJohn Hall if (!device) {
8577ea28254SJohn Hall return false;
8587ea28254SJohn Hall }
8597ea28254SJohn Hall
8607ea28254SJohn Hall /*
8617ea28254SJohn Hall * check for R5/R6 streams.
8627ea28254SJohn Hall */
8637ea28254SJohn Hall if (device->raid_level != SA_RAID_5 && device->raid_level != SA_RAID_6) {
8647ea28254SJohn Hall return false;
8657ea28254SJohn Hall }
8667ea28254SJohn Hall
8677ea28254SJohn Hall /*
8687ea28254SJohn Hall * If controller does not support AIO R{5,6} writes, need to send
8697ea28254SJohn Hall * requests down non-aio path.
8707ea28254SJohn Hall */
8717ea28254SJohn Hall if ((device->raid_level == SA_RAID_5 && !softs->aio_raid5_write_bypass) ||
8727ea28254SJohn Hall (device->raid_level == SA_RAID_6 && !softs->aio_raid6_write_bypass)) {
8737ea28254SJohn Hall return true;
8747ea28254SJohn Hall }
8757ea28254SJohn Hall
8767ea28254SJohn Hall lru_index = 0;
8777ea28254SJohn Hall oldest_ticks = INT_MAX;
8787ea28254SJohn Hall for (i = 0; i < NUM_STREAMS_PER_LUN; i++) {
8797ea28254SJohn Hall pqi_stream_data = &device->stream_data[i];
8807ea28254SJohn Hall /*
8817ea28254SJohn Hall * check for adjacent request or request is within
8827ea28254SJohn Hall * the previous request.
8837ea28254SJohn Hall */
8847ea28254SJohn Hall if ((pqi_stream_data->next_lba &&
8857ea28254SJohn Hall loc.block.first >= pqi_stream_data->next_lba) &&
8867ea28254SJohn Hall loc.block.first <= pqi_stream_data->next_lba +
8877ea28254SJohn Hall loc.block.cnt) {
8887ea28254SJohn Hall pqi_stream_data->next_lba = loc.block.first +
8897ea28254SJohn Hall loc.block.cnt;
8907ea28254SJohn Hall pqi_stream_data->last_accessed = TICKS;
8917ea28254SJohn Hall return true;
8927ea28254SJohn Hall }
8937ea28254SJohn Hall
8947ea28254SJohn Hall /* unused entry */
8957ea28254SJohn Hall if (pqi_stream_data->last_accessed == 0) {
8967ea28254SJohn Hall lru_index = i;
8977ea28254SJohn Hall break;
8987ea28254SJohn Hall }
8997ea28254SJohn Hall
9007ea28254SJohn Hall /* Find entry with oldest last accessed time */
9017ea28254SJohn Hall if (pqi_stream_data->last_accessed <= oldest_ticks) {
9027ea28254SJohn Hall oldest_ticks = pqi_stream_data->last_accessed;
9037ea28254SJohn Hall lru_index = i;
9047ea28254SJohn Hall }
9057ea28254SJohn Hall }
9067ea28254SJohn Hall
9077ea28254SJohn Hall /*
9087ea28254SJohn Hall * Set LRU entry
9097ea28254SJohn Hall */
9107ea28254SJohn Hall pqi_stream_data = &device->stream_data[lru_index];
9117ea28254SJohn Hall pqi_stream_data->last_accessed = TICKS;
9127ea28254SJohn Hall pqi_stream_data->next_lba = loc.block.first + loc.block.cnt;
9137ea28254SJohn Hall
9147ea28254SJohn Hall DBG_FUNC("OUT\n");
9157ea28254SJohn Hall
9167ea28254SJohn Hall return false;
9177ea28254SJohn Hall }
9187ea28254SJohn Hall
9197ea28254SJohn Hall /**
9207ea28254SJohn Hall Determine if a request is eligible for AIO. Build/map
9217ea28254SJohn Hall the request if using AIO path to a RAID volume.
9227ea28254SJohn Hall
9237ea28254SJohn Hall return the path that should be used for this request
9247ea28254SJohn Hall */
9257ea28254SJohn Hall static IO_PATH_T
determine_io_path_build_bypass(pqisrc_softstate_t * softs,rcb_t * rcb)9267ea28254SJohn Hall determine_io_path_build_bypass(pqisrc_softstate_t *softs,rcb_t *rcb)
9277ea28254SJohn Hall {
9287ea28254SJohn Hall IO_PATH_T io_path = AIO_PATH;
9297ea28254SJohn Hall pqi_scsi_dev_t *devp = rcb->dvp;
9307ea28254SJohn Hall int ret = PQI_STATUS_FAILURE;
9317ea28254SJohn Hall
9327ea28254SJohn Hall /* Default to using the host CDB directly (will be used if targeting RAID
9337ea28254SJohn Hall path or HBA mode */
9347ea28254SJohn Hall rcb->cdbp = OS_GET_CDBP(rcb);
9357ea28254SJohn Hall
9367ea28254SJohn Hall if(!rcb->aio_retry) {
9377ea28254SJohn Hall
9387ea28254SJohn Hall /** IO for Physical Drive, Send in AIO PATH **/
9397ea28254SJohn Hall if(IS_AIO_PATH(devp)) {
9407ea28254SJohn Hall rcb->ioaccel_handle = devp->ioaccel_handle;
9417ea28254SJohn Hall return io_path;
9427ea28254SJohn Hall }
9437ea28254SJohn Hall
9447ea28254SJohn Hall /** IO for RAID Volume, ByPass IO, Send in AIO PATH unless part of stream **/
9457ea28254SJohn Hall if (devp->offload_enabled && !pqisrc_is_parity_write_stream(softs, rcb)) {
9467ea28254SJohn Hall ret = pqisrc_build_scsi_cmd_raidbypass(softs, devp, rcb);
9477ea28254SJohn Hall }
9487ea28254SJohn Hall
9497ea28254SJohn Hall if (PQI_STATUS_FAILURE == ret) {
9507ea28254SJohn Hall io_path = RAID_PATH;
9517ea28254SJohn Hall } else {
9527ea28254SJohn Hall ASSERT(rcb->cdbp == rcb->bypass_cdb);
9537ea28254SJohn Hall }
9547ea28254SJohn Hall } else {
9557ea28254SJohn Hall /* Retrying failed AIO IO */
9567ea28254SJohn Hall io_path = RAID_PATH;
9577ea28254SJohn Hall }
9587ea28254SJohn Hall
9597ea28254SJohn Hall return io_path;
9607ea28254SJohn Hall }
9617ea28254SJohn Hall
9627ea28254SJohn Hall uint8_t
pqisrc_get_aio_data_direction(rcb_t * rcb)9637ea28254SJohn Hall pqisrc_get_aio_data_direction(rcb_t *rcb)
9647ea28254SJohn Hall {
9657ea28254SJohn Hall switch (rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) {
9667ea28254SJohn Hall case CAM_DIR_IN: return SOP_DATA_DIR_FROM_DEVICE;
9677ea28254SJohn Hall case CAM_DIR_OUT: return SOP_DATA_DIR_TO_DEVICE;
9687ea28254SJohn Hall case CAM_DIR_NONE: return SOP_DATA_DIR_NONE;
9697ea28254SJohn Hall default: return SOP_DATA_DIR_UNKNOWN;
9707ea28254SJohn Hall }
9717ea28254SJohn Hall }
9727ea28254SJohn Hall
9737ea28254SJohn Hall uint8_t
pqisrc_get_raid_data_direction(rcb_t * rcb)9747ea28254SJohn Hall pqisrc_get_raid_data_direction(rcb_t *rcb)
9757ea28254SJohn Hall {
9767ea28254SJohn Hall switch (rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) {
9777ea28254SJohn Hall case CAM_DIR_IN: return SOP_DATA_DIR_TO_DEVICE;
9787ea28254SJohn Hall case CAM_DIR_OUT: return SOP_DATA_DIR_FROM_DEVICE;
9797ea28254SJohn Hall case CAM_DIR_NONE: return SOP_DATA_DIR_NONE;
9807ea28254SJohn Hall default: return SOP_DATA_DIR_UNKNOWN;
9817ea28254SJohn Hall }
9821e66f787SSean Bruno }
9831e66f787SSean Bruno
9841e66f787SSean Bruno /* Function used to build and send RAID/AIO */
9859fac68fcSPAPANI SRIKANTH int
pqisrc_build_send_io(pqisrc_softstate_t * softs,rcb_t * rcb)9869fac68fcSPAPANI SRIKANTH pqisrc_build_send_io(pqisrc_softstate_t *softs,rcb_t *rcb)
9871e66f787SSean Bruno {
9881e66f787SSean Bruno ib_queue_t *ib_q_array = softs->op_aio_ib_q;
9891e66f787SSean Bruno ib_queue_t *ib_q = NULL;
9901e66f787SSean Bruno char *ib_iu = NULL;
9917ea28254SJohn Hall IO_PATH_T io_path;
9921e66f787SSean Bruno uint32_t TraverseCount = 0;
9931e66f787SSean Bruno int first_qindex = OS_GET_IO_REQ_QINDEX(softs, rcb);
9941e66f787SSean Bruno int qindex = first_qindex;
9951e66f787SSean Bruno uint32_t num_op_ib_q = softs->num_op_aio_ibq;
9961e66f787SSean Bruno uint32_t num_elem_needed;
9971e66f787SSean Bruno uint32_t num_elem_alloted = 0;
9981e66f787SSean Bruno pqi_scsi_dev_t *devp = rcb->dvp;
9997ea28254SJohn Hall boolean_t is_write;
10001e66f787SSean Bruno
10017ea28254SJohn Hall DBG_FUNC("IN\n");
10021e66f787SSean Bruno
10037ea28254SJohn Hall /* Note: this will determine if the request is eligble for AIO */
10047ea28254SJohn Hall io_path = determine_io_path_build_bypass(softs, rcb);
10057ea28254SJohn Hall
10067ea28254SJohn Hall if (io_path == RAID_PATH)
10077ea28254SJohn Hall {
10087ea28254SJohn Hall /* Update direction for RAID path */
10097ea28254SJohn Hall rcb->data_dir = pqisrc_get_raid_data_direction(rcb);
10109fac68fcSPAPANI SRIKANTH num_op_ib_q = softs->num_op_raid_ibq;
10119fac68fcSPAPANI SRIKANTH ib_q_array = softs->op_raid_ib_q;
10129fac68fcSPAPANI SRIKANTH }
10137ea28254SJohn Hall else {
10147ea28254SJohn Hall rcb->data_dir = pqisrc_get_aio_data_direction(rcb);
10157ea28254SJohn Hall if (rcb->data_dir == SOP_DATA_DIR_UNKNOWN) {
10167ea28254SJohn Hall DBG_ERR("Unknown Direction\n");
10177ea28254SJohn Hall }
10187ea28254SJohn Hall }
10191e66f787SSean Bruno
10207ea28254SJohn Hall is_write = pqisrc_cdb_is_write(rcb->cdbp);
10217ea28254SJohn Hall /* coverity[unchecked_value] */
10227ea28254SJohn Hall num_elem_needed = pqisrc_num_elem_needed(softs,
10237ea28254SJohn Hall OS_GET_IO_SG_COUNT(rcb), devp, is_write, io_path);
10247ea28254SJohn Hall DBG_IO("num_elem_needed :%u",num_elem_needed);
10251e66f787SSean Bruno
10261e66f787SSean Bruno do {
10271e66f787SSean Bruno uint32_t num_elem_available;
10281e66f787SSean Bruno ib_q = (ib_q_array + qindex);
10291e66f787SSean Bruno PQI_LOCK(&ib_q->lock);
10301e66f787SSean Bruno num_elem_available = pqisrc_contiguous_free_elem(ib_q->pi_local,
10311e66f787SSean Bruno *(ib_q->ci_virt_addr), ib_q->num_elem);
10321e66f787SSean Bruno
10337ea28254SJohn Hall DBG_IO("num_elem_avialable :%u\n",num_elem_available);
10341e66f787SSean Bruno if(num_elem_available >= num_elem_needed) {
10351e66f787SSean Bruno num_elem_alloted = num_elem_needed;
10361e66f787SSean Bruno break;
10371e66f787SSean Bruno }
10381e66f787SSean Bruno DBG_IO("Current queue is busy! Hop to next queue\n");
10391e66f787SSean Bruno
10401e66f787SSean Bruno PQI_UNLOCK(&ib_q->lock);
10411e66f787SSean Bruno qindex = (qindex + 1) % num_op_ib_q;
10421e66f787SSean Bruno if(qindex == first_qindex) {
10431e66f787SSean Bruno if (num_elem_needed == 1)
10441e66f787SSean Bruno break;
10451e66f787SSean Bruno TraverseCount += 1;
10461e66f787SSean Bruno num_elem_needed = 1;
10471e66f787SSean Bruno }
10481e66f787SSean Bruno }while(TraverseCount < 2);
10491e66f787SSean Bruno
10507ea28254SJohn Hall DBG_IO("num_elem_alloted :%u",num_elem_alloted);
10511e66f787SSean Bruno if (num_elem_alloted == 0) {
10521e66f787SSean Bruno DBG_WARN("OUT: IB Queues were full\n");
10531e66f787SSean Bruno return PQI_STATUS_QFULL;
10541e66f787SSean Bruno }
10551e66f787SSean Bruno
10569fac68fcSPAPANI SRIKANTH pqisrc_increment_device_active_io(softs,devp);
10579fac68fcSPAPANI SRIKANTH
10581e66f787SSean Bruno /* Get IB Queue Slot address to build IU */
10591e66f787SSean Bruno ib_iu = ib_q->array_virt_addr + (ib_q->pi_local * ib_q->elem_size);
10601e66f787SSean Bruno
10611e66f787SSean Bruno if(io_path == AIO_PATH) {
10627ea28254SJohn Hall /* Fill in the AIO IU per request and raid type */
10631e66f787SSean Bruno pqisrc_build_aio_io(softs, rcb, (pqi_aio_req_t *)ib_iu,
10641e66f787SSean Bruno num_elem_alloted);
10651e66f787SSean Bruno } else {
10661e66f787SSean Bruno /** Build RAID structure **/
10671e66f787SSean Bruno pqisrc_build_raid_io(softs, rcb, (pqisrc_raid_req_t *)ib_iu,
10681e66f787SSean Bruno num_elem_alloted);
10691e66f787SSean Bruno }
10701e66f787SSean Bruno
10711e66f787SSean Bruno rcb->req_pending = true;
10729fac68fcSPAPANI SRIKANTH rcb->req_q = ib_q;
10739fac68fcSPAPANI SRIKANTH rcb->path = io_path;
10741e66f787SSean Bruno
10757ea28254SJohn Hall pqisrc_increment_io_counters(softs, rcb);
10767ea28254SJohn Hall
10771e66f787SSean Bruno /* Update the local PI */
10781e66f787SSean Bruno ib_q->pi_local = (ib_q->pi_local + num_elem_alloted) % ib_q->num_elem;
10791e66f787SSean Bruno
10807ea28254SJohn Hall DBG_IO("ib_q->pi_local : %x\n", ib_q->pi_local);
10817ea28254SJohn Hall DBG_IO("*ib_q->ci_virt_addr: %x\n",*(ib_q->ci_virt_addr));
10821e66f787SSean Bruno
10831e66f787SSean Bruno /* Inform the fw about the new IU */
10841e66f787SSean Bruno PCI_MEM_PUT32(softs, ib_q->pi_register_abs, ib_q->pi_register_offset, ib_q->pi_local);
10851e66f787SSean Bruno
10861e66f787SSean Bruno PQI_UNLOCK(&ib_q->lock);
10877ea28254SJohn Hall DBG_FUNC("OUT\n");
10881e66f787SSean Bruno return PQI_STATUS_SUCCESS;
10891e66f787SSean Bruno }
10901e66f787SSean Bruno
10911e66f787SSean Bruno /* Subroutine used to set encryption info as part of RAID bypass IO*/
10929fac68fcSPAPANI SRIKANTH static inline void
pqisrc_set_enc_info(struct pqi_enc_info * enc_info,struct raid_map * raid_map,uint64_t first_block)10939fac68fcSPAPANI SRIKANTH pqisrc_set_enc_info(struct pqi_enc_info *enc_info,
10949fac68fcSPAPANI SRIKANTH struct raid_map *raid_map, uint64_t first_block)
10951e66f787SSean Bruno {
10961e66f787SSean Bruno uint32_t volume_blk_size;
10971e66f787SSean Bruno
10981e66f787SSean Bruno /*
10991e66f787SSean Bruno * Set the encryption tweak values based on logical block address.
11001e66f787SSean Bruno * If the block size is 512, the tweak value is equal to the LBA.
11011e66f787SSean Bruno * For other block sizes, tweak value is (LBA * block size) / 512.
11021e66f787SSean Bruno */
11031e66f787SSean Bruno volume_blk_size = GET_LE32((uint8_t *)&raid_map->volume_blk_size);
11041e66f787SSean Bruno if (volume_blk_size != 512)
11051e66f787SSean Bruno first_block = (first_block * volume_blk_size) / 512;
11061e66f787SSean Bruno
11071e66f787SSean Bruno enc_info->data_enc_key_index =
11081e66f787SSean Bruno GET_LE16((uint8_t *)&raid_map->data_encryption_key_index);
11091e66f787SSean Bruno enc_info->encrypt_tweak_upper = ((uint32_t)(((first_block) >> 16) >> 16));
11101e66f787SSean Bruno enc_info->encrypt_tweak_lower = ((uint32_t)(first_block));
11111e66f787SSean Bruno }
11121e66f787SSean Bruno
11137ea28254SJohn Hall
11147ea28254SJohn Hall /*
11157ea28254SJohn Hall * Attempt to perform offload RAID mapping for a logical volume I/O.
11167ea28254SJohn Hall */
11177ea28254SJohn Hall
11187ea28254SJohn Hall #define HPSA_RAID_0 0
11197ea28254SJohn Hall #define HPSA_RAID_4 1
11207ea28254SJohn Hall #define HPSA_RAID_1 2 /* also used for RAID 10 */
11217ea28254SJohn Hall #define HPSA_RAID_5 3 /* also used for RAID 50 */
11227ea28254SJohn Hall #define HPSA_RAID_51 4
11237ea28254SJohn Hall #define HPSA_RAID_6 5 /* also used for RAID 60 */
11247ea28254SJohn Hall #define HPSA_RAID_ADM 6 /* also used for RAID 1+0 ADM */
11257ea28254SJohn Hall #define HPSA_RAID_MAX HPSA_RAID_ADM
11267ea28254SJohn Hall #define HPSA_RAID_UNKNOWN 0xff
11277ea28254SJohn Hall
11281e66f787SSean Bruno /* Subroutine used to parse the scsi opcode and build the CDB for RAID bypass*/
11297ea28254SJohn Hall static int
fill_lba_for_scsi_rw(pqisrc_softstate_t * softs,uint8_t * cdb,aio_req_locator_t * l)11307ea28254SJohn Hall fill_lba_for_scsi_rw(pqisrc_softstate_t *softs, uint8_t *cdb, aio_req_locator_t *l)
11319fac68fcSPAPANI SRIKANTH {
11329fac68fcSPAPANI SRIKANTH
11337ea28254SJohn Hall if (!l) {
11347ea28254SJohn Hall DBG_INFO("No locator ptr: AIO ineligible");
11357ea28254SJohn Hall return PQI_STATUS_FAILURE;
11367ea28254SJohn Hall }
11377ea28254SJohn Hall
11387ea28254SJohn Hall if (cdb == NULL)
11397ea28254SJohn Hall return PQI_STATUS_FAILURE;
11407ea28254SJohn Hall
11411e66f787SSean Bruno switch (cdb[0]) {
11421e66f787SSean Bruno case SCMD_WRITE_6:
11437ea28254SJohn Hall l->is_write = true;
11447ea28254SJohn Hall /* coverity[fallthrough] */
11451e66f787SSean Bruno case SCMD_READ_6:
11467ea28254SJohn Hall l->block.first = (uint64_t)(((cdb[1] & 0x1F) << 16) |
11471e66f787SSean Bruno (cdb[2] << 8) | cdb[3]);
11487ea28254SJohn Hall l->block.cnt = (uint32_t)cdb[4];
11497ea28254SJohn Hall if (l->block.cnt == 0)
11507ea28254SJohn Hall l->block.cnt = 256; /*blkcnt 0 means 256 */
11511e66f787SSean Bruno break;
11521e66f787SSean Bruno case SCMD_WRITE_10:
11537ea28254SJohn Hall l->is_write = true;
11547ea28254SJohn Hall /* coverity[fallthrough] */
11551e66f787SSean Bruno case SCMD_READ_10:
11567ea28254SJohn Hall l->block.first = (uint64_t)GET_BE32(&cdb[2]);
11577ea28254SJohn Hall l->block.cnt = (uint32_t)GET_BE16(&cdb[7]);
11581e66f787SSean Bruno break;
11591e66f787SSean Bruno case SCMD_WRITE_12:
11607ea28254SJohn Hall l->is_write = true;
11617ea28254SJohn Hall /* coverity[fallthrough] */
11621e66f787SSean Bruno case SCMD_READ_12:
11637ea28254SJohn Hall l->block.first = (uint64_t)GET_BE32(&cdb[2]);
11647ea28254SJohn Hall l->block.cnt = GET_BE32(&cdb[6]);
11651e66f787SSean Bruno break;
11661e66f787SSean Bruno case SCMD_WRITE_16:
11677ea28254SJohn Hall l->is_write = true;
11687ea28254SJohn Hall /* coverity[fallthrough] */
11691e66f787SSean Bruno case SCMD_READ_16:
11707ea28254SJohn Hall l->block.first = GET_BE64(&cdb[2]);
11717ea28254SJohn Hall l->block.cnt = GET_BE32(&cdb[10]);
11721e66f787SSean Bruno break;
11731e66f787SSean Bruno default:
11741e66f787SSean Bruno /* Process via normal I/O path. */
11757ea28254SJohn Hall DBG_AIO("NOT read or write 6/10/12/16: AIO ineligible");
11761e66f787SSean Bruno return PQI_STATUS_FAILURE;
11771e66f787SSean Bruno }
11781e66f787SSean Bruno return PQI_STATUS_SUCCESS;
11791e66f787SSean Bruno }
11801e66f787SSean Bruno
11817ea28254SJohn Hall
11827ea28254SJohn Hall /* determine whether writes to certain types of RAID are supported. */
11832f06449dSWarner Losh static boolean_t
pqisrc_is_supported_write(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)11847ea28254SJohn Hall pqisrc_is_supported_write(pqisrc_softstate_t *softs,
11857ea28254SJohn Hall pqi_scsi_dev_t *device)
11867ea28254SJohn Hall {
11877ea28254SJohn Hall
11887ea28254SJohn Hall DBG_FUNC("IN\n");
11897ea28254SJohn Hall
11907ea28254SJohn Hall /* Raid0 was always supported */
11917ea28254SJohn Hall if (device->raid_level == SA_RAID_0)
11927ea28254SJohn Hall return true;
11937ea28254SJohn Hall
11947ea28254SJohn Hall /* module params for individual adv. aio write features may be on,
11957ea28254SJohn Hall * which affects ALL controllers, but some controllers
11967ea28254SJohn Hall * do not support adv. aio write.
11977ea28254SJohn Hall */
11987ea28254SJohn Hall if (!softs->adv_aio_capable)
11997ea28254SJohn Hall return false;
12007ea28254SJohn Hall
12017ea28254SJohn Hall /* if the raid write bypass feature is turned on,
12027ea28254SJohn Hall * then the write is supported.
12037ea28254SJohn Hall */
12047ea28254SJohn Hall switch (device->raid_level) {
12057ea28254SJohn Hall case SA_RAID_1:
12067ea28254SJohn Hall case SA_RAID_ADM:
12077ea28254SJohn Hall if (softs->aio_raid1_write_bypass)
12087ea28254SJohn Hall return true;
12097ea28254SJohn Hall break;
12107ea28254SJohn Hall case SA_RAID_5:
12117ea28254SJohn Hall if (softs->aio_raid5_write_bypass)
12127ea28254SJohn Hall return true;
12137ea28254SJohn Hall break;
12147ea28254SJohn Hall case SA_RAID_6:
12157ea28254SJohn Hall if (softs->aio_raid6_write_bypass)
12167ea28254SJohn Hall return true;
12177ea28254SJohn Hall }
12187ea28254SJohn Hall
12197ea28254SJohn Hall /* otherwise, it must be an unsupported write. */
12207ea28254SJohn Hall DBG_IO("AIO ineligible: write not supported for raid type\n");
12217ea28254SJohn Hall DBG_FUNC("OUT\n");
12227ea28254SJohn Hall return false;
12237ea28254SJohn Hall
12247ea28254SJohn Hall }
12257ea28254SJohn Hall
12267ea28254SJohn Hall /* check for zero-byte transfers, invalid blocks, and wraparound */
12277ea28254SJohn Hall static inline boolean_t
pqisrc_is_invalid_block(pqisrc_softstate_t * softs,aio_req_locator_t * l)12287ea28254SJohn Hall pqisrc_is_invalid_block(pqisrc_softstate_t *softs, aio_req_locator_t *l)
12297ea28254SJohn Hall {
12307ea28254SJohn Hall DBG_FUNC("IN\n");
12317ea28254SJohn Hall
12327ea28254SJohn Hall if (l->block.cnt == 0) {
12337ea28254SJohn Hall DBG_AIO("AIO ineligible: blk_cnt=0\n");
12347ea28254SJohn Hall DBG_FUNC("OUT\n");
12357ea28254SJohn Hall return true;
12367ea28254SJohn Hall }
12377ea28254SJohn Hall
12387ea28254SJohn Hall if (l->block.last < l->block.first ||
12397ea28254SJohn Hall l->block.last >=
12407ea28254SJohn Hall GET_LE64((uint8_t *)&l->raid_map->volume_blk_cnt)) {
12417ea28254SJohn Hall DBG_AIO("AIO ineligible: last block < first\n");
12427ea28254SJohn Hall DBG_FUNC("OUT\n");
12437ea28254SJohn Hall return true;
12447ea28254SJohn Hall }
12457ea28254SJohn Hall
12467ea28254SJohn Hall DBG_FUNC("OUT\n");
12477ea28254SJohn Hall return false;
12487ea28254SJohn Hall }
12497ea28254SJohn Hall
12507ea28254SJohn Hall /* Compute various attributes of request's location */
12517ea28254SJohn Hall static inline boolean_t
pqisrc_calc_disk_params(pqisrc_softstate_t * softs,aio_req_locator_t * l,rcb_t * rcb)12527ea28254SJohn Hall pqisrc_calc_disk_params(pqisrc_softstate_t *softs, aio_req_locator_t *l, rcb_t *rcb)
12537ea28254SJohn Hall {
12547ea28254SJohn Hall DBG_FUNC("IN\n");
12557ea28254SJohn Hall
12567ea28254SJohn Hall /* grab #disks, strip size, and layout map count from raid map */
12577ea28254SJohn Hall l->row.data_disks =
12587ea28254SJohn Hall GET_LE16((uint8_t *)&l->raid_map->data_disks_per_row);
12597ea28254SJohn Hall l->strip_sz =
12607ea28254SJohn Hall GET_LE16((uint8_t *)(&l->raid_map->strip_size));
12617ea28254SJohn Hall l->map.layout_map_count =
12627ea28254SJohn Hall GET_LE16((uint8_t *)(&l->raid_map->layout_map_count));
12637ea28254SJohn Hall
12647ea28254SJohn Hall /* Calculate stripe information for the request. */
12657ea28254SJohn Hall l->row.blks_per_row = l->row.data_disks * l->strip_sz;
12667ea28254SJohn Hall if (!l->row.blks_per_row || !l->strip_sz) {
12677ea28254SJohn Hall DBG_AIO("AIO ineligible\n");
12687ea28254SJohn Hall DBG_FUNC("OUT\n");
12697ea28254SJohn Hall return false;
12707ea28254SJohn Hall }
12717ea28254SJohn Hall /* use __udivdi3 ? */
12727ea28254SJohn Hall rcb->blocks_per_row = l->row.blks_per_row;
12737ea28254SJohn Hall l->row.first = l->block.first / l->row.blks_per_row;
12747ea28254SJohn Hall rcb->row_num = l->row.first;
12757ea28254SJohn Hall l->row.last = l->block.last / l->row.blks_per_row;
12767ea28254SJohn Hall l->row.offset_first = (uint32_t)(l->block.first -
12777ea28254SJohn Hall (l->row.first * l->row.blks_per_row));
12787ea28254SJohn Hall l->row.offset_last = (uint32_t)(l->block.last -
12797ea28254SJohn Hall (l->row.last * l->row.blks_per_row));
12807ea28254SJohn Hall l->col.first = l->row.offset_first / l->strip_sz;
12817ea28254SJohn Hall l->col.last = l->row.offset_last / l->strip_sz;
12827ea28254SJohn Hall
12837ea28254SJohn Hall DBG_FUNC("OUT\n");
12847ea28254SJohn Hall return true;
12857ea28254SJohn Hall }
12867ea28254SJohn Hall
1287*b0c318efSGordon Bergling /* Not AIO-eligible if it isn't a single row/column. */
12887ea28254SJohn Hall static inline boolean_t
pqisrc_is_single_row_column(pqisrc_softstate_t * softs,aio_req_locator_t * l)12897ea28254SJohn Hall pqisrc_is_single_row_column(pqisrc_softstate_t *softs, aio_req_locator_t *l)
12907ea28254SJohn Hall {
12917ea28254SJohn Hall boolean_t ret = true;
12927ea28254SJohn Hall DBG_FUNC("IN\n");
12937ea28254SJohn Hall
12947ea28254SJohn Hall if (l->row.first != l->row.last || l->col.first != l->col.last) {
12957ea28254SJohn Hall DBG_AIO("AIO ineligible\n");
12967ea28254SJohn Hall ret = false;
12977ea28254SJohn Hall }
12987ea28254SJohn Hall DBG_FUNC("OUT\n");
12997ea28254SJohn Hall return ret;
13007ea28254SJohn Hall }
13017ea28254SJohn Hall
13027ea28254SJohn Hall /* figure out disks/row, row, and map index. */
13037ea28254SJohn Hall static inline boolean_t
pqisrc_set_map_row_and_idx(pqisrc_softstate_t * softs,aio_req_locator_t * l,rcb_t * rcb)13047ea28254SJohn Hall pqisrc_set_map_row_and_idx(pqisrc_softstate_t *softs, aio_req_locator_t *l, rcb_t *rcb)
13057ea28254SJohn Hall {
13067ea28254SJohn Hall if (!l->row.data_disks) {
13077ea28254SJohn Hall DBG_INFO("AIO ineligible: no data disks?\n");
13087ea28254SJohn Hall return false;
13097ea28254SJohn Hall }
13107ea28254SJohn Hall
13117ea28254SJohn Hall l->row.total_disks = l->row.data_disks +
13127ea28254SJohn Hall LE_16(l->raid_map->metadata_disks_per_row);
13137ea28254SJohn Hall
13147ea28254SJohn Hall l->map.row = ((uint32_t)(l->row.first >>
13157ea28254SJohn Hall l->raid_map->parity_rotation_shift)) %
13167ea28254SJohn Hall GET_LE16((uint8_t *)(&l->raid_map->row_cnt));
13177ea28254SJohn Hall
13187ea28254SJohn Hall l->map.idx = (l->map.row * l->row.total_disks) + l->col.first;
13197ea28254SJohn Hall rcb->raid_map_index = l->map.idx;
13207ea28254SJohn Hall rcb->raid_map_row = l->map.row;
13217ea28254SJohn Hall
13227ea28254SJohn Hall return true;
13237ea28254SJohn Hall }
13247ea28254SJohn Hall
13257ea28254SJohn Hall /* set the mirror for a raid 1/10/ADM */
13267ea28254SJohn Hall static inline void
pqisrc_set_read_mirror(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device,aio_req_locator_t * l)13277ea28254SJohn Hall pqisrc_set_read_mirror(pqisrc_softstate_t *softs,
13287ea28254SJohn Hall pqi_scsi_dev_t *device, aio_req_locator_t *l)
13297ea28254SJohn Hall {
13307ea28254SJohn Hall /* Avoid direct use of device->offload_to_mirror within this
13317ea28254SJohn Hall * function since multiple threads might simultaneously
13327ea28254SJohn Hall * increment it beyond the range of device->layout_map_count -1.
13337ea28254SJohn Hall */
13347ea28254SJohn Hall
13357ea28254SJohn Hall int mirror = device->offload_to_mirror[l->map.idx];
13367ea28254SJohn Hall int next_mirror = mirror + 1;
13377ea28254SJohn Hall
13387ea28254SJohn Hall if (next_mirror >= l->map.layout_map_count)
13397ea28254SJohn Hall next_mirror = 0;
13407ea28254SJohn Hall
13417ea28254SJohn Hall device->offload_to_mirror[l->map.idx] = next_mirror;
13427ea28254SJohn Hall l->map.idx += mirror * l->row.data_disks;
13437ea28254SJohn Hall }
13447ea28254SJohn Hall
13457ea28254SJohn Hall /* collect ioaccel handles for mirrors of given location. */
13467ea28254SJohn Hall static inline boolean_t
pqisrc_set_write_mirrors(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device,aio_req_locator_t * l,rcb_t * rcb)13477ea28254SJohn Hall pqisrc_set_write_mirrors(
13487ea28254SJohn Hall pqisrc_softstate_t *softs,
13497ea28254SJohn Hall pqi_scsi_dev_t *device,
13507ea28254SJohn Hall aio_req_locator_t *l,
13517ea28254SJohn Hall rcb_t *rcb)
13527ea28254SJohn Hall {
13537ea28254SJohn Hall uint32_t mirror = 0;
13547ea28254SJohn Hall uint32_t index;
13557ea28254SJohn Hall
13567ea28254SJohn Hall if (l->map.layout_map_count > PQISRC_MAX_SUPPORTED_MIRRORS)
13577ea28254SJohn Hall return false;
13587ea28254SJohn Hall
13597ea28254SJohn Hall do {
13607ea28254SJohn Hall index = l->map.idx + (l->row.data_disks * mirror);
13617ea28254SJohn Hall rcb->it_nexus[mirror] =
13627ea28254SJohn Hall l->raid_map->dev_data[index].ioaccel_handle;
13637ea28254SJohn Hall mirror++;
13647ea28254SJohn Hall } while (mirror != l->map.layout_map_count);
13657ea28254SJohn Hall
13667ea28254SJohn Hall return true;
13677ea28254SJohn Hall }
13687ea28254SJohn Hall
13697ea28254SJohn Hall /* Make sure first and last block are in the same R5/R6 RAID group. */
13707ea28254SJohn Hall static inline boolean_t
pqisrc_is_r5or6_single_group(pqisrc_softstate_t * softs,aio_req_locator_t * l)13717ea28254SJohn Hall pqisrc_is_r5or6_single_group(pqisrc_softstate_t *softs, aio_req_locator_t *l)
13727ea28254SJohn Hall {
13737ea28254SJohn Hall boolean_t ret = true;
13747ea28254SJohn Hall
13757ea28254SJohn Hall DBG_FUNC("IN\n");
13767ea28254SJohn Hall l->r5or6.row.blks_per_row = l->strip_sz * l->row.data_disks;
13777ea28254SJohn Hall l->stripesz = l->r5or6.row.blks_per_row * l->map.layout_map_count;
13787ea28254SJohn Hall l->group.first = (l->block.first % l->stripesz) /
13797ea28254SJohn Hall l->r5or6.row.blks_per_row;
13807ea28254SJohn Hall l->group.last = (l->block.last % l->stripesz) /
13817ea28254SJohn Hall l->r5or6.row.blks_per_row;
13827ea28254SJohn Hall
13837ea28254SJohn Hall if (l->group.first != l->group.last) {
13847ea28254SJohn Hall DBG_AIO("AIO ineligible");
13857ea28254SJohn Hall ret = false;
13867ea28254SJohn Hall }
13877ea28254SJohn Hall
13887ea28254SJohn Hall DBG_FUNC("OUT\n");
13897ea28254SJohn Hall ASSERT(ret == true);
13907ea28254SJohn Hall return ret;
13917ea28254SJohn Hall }
13927ea28254SJohn Hall /* Make sure R5 or R6 request doesn't span rows. */
13937ea28254SJohn Hall static inline boolean_t
pqisrc_is_r5or6_single_row(pqisrc_softstate_t * softs,aio_req_locator_t * l)13947ea28254SJohn Hall pqisrc_is_r5or6_single_row(pqisrc_softstate_t *softs, aio_req_locator_t *l)
13957ea28254SJohn Hall {
13967ea28254SJohn Hall boolean_t ret = true;
13977ea28254SJohn Hall
13987ea28254SJohn Hall DBG_FUNC("IN\n");
13997ea28254SJohn Hall
14007ea28254SJohn Hall /* figure row nums containing first & last block */
14017ea28254SJohn Hall l->row.first = l->r5or6.row.first =
14027ea28254SJohn Hall l->block.first / l->stripesz;
14037ea28254SJohn Hall l->r5or6.row.last = l->block.last / l->stripesz;
14047ea28254SJohn Hall
14057ea28254SJohn Hall if (l->r5or6.row.first != l->r5or6.row.last) {
14067ea28254SJohn Hall DBG_AIO("AIO ineligible");
14077ea28254SJohn Hall ret = false;
14087ea28254SJohn Hall }
14097ea28254SJohn Hall
14107ea28254SJohn Hall DBG_FUNC("OUT\n");
14117ea28254SJohn Hall ASSERT(ret == true);
14127ea28254SJohn Hall return ret;
14137ea28254SJohn Hall }
14147ea28254SJohn Hall
14157ea28254SJohn Hall /* Make sure R5 or R6 request doesn't span columns. */
14167ea28254SJohn Hall static inline boolean_t
pqisrc_is_r5or6_single_column(pqisrc_softstate_t * softs,aio_req_locator_t * l)14177ea28254SJohn Hall pqisrc_is_r5or6_single_column(pqisrc_softstate_t *softs, aio_req_locator_t *l)
14187ea28254SJohn Hall {
14197ea28254SJohn Hall boolean_t ret = true;
14207ea28254SJohn Hall
14217ea28254SJohn Hall /* Find the columns of the first and last block */
14227ea28254SJohn Hall l->row.offset_first = l->r5or6.row.offset_first =
14237ea28254SJohn Hall (uint32_t)((l->block.first % l->stripesz) %
14247ea28254SJohn Hall l->r5or6.row.blks_per_row);
14257ea28254SJohn Hall l->r5or6.row.offset_last =
14267ea28254SJohn Hall (uint32_t)((l->block.last % l->stripesz) %
14277ea28254SJohn Hall l->r5or6.row.blks_per_row);
14287ea28254SJohn Hall
14297ea28254SJohn Hall l->col.first = l->r5or6.row.offset_first / l->strip_sz;
14307ea28254SJohn Hall l->r5or6.col.first = l->col.first;
14317ea28254SJohn Hall l->r5or6.col.last = l->r5or6.row.offset_last / l->strip_sz;
14327ea28254SJohn Hall
14337ea28254SJohn Hall if (l->r5or6.col.first != l->r5or6.col.last) {
14347ea28254SJohn Hall DBG_AIO("AIO ineligible");
14357ea28254SJohn Hall ret = false;
14367ea28254SJohn Hall }
14377ea28254SJohn Hall
14387ea28254SJohn Hall ASSERT(ret == true);
14397ea28254SJohn Hall return ret;
14407ea28254SJohn Hall }
14417ea28254SJohn Hall
14427ea28254SJohn Hall
14437ea28254SJohn Hall /* Set the map row and index for a R5 or R6 AIO request */
14447ea28254SJohn Hall static inline void
pqisrc_set_r5or6_row_and_index(aio_req_locator_t * l,rcb_t * rcb)14457ea28254SJohn Hall pqisrc_set_r5or6_row_and_index(aio_req_locator_t *l,
14467ea28254SJohn Hall rcb_t *rcb)
14477ea28254SJohn Hall {
14487ea28254SJohn Hall l->map.row = ((uint32_t)
14497ea28254SJohn Hall (l->row.first >> l->raid_map->parity_rotation_shift)) %
14507ea28254SJohn Hall GET_LE16((uint8_t *)(&l->raid_map->row_cnt));
14517ea28254SJohn Hall
14527ea28254SJohn Hall l->map.idx = (l->group.first *
14537ea28254SJohn Hall (GET_LE16((uint8_t *)(&l->raid_map->row_cnt))
14547ea28254SJohn Hall * l->row.total_disks))
14557ea28254SJohn Hall + (l->map.row * l->row.total_disks)
14567ea28254SJohn Hall + l->col.first;
14577ea28254SJohn Hall
14587ea28254SJohn Hall rcb->raid_map_index = l->map.idx;
14597ea28254SJohn Hall rcb->raid_map_row = l->map.row;
14607ea28254SJohn Hall }
14617ea28254SJohn Hall
14627ea28254SJohn Hall /* calculate physical disk block for aio request */
14637ea28254SJohn Hall static inline boolean_t
pqisrc_calc_aio_block(aio_req_locator_t * l)14647ea28254SJohn Hall pqisrc_calc_aio_block(aio_req_locator_t *l)
14657ea28254SJohn Hall {
14667ea28254SJohn Hall boolean_t ret = true;
14677ea28254SJohn Hall
14687ea28254SJohn Hall l->block.disk_block =
14697ea28254SJohn Hall GET_LE64((uint8_t *) (&l->raid_map->disk_starting_blk))
14707ea28254SJohn Hall + (l->row.first * l->strip_sz)
14717ea28254SJohn Hall + ((uint64_t)(l->row.offset_first) - (uint64_t)(l->col.first) * l->strip_sz);
14727ea28254SJohn Hall
14737ea28254SJohn Hall /* any values we should be checking here? if not convert to void */
14747ea28254SJohn Hall return ret;
14757ea28254SJohn Hall }
14767ea28254SJohn Hall
14777ea28254SJohn Hall /* Handle differing logical/physical block sizes. */
14787ea28254SJohn Hall static inline uint32_t
pqisrc_handle_blk_size_diffs(aio_req_locator_t * l)14797ea28254SJohn Hall pqisrc_handle_blk_size_diffs(aio_req_locator_t *l)
14807ea28254SJohn Hall {
14817ea28254SJohn Hall uint32_t disk_blk_cnt;
14827ea28254SJohn Hall disk_blk_cnt = l->block.cnt;
14837ea28254SJohn Hall
14847ea28254SJohn Hall if (l->raid_map->phys_blk_shift) {
14857ea28254SJohn Hall l->block.disk_block <<= l->raid_map->phys_blk_shift;
14867ea28254SJohn Hall disk_blk_cnt <<= l->raid_map->phys_blk_shift;
14877ea28254SJohn Hall }
14887ea28254SJohn Hall return disk_blk_cnt;
14897ea28254SJohn Hall }
14907ea28254SJohn Hall
14917ea28254SJohn Hall /* Make sure AIO request doesn't exceed the max that AIO device can
14927ea28254SJohn Hall * handle based on dev type, Raid level, and encryption status.
14937ea28254SJohn Hall * TODO: make limits dynamic when this becomes possible.
14947ea28254SJohn Hall */
14952f06449dSWarner Losh static boolean_t
pqisrc_aio_req_too_big(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device,rcb_t * rcb,aio_req_locator_t * l,uint32_t disk_blk_cnt)14967ea28254SJohn Hall pqisrc_aio_req_too_big(pqisrc_softstate_t *softs,
14977ea28254SJohn Hall pqi_scsi_dev_t *device, rcb_t *rcb,
14987ea28254SJohn Hall aio_req_locator_t *l, uint32_t disk_blk_cnt)
14997ea28254SJohn Hall {
15007ea28254SJohn Hall boolean_t ret = false;
15017ea28254SJohn Hall uint32_t dev_max;
15027ea28254SJohn Hall uint32_t size = disk_blk_cnt * device->raid_map->volume_blk_size;
15037ea28254SJohn Hall dev_max = size;
15047ea28254SJohn Hall
15057ea28254SJohn Hall /* filter for nvme crypto */
15067ea28254SJohn Hall if (device->is_nvme && rcb->encrypt_enable) {
15077ea28254SJohn Hall if (softs->max_aio_rw_xfer_crypto_nvme != 0) {
15087ea28254SJohn Hall dev_max = MIN(dev_max,softs->max_aio_rw_xfer_crypto_nvme);
15097ea28254SJohn Hall }
15107ea28254SJohn Hall }
15117ea28254SJohn Hall
15127ea28254SJohn Hall /* filter for RAID 5/6/50/60 */
15137ea28254SJohn Hall if (!device->is_physical_device &&
15147ea28254SJohn Hall (device->raid_level == SA_RAID_5 ||
15157ea28254SJohn Hall device->raid_level == SA_RAID_51 ||
15167ea28254SJohn Hall device->raid_level == SA_RAID_6)) {
15177ea28254SJohn Hall if (softs->max_aio_write_raid5_6 != 0) {
15187ea28254SJohn Hall dev_max = MIN(dev_max,softs->max_aio_write_raid5_6);
15197ea28254SJohn Hall }
15207ea28254SJohn Hall }
15217ea28254SJohn Hall
15227ea28254SJohn Hall /* filter for RAID ADM */
15237ea28254SJohn Hall if (!device->is_physical_device &&
15247ea28254SJohn Hall (device->raid_level == SA_RAID_ADM) &&
15257ea28254SJohn Hall (softs->max_aio_write_raid1_10_3drv != 0)) {
15267ea28254SJohn Hall dev_max = MIN(dev_max,
15277ea28254SJohn Hall softs->max_aio_write_raid1_10_3drv);
15287ea28254SJohn Hall }
15297ea28254SJohn Hall
15307ea28254SJohn Hall /* filter for RAID 1/10 */
15317ea28254SJohn Hall if (!device->is_physical_device &&
15327ea28254SJohn Hall (device->raid_level == SA_RAID_1) &&
15337ea28254SJohn Hall (softs->max_aio_write_raid1_10_2drv != 0)) {
15347ea28254SJohn Hall dev_max = MIN(dev_max,
15357ea28254SJohn Hall softs->max_aio_write_raid1_10_2drv);
15367ea28254SJohn Hall }
15377ea28254SJohn Hall
15387ea28254SJohn Hall
15397ea28254SJohn Hall if (size > dev_max) {
15407ea28254SJohn Hall DBG_AIO("AIO ineligible: size=%u, max=%u", size, dev_max);
15417ea28254SJohn Hall ret = true;
15427ea28254SJohn Hall }
15437ea28254SJohn Hall
15447ea28254SJohn Hall return ret;
15457ea28254SJohn Hall }
15467ea28254SJohn Hall
15477ea28254SJohn Hall
15487ea28254SJohn Hall #ifdef DEBUG_RAID_MAP
15497ea28254SJohn Hall static inline void
pqisrc_aio_show_raid_map(pqisrc_softstate_t * softs,struct raid_map * m)15507ea28254SJohn Hall pqisrc_aio_show_raid_map(pqisrc_softstate_t *softs, struct raid_map *m)
15517ea28254SJohn Hall {
15527ea28254SJohn Hall int i;
15537ea28254SJohn Hall
15547ea28254SJohn Hall if (!m) {
15557ea28254SJohn Hall DBG_WARN("No RAID MAP!\n");
15567ea28254SJohn Hall return;
15577ea28254SJohn Hall }
15587ea28254SJohn Hall DBG_INFO("======= Raid Map ================\n");
15597ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "StructureSize", m->structure_size);
15607ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "LogicalBlockSize", m->volume_blk_size);
15617ea28254SJohn Hall DBG_INFO("%-25s: 0x%lx\n", "LogicalBlockCount", m->volume_blk_cnt);
15627ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "PhysicalBlockShift", m->phys_blk_shift);
15637ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "ParityRotationShift",
15647ea28254SJohn Hall m->parity_rotation_shift);
15657ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "StripSize", m->strip_size);
15667ea28254SJohn Hall DBG_INFO("%-25s: 0x%lx\n", "DiskStartingBlock", m->disk_starting_blk);
15677ea28254SJohn Hall DBG_INFO("%-25s: 0x%lx\n", "DiskBlockCount", m->disk_blk_cnt);
15687ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "DataDisksPerRow", m->data_disks_per_row);
15697ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "MetdataDisksPerRow",
15707ea28254SJohn Hall m->metadata_disks_per_row);
15717ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "RowCount", m->row_cnt);
15727ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "LayoutMapCnt", m->layout_map_count);
15737ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "fEncryption", m->flags);
15747ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "DEK", m->data_encryption_key_index);
15757ea28254SJohn Hall for (i = 0; i < RAID_MAP_MAX_ENTRIES; i++) {
15767ea28254SJohn Hall if (m->dev_data[i].ioaccel_handle == 0)
15777ea28254SJohn Hall break;
15787ea28254SJohn Hall DBG_INFO("%-25s: %d: 0x%04x\n", "ioaccel_handle, disk",
15797ea28254SJohn Hall i, m->dev_data[i].ioaccel_handle);
15807ea28254SJohn Hall }
15817ea28254SJohn Hall }
15827ea28254SJohn Hall #endif /* DEBUG_RAID_MAP */
15837ea28254SJohn Hall
15847ea28254SJohn Hall static inline void
pqisrc_aio_show_locator_info(pqisrc_softstate_t * softs,aio_req_locator_t * l,uint32_t disk_blk_cnt,rcb_t * rcb)15857ea28254SJohn Hall pqisrc_aio_show_locator_info(pqisrc_softstate_t *softs,
15867ea28254SJohn Hall aio_req_locator_t *l, uint32_t disk_blk_cnt, rcb_t *rcb)
15877ea28254SJohn Hall {
15887ea28254SJohn Hall #ifdef DEBUG_AIO_LOCATOR
15897ea28254SJohn Hall pqisrc_aio_show_raid_map(softs, l->raid_map);
15907ea28254SJohn Hall
15917ea28254SJohn Hall DBG_INFO("======= AIO Locator Content, tag#0x%08x =====\n", rcb->tag);
15927ea28254SJohn Hall DBG_INFO("%-25s: 0x%lx\n", "block.first", l->block.first);
15937ea28254SJohn Hall DBG_INFO("%-25s: 0x%lx\n", "block.last", l->block.last);
15947ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "block.cnt", l->block.cnt);
15957ea28254SJohn Hall DBG_INFO("%-25s: 0x%lx\n", "block.disk_block", l->block.disk_block);
15967ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "row.blks_per_row", l->row.blks_per_row);
15977ea28254SJohn Hall DBG_INFO("%-25s: 0x%lx\n", "row.first", l->row.first);
15987ea28254SJohn Hall DBG_INFO("%-25s: 0x%lx\n", "row.last", l->row.last);
15997ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "row.offset_first", l->row.offset_first);
16007ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "row.offset_last", l->row.offset_last);
16017ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "row.data_disks", l->row.data_disks);
16027ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "row.total_disks", l->row.total_disks);
16037ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "col.first", l->col.first);
16047ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "col.last", l->col.last);
16057ea28254SJohn Hall
16067ea28254SJohn Hall if (l->raid_level == SA_RAID_5 || l->raid_level == SA_RAID_6) {
16077ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "r5or6.row.blks_per_row",
16087ea28254SJohn Hall l->r5or6.row.blks_per_row);
16097ea28254SJohn Hall DBG_INFO("%-25s: 0x%lx\n", "r5or6.row.first", l->r5or6.row.first);
16107ea28254SJohn Hall DBG_INFO("%-25s: 0x%lx\n", "r5or6.row.last", l->r5or6.row.last);
16117ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "r5or6.row.offset_first",
16127ea28254SJohn Hall l->r5or6.row.offset_first);
16137ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "r5or6.row.offset_last",
16147ea28254SJohn Hall l->r5or6.row.offset_last);
16157ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "r5or6.row.data_disks",
16167ea28254SJohn Hall l->r5or6.row.data_disks);
16177ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "r5or6.row.total_disks",
16187ea28254SJohn Hall l->r5or6.row.total_disks);
16197ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "r5or6.col.first", l->r5or6.col.first);
16207ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "r5or6.col.last", l->r5or6.col.last);
16217ea28254SJohn Hall }
16227ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "map.row", l->map.row);
16237ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "map.idx", l->map.idx);
16247ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "map.layout_map_count",
16257ea28254SJohn Hall l->map.layout_map_count);
16267ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "group.first", l->group.first);
16277ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "group.last", l->group.last);
16287ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "group.cur", l->group.cur);
16297ea28254SJohn Hall DBG_INFO("%-25s: %d\n", "is_write", l->is_write);
16307ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "stripesz", l->stripesz);
16317ea28254SJohn Hall DBG_INFO("%-25s: 0x%x\n", "strip_sz", l->strip_sz);
16327ea28254SJohn Hall DBG_INFO("%-25s: %d\n", "offload_to_mirror", l->offload_to_mirror);
16337ea28254SJohn Hall DBG_INFO("%-25s: %d\n", "raid_level", l->raid_level);
16347ea28254SJohn Hall
16357ea28254SJohn Hall #endif /* DEBUG_AIO_LOCATOR */
16367ea28254SJohn Hall }
16377ea28254SJohn Hall
16387ea28254SJohn Hall /* build the aio cdb */
16392f06449dSWarner Losh static void
pqisrc_aio_build_cdb(aio_req_locator_t * l,uint32_t disk_blk_cnt,rcb_t * rcb,uint8_t * cdb)16407ea28254SJohn Hall pqisrc_aio_build_cdb(aio_req_locator_t *l,
16417ea28254SJohn Hall uint32_t disk_blk_cnt, rcb_t *rcb, uint8_t *cdb)
16427ea28254SJohn Hall {
16437ea28254SJohn Hall uint8_t cdb_length;
16447ea28254SJohn Hall
16457ea28254SJohn Hall if (l->block.disk_block > 0xffffffff) {
16467ea28254SJohn Hall cdb[0] = l->is_write ? SCMD_WRITE_16 : SCMD_READ_16;
16477ea28254SJohn Hall cdb[1] = 0;
16487ea28254SJohn Hall PUT_BE64(l->block.disk_block, &cdb[2]);
16497ea28254SJohn Hall PUT_BE32(disk_blk_cnt, &cdb[10]);
16507ea28254SJohn Hall cdb[15] = 0;
16517ea28254SJohn Hall cdb_length = 16;
16527ea28254SJohn Hall } else {
16537ea28254SJohn Hall cdb[0] = l->is_write ? SCMD_WRITE_10 : SCMD_READ_10;
16547ea28254SJohn Hall cdb[1] = 0;
16557ea28254SJohn Hall PUT_BE32(l->block.disk_block, &cdb[2]);
16567ea28254SJohn Hall cdb[6] = 0;
16577ea28254SJohn Hall PUT_BE16(disk_blk_cnt, &cdb[7]);
16587ea28254SJohn Hall cdb[9] = 0;
16597ea28254SJohn Hall cdb_length = 10;
16607ea28254SJohn Hall }
16617ea28254SJohn Hall
16627ea28254SJohn Hall rcb->cmdlen = cdb_length;
16637ea28254SJohn Hall
16647ea28254SJohn Hall }
16657ea28254SJohn Hall
16669fac68fcSPAPANI SRIKANTH /* print any arbitrary buffer of length total_len */
16679fac68fcSPAPANI SRIKANTH void
pqisrc_print_buffer(pqisrc_softstate_t * softs,char * msg,void * user_buf,uint32_t total_len,uint32_t flags)16689fac68fcSPAPANI SRIKANTH pqisrc_print_buffer(pqisrc_softstate_t *softs, char *msg, void *user_buf,
16699fac68fcSPAPANI SRIKANTH uint32_t total_len, uint32_t flags)
16709fac68fcSPAPANI SRIKANTH {
16719fac68fcSPAPANI SRIKANTH #define LINE_BUF_LEN 60
16729fac68fcSPAPANI SRIKANTH #define INDEX_PER_LINE 16
16739fac68fcSPAPANI SRIKANTH uint32_t buf_consumed = 0;
16749fac68fcSPAPANI SRIKANTH int ii;
16759fac68fcSPAPANI SRIKANTH char line_buf[LINE_BUF_LEN];
16769fac68fcSPAPANI SRIKANTH int line_len; /* written length per line */
16779fac68fcSPAPANI SRIKANTH uint8_t this_char;
16789fac68fcSPAPANI SRIKANTH
16799fac68fcSPAPANI SRIKANTH if (user_buf == NULL)
16809fac68fcSPAPANI SRIKANTH return;
16819fac68fcSPAPANI SRIKANTH
16827ea28254SJohn Hall memset(line_buf, 0, LINE_BUF_LEN);
16837ea28254SJohn Hall
16849fac68fcSPAPANI SRIKANTH /* Print index columns */
16859fac68fcSPAPANI SRIKANTH if (flags & PRINT_FLAG_HDR_COLUMN)
16869fac68fcSPAPANI SRIKANTH {
16879fac68fcSPAPANI SRIKANTH for (ii = 0, line_len = 0; ii < MIN(total_len, 16); ii++)
16889fac68fcSPAPANI SRIKANTH {
16899fac68fcSPAPANI SRIKANTH line_len += snprintf(line_buf + line_len, (LINE_BUF_LEN - line_len), "%02d ", ii);
16909fac68fcSPAPANI SRIKANTH if ((line_len + 4) >= LINE_BUF_LEN)
16919fac68fcSPAPANI SRIKANTH break;
16929fac68fcSPAPANI SRIKANTH }
16937ea28254SJohn Hall DBG_INFO("%15.15s:[ %s ]\n", "header", line_buf);
16949fac68fcSPAPANI SRIKANTH }
16959fac68fcSPAPANI SRIKANTH
16969fac68fcSPAPANI SRIKANTH /* Print index columns */
16979fac68fcSPAPANI SRIKANTH while(buf_consumed < total_len)
16989fac68fcSPAPANI SRIKANTH {
16999fac68fcSPAPANI SRIKANTH memset(line_buf, 0, LINE_BUF_LEN);
17009fac68fcSPAPANI SRIKANTH
17019fac68fcSPAPANI SRIKANTH for (ii = 0, line_len = 0; ii < INDEX_PER_LINE; ii++)
17029fac68fcSPAPANI SRIKANTH {
17039fac68fcSPAPANI SRIKANTH this_char = *((char*)(user_buf) + buf_consumed);
17049fac68fcSPAPANI SRIKANTH line_len += snprintf(line_buf + line_len, (LINE_BUF_LEN - line_len), "%02x ", this_char);
17059fac68fcSPAPANI SRIKANTH
17069fac68fcSPAPANI SRIKANTH buf_consumed++;
17079fac68fcSPAPANI SRIKANTH if (buf_consumed >= total_len || (line_len + 4) >= LINE_BUF_LEN)
17089fac68fcSPAPANI SRIKANTH break;
17099fac68fcSPAPANI SRIKANTH }
17107ea28254SJohn Hall DBG_INFO("%15.15s:[ %s ]\n", msg, line_buf);
17119fac68fcSPAPANI SRIKANTH }
17129fac68fcSPAPANI SRIKANTH }
17139fac68fcSPAPANI SRIKANTH
17147ea28254SJohn Hall /* print CDB with column header */
17157ea28254SJohn Hall void
pqisrc_show_cdb(pqisrc_softstate_t * softs,char * msg,rcb_t * rcb,uint8_t * cdb)17167ea28254SJohn Hall pqisrc_show_cdb(pqisrc_softstate_t *softs, char *msg, rcb_t *rcb, uint8_t *cdb)
17177ea28254SJohn Hall {
17187ea28254SJohn Hall /* Print the CDB contents */
17197ea28254SJohn Hall pqisrc_print_buffer(softs, msg, cdb, rcb->cmdlen, PRINT_FLAG_HDR_COLUMN);
17207ea28254SJohn Hall }
17217ea28254SJohn Hall
17227ea28254SJohn Hall void
pqisrc_show_rcb_details(pqisrc_softstate_t * softs,rcb_t * rcb,char * msg,void * err_info)17237ea28254SJohn Hall pqisrc_show_rcb_details(pqisrc_softstate_t *softs, rcb_t *rcb, char *msg, void *err_info)
17247ea28254SJohn Hall {
17257ea28254SJohn Hall pqi_scsi_dev_t *devp;
17267ea28254SJohn Hall
17277ea28254SJohn Hall if (rcb == NULL || rcb->dvp == NULL)
17287ea28254SJohn Hall {
17297ea28254SJohn Hall DBG_ERR("Invalid rcb or dev ptr! rcb=%p\n", rcb);
17307ea28254SJohn Hall return;
17317ea28254SJohn Hall }
17327ea28254SJohn Hall
17337ea28254SJohn Hall devp = rcb->dvp;
17347ea28254SJohn Hall
17357ea28254SJohn Hall /* print the host and mapped CDB */
17367ea28254SJohn Hall DBG_INFO("\n");
17377ea28254SJohn Hall DBG_INFO("----- Start Dump: %s -----\n", msg);
17387ea28254SJohn Hall pqisrc_print_buffer(softs, "host cdb", OS_GET_CDBP(rcb), rcb->cmdlen, PRINT_FLAG_HDR_COLUMN);
17397ea28254SJohn Hall if (OS_GET_CDBP(rcb) != rcb->cdbp)
17407ea28254SJohn Hall pqisrc_print_buffer(softs, "aio mapped cdb", rcb->cdbp, rcb->cmdlen, 0);
17417ea28254SJohn Hall
17427ea28254SJohn Hall DBG_INFO("tag=0x%x dir=%u host_timeout=%ums\n", rcb->tag,
17437ea28254SJohn Hall rcb->data_dir, (uint32_t)rcb->host_timeout_ms);
17447ea28254SJohn Hall
17457ea28254SJohn Hall DBG_INFO("BTL: %d:%d:%d addr=0x%x\n", devp->bus, devp->target,
17467ea28254SJohn Hall devp->lun, GET_LE32(devp->scsi3addr));
17477ea28254SJohn Hall
17487ea28254SJohn Hall if (rcb->path == AIO_PATH)
17497ea28254SJohn Hall {
17507ea28254SJohn Hall DBG_INFO("handle=0x%x\n", rcb->ioaccel_handle);
17517ea28254SJohn Hall DBG_INFO("row=%u blk/row=%u index=%u map_row=%u\n",
17527ea28254SJohn Hall rcb->row_num, rcb->blocks_per_row, rcb->raid_map_index, rcb->raid_map_row);
17537ea28254SJohn Hall
17547ea28254SJohn Hall if (err_info)
17557ea28254SJohn Hall pqisrc_show_aio_error_info(softs, rcb, err_info);
17567ea28254SJohn Hall }
17577ea28254SJohn Hall
17587ea28254SJohn Hall else /* RAID path */
17597ea28254SJohn Hall {
17607ea28254SJohn Hall if (err_info)
17617ea28254SJohn Hall pqisrc_show_raid_error_info(softs, rcb, err_info);
17627ea28254SJohn Hall }
17637ea28254SJohn Hall
17647ea28254SJohn Hall
17657ea28254SJohn Hall DBG_INFO("----- Done -----\n\n");
17667ea28254SJohn Hall }
17677ea28254SJohn Hall
17689fac68fcSPAPANI SRIKANTH
17691e66f787SSean Bruno /*
17701e66f787SSean Bruno * Function used to build and send RAID bypass request to the adapter
17711e66f787SSean Bruno */
17729fac68fcSPAPANI SRIKANTH int
pqisrc_build_scsi_cmd_raidbypass(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device,rcb_t * rcb)17737ea28254SJohn Hall pqisrc_build_scsi_cmd_raidbypass(pqisrc_softstate_t *softs,
17747ea28254SJohn Hall pqi_scsi_dev_t *device, rcb_t *rcb)
17751e66f787SSean Bruno {
17761e66f787SSean Bruno uint32_t disk_blk_cnt;
17777ea28254SJohn Hall struct aio_req_locator loc;
17787ea28254SJohn Hall struct aio_req_locator *l = &loc;
17797ea28254SJohn Hall int rc;
17807ea28254SJohn Hall memset(l, 0, sizeof(*l));
17817ea28254SJohn Hall
17821e66f787SSean Bruno DBG_FUNC("IN\n");
17831e66f787SSean Bruno
17847ea28254SJohn Hall if (device == NULL) {
17857ea28254SJohn Hall DBG_INFO("device is NULL\n");
17861e66f787SSean Bruno return PQI_STATUS_FAILURE;
17877ea28254SJohn Hall }
17887ea28254SJohn Hall if (device->raid_map == NULL) {
17897ea28254SJohn Hall DBG_INFO("tag=0x%x BTL: %d:%d:%d Raid map is NULL\n",
17907ea28254SJohn Hall rcb->tag, device->bus, device->target, device->lun);
17917ea28254SJohn Hall return PQI_STATUS_FAILURE;
17927ea28254SJohn Hall }
17937ea28254SJohn Hall
17947ea28254SJohn Hall /* Check for eligible op, get LBA and block count. */
17957ea28254SJohn Hall rc = fill_lba_for_scsi_rw(softs, OS_GET_CDBP(rcb), l);
17967ea28254SJohn Hall if (rc == PQI_STATUS_FAILURE)
1797aeb665b5SEd Maste return PQI_STATUS_FAILURE;
17981e66f787SSean Bruno
17997ea28254SJohn Hall if (l->is_write && !pqisrc_is_supported_write(softs, device))
18001e66f787SSean Bruno return PQI_STATUS_FAILURE;
18011e66f787SSean Bruno
18027ea28254SJohn Hall l->raid_map = device->raid_map;
18037ea28254SJohn Hall l->block.last = l->block.first + l->block.cnt - 1;
18047ea28254SJohn Hall l->raid_level = device->raid_level;
18051e66f787SSean Bruno
18067ea28254SJohn Hall if (pqisrc_is_invalid_block(softs, l))
18071e66f787SSean Bruno return PQI_STATUS_FAILURE;
18081e66f787SSean Bruno
18097ea28254SJohn Hall if (!pqisrc_calc_disk_params(softs, l, rcb))
18107ea28254SJohn Hall return PQI_STATUS_FAILURE;
18111e66f787SSean Bruno
18127ea28254SJohn Hall if (!pqisrc_is_single_row_column(softs, l))
18137ea28254SJohn Hall return PQI_STATUS_FAILURE;
18149fac68fcSPAPANI SRIKANTH
18157ea28254SJohn Hall if (!pqisrc_set_map_row_and_idx(softs, l, rcb))
18161e66f787SSean Bruno return PQI_STATUS_FAILURE;
18171e66f787SSean Bruno
18181e66f787SSean Bruno /* Proceeding with driver mapping. */
18191e66f787SSean Bruno
18201e66f787SSean Bruno
18217ea28254SJohn Hall switch (device->raid_level) {
18227ea28254SJohn Hall case SA_RAID_1:
18237ea28254SJohn Hall case SA_RAID_ADM:
18247ea28254SJohn Hall if (l->is_write) {
18257ea28254SJohn Hall if (!pqisrc_set_write_mirrors(softs, device, l, rcb))
18267ea28254SJohn Hall return PQI_STATUS_FAILURE;
18277ea28254SJohn Hall } else
18287ea28254SJohn Hall pqisrc_set_read_mirror(softs, device, l);
18297ea28254SJohn Hall break;
18307ea28254SJohn Hall case SA_RAID_5:
18317ea28254SJohn Hall case SA_RAID_6:
18327ea28254SJohn Hall if (l->map.layout_map_count > 1 || l->is_write) {
18331e66f787SSean Bruno
18347ea28254SJohn Hall if (!pqisrc_is_r5or6_single_group(softs, l))
18351e66f787SSean Bruno return PQI_STATUS_FAILURE;
18361e66f787SSean Bruno
18377ea28254SJohn Hall if (!pqisrc_is_r5or6_single_row(softs, l))
18381e66f787SSean Bruno return PQI_STATUS_FAILURE;
18391e66f787SSean Bruno
18407ea28254SJohn Hall if (!pqisrc_is_r5or6_single_column(softs, l))
18411e66f787SSean Bruno return PQI_STATUS_FAILURE;
18421e66f787SSean Bruno
18437ea28254SJohn Hall pqisrc_set_r5or6_row_and_index(l, rcb);
18447ea28254SJohn Hall }
18457ea28254SJohn Hall break;
18461e66f787SSean Bruno }
18471e66f787SSean Bruno
18487ea28254SJohn Hall if (l->map.idx >= RAID_MAP_MAX_ENTRIES) {
18497ea28254SJohn Hall DBG_INFO("AIO ineligible: index exceeds max map entries");
18507ea28254SJohn Hall return PQI_STATUS_FAILURE;
18511e66f787SSean Bruno }
18521e66f787SSean Bruno
18537ea28254SJohn Hall rcb->ioaccel_handle =
18547ea28254SJohn Hall l->raid_map->dev_data[l->map.idx].ioaccel_handle;
18557ea28254SJohn Hall
18567ea28254SJohn Hall if (!pqisrc_calc_aio_block(l))
18571e66f787SSean Bruno return PQI_STATUS_FAILURE;
18581e66f787SSean Bruno
18597ea28254SJohn Hall disk_blk_cnt = pqisrc_handle_blk_size_diffs(l);
18607ea28254SJohn Hall
18617ea28254SJohn Hall
18627ea28254SJohn Hall /* Set encryption flag if needed. */
18637ea28254SJohn Hall rcb->encrypt_enable = false;
18647ea28254SJohn Hall if (GET_LE16((uint8_t *)(&l->raid_map->flags)) &
18657ea28254SJohn Hall RAID_MAP_ENCRYPTION_ENABLED) {
18667ea28254SJohn Hall pqisrc_set_enc_info(&rcb->enc_info, l->raid_map,
18677ea28254SJohn Hall l->block.first);
18687ea28254SJohn Hall rcb->encrypt_enable = true;
18697ea28254SJohn Hall }
18707ea28254SJohn Hall
18717ea28254SJohn Hall if (pqisrc_aio_req_too_big(softs, device, rcb, l, disk_blk_cnt))
18727ea28254SJohn Hall return PQI_STATUS_FAILURE;
18737ea28254SJohn Hall
18747ea28254SJohn Hall /* set the cdb ptr to the local bypass cdb */
18757ea28254SJohn Hall rcb->cdbp = &rcb->bypass_cdb[0];
18767ea28254SJohn Hall
18771e66f787SSean Bruno /* Build the new CDB for the physical disk I/O. */
18787ea28254SJohn Hall pqisrc_aio_build_cdb(l, disk_blk_cnt, rcb, rcb->cdbp);
18791e66f787SSean Bruno
18807ea28254SJohn Hall pqisrc_aio_show_locator_info(softs, l, disk_blk_cnt, rcb);
18811e66f787SSean Bruno
18827ea28254SJohn Hall DBG_FUNC("OUT\n");
18831e66f787SSean Bruno
18841e66f787SSean Bruno return PQI_STATUS_SUCCESS;
18851e66f787SSean Bruno }
18861e66f787SSean Bruno
18879fac68fcSPAPANI SRIKANTH /* Function used to submit an AIO TMF to the adapter
18889fac68fcSPAPANI SRIKANTH * DEVICE_RESET is not supported.
18899fac68fcSPAPANI SRIKANTH */
18907ea28254SJohn Hall
18919fac68fcSPAPANI SRIKANTH static int
pqisrc_send_aio_tmf(pqisrc_softstate_t * softs,pqi_scsi_dev_t * devp,rcb_t * rcb,rcb_t * rcb_to_manage,int tmf_type)18929fac68fcSPAPANI SRIKANTH pqisrc_send_aio_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t *devp,
18939fac68fcSPAPANI SRIKANTH rcb_t *rcb, rcb_t *rcb_to_manage, int tmf_type)
18941e66f787SSean Bruno {
18951e66f787SSean Bruno int rval = PQI_STATUS_SUCCESS;
18969fac68fcSPAPANI SRIKANTH pqi_aio_tmf_req_t tmf_req;
18979fac68fcSPAPANI SRIKANTH ib_queue_t *op_ib_q = NULL;
18987ea28254SJohn Hall boolean_t is_write;
18991e66f787SSean Bruno
19009fac68fcSPAPANI SRIKANTH memset(&tmf_req, 0, sizeof(pqi_aio_tmf_req_t));
19011e66f787SSean Bruno
19027ea28254SJohn Hall DBG_FUNC("IN\n");
19031e66f787SSean Bruno
19049fac68fcSPAPANI SRIKANTH tmf_req.header.iu_type = PQI_REQUEST_IU_AIO_TASK_MANAGEMENT;
19051e66f787SSean Bruno tmf_req.header.iu_length = sizeof(tmf_req) - sizeof(iu_header_t);
19061e66f787SSean Bruno tmf_req.req_id = rcb->tag;
19079fac68fcSPAPANI SRIKANTH tmf_req.error_idx = rcb->tag;
19089fac68fcSPAPANI SRIKANTH tmf_req.nexus = devp->ioaccel_handle;
19097ea28254SJohn Hall /* memcpy(tmf_req.lun, devp->scsi3addr, sizeof(tmf_req.lun)); */
19101e66f787SSean Bruno tmf_req.tmf = tmf_type;
19111e66f787SSean Bruno tmf_req.resp_qid = OS_GET_TMF_RESP_QID(softs, rcb);
19129fac68fcSPAPANI SRIKANTH op_ib_q = &softs->op_aio_ib_q[0];
19137ea28254SJohn Hall is_write = pqisrc_cdb_is_write(rcb->cdbp);
19147ea28254SJohn Hall
19157ea28254SJohn Hall uint64_t lun = rcb->cm_ccb->ccb_h.target_lun;
19167ea28254SJohn Hall if (lun && (rcb->dvp->is_multi_lun)) {
19177ea28254SJohn Hall int_to_scsilun(lun, tmf_req.lun);
19187ea28254SJohn Hall }
19197ea28254SJohn Hall else {
19207ea28254SJohn Hall memset(tmf_req.lun, 0, sizeof(tmf_req.lun));
19217ea28254SJohn Hall }
19229fac68fcSPAPANI SRIKANTH
19239fac68fcSPAPANI SRIKANTH if (tmf_type == SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK) {
19249fac68fcSPAPANI SRIKANTH tmf_req.req_id_to_manage = rcb_to_manage->tag;
19259fac68fcSPAPANI SRIKANTH tmf_req.nexus = rcb_to_manage->ioaccel_handle;
19269fac68fcSPAPANI SRIKANTH }
19279fac68fcSPAPANI SRIKANTH
19287ea28254SJohn Hall if (devp->raid_level == SA_RAID_1 ||
19297ea28254SJohn Hall devp->raid_level == SA_RAID_5 ||
19307ea28254SJohn Hall devp->raid_level == SA_RAID_6) {
19317ea28254SJohn Hall if (tmf_type == SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK && is_write)
19327ea28254SJohn Hall tmf_req.header.iu_type = PQI_REQUEST_IU_AIO_BYPASS_TASK_MGMT;
19337ea28254SJohn Hall }
19341e66f787SSean Bruno
19354f77349dSWarner Losh DBG_WARN("aio tmf: iu_type=0x%x req_id_to_manage=0x%x\n",
19364f77349dSWarner Losh tmf_req.header.iu_type, tmf_req.req_id_to_manage);
19377ea28254SJohn Hall DBG_WARN("aio tmf: req_id=0x%x nexus=0x%x tmf=0x%x QID=%u\n",
19384f77349dSWarner Losh tmf_req.req_id, tmf_req.nexus, tmf_req.tmf, op_ib_q->q_id);
19394f77349dSWarner Losh
19404f77349dSWarner Losh rcb->path = AIO_PATH;
19411e66f787SSean Bruno rcb->req_pending = true;
19429fac68fcSPAPANI SRIKANTH /* Timedout tmf response goes here */
19439fac68fcSPAPANI SRIKANTH rcb->error_cmp_callback = pqisrc_process_aio_response_error;
19441e66f787SSean Bruno
19459fac68fcSPAPANI SRIKANTH rval = pqisrc_submit_cmnd(softs, op_ib_q, &tmf_req);
19461e66f787SSean Bruno if (rval != PQI_STATUS_SUCCESS) {
19471e66f787SSean Bruno DBG_ERR("Unable to submit command rval=%d\n", rval);
19481e66f787SSean Bruno return rval;
19491e66f787SSean Bruno }
19501e66f787SSean Bruno
19519fac68fcSPAPANI SRIKANTH rval = pqisrc_wait_on_condition(softs, rcb, PQISRC_TMF_TIMEOUT);
19521e66f787SSean Bruno if (rval != PQI_STATUS_SUCCESS){
19531e66f787SSean Bruno DBG_ERR("Task Management tmf_type : %d timeout\n", tmf_type);
19549fac68fcSPAPANI SRIKANTH rcb->status = rval;
19551e66f787SSean Bruno }
19561e66f787SSean Bruno
19577ea28254SJohn Hall if (rcb->status != PQI_STATUS_SUCCESS) {
19581e66f787SSean Bruno DBG_ERR_BTL(devp, "Task Management failed tmf_type:%d "
19591e66f787SSean Bruno "stat:0x%x\n", tmf_type, rcb->status);
19601e66f787SSean Bruno rval = PQI_STATUS_FAILURE;
19611e66f787SSean Bruno }
19621e66f787SSean Bruno
19637ea28254SJohn Hall DBG_FUNC("OUT\n");
19641e66f787SSean Bruno return rval;
19651e66f787SSean Bruno }
19669fac68fcSPAPANI SRIKANTH
19679fac68fcSPAPANI SRIKANTH /* Function used to submit a Raid TMF to the adapter */
19689fac68fcSPAPANI SRIKANTH static int
pqisrc_send_raid_tmf(pqisrc_softstate_t * softs,pqi_scsi_dev_t * devp,rcb_t * rcb,rcb_t * rcb_to_manage,int tmf_type)19699fac68fcSPAPANI SRIKANTH pqisrc_send_raid_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t *devp,
19709fac68fcSPAPANI SRIKANTH rcb_t *rcb, rcb_t *rcb_to_manage, int tmf_type)
19719fac68fcSPAPANI SRIKANTH {
19729fac68fcSPAPANI SRIKANTH int rval = PQI_STATUS_SUCCESS;
19739fac68fcSPAPANI SRIKANTH pqi_raid_tmf_req_t tmf_req;
19749fac68fcSPAPANI SRIKANTH ib_queue_t *op_ib_q = NULL;
19759fac68fcSPAPANI SRIKANTH
19769fac68fcSPAPANI SRIKANTH memset(&tmf_req, 0, sizeof(pqi_raid_tmf_req_t));
19779fac68fcSPAPANI SRIKANTH
19787ea28254SJohn Hall DBG_FUNC("IN\n");
19799fac68fcSPAPANI SRIKANTH
19809fac68fcSPAPANI SRIKANTH tmf_req.header.iu_type = PQI_REQUEST_IU_RAID_TASK_MANAGEMENT;
19819fac68fcSPAPANI SRIKANTH tmf_req.header.iu_length = sizeof(tmf_req) - sizeof(iu_header_t);
19829fac68fcSPAPANI SRIKANTH tmf_req.req_id = rcb->tag;
19839fac68fcSPAPANI SRIKANTH
19849fac68fcSPAPANI SRIKANTH memcpy(tmf_req.lun, devp->scsi3addr, sizeof(tmf_req.lun));
19857ea28254SJohn Hall tmf_req.ml_device_lun_number = (uint8_t)rcb->cm_ccb->ccb_h.target_lun;
19867ea28254SJohn Hall
19879fac68fcSPAPANI SRIKANTH tmf_req.tmf = tmf_type;
19889fac68fcSPAPANI SRIKANTH tmf_req.resp_qid = OS_GET_TMF_RESP_QID(softs, rcb);
19899fac68fcSPAPANI SRIKANTH
19909fac68fcSPAPANI SRIKANTH /* Decide the queue where the tmf request should be submitted */
19919fac68fcSPAPANI SRIKANTH if (tmf_type == SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK) {
19929fac68fcSPAPANI SRIKANTH tmf_req.obq_id_to_manage = rcb_to_manage->resp_qid;
19939fac68fcSPAPANI SRIKANTH tmf_req.req_id_to_manage = rcb_to_manage->tag;
19949fac68fcSPAPANI SRIKANTH }
19959fac68fcSPAPANI SRIKANTH
19969fac68fcSPAPANI SRIKANTH if (softs->timeout_in_tmf &&
19979fac68fcSPAPANI SRIKANTH tmf_type == SOP_TASK_MANAGEMENT_LUN_RESET) {
19987ea28254SJohn Hall /* OS_TMF_TIMEOUT_SEC - 1 to accomodate driver processing */
19999fac68fcSPAPANI SRIKANTH tmf_req.timeout_in_sec = OS_TMF_TIMEOUT_SEC - 1;
20009fac68fcSPAPANI SRIKANTH /* if OS tmf timeout is 0, set minimum value for timeout */
20019fac68fcSPAPANI SRIKANTH if (!tmf_req.timeout_in_sec)
20029fac68fcSPAPANI SRIKANTH tmf_req.timeout_in_sec = 1;
20039fac68fcSPAPANI SRIKANTH }
20049fac68fcSPAPANI SRIKANTH
20059fac68fcSPAPANI SRIKANTH op_ib_q = &softs->op_raid_ib_q[0];
20067ea28254SJohn Hall
20077ea28254SJohn Hall DBG_WARN("raid tmf: iu_type=0x%x req_id_to_manage=%d\n",
20087ea28254SJohn Hall tmf_req.header.iu_type, tmf_req.req_id_to_manage);
20097ea28254SJohn Hall
20104f77349dSWarner Losh rcb->path = RAID_PATH;
20119fac68fcSPAPANI SRIKANTH rcb->req_pending = true;
20129fac68fcSPAPANI SRIKANTH /* Timedout tmf response goes here */
20139fac68fcSPAPANI SRIKANTH rcb->error_cmp_callback = pqisrc_process_raid_response_error;
20149fac68fcSPAPANI SRIKANTH
20159fac68fcSPAPANI SRIKANTH rval = pqisrc_submit_cmnd(softs, op_ib_q, &tmf_req);
20169fac68fcSPAPANI SRIKANTH if (rval != PQI_STATUS_SUCCESS) {
20179fac68fcSPAPANI SRIKANTH DBG_ERR("Unable to submit command rval=%d\n", rval);
20189fac68fcSPAPANI SRIKANTH return rval;
20199fac68fcSPAPANI SRIKANTH }
20209fac68fcSPAPANI SRIKANTH
20219fac68fcSPAPANI SRIKANTH rval = pqisrc_wait_on_condition(softs, rcb, PQISRC_TMF_TIMEOUT);
20229fac68fcSPAPANI SRIKANTH if (rval != PQI_STATUS_SUCCESS) {
20239fac68fcSPAPANI SRIKANTH DBG_ERR("Task Management tmf_type : %d timeout\n", tmf_type);
20249fac68fcSPAPANI SRIKANTH rcb->status = rval;
20259fac68fcSPAPANI SRIKANTH }
20269fac68fcSPAPANI SRIKANTH
20277ea28254SJohn Hall if (rcb->status != PQI_STATUS_SUCCESS) {
20289fac68fcSPAPANI SRIKANTH DBG_NOTE("Task Management failed tmf_type:%d "
20299fac68fcSPAPANI SRIKANTH "stat:0x%x\n", tmf_type, rcb->status);
20309fac68fcSPAPANI SRIKANTH rval = PQI_STATUS_FAILURE;
20319fac68fcSPAPANI SRIKANTH }
20329fac68fcSPAPANI SRIKANTH
20337ea28254SJohn Hall DBG_FUNC("OUT\n");
20349fac68fcSPAPANI SRIKANTH return rval;
20359fac68fcSPAPANI SRIKANTH }
20369fac68fcSPAPANI SRIKANTH
20377ea28254SJohn Hall void
dump_tmf_details(pqisrc_softstate_t * softs,rcb_t * rcb,char * msg)20387ea28254SJohn Hall dump_tmf_details(pqisrc_softstate_t *softs, rcb_t *rcb, char *msg)
20397ea28254SJohn Hall {
20407ea28254SJohn Hall uint32_t qid = rcb->req_q ? rcb->req_q->q_id : -1;
20417ea28254SJohn Hall
20427ea28254SJohn Hall DBG_INFO("%s: pending=%d path=%d tag=0x%x=%u qid=%u timeout=%ums\n",
20437ea28254SJohn Hall msg, rcb->req_pending, rcb->path, rcb->tag,
20447ea28254SJohn Hall rcb->tag, qid, (uint32_t)rcb->host_timeout_ms);
20457ea28254SJohn Hall }
20467ea28254SJohn Hall
20479fac68fcSPAPANI SRIKANTH int
pqisrc_send_tmf(pqisrc_softstate_t * softs,pqi_scsi_dev_t * devp,rcb_t * rcb,rcb_t * rcb_to_manage,int tmf_type)20489fac68fcSPAPANI SRIKANTH pqisrc_send_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t *devp,
20499fac68fcSPAPANI SRIKANTH rcb_t *rcb, rcb_t *rcb_to_manage, int tmf_type)
20509fac68fcSPAPANI SRIKANTH {
20519fac68fcSPAPANI SRIKANTH int ret = PQI_STATUS_SUCCESS;
20529fac68fcSPAPANI SRIKANTH
20537ea28254SJohn Hall DBG_FUNC("IN\n");
20547ea28254SJohn Hall
20557ea28254SJohn Hall DBG_WARN("sending TMF. io outstanding=%u\n",
20567ea28254SJohn Hall softs->max_outstanding_io - softs->taglist.num_elem);
20577ea28254SJohn Hall
20587ea28254SJohn Hall rcb->is_abort_cmd_from_host = true;
20594f77349dSWarner Losh rcb->softs = softs;
20609fac68fcSPAPANI SRIKANTH
20617ea28254SJohn Hall /* No target rcb for general purpose TMFs like LUN RESET */
20627ea28254SJohn Hall if (tmf_type == SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK)
20637ea28254SJohn Hall {
20647ea28254SJohn Hall rcb_to_manage->host_wants_to_abort_this = true;
20657ea28254SJohn Hall dump_tmf_details(softs, rcb_to_manage, "rcb_to_manage");
20667ea28254SJohn Hall }
20677ea28254SJohn Hall
20687ea28254SJohn Hall
20697ea28254SJohn Hall dump_tmf_details(softs, rcb, "rcb");
20707ea28254SJohn Hall
20719fac68fcSPAPANI SRIKANTH if(!devp->is_physical_device) {
20729fac68fcSPAPANI SRIKANTH if (tmf_type == SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK) {
20739fac68fcSPAPANI SRIKANTH if(rcb_to_manage->path == AIO_PATH) {
20749fac68fcSPAPANI SRIKANTH if(devp->offload_enabled)
20759fac68fcSPAPANI SRIKANTH ret = pqisrc_send_aio_tmf(softs, devp, rcb, rcb_to_manage, tmf_type);
20769fac68fcSPAPANI SRIKANTH }
20779fac68fcSPAPANI SRIKANTH else {
20789fac68fcSPAPANI SRIKANTH DBG_INFO("TASK ABORT not supported in raid\n");
20799fac68fcSPAPANI SRIKANTH ret = PQI_STATUS_FAILURE;
20809fac68fcSPAPANI SRIKANTH }
20819fac68fcSPAPANI SRIKANTH }
20829fac68fcSPAPANI SRIKANTH else {
20839fac68fcSPAPANI SRIKANTH ret = pqisrc_send_raid_tmf(softs, devp, rcb, rcb_to_manage, tmf_type);
20849fac68fcSPAPANI SRIKANTH }
20859fac68fcSPAPANI SRIKANTH } else {
20869fac68fcSPAPANI SRIKANTH if (tmf_type == SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK)
20879fac68fcSPAPANI SRIKANTH ret = pqisrc_send_aio_tmf(softs, devp, rcb, rcb_to_manage, tmf_type);
20889fac68fcSPAPANI SRIKANTH else
20899fac68fcSPAPANI SRIKANTH ret = pqisrc_send_raid_tmf(softs, devp, rcb, rcb_to_manage, tmf_type);
20909fac68fcSPAPANI SRIKANTH }
20919fac68fcSPAPANI SRIKANTH
20929fac68fcSPAPANI SRIKANTH DBG_FUNC("OUT\n");
20939fac68fcSPAPANI SRIKANTH
20949fac68fcSPAPANI SRIKANTH return ret;
20959fac68fcSPAPANI SRIKANTH }
20969fac68fcSPAPANI SRIKANTH
20977ea28254SJohn Hall /* return index into the global (softs) counters based on raid level */
20987ea28254SJohn Hall static counter_types_t
get_counter_index(rcb_t * rcb)20997ea28254SJohn Hall get_counter_index(rcb_t *rcb)
21007ea28254SJohn Hall {
21017ea28254SJohn Hall if (IS_AIO_PATH(rcb->dvp))
21027ea28254SJohn Hall return HBA_COUNTER;
21037ea28254SJohn Hall
21047ea28254SJohn Hall switch (rcb->dvp->raid_level) {
21057ea28254SJohn Hall case SA_RAID_0: return RAID0_COUNTER;
21067ea28254SJohn Hall case SA_RAID_1:
21077ea28254SJohn Hall case SA_RAID_ADM: return RAID1_COUNTER;
21087ea28254SJohn Hall case SA_RAID_5: return RAID5_COUNTER;
21097ea28254SJohn Hall case SA_RAID_6: return RAID6_COUNTER;
21107ea28254SJohn Hall case SA_RAID_UNKNOWN:
21117ea28254SJohn Hall default:
21127ea28254SJohn Hall {
21137ea28254SJohn Hall static boolean_t asserted = false;
21147ea28254SJohn Hall if (!asserted)
21157ea28254SJohn Hall {
21167ea28254SJohn Hall asserted = true;
21177ea28254SJohn Hall ASSERT(rcb->path == RAID_PATH);
21187ea28254SJohn Hall ASSERT(0);
21197ea28254SJohn Hall }
21207ea28254SJohn Hall return UNKNOWN_COUNTER;
21217ea28254SJohn Hall }
21227ea28254SJohn Hall }
21237ea28254SJohn Hall }
21247ea28254SJohn Hall
21257ea28254SJohn Hall /* return the counter type as ASCII-string */
21267ea28254SJohn Hall static char *
counter_type_to_raid_ascii(counter_types_t type)21277ea28254SJohn Hall counter_type_to_raid_ascii(counter_types_t type)
21287ea28254SJohn Hall {
21297ea28254SJohn Hall switch (type)
21307ea28254SJohn Hall {
21317ea28254SJohn Hall case UNKNOWN_COUNTER: return "Unknown";
21327ea28254SJohn Hall case HBA_COUNTER: return "HbaPath";
21337ea28254SJohn Hall case RAID0_COUNTER: return "Raid0";
21347ea28254SJohn Hall case RAID1_COUNTER: return "Raid1";
21357ea28254SJohn Hall case RAID5_COUNTER: return "Raid5";
21367ea28254SJohn Hall case RAID6_COUNTER: return "Raid6";
21377ea28254SJohn Hall default: return "Unsupported";
21387ea28254SJohn Hall }
21397ea28254SJohn Hall }
21407ea28254SJohn Hall
21419fac68fcSPAPANI SRIKANTH /* return the path as ASCII-string */
21429fac68fcSPAPANI SRIKANTH char *
io_path_to_ascii(IO_PATH_T path)21439fac68fcSPAPANI SRIKANTH io_path_to_ascii(IO_PATH_T path)
21449fac68fcSPAPANI SRIKANTH {
21459fac68fcSPAPANI SRIKANTH switch (path)
21469fac68fcSPAPANI SRIKANTH {
21479fac68fcSPAPANI SRIKANTH case AIO_PATH: return "Aio";
21489fac68fcSPAPANI SRIKANTH case RAID_PATH: return "Raid";
21499fac68fcSPAPANI SRIKANTH default: return "Unknown";
21509fac68fcSPAPANI SRIKANTH }
21519fac68fcSPAPANI SRIKANTH }
21527ea28254SJohn Hall
21537ea28254SJohn Hall /* return the io type as ASCII-string */
21547ea28254SJohn Hall static char *
io_type_to_ascii(io_type_t io_type)21557ea28254SJohn Hall io_type_to_ascii(io_type_t io_type)
21567ea28254SJohn Hall {
21577ea28254SJohn Hall switch (io_type)
21587ea28254SJohn Hall {
21597ea28254SJohn Hall case UNKNOWN_IO_TYPE: return "Unknown";
21607ea28254SJohn Hall case READ_IO_TYPE: return "Read";
21617ea28254SJohn Hall case WRITE_IO_TYPE: return "Write";
21627ea28254SJohn Hall case NON_RW_IO_TYPE: return "NonRW";
21637ea28254SJohn Hall default: return "Unsupported";
21647ea28254SJohn Hall }
21657ea28254SJohn Hall }
21667ea28254SJohn Hall
21677ea28254SJohn Hall
21687ea28254SJohn Hall /* return the io type based on cdb */
21697ea28254SJohn Hall io_type_t
get_io_type_from_cdb(uint8_t * cdb)21707ea28254SJohn Hall get_io_type_from_cdb(uint8_t *cdb)
21717ea28254SJohn Hall {
21727ea28254SJohn Hall if (cdb == NULL)
21737ea28254SJohn Hall return UNKNOWN_IO_TYPE;
21747ea28254SJohn Hall
21757ea28254SJohn Hall else if (pqisrc_cdb_is_read(cdb))
21767ea28254SJohn Hall return READ_IO_TYPE;
21777ea28254SJohn Hall
21787ea28254SJohn Hall else if (pqisrc_cdb_is_write(cdb))
21797ea28254SJohn Hall return WRITE_IO_TYPE;
21807ea28254SJohn Hall
21817ea28254SJohn Hall return NON_RW_IO_TYPE;
21827ea28254SJohn Hall }
21837ea28254SJohn Hall
21847ea28254SJohn Hall /* increment this counter based on path and read/write */
21857ea28254SJohn Hall OS_ATOMIC64_T
increment_this_counter(io_counters_t * pcounter,IO_PATH_T path,io_type_t io_type)21867ea28254SJohn Hall increment_this_counter(io_counters_t *pcounter, IO_PATH_T path, io_type_t io_type)
21877ea28254SJohn Hall {
21887ea28254SJohn Hall OS_ATOMIC64_T ret_val;
21897ea28254SJohn Hall
21907ea28254SJohn Hall if (path == AIO_PATH)
21917ea28254SJohn Hall {
21927ea28254SJohn Hall if (io_type == READ_IO_TYPE)
21937ea28254SJohn Hall ret_val = OS_ATOMIC64_INC(&pcounter->aio_read_cnt);
21947ea28254SJohn Hall else if (io_type == WRITE_IO_TYPE)
21957ea28254SJohn Hall ret_val = OS_ATOMIC64_INC(&pcounter->aio_write_cnt);
21967ea28254SJohn Hall else
21977ea28254SJohn Hall ret_val = OS_ATOMIC64_INC(&pcounter->aio_non_read_write);
21987ea28254SJohn Hall }
21997ea28254SJohn Hall else
22007ea28254SJohn Hall {
22017ea28254SJohn Hall if (io_type == READ_IO_TYPE)
22027ea28254SJohn Hall ret_val = OS_ATOMIC64_INC(&pcounter->raid_read_cnt);
22037ea28254SJohn Hall else if (io_type == WRITE_IO_TYPE)
22047ea28254SJohn Hall ret_val = OS_ATOMIC64_INC(&pcounter->raid_write_cnt);
22057ea28254SJohn Hall else
22067ea28254SJohn Hall ret_val = OS_ATOMIC64_INC(&pcounter->raid_non_read_write);
22077ea28254SJohn Hall }
22087ea28254SJohn Hall
22097ea28254SJohn Hall return ret_val;
22107ea28254SJohn Hall }
22117ea28254SJohn Hall
22127ea28254SJohn Hall /* increment appropriate counter(s) anytime we post a new request */
22137ea28254SJohn Hall static void
pqisrc_increment_io_counters(pqisrc_softstate_t * softs,rcb_t * rcb)22147ea28254SJohn Hall pqisrc_increment_io_counters(pqisrc_softstate_t *softs, rcb_t *rcb)
22157ea28254SJohn Hall {
22167ea28254SJohn Hall io_type_t io_type = get_io_type_from_cdb(rcb->cdbp);
22177ea28254SJohn Hall counter_types_t type_index = get_counter_index(rcb);
22187ea28254SJohn Hall io_counters_t *pcounter = &softs->counters[type_index];
22197ea28254SJohn Hall OS_ATOMIC64_T ret_val;
22207ea28254SJohn Hall
22217ea28254SJohn Hall ret_val = increment_this_counter(pcounter, rcb->path, io_type);
22227ea28254SJohn Hall
22237ea28254SJohn Hall #if 1 /* leave this enabled while we gain confidence for each io path */
22247ea28254SJohn Hall if (ret_val == 1)
22257ea28254SJohn Hall {
22267ea28254SJohn Hall char *raid_type = counter_type_to_raid_ascii(type_index);
22277ea28254SJohn Hall char *path = io_path_to_ascii(rcb->path);
22287ea28254SJohn Hall char *io_ascii = io_type_to_ascii(io_type);
22297ea28254SJohn Hall
22307ea28254SJohn Hall DBG_INFO("Got first path/type hit. "
22317ea28254SJohn Hall "Path=%s RaidType=%s IoType=%s\n",
22327ea28254SJohn Hall path, raid_type, io_ascii);
22337ea28254SJohn Hall }
22347ea28254SJohn Hall #endif
22357ea28254SJohn Hall
22367ea28254SJohn Hall /* @todo future: may want to make a per-dev counter */
22377ea28254SJohn Hall }
22387ea28254SJohn Hall
22397ea28254SJohn Hall /* public routine to print a particular counter with header msg */
22407ea28254SJohn Hall void
print_this_counter(pqisrc_softstate_t * softs,io_counters_t * pcounter,char * msg)22417ea28254SJohn Hall print_this_counter(pqisrc_softstate_t *softs, io_counters_t *pcounter, char *msg)
22427ea28254SJohn Hall {
22437ea28254SJohn Hall io_counters_t counter;
22447ea28254SJohn Hall uint32_t percent_reads;
22457ea28254SJohn Hall uint32_t percent_aio;
22467ea28254SJohn Hall
22477ea28254SJohn Hall if (!softs->log_io_counters)
22487ea28254SJohn Hall return;
22497ea28254SJohn Hall
22507ea28254SJohn Hall /* Use a cached copy so percentages are based on the data that is printed */
22517ea28254SJohn Hall memcpy(&counter, pcounter, sizeof(counter));
22527ea28254SJohn Hall
22537ea28254SJohn Hall DBG_NOTE("Counter: %s (ptr=%p)\n", msg, pcounter);
22547ea28254SJohn Hall
22557ea28254SJohn Hall percent_reads = CALC_PERCENT_VS(counter.aio_read_cnt + counter.raid_read_cnt,
22567ea28254SJohn Hall counter.aio_write_cnt + counter.raid_write_cnt);
22577ea28254SJohn Hall
22587ea28254SJohn Hall percent_aio = CALC_PERCENT_VS(counter.aio_read_cnt + counter.aio_write_cnt,
22597ea28254SJohn Hall counter.raid_read_cnt + counter.raid_write_cnt);
22607ea28254SJohn Hall
22617ea28254SJohn Hall DBG_NOTE(" R/W Percentages: Reads=%3u%% AIO=%3u%%\n", percent_reads, percent_aio);
22627ea28254SJohn Hall
22637ea28254SJohn Hall /* Print the Read counts */
22647ea28254SJohn Hall percent_aio = CALC_PERCENT_VS(counter.aio_read_cnt, counter.raid_read_cnt);
22657ea28254SJohn Hall DBG_NOTE(" Reads : AIO=%8u(%3u%%) RAID=%8u\n",
22667ea28254SJohn Hall (uint32_t)counter.aio_read_cnt, percent_aio, (uint32_t)counter.raid_read_cnt);
22677ea28254SJohn Hall
22687ea28254SJohn Hall /* Print the Write counts */
22697ea28254SJohn Hall percent_aio = CALC_PERCENT_VS(counter.aio_write_cnt, counter.raid_write_cnt);
22707ea28254SJohn Hall DBG_NOTE(" Writes: AIO=%8u(%3u%%) RAID=%8u\n",
22717ea28254SJohn Hall (uint32_t)counter.aio_write_cnt, percent_aio, (uint32_t)counter.raid_write_cnt);
22727ea28254SJohn Hall
22737ea28254SJohn Hall /* Print the Non-Rw counts */
22747ea28254SJohn Hall percent_aio = CALC_PERCENT_VS(counter.aio_non_read_write, counter.raid_non_read_write);
22757ea28254SJohn Hall DBG_NOTE(" Non-RW: AIO=%8u(%3u%%) RAID=%8u\n",
22767ea28254SJohn Hall (uint32_t)counter.aio_non_read_write, percent_aio, (uint32_t)counter.raid_non_read_write);
22777ea28254SJohn Hall }
22787ea28254SJohn Hall
22797ea28254SJohn Hall /* return true if buffer is all zeroes */
22807ea28254SJohn Hall boolean_t
is_buffer_zero(void * buffer,uint32_t size)22817ea28254SJohn Hall is_buffer_zero(void *buffer, uint32_t size)
22827ea28254SJohn Hall {
22837ea28254SJohn Hall char *buf = buffer;
22847ea28254SJohn Hall DWORD ii;
22857ea28254SJohn Hall
22867ea28254SJohn Hall if (buffer == NULL || size == 0)
22877ea28254SJohn Hall return false;
22887ea28254SJohn Hall
22897ea28254SJohn Hall for (ii = 0; ii < size; ii++)
22907ea28254SJohn Hall {
22917ea28254SJohn Hall if (buf[ii] != 0x00)
22927ea28254SJohn Hall return false;
22937ea28254SJohn Hall }
22947ea28254SJohn Hall return true;
22957ea28254SJohn Hall }
22967ea28254SJohn Hall
22977ea28254SJohn Hall /* public routine to print a all global counter types */
22987ea28254SJohn Hall void
print_all_counters(pqisrc_softstate_t * softs,uint32_t flags)22997ea28254SJohn Hall print_all_counters(pqisrc_softstate_t *softs, uint32_t flags)
23007ea28254SJohn Hall {
23017ea28254SJohn Hall int ii;
23027ea28254SJohn Hall io_counters_t *pcounter;
23037ea28254SJohn Hall char *raid_type;
23047ea28254SJohn Hall
23057ea28254SJohn Hall for (ii = 0; ii < MAX_IO_COUNTER; ii++)
23067ea28254SJohn Hall {
23077ea28254SJohn Hall pcounter = &softs->counters[ii];
23087ea28254SJohn Hall raid_type = counter_type_to_raid_ascii(ii);
23097ea28254SJohn Hall
23107ea28254SJohn Hall if ((flags & COUNTER_FLAG_ONLY_NON_ZERO) &&
23117ea28254SJohn Hall is_buffer_zero(pcounter, sizeof(*pcounter)))
23127ea28254SJohn Hall {
23137ea28254SJohn Hall continue;
23147ea28254SJohn Hall }
23157ea28254SJohn Hall
23167ea28254SJohn Hall print_this_counter(softs, pcounter, raid_type);
23177ea28254SJohn Hall }
23187ea28254SJohn Hall
23197ea28254SJohn Hall if (flags & COUNTER_FLAG_CLEAR_COUNTS)
23207ea28254SJohn Hall {
23217ea28254SJohn Hall DBG_NOTE("Clearing all counters\n");
23227ea28254SJohn Hall memset(softs->counters, 0, sizeof(softs->counters));
23237ea28254SJohn Hall }
23247ea28254SJohn Hall }
2325