From nobody Fri Apr 28 17:15:29 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Q7K4L1NDvz47jNb; Fri, 28 Apr 2023 17:15:30 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Q7K4L0tYZz4HyL; Fri, 28 Apr 2023 17:15:30 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1682702130; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=dgahQ7xaqGQ9LHNnXuQvdsr0R+929ueDAKoHSoRBYok=; b=HoMvc/vR0x3P6jqd/ND6w+crXZdftXf4lYNuOrstMXPLwTrik+J0lmRDipwnE397DA+23g jISdJWmufXJMOPXji9U+ISJlF7vOeDS1uUUxyVJY4QbvU6s3shCsXXiAp9wP0nqRRrUzdY p3ft5Lg2n71wQkr7UcpeETF7FBWKvHlmmIcrcF1zPIxYBz7IFbVYAGWX9MnlSUGMSUW/Xf aK2hyw/yP2BATrs5sXnRyk2rztiNuHJFt/wayl5jcWlEVBiAB+wyjeewwujfrgGMB6vDWx 0BZfdsnmHbwHAkYOPvUrIf6eQCRhnyBS/tWlkHJM4vjW7YGg2R7ZGmmhKDV19w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1682702130; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=dgahQ7xaqGQ9LHNnXuQvdsr0R+929ueDAKoHSoRBYok=; b=jSLQAbkc3WQDyuvSsknVxf1YEo06nkGcrik0R3VIRCdTVS8FeJyX+71Eb2w6HeZGs5UoYq UaFW0GnyAmkbLbsyIPEbJ74TIfat1KJS/vAd5xFeMpM8e0zqHqCwebZVQ5P7gDebuFBfc1 LWjxy4MdoXKMhGD74nb0V3v+I63+sLRo+aEB8owpbRSQPWXk3ChVflDMhSin2KZHfghJz+ ihduwiT8BuKCSRdy4A1OF8O1ToAbTYgGZit5o7Z1Bg4iGzvHlDY7zc69JNY+ZtRVHXwjLV e0zrMQLb76S7Ye3uHG1GxY4EJNDmwSwBCi5lt6DfQnDgt243misEJJPRQ0hAXQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1682702130; a=rsa-sha256; cv=none; b=ovjfbkrLWwW/17lZsYnDQWzt/jz1rIXrTJoxFIj59bqFz5KOCBuw5938RCVa0C6/ygwT+3 GJifwMeqa8chesgGKhzWJBa9wVRNI1gChemya1Rm8dM46bTRRlRD6lixWOJAaeAXVXAo7c 3I5th8kN7eQmjZy4a52N4P4GOpIprrd1+LLozXv+wVWdZdxwYkXJI58tSsmjyFm9YPMRzv 6X2wkE33tAB2INd8mleizIT1OfNTLQO9S0ozB7oai38neWG8cpEOAgtfc47hK1BM6bQegZ iIF8nXJpTONbFuCNWyqa5TgJ54z/skelofobKPf9u8UlyiVfPALWtefadMkgGg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Q7K4K71qcz17HY; Fri, 28 Apr 2023 17:15:29 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 33SHFTdb043934; Fri, 28 Apr 2023 17:15:29 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 33SHFT3P043933; Fri, 28 Apr 2023 17:15:29 GMT (envelope-from git) Date: Fri, 28 Apr 2023 17:15:29 GMT Message-Id: <202304281715.33SHFT3P043933@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Doug Ambrisko Subject: git: e315351fc7af - main - Add the mfi(4) ioctl support to mrsas(4) List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: ambrisko X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e315351fc7af11638c85fa22222536f4a2538f11 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by ambrisko: URL: https://cgit.FreeBSD.org/src/commit/?id=e315351fc7af11638c85fa22222536f4a2538f11 commit e315351fc7af11638c85fa22222536f4a2538f11 Author: Doug Ambrisko AuthorDate: 2022-08-24 22:27:03 +0000 Commit: Doug Ambrisko CommitDate: 2023-04-28 17:14:30 +0000 Add the mfi(4) ioctl support to mrsas(4) The hardware supported by mfi(4) and mrsas(4) use the same dcmd's. mfiutil(8) in theory could run on controlled attached to mrsas(4). It can't since mrsas(4) doesn't have support for the FreeBSD mfi(4) ioctl. Porting the ioctl from mfi(4) to mrsas(4) would be the first step in making mrsasutil(8) which is an additional name for mfiutil(8) but opens /dev/mrsasX instead of /dev/mfiX PR: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=265794 Reviewed by: jhb Differential revision: https://reviews.freebsd.org/D36342 Tested by: Dan Mahoney --- sys/dev/mrsas/mrsas.c | 13 ++- sys/dev/mrsas/mrsas.h | 3 + sys/dev/mrsas/mrsas_ioctl.c | 254 ++++++++++++++++++++++++++++++++++++++++++++ sys/dev/mrsas/mrsas_ioctl.h | 9 ++ 4 files changed, 278 insertions(+), 1 deletion(-) diff --git a/sys/dev/mrsas/mrsas.c b/sys/dev/mrsas/mrsas.c index 2f531bb44674..a865f5ab04d3 100644 --- a/sys/dev/mrsas/mrsas.c +++ b/sys/dev/mrsas/mrsas.c @@ -1449,7 +1449,14 @@ mrsas_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, int ret = 0, i = 0; MRSAS_DRV_PCI_INFORMATION *pciDrvInfo; - sc = mrsas_get_softc_instance(dev, cmd, arg); + switch (cmd) { + case MFIIO_PASSTHRU: + sc = (struct mrsas_softc *)(dev->si_drv1); + break; + default: + sc = mrsas_get_softc_instance(dev, cmd, arg); + break; + } if (!sc) return ENOENT; @@ -1512,6 +1519,10 @@ do_ioctl: ret = 0; break; + case MFIIO_PASSTHRU: + ret = mrsas_user_command(sc, (struct mfi_ioc_passthru *)arg); + break; + default: mrsas_dprint(sc, MRSAS_TRACE, "IOCTL command 0x%lx is not handled\n", cmd); ret = ENOENT; diff --git a/sys/dev/mrsas/mrsas.h b/sys/dev/mrsas/mrsas.h index 76894bbdbc4e..fa9a5cf118e6 100644 --- a/sys/dev/mrsas/mrsas.h +++ b/sys/dev/mrsas/mrsas.h @@ -3648,4 +3648,7 @@ mrsas_test_bit(int b, volatile void *p) return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f)); } +#include "mrsas_ioctl.h" +extern int mrsas_user_command(struct mrsas_softc *, struct mfi_ioc_passthru *); + #endif /* MRSAS_H */ diff --git a/sys/dev/mrsas/mrsas_ioctl.c b/sys/dev/mrsas/mrsas_ioctl.c index 1044fcbbcf92..b8d88c164e81 100644 --- a/sys/dev/mrsas/mrsas_ioctl.c +++ b/sys/dev/mrsas/mrsas_ioctl.c @@ -43,6 +43,18 @@ __FBSDID("$FreeBSD$"); #include #include +struct mrsas_passthru_cmd { + struct iovec *kern_sge; + struct mrsas_softc *sc; + struct mrsas_mfi_cmd *cmd; + bus_dma_tag_t ioctl_data_tag; + bus_dmamap_t ioctl_data_dmamap; + + u_int32_t error_code; + u_int32_t sge_count; + int complete; +}; + /* * Function prototypes */ @@ -62,6 +74,54 @@ extern int mrsas_issue_blocked_cmd(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); +/* + * mrsas_data_load_cb: Callback entry point + * input: Pointer to command packet as argument + * Pointer to segment + * Number of segments Error + * + * This is the callback function of the bus dma map load. It builds the SG + * list. + */ +static void +mrsas_passthru_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + struct mrsas_passthru_cmd *cb = (struct mrsas_passthru_cmd *)arg; + struct mrsas_softc *sc = cb->sc; + int i = 0; + + if (error) { + cb->error_code = error; + if (error == EFBIG) { + device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: " + "error=%d EFBIG\n", error); + cb->complete = 1; + return; + } else { + device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: " + "error=%d UNKNOWN\n", error); + } + } + if (nseg > MAX_IOCTL_SGE) { + cb->error_code = EFBIG; + device_printf(sc->mrsas_dev, "mrsas_passthru_load_cb: " + "too many segments: %d\n", nseg); + cb->complete = 1; + return; + } + + for (i = 0; i < nseg; i++) { + cb->kern_sge[i].iov_base = PTRIN(segs[i].ds_addr); + cb->kern_sge[i].iov_len = segs[i].ds_len; + } + cb->sge_count = nseg; + + bus_dmamap_sync(cb->ioctl_data_tag, cb->ioctl_data_dmamap, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + cb->complete = 1; +} + /* * mrsas_passthru: Handle pass-through commands * input: Adapter instance soft state argument pointer @@ -344,6 +404,200 @@ out: return (ret); } +/** + * mrsas_user_command: Handle user mode DCMD and buffer + * input: Adapter instance soft state + * argument pointer + * + * This function is called from mrsas_ioctl() DCMDs to firmware for mfiutil + */ +int +mrsas_user_command(struct mrsas_softc *sc, struct mfi_ioc_passthru *ioc) +{ + struct mrsas_mfi_cmd *cmd; + struct mrsas_dcmd_frame *dcmd; + struct mrsas_passthru_cmd *passcmd; + bus_dma_tag_t ioctl_data_tag; + bus_dmamap_t ioctl_data_dmamap; + bus_addr_t ioctl_data_phys_addr; + struct iovec *kern_sge; + int ret, ioctl_data_size; + char *ioctl_temp_data_mem; + + ret = 0; + ioctl_temp_data_mem = NULL; + passcmd = NULL; + ioctl_data_phys_addr = 0; + dcmd = NULL; + cmd = NULL; + ioctl_data_tag = NULL; + ioctl_data_dmamap = NULL; + ioctl_data_dmamap = NULL; + + /* Get a command */ + cmd = mrsas_get_mfi_cmd(sc); + if (!cmd) { + device_printf(sc->mrsas_dev, + "Failed to get a free cmd for IOCTL\n"); + return(ENOMEM); + } + + /* + * Frame is DCMD + */ + dcmd = (struct mrsas_dcmd_frame *)cmd->frame; + memcpy(dcmd, &ioc->ioc_frame, sizeof(struct mrsas_dcmd_frame)); + + ioctl_data_size = ioc->buf_size; + + cmd->frame->hdr.context = cmd->index; + cmd->frame->hdr.pad_0 = 0; + cmd->frame->hdr.flags = MFI_FRAME_DIR_BOTH; + if (sizeof(bus_addr_t) == 8) + cmd->frame->hdr.flags |= MFI_FRAME_SGL64 | MFI_FRAME_SENSE64; + + kern_sge = (struct iovec *)(&dcmd->sgl); + + if (ioctl_data_size == 0) { + kern_sge[0].iov_base = 0; + kern_sge[0].iov_len = 0; + } else { + ioctl_temp_data_mem = malloc(ioc->buf_size, M_MRSAS, M_WAITOK); + if (ioctl_temp_data_mem == NULL) { + device_printf(sc->mrsas_dev, "Could not allocate " + "%d memory for temporary passthrough ioctl\n", + ioc->buf_size); + ret = ENOMEM; + goto out; + } + + /* Copy in data from user space */ + ret = copyin(ioc->buf, ioctl_temp_data_mem, ioc->buf_size); + if (ret) { + device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n"); + goto out; + } + + /* + * Allocate a temporary struct to hold parameters for the + * callback + */ + passcmd = malloc(sizeof(struct mrsas_passthru_cmd), M_MRSAS, + M_WAITOK); + if (passcmd == NULL) { + device_printf(sc->mrsas_dev, "Could not allocate " + "memory for temporary passthrough cb struct\n"); + ret = ENOMEM; + goto out; + } + passcmd->complete = 0; + passcmd->sc = sc; + passcmd->cmd = cmd; + passcmd->kern_sge = kern_sge; + + /* + * Create a dma tag for passthru buffers + */ + if (bus_dma_tag_create(sc->mrsas_parent_tag, /* parent */ + 1, 0, /* algnmnt, boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + ioctl_data_size, /* maxsize */ + MAX_IOCTL_SGE, /* msegments */ + ioctl_data_size, /* maxsegsize */ + BUS_DMA_ALLOCNOW, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &sc->ioctl_lock, /* lockarg */ + &ioctl_data_tag)) { + device_printf(sc->mrsas_dev, + "Cannot allocate ioctl data tag %d\n", + ioc->buf_size); + ret = ENOMEM; + goto out; + } + + /* Create memmap */ + if (bus_dmamap_create(ioctl_data_tag, 0, &ioctl_data_dmamap)) { + device_printf(sc->mrsas_dev, "Cannot create ioctl " + "passthru dmamap\n"); + ret = ENOMEM; + goto out; + } + + passcmd->ioctl_data_tag = ioctl_data_tag; + passcmd->ioctl_data_dmamap = ioctl_data_dmamap; + + /* Map data buffer into bus space */ + if (bus_dmamap_load(ioctl_data_tag, ioctl_data_dmamap, + ioctl_temp_data_mem, ioc->buf_size, mrsas_passthru_load_cb, + passcmd, BUS_DMA_NOWAIT)) { + device_printf(sc->mrsas_dev, "Cannot load ioctl " + "passthru data mem%s %d\n", curproc->p_comm, ioctl_data_size); + ret = ENOMEM; + goto out; + } + + while (passcmd->complete == 0) { + pause("mrsas_passthru", hz); + } + + cmd->frame->dcmd.sge_count = passcmd->sge_count; + } + + /* + * Set the sync_cmd flag so that the ISR knows not to complete this + * cmd to the SCSI mid-layer + */ + cmd->sync_cmd = 1; + mrsas_issue_blocked_cmd(sc, cmd); + cmd->sync_cmd = 0; + + if (ioctl_data_size != 0) { + bus_dmamap_sync(ioctl_data_tag, ioctl_data_dmamap, + BUS_DMASYNC_POSTREAD); + /* + * copy out the kernel buffers to user buffers + */ + ret = copyout(ioctl_temp_data_mem, ioc->buf, ioc->buf_size); + if (ret) { + device_printf(sc->mrsas_dev, + "IOCTL copyout failed!\n"); + goto out; + } + } + + /* + * Return command status to user space + */ + memcpy(&ioc->ioc_frame.cmd_status, &cmd->frame->hdr.cmd_status, + sizeof(u_int8_t)); + +out: + /* + * Release temporary passthrough ioctl + */ + if (ioctl_temp_data_mem) + free(ioctl_temp_data_mem, M_MRSAS); + if (passcmd) + free(passcmd, M_MRSAS); + + /* + * Release data buffers + */ + if (ioctl_data_phys_addr) { + bus_dmamap_unload(ioctl_data_tag, ioctl_data_dmamap); + bus_dmamap_destroy(ioctl_data_tag, ioctl_data_dmamap); + } + if (ioctl_data_tag != NULL) + bus_dma_tag_destroy(ioctl_data_tag); + /* Free command */ + mrsas_release_mfi_cmd(cmd); + + return(ret); +} + + /* * mrsas_alloc_mfi_cmds: Allocates the command packets * input: Adapter instance soft state diff --git a/sys/dev/mrsas/mrsas_ioctl.h b/sys/dev/mrsas/mrsas_ioctl.h index 07ee211714cc..3851de710b5a 100644 --- a/sys/dev/mrsas/mrsas_ioctl.h +++ b/sys/dev/mrsas/mrsas_ioctl.h @@ -121,4 +121,13 @@ struct mrsas_iocpacket32 { #pragma pack() #endif /* COMPAT_FREEBSD32 */ +struct mfi_ioc_passthru { + struct mrsas_dcmd_frame ioc_frame; + uint32_t pad_skinny_flag; + uint32_t buf_size; + uint8_t *buf; +} __packed; + +#define MFIIO_PASSTHRU _IOWR('C', 102, struct mfi_ioc_passthru) + #endif /* MRSAS_IOCTL_H */