History

scsi: mpi3mr: Support for preallocation of SGL BSG data buffers part-3

The driver acquires the required NVMe SGLs from the pre-allocated pool.

Chandrakanth patil committed 2 years ago

Commit 9536af61 parent fb231d73 files · +109 −27Browse files

Unified · Split

3 files
  1. drivers/scsi/mpi3mr/mpi3mr.h +6 −4
  2. drivers/scsi/mpi3mr/mpi3mr_app.c +101 −23
  3. include/uapi/scsi/scsi_bsg_mpi3mr.h +2 −0
drivers/scsi/mpi3mr/mpi3mr.h+6−4
@@ -218,14 +218,16 @@ extern atomic64_t event_counter; · 217 unmodified lines
218218 * @length: SGE length
219219 * @rsvd: Reserved
220220 * @rsvd1: Reserved
221− * @sgl_type: sgl type
221+ * @sub_type: sgl sub type
222+ * @type: sgl type
222223 */
223224 struct mpi3mr_nvme_pt_sge {
224− u64 base_addr;
225− u32 length;
225+ __le64 base_addr;
226+ __le32 length;
226227 u16 rsvd;
227228 u8 rsvd1;
228− u8 sgl_type;
229+ u8 sub_type:4;
230+ u8 type:4;
229231 };
230232
231233 /**
drivers/scsi/mpi3mr/mpi3mr_app.c+101−23
@@ -783,14 +783,20 @@ static int mpi3mr_build_nvme_sgl(struct mpi3mr_ioc *mrioc, · 782 unmodified lines
783783 struct mpi3mr_buf_map *drv_bufs, u8 bufcnt)
784784 {
785785 struct mpi3mr_nvme_pt_sge *nvme_sgl;
786− u64 sgl_ptr;
786+ __le64 sgl_dma;
787787 u8 count;
788788 size_t length = 0;
789+ u16 available_sges = 0, i;
790+ u32 sge_element_size = sizeof(struct mpi3mr_nvme_pt_sge);
789791 struct mpi3mr_buf_map *drv_buf_iter = drv_bufs;
790792 u64 sgemod_mask = ((u64)((mrioc->facts.sge_mod_mask) <<
791793 mrioc->facts.sge_mod_shift) << 32);
792794 u64 sgemod_val = ((u64)(mrioc->facts.sge_mod_value) <<
793795 mrioc->facts.sge_mod_shift) << 32;
796+ u32 size;
797+
798+ nvme_sgl = (struct mpi3mr_nvme_pt_sge *)
799+ ((u8 *)(nvme_encap_request->command) + MPI3MR_NVME_CMD_SGL_OFFSET);
794800
795801 /*
796802 * Not all commands require a data transfer. If no data, just return
@@ -799,27 +805,59 @@ static int mpi3mr_build_nvme_sgl(struct mpi3mr_ioc *mrioc, · 2 unmodified lines
799805 for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
800806 if (drv_buf_iter->data_dir == DMA_NONE)
801807 continue;
802− sgl_ptr = (u64)drv_buf_iter->kern_buf_dma;
803808 length = drv_buf_iter->kern_buf_len;
804809 break;
805810 }
806− if (!length)
811+ if (!length || !drv_buf_iter->num_dma_desc)
807812 return 0;
808813
809− if (sgl_ptr & sgemod_mask) {
814+ if (drv_buf_iter->num_dma_desc == 1) {
815+ available_sges = 1;
816+ goto build_sges;
817+ }
818+
819+ sgl_dma = cpu_to_le64(mrioc->ioctl_chain_sge.dma_addr);
820+ if (sgl_dma & sgemod_mask) {
810821 dprint_bsg_err(mrioc,
811− "%s: SGL address collides with SGE modifier\n",
822+ "%s: SGL chain address collides with SGE modifier\n",
812823 __func__);
813824 return -1;
814825 }
815826
816− sgl_ptr &= ~sgemod_mask;
817− sgl_ptr |= sgemod_val;
818− nvme_sgl = (struct mpi3mr_nvme_pt_sge *)
819− ((u8 *)(nvme_encap_request->command) + MPI3MR_NVME_CMD_SGL_OFFSET);
827+ sgl_dma &= ~sgemod_mask;
828+ sgl_dma |= sgemod_val;
829+
830+ memset(mrioc->ioctl_chain_sge.addr, 0, mrioc->ioctl_chain_sge.size);
831+ available_sges = mrioc->ioctl_chain_sge.size / sge_element_size;
832+ if (available_sges < drv_buf_iter->num_dma_desc)
833+ return -1;
820834 memset(nvme_sgl, 0, sizeof(struct mpi3mr_nvme_pt_sge));
821− nvme_sgl->base_addr = sgl_ptr;
822− nvme_sgl->length = length;
835+ nvme_sgl->base_addr = sgl_dma;
836+ size = drv_buf_iter->num_dma_desc * sizeof(struct mpi3mr_nvme_pt_sge);
837+ nvme_sgl->length = cpu_to_le32(size);
838+ nvme_sgl->type = MPI3MR_NVMESGL_LAST_SEGMENT;
839+ nvme_sgl = (struct mpi3mr_nvme_pt_sge *)mrioc->ioctl_chain_sge.addr;
840+
841+build_sges:
842+ for (i = 0; i < drv_buf_iter->num_dma_desc; i++) {
843+ sgl_dma = cpu_to_le64(drv_buf_iter->dma_desc[i].dma_addr);
844+ if (sgl_dma & sgemod_mask) {
845+ dprint_bsg_err(mrioc,
846+ "%s: SGL address collides with SGE modifier\n",
847+ __func__);
848+ return -1;
849+ }
850+
851+ sgl_dma &= ~sgemod_mask;
852+ sgl_dma |= sgemod_val;
853+
854+ nvme_sgl->base_addr = sgl_dma;
855+ nvme_sgl->length = cpu_to_le32(drv_buf_iter->dma_desc[i].size);
856+ nvme_sgl->type = MPI3MR_NVMESGL_DATA_SEGMENT;
857+ nvme_sgl++;
858+ available_sges--;
859+ }
860+
823861 return 0;
824862 }
825863
@@ -847,7 +885,7 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc, · 21 unmodified lines
847885 dma_addr_t prp_entry_dma, prp_page_dma, dma_addr;
848886 u32 offset, entry_len, dev_pgsz;
849887 u32 page_mask_result, page_mask;
850− size_t length = 0;
888+ size_t length = 0, desc_len;
851889 u8 count;
852890 struct mpi3mr_buf_map *drv_buf_iter = drv_bufs;
853891 u64 sgemod_mask = ((u64)((mrioc->facts.sge_mod_mask) <<
@@ -856,6 +894,7 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc, · 2 unmodified lines
856894 mrioc->facts.sge_mod_shift) << 32;
857895 u16 dev_handle = nvme_encap_request->dev_handle;
858896 struct mpi3mr_tgt_dev *tgtdev;
897+ u16 desc_count = 0;
859898
860899 tgtdev = mpi3mr_get_tgtdev_by_handle(mrioc, dev_handle);
861900 if (!tgtdev) {
@@ -874,6 +913,21 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc, · 12 unmodified lines
874913
875914 dev_pgsz = 1 << (tgtdev->dev_spec.pcie_inf.pgsz);
876915 mpi3mr_tgtdev_put(tgtdev);
916+ page_mask = dev_pgsz - 1;
917+
918+ if (dev_pgsz > MPI3MR_IOCTL_SGE_SIZE) {
919+ dprint_bsg_err(mrioc,
920+ "%s: NVMe device page size(%d) is greater than ioctl data sge size(%d) for handle 0x%04x\n",
921+ __func__, dev_pgsz, MPI3MR_IOCTL_SGE_SIZE, dev_handle);
922+ return -1;
923+ }
924+
925+ if (MPI3MR_IOCTL_SGE_SIZE % dev_pgsz) {
926+ dprint_bsg_err(mrioc,
927+ "%s: ioctl data sge size(%d) is not a multiple of NVMe device page size(%d) for handle 0x%04x\n",
928+ __func__, MPI3MR_IOCTL_SGE_SIZE, dev_pgsz, dev_handle);
929+ return -1;
930+ }
877931
878932 /*
879933 * Not all commands require a data transfer. If no data, just return
@@ -882,14 +936,26 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc, · 2 unmodified lines
882936 for (count = 0; count < bufcnt; count++, drv_buf_iter++) {
883937 if (drv_buf_iter->data_dir == DMA_NONE)
884938 continue;
885− dma_addr = drv_buf_iter->kern_buf_dma;
886939 length = drv_buf_iter->kern_buf_len;
887940 break;
888941 }
889942
890− if (!length)
943+ if (!length || !drv_buf_iter->num_dma_desc)
891944 return 0;
892945
946+ for (count = 0; count < drv_buf_iter->num_dma_desc; count++) {
947+ dma_addr = drv_buf_iter->dma_desc[count].dma_addr;
948+ if (dma_addr & page_mask) {
949+ dprint_bsg_err(mrioc,
950+ "%s:dma_addr 0x%llx is not aligned with page size 0x%x\n",
951+ __func__, dma_addr, dev_pgsz);
952+ return -1;
953+ }
954+ }
955+
956+ dma_addr = drv_buf_iter->dma_desc[0].dma_addr;
957+ desc_len = drv_buf_iter->dma_desc[0].size;
958+
893959 mrioc->prp_sz = 0;
894960 mrioc->prp_list_virt = dma_alloc_coherent(&mrioc->pdev->dev,
895961 dev_pgsz, &mrioc->prp_list_dma, GFP_KERNEL);
@@ -919,7 +985,6 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc, · 23 unmodified lines
919985 * Check if we are within 1 entry of a page boundary we don't
920986 * want our first entry to be a PRP List entry.
921987 */
922− page_mask = dev_pgsz - 1;
923988 page_mask_result = (uintptr_t)((u8 *)prp_page + prp_size) & page_mask;
924989 if (!page_mask_result) {
925990 dprint_bsg_err(mrioc, "%s: PRP page is not page aligned\n",
@@ -1033,18 +1098,31 @@ static int mpi3mr_build_nvme_prp(struct mpi3mr_ioc *mrioc, · 107 unmodified lines
10331098 prp_entry_dma += prp_size;
10341099 }
10351100
1036− /*
1037− * Bump the phys address of the command's data buffer by the
1038− * entry_len.
1039− */
1040− dma_addr += entry_len;
1041−
10421101 /* decrement length accounting for last partial page. */
1043− if (entry_len > length)
1102+ if (entry_len >= length) {
10441103 length = 0;
1045− else
1104+ } else {
1105+ if (entry_len <= desc_len) {
1106+ dma_addr += entry_len;
1107+ desc_len -= entry_len;
1108+ }
1109+ if (!desc_len) {
1110+ if ((++desc_count) >=
1111+ drv_buf_iter->num_dma_desc) {
1112+ dprint_bsg_err(mrioc,
1113+ "%s: Invalid len %ld while building PRP\n",
1114+ __func__, length);
1115+ goto err_out;
1116+ }
1117+ dma_addr =
1118+ drv_buf_iter->dma_desc[desc_count].dma_addr;
1119+ desc_len =
1120+ drv_buf_iter->dma_desc[desc_count].size;
1121+ }
10461122 length -= entry_len;
1123+ }
10471124 }
1125+
10481126 return 0;
10491127 err_out:
10501128 if (mrioc->prp_list_virt) {
include/uapi/scsi/scsi_bsg_mpi3mr.h+2−0
@@ -491,6 +491,8 @@ struct mpi3_nvme_encapsulated_error_reply { · 490 unmodified lines
491491 #define MPI3MR_NVME_DATA_FORMAT_PRP 0
492492 #define MPI3MR_NVME_DATA_FORMAT_SGL1 1
493493 #define MPI3MR_NVME_DATA_FORMAT_SGL2 2
494+#define MPI3MR_NVMESGL_DATA_SEGMENT 0x00
495+#define MPI3MR_NVMESGL_LAST_SEGMENT 0x03
494496
495497 /* MPI3: task management related definitions */
496498 struct mpi3_scsi_task_mgmt_request {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t