Skip to content

Commit

Permalink
Merge pull request #201 from truenas/NAS-130424-6.12-2
Browse files Browse the repository at this point in the history
NAS-130424 / None / scsi: mpi3mr: NVMe encapsulation support for tri-mode HBA
  • Loading branch information
ixhamza authored Nov 27, 2024
2 parents 3b44d5c + 5bf0848 commit 69dd353
Show file tree
Hide file tree
Showing 4 changed files with 490 additions and 20 deletions.
12 changes: 12 additions & 0 deletions drivers/scsi/mpi3mr/mpi3mr.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
#include "mpi/mpi30_pci.h"
#include "mpi/mpi30_tool.h"
#include "mpi3mr_debug.h"
#include <linux/nvme.h>
#include <linux/nvme_ioctl.h>

/* Global list and lock for storing multiple adapters managed by the driver */
extern spinlock_t mrioc_list_lock;
Expand Down Expand Up @@ -1492,6 +1494,16 @@ extern const struct attribute_group *mpi3mr_dev_groups[];
extern struct sas_function_template mpi3mr_transport_functions;
extern struct scsi_transport_template *mpi3mr_transport_template;

int mpi3mr_build_nvme_sgl(struct mpi3mr_ioc *mrioc,
struct mpi3_nvme_encapsulated_request *nvme_encap_request,
struct mpi3mr_buf_map *drv_bufs, u8 bufcnt);
int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
struct mpi3_nvme_encapsulated_request *nvme_encap_request,
struct mpi3mr_buf_map *drv_bufs, u8 bufcnt);
unsigned int mpi3mr_get_nvme_data_fmt(
struct mpi3_nvme_encapsulated_request *nvme_encap_request);
int mpi3mr_map_data_buffer_dma(struct mpi3mr_ioc *mrioc,
struct mpi3mr_buf_map *drv_buf, u16 desc_count, void *ubuf);
int mpi3mr_cfg_get_dev_pg0(struct mpi3mr_ioc *mrioc, u16 *ioc_status,
struct mpi3_device_page0 *dev_pg0, u16 pg_sz, u32 form, u32 form_spec);
int mpi3mr_cfg_get_sas_phy_pg0(struct mpi3mr_ioc *mrioc, u16 *ioc_status,
Expand Down
61 changes: 41 additions & 20 deletions drivers/scsi/mpi3mr/mpi3mr_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -1843,7 +1843,7 @@ static int mpi3mr_bsg_build_sgl(struct mpi3mr_ioc *mrioc, u8 *mpi_req,
*
* Return: Data format of the NVMe command (PRP/SGL etc)
*/
static unsigned int mpi3mr_get_nvme_data_fmt(
unsigned int mpi3mr_get_nvme_data_fmt(
struct mpi3_nvme_encapsulated_request *nvme_encap_request)
{
u8 format = 0;
Expand All @@ -1866,7 +1866,7 @@ static unsigned int mpi3mr_get_nvme_data_fmt(
*
* Return: 0 on success, -1 on failure
*/
static int mpi3mr_build_nvme_sgl(struct mpi3mr_ioc *mrioc,
int mpi3mr_build_nvme_sgl(struct mpi3mr_ioc *mrioc,
struct mpi3_nvme_encapsulated_request *nvme_encap_request,
struct mpi3mr_buf_map *drv_bufs, u8 bufcnt)
{
Expand Down Expand Up @@ -1963,7 +1963,7 @@ static int mpi3mr_build_nvme_sgl(struct mpi3mr_ioc *mrioc,
*
* Return: 0 on success, -1 on failure
*/
static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
struct mpi3_nvme_encapsulated_request *nvme_encap_request,
struct mpi3mr_buf_map *drv_bufs, u8 bufcnt)
{
Expand Down Expand Up @@ -2237,9 +2237,9 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc,
*
* Return: 0 on success, -1 on failure
*/
static int mpi3mr_map_data_buffer_dma(struct mpi3mr_ioc *mrioc,
int mpi3mr_map_data_buffer_dma(struct mpi3mr_ioc *mrioc,
struct mpi3mr_buf_map *drv_buf,
u16 desc_count)
u16 desc_count, void *ubuf)
{
u16 i, needed_desc = drv_buf->kern_buf_len / MPI3MR_IOCTL_SGE_SIZE;
u32 buf_len = drv_buf->kern_buf_len, copied_len = 0;
Expand Down Expand Up @@ -2268,9 +2268,15 @@ static int mpi3mr_map_data_buffer_dma(struct mpi3mr_ioc *mrioc,
memset(drv_buf->dma_desc[i].addr, 0,
mrioc->ioctl_sge[desc_count].size);
if (drv_buf->data_dir == DMA_TO_DEVICE) {
memcpy(drv_buf->dma_desc[i].addr,
drv_buf->bsg_buf + copied_len,
drv_buf->dma_desc[i].size);
if (ubuf) {
if (copy_from_user(drv_buf->dma_desc[i].addr,
ubuf + copied_len, drv_buf->dma_desc[i].size))
return (-EFAULT);
} else {
memcpy(drv_buf->dma_desc[i].addr,
drv_buf->bsg_buf + copied_len,
drv_buf->dma_desc[i].size);
}
copied_len += drv_buf->dma_desc[i].size;
}
}
Expand Down Expand Up @@ -2329,6 +2335,15 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
if (!mrioc)
return -ENODEV;

if (mutex_lock_interruptible(&mrioc->bsg_cmds.mutex))
return -ERESTARTSYS;

if (mrioc->bsg_cmds.state & MPI3MR_CMD_PENDING) {
dprint_bsg_err(mrioc, "%s: command is in use\n", __func__);
mutex_unlock(&mrioc->bsg_cmds.mutex);
return -EAGAIN;
}

if (!mrioc->ioctl_sges_allocated) {
dprint_bsg_err(mrioc, "%s: DMA memory was not allocated\n",
__func__);
Expand All @@ -2339,27 +2354,32 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
karg->timeout = MPI3MR_APP_DEFAULT_TIMEOUT;

mpi_req = kzalloc(MPI3MR_ADMIN_REQ_FRAME_SZ, GFP_KERNEL);
if (!mpi_req)
if (!mpi_req) {
mutex_unlock(&mrioc->bsg_cmds.mutex);
return -ENOMEM;
}
mpi_header = (struct mpi3_request_header *)mpi_req;

bufcnt = karg->buf_entry_list.num_of_entries;
drv_bufs = kzalloc((sizeof(*drv_bufs) * bufcnt), GFP_KERNEL);
if (!drv_bufs) {
mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -ENOMEM;
goto out;
}

dout_buf = kzalloc(job->request_payload.payload_len,
GFP_KERNEL);
if (!dout_buf) {
mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -ENOMEM;
goto out;
}

din_buf = kzalloc(job->reply_payload.payload_len,
GFP_KERNEL);
if (!din_buf) {
mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -ENOMEM;
goto out;
}
Expand Down Expand Up @@ -2435,6 +2455,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
(mpi_msg_size > MPI3MR_ADMIN_REQ_FRAME_SZ)) {
dprint_bsg_err(mrioc, "%s: invalid MPI message size\n",
__func__);
mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
Expand All @@ -2447,19 +2468,22 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
if (invalid_be) {
dprint_bsg_err(mrioc, "%s: invalid buffer entries passed\n",
__func__);
mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}

if (sgl_dout_iter > (dout_buf + job->request_payload.payload_len)) {
dprint_bsg_err(mrioc, "%s: data_out buffer length mismatch\n",
__func__);
mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
if (sgl_din_iter > (din_buf + job->reply_payload.payload_len)) {
dprint_bsg_err(mrioc, "%s: data_in buffer length mismatch\n",
__func__);
mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
Expand All @@ -2472,6 +2496,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
dprint_bsg_err(mrioc, "%s:%d: invalid data transfer size passed for function 0x%x din_size = %d, dout_size = %d\n",
__func__, __LINE__, mpi_header->function, din_size,
dout_size);
mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
Expand All @@ -2480,13 +2505,15 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
dprint_bsg_err(mrioc,
"%s:%d: invalid data transfer size passed for function 0x%x din_size=%d\n",
__func__, __LINE__, mpi_header->function, din_size);
mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
if (dout_size > MPI3MR_MAX_APP_XFER_SIZE) {
dprint_bsg_err(mrioc,
"%s:%d: invalid data transfer size passed for function 0x%x dout_size = %d\n",
__func__, __LINE__, mpi_header->function, dout_size);
mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
Expand All @@ -2497,6 +2524,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
dprint_bsg_err(mrioc, "%s:%d: invalid message size passed:%d:%d:%d:%d\n",
__func__, __LINE__, din_cnt, dout_cnt, din_size,
dout_size);
mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
Expand Down Expand Up @@ -2542,8 +2570,10 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
} else {
if (!drv_buf_iter->kern_buf_len)
continue;
if (mpi3mr_map_data_buffer_dma(mrioc, drv_buf_iter, desc_count)) {
if (mpi3mr_map_data_buffer_dma(mrioc, drv_buf_iter,
desc_count, NULL)) {
rval = -ENOMEM;
mutex_unlock(&mrioc->bsg_cmds.mutex);
dprint_bsg_err(mrioc, "%s:%d: mapping data buffers failed\n",
__func__, __LINE__);
goto out;
Expand All @@ -2556,20 +2586,11 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
sense_buff_k = kzalloc(erbsz, GFP_KERNEL);
if (!sense_buff_k) {
rval = -ENOMEM;
mutex_unlock(&mrioc->bsg_cmds.mutex);
goto out;
}
}

if (mutex_lock_interruptible(&mrioc->bsg_cmds.mutex)) {
rval = -ERESTARTSYS;
goto out;
}
if (mrioc->bsg_cmds.state & MPI3MR_CMD_PENDING) {
rval = -EAGAIN;
dprint_bsg_err(mrioc, "%s: command is in use\n", __func__);
mutex_unlock(&mrioc->bsg_cmds.mutex);
goto out;
}
if (mrioc->unrecoverable) {
dprint_bsg_err(mrioc, "%s: unrecoverable controller\n",
__func__);
Expand Down
Loading

0 comments on commit 69dd353

Please sign in to comment.