Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/smartpqi/smartpqi_ioctl.c
/*- | /*- | ||||
* Copyright (c) 2018 Microsemi Corporation. | * Copyright (c) 2016-2019 Microsemi Corporation. | ||||
* Copyright (c) 2020 Microchip Technology Inc. and it's subsidiaries. | |||||
* | |||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
Context not available. | |||||
static int smartpqi_open(struct cdev *cdev, int flags, int devtype, | static int smartpqi_open(struct cdev *cdev, int flags, int devtype, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
int error = PQI_STATUS_SUCCESS; | return BSD_SUCCESS; | ||||
return error; | |||||
} | } | ||||
/* | /* | ||||
* Device close function for ioctl entry | * Device close function for ioctl entry | ||||
*/ | */ | ||||
static int smartpqi_close(struct cdev *cdev, int flags, int devtype, | static int smartpqi_close(struct cdev *cdev, int flags, int devtype, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
int error = PQI_STATUS_SUCCESS; | return BSD_SUCCESS; | ||||
return error; | |||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
static int smartpqi_ioctl(struct cdev *cdev, u_long cmd, caddr_t udata, | static int smartpqi_ioctl(struct cdev *cdev, u_long cmd, caddr_t udata, | ||||
int flags, struct thread *td) | int flags, struct thread *td) | ||||
{ | { | ||||
int error = PQI_STATUS_SUCCESS; | int bsd_error, pqi_error; | ||||
struct pqisrc_softstate *softs = cdev->si_drv1; | struct pqisrc_softstate *softs = cdev->si_drv1; | ||||
DBG_FUNC("IN cmd = 0x%lx udata = %p cdev = %p\n", cmd, udata, cdev); | DBG_FUNC("IN cmd = 0x%lx udata = %p cdev = %p\n", cmd, udata, cdev); | ||||
if (!udata) { | if (!udata) { | ||||
DBG_ERR("udata is null !!\n"); | DBG_ERR("udata is null !!\n"); | ||||
return EINVAL; | |||||
} | } | ||||
if (pqisrc_ctrl_offline(softs)){ | if (pqisrc_ctrl_offline(softs)){ | ||||
DBG_ERR("Controller s offline !!\n"); | |||||
return ENOTTY; | return ENOTTY; | ||||
} | } | ||||
switch (cmd) { | switch (cmd) { | ||||
case CCISS_GETDRIVVER: | case CCISS_GETDRIVVER: | ||||
smartpqi_get_driver_info_ioctl(udata, cdev); | smartpqi_get_driver_info_ioctl(udata, cdev); | ||||
bsd_error = BSD_SUCCESS; | |||||
break; | break; | ||||
case CCISS_GETPCIINFO: | case CCISS_GETPCIINFO: | ||||
smartpqi_get_pci_info_ioctl(udata, cdev); | smartpqi_get_pci_info_ioctl(udata, cdev); | ||||
bsd_error = BSD_SUCCESS; | |||||
break; | break; | ||||
case SMARTPQI_PASS_THRU: | case SMARTPQI_PASS_THRU: | ||||
case CCISS_PASSTHRU: | case CCISS_PASSTHRU: | ||||
error = pqisrc_passthru_ioctl(softs, udata, 0); | pqi_error = pqisrc_passthru_ioctl(softs, udata, 0); | ||||
error = PQI_STATUS_SUCCESS; | bsd_error = pqi_error_to_bsd_error(pqi_error); | ||||
break; | break; | ||||
case CCISS_REGNEWD: | case CCISS_REGNEWD: | ||||
error = pqisrc_scan_devices(softs); | pqi_error = pqisrc_scan_devices(softs); | ||||
bsd_error = pqi_error_to_bsd_error(pqi_error); | |||||
break; | break; | ||||
default: | default: | ||||
DBG_WARN( "!IOCTL cmd 0x%lx not supported", cmd); | DBG_WARN( "!IOCTL cmd 0x%lx not supported\n", cmd); | ||||
error = ENOTTY; | bsd_error = ENOTTY; | ||||
break; | break; | ||||
} | } | ||||
DBG_FUNC("OUT error = %d\n", error); | DBG_FUNC("OUT error = %d\n", bsd_error); | ||||
return error; | return bsd_error; | ||||
} | } | ||||
static struct cdevsw smartpqi_cdevsw = | static struct cdevsw smartpqi_cdevsw = | ||||
Context not available. | |||||
*/ | */ | ||||
int create_char_dev(struct pqisrc_softstate *softs, int card_index) | int create_char_dev(struct pqisrc_softstate *softs, int card_index) | ||||
{ | { | ||||
int error = PQI_STATUS_SUCCESS; | int error = BSD_SUCCESS; | ||||
DBG_FUNC("IN idx = %d\n", card_index); | DBG_FUNC("IN idx = %d\n", card_index); | ||||
Context not available. | |||||
if(softs->os_specific.cdev) { | if(softs->os_specific.cdev) { | ||||
softs->os_specific.cdev->si_drv1 = softs; | softs->os_specific.cdev->si_drv1 = softs; | ||||
} else { | } else { | ||||
error = PQI_STATUS_FAILURE; | error = BSD_FAILURE; | ||||
} | } | ||||
DBG_FUNC("OUT error = %d\n", error); | DBG_FUNC("OUT error = %d\n", error); | ||||
return error; | return error; | ||||
} | } | ||||
Context not available. | |||||
memset(&request, 0, sizeof(request)); | memset(&request, 0, sizeof(request)); | ||||
memset(&error_info, 0, sizeof(error_info)); | memset(&error_info, 0, sizeof(error_info)); | ||||
DBG_FUNC("IN"); | DBG_FUNC("IN"); | ||||
if (pqisrc_ctrl_offline(softs)) | if (pqisrc_ctrl_offline(softs)) | ||||
return PQI_STATUS_FAILURE; | return PQI_STATUS_FAILURE; | ||||
if (!arg) | if (!arg) | ||||
return (PQI_STATUS_FAILURE); | return (PQI_STATUS_FAILURE); | ||||
if (iocommand->buf_size < 1 && | if (iocommand->buf_size < 1 && | ||||
iocommand->Request.Type.Direction != PQIIOCTL_NONE) | iocommand->Request.Type.Direction != PQIIOCTL_NONE) | ||||
return PQI_STATUS_FAILURE; | return PQI_STATUS_FAILURE; | ||||
if (iocommand->Request.CDBLen > sizeof(request.cdb)) | if (iocommand->Request.CDBLen > sizeof(request.cdb)) | ||||
Context not available. | |||||
ret = PQI_STATUS_FAILURE; | ret = PQI_STATUS_FAILURE; | ||||
goto out; | goto out; | ||||
} | } | ||||
DBG_INFO("ioctl_dma_buf.dma_addr = %p\n",(void*)ioctl_dma_buf.dma_addr); | DBG_INFO("ioctl_dma_buf.dma_addr = %p\n",(void*)ioctl_dma_buf.dma_addr); | ||||
DBG_INFO("ioctl_dma_buf.virt_addr = %p\n",(void*)ioctl_dma_buf.virt_addr); | DBG_INFO("ioctl_dma_buf.virt_addr = %p\n",(void*)ioctl_dma_buf.virt_addr); | ||||
drv_buf = (char *)ioctl_dma_buf.virt_addr; | drv_buf = (char *)ioctl_dma_buf.virt_addr; | ||||
if (iocommand->Request.Type.Direction & PQIIOCTL_WRITE) { | if (iocommand->Request.Type.Direction & PQIIOCTL_WRITE) { | ||||
if ((ret = os_copy_from_user(softs, (void *)drv_buf, (void *)iocommand->buf, | if ((ret = os_copy_from_user(softs, (void *)drv_buf, (void *)iocommand->buf, | ||||
iocommand->buf_size, mode)) != 0) { | iocommand->buf_size, mode)) != 0) { | ||||
ret = PQI_STATUS_FAILURE; | ret = PQI_STATUS_FAILURE; | ||||
goto free_mem; | goto free_mem; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
request.header.iu_type = PQI_IU_TYPE_RAID_PATH_IO_REQUEST; | request.header.iu_type = PQI_IU_TYPE_RAID_PATH_IO_REQUEST; | ||||
request.header.iu_length = offsetof(pqisrc_raid_req_t, sg_descriptors[1]) - | request.header.iu_length = offsetof(pqisrc_raid_req_t, sg_descriptors[1]) - | ||||
PQI_REQUEST_HEADER_LENGTH; | PQI_REQUEST_HEADER_LENGTH; | ||||
memcpy(request.lun_number, iocommand->LUN_info.LunAddrBytes, | memcpy(request.lun_number, iocommand->LUN_info.LunAddrBytes, | ||||
sizeof(request.lun_number)); | sizeof(request.lun_number)); | ||||
memcpy(request.cdb, iocommand->Request.CDB, iocommand->Request.CDBLen); | memcpy(request.cdb, iocommand->Request.CDB, iocommand->Request.CDBLen); | ||||
request.additional_cdb_bytes_usage = PQI_ADDITIONAL_CDB_BYTES_0; | request.additional_cdb_bytes_usage = PQI_ADDITIONAL_CDB_BYTES_0; | ||||
switch (iocommand->Request.Type.Direction) { | switch (iocommand->Request.Type.Direction) { | ||||
case PQIIOCTL_NONE: | case PQIIOCTL_NONE: | ||||
request.data_direction = SOP_DATA_DIR_NONE; | request.data_direction = SOP_DATA_DIR_NONE; | ||||
Context not available. | |||||
request.request_id = tag; | request.request_id = tag; | ||||
request.response_queue_id = ob_q->q_id; | request.response_queue_id = ob_q->q_id; | ||||
request.error_index = request.request_id; | request.error_index = request.request_id; | ||||
rcb = &softs->rcb[tag]; | if (softs->timeout_in_passthrough) { | ||||
request.timeout_in_sec = iocommand->Request.Timeout; | |||||
} | |||||
rcb = &softs->rcb[tag]; | |||||
rcb->success_cmp_callback = pqisrc_process_internal_raid_response_success; | rcb->success_cmp_callback = pqisrc_process_internal_raid_response_success; | ||||
rcb->error_cmp_callback = pqisrc_process_internal_raid_response_error; | rcb->error_cmp_callback = pqisrc_process_internal_raid_response_error; | ||||
rcb->tag = tag; | rcb->tag = tag; | ||||
Context not available. | |||||
goto err_out; | goto err_out; | ||||
} | } | ||||
ret = pqisrc_wait_on_condition(softs, rcb); | ret = pqisrc_wait_on_condition(softs, rcb, | ||||
PQISRC_PASSTHROUGH_CMD_TIMEOUT); | |||||
if (ret != PQI_STATUS_SUCCESS) { | if (ret != PQI_STATUS_SUCCESS) { | ||||
DBG_ERR("Passthru IOCTL cmd timed out !!\n"); | DBG_ERR("Passthru IOCTL cmd timed out !!\n"); | ||||
goto err_out; | goto err_out; | ||||
Context not available. | |||||
if (!sense_data_length) | if (!sense_data_length) | ||||
sense_data_length = error_info.resp_data_len; | sense_data_length = error_info.resp_data_len; | ||||
if (sense_data_length && | if (sense_data_length && | ||||
(sense_data_length > sizeof(error_info.data))) | (sense_data_length > sizeof(error_info.data))) | ||||
sense_data_length = sizeof(error_info.data); | sense_data_length = sizeof(error_info.data); | ||||
Context not available. | |||||
iocommand->error_info.SenseLen = sense_data_length; | iocommand->error_info.SenseLen = sense_data_length; | ||||
} | } | ||||
if (error_info.data_out_result == | if (error_info.data_out_result == | ||||
PQI_RAID_DATA_IN_OUT_UNDERFLOW){ | PQI_RAID_DATA_IN_OUT_UNDERFLOW){ | ||||
rcb->status = REQUEST_SUCCESS; | rcb->status = REQUEST_SUCCESS; | ||||
} | } | ||||
} | } | ||||
if (rcb->status == REQUEST_SUCCESS && iocommand->buf_size > 0 && | if (rcb->status == REQUEST_SUCCESS && iocommand->buf_size > 0 && | ||||
(iocommand->Request.Type.Direction & PQIIOCTL_READ)) { | (iocommand->Request.Type.Direction & PQIIOCTL_READ)) { | ||||
if ((ret = os_copy_to_user(softs, (void*)iocommand->buf, | if ((ret = os_copy_to_user(softs, (void*)iocommand->buf, | ||||
(void*)drv_buf, iocommand->buf_size, mode)) != 0) { | (void*)drv_buf, iocommand->buf_size, mode)) != 0) { | ||||
DBG_ERR("Failed to copy the response\n"); | DBG_ERR("Failed to copy the response\n"); | ||||
goto err_out; | goto err_out; | ||||
} | } | ||||
} | } | ||||
os_reset_rcb(rcb); | os_reset_rcb(rcb); | ||||
pqisrc_put_tag(&softs->taglist, request.request_id); | pqisrc_put_tag(&softs->taglist, request.request_id); | ||||
if (iocommand->buf_size > 0) | if (iocommand->buf_size > 0) | ||||
os_dma_mem_free(softs,&ioctl_dma_buf); | os_dma_mem_free(softs,&ioctl_dma_buf); | ||||
Context not available. | |||||
DBG_FUNC("OUT\n"); | DBG_FUNC("OUT\n"); | ||||
return ret; | return ret; | ||||
err_out: | err_out: | ||||
os_reset_rcb(rcb); | os_reset_rcb(rcb); | ||||
pqisrc_put_tag(&softs->taglist, request.request_id); | pqisrc_put_tag(&softs->taglist, request.request_id); | ||||
free_mem: | free_mem: | ||||
Context not available. |