The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/mrsas/mrsas_ioctl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2015, AVAGO Tech. All rights reserved. Author: Marian Choy
    3  * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy
    4  * Support: freebsdraid@avagotech.com
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions are
    8  * met:
    9  *
   10  * 1. Redistributions of source code must retain the above copyright notice,
   11  * this list of conditions and the following disclaimer. 2. Redistributions
   12  * in binary form must reproduce the above copyright notice, this list of
   13  * conditions and the following disclaimer in the documentation and/or other
   14  * materials provided with the distribution. 3. Neither the name of the
   15  * <ORGANIZATION> nor the names of its contributors may be used to endorse or
   16  * promote products derived from this software without specific prior written
   17  * permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  *
   31  * The views and conclusions contained in the software and documentation are
   32  * those of the authors and should not be interpreted as representing
   33  * official policies,either expressed or implied, of the FreeBSD Project.
   34  *
   35  * Send feedback to: <megaraidfbsd@avagotech.com> Mail to: AVAGO TECHNOLOGIES, 1621
   36  * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD
   37  *
   38  */
   39 
   40 #include <sys/cdefs.h>
   41 __FBSDID("$FreeBSD$");
   42 
   43 #include <dev/mrsas/mrsas.h>
   44 #include <dev/mrsas/mrsas_ioctl.h>
   45 
   46 /*
   47  * Function prototypes
   48  */
   49 int     mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
   50 int     mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd);
   51 void    mrsas_free_ioc_cmd(struct mrsas_softc *sc);
   52 void    mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
   53 void   *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
   54 static int mrsas_create_frame_pool(struct mrsas_softc *sc);
   55 static void
   56 mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
   57     int nsegs, int error);
   58 
   59 extern struct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc);
   60 extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
   61 extern int
   62 mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
   63     struct mrsas_mfi_cmd *cmd);
   64 
   65 /*
   66  * mrsas_passthru:      Handle pass-through commands
   67  * input:                       Adapter instance soft state argument pointer
   68  *
   69  * This function is called from mrsas_ioctl() to handle pass-through and ioctl
   70  * commands to Firmware.
   71  */
   72 int
   73 mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd)
   74 {
   75         struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
   76 
   77 #ifdef COMPAT_FREEBSD32
   78         struct mrsas_iocpacket32 *user_ioc32 = (struct mrsas_iocpacket32 *)arg;
   79 
   80 #endif
   81         union mrsas_frame *in_cmd = (union mrsas_frame *)&(user_ioc->frame.raw);
   82         struct mrsas_mfi_cmd *cmd = NULL;
   83         bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE];
   84         bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE];
   85         void *ioctl_data_mem[MAX_IOCTL_SGE];
   86         bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE];
   87         bus_dma_tag_t ioctl_sense_tag = 0;
   88         bus_dmamap_t ioctl_sense_dmamap = 0;
   89         void *ioctl_sense_mem = NULL;
   90         bus_addr_t ioctl_sense_phys_addr = 0;
   91         int i, ioctl_data_size = 0, ioctl_sense_size, ret = 0;
   92         struct mrsas_sge32 *kern_sge32;
   93         unsigned long *sense_ptr;
   94         uint8_t *iov_base_ptrin = NULL;
   95         size_t iov_len = 0;
   96 
   97         /*
   98          * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0.  In
   99          * this case do nothing and return 0 to it as status.
  100          */
  101         if (in_cmd->dcmd.opcode == 0) {
  102                 device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__);
  103                 user_ioc->frame.hdr.cmd_status = MFI_STAT_OK;
  104                 return (0);
  105         }
  106         /* Validate SGL length */
  107         if (user_ioc->sge_count > MAX_IOCTL_SGE) {
  108                 device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n",
  109                     __func__, user_ioc->sge_count);
  110                 return (ENOENT);
  111         }
  112         /* Get a command */
  113         cmd = mrsas_get_mfi_cmd(sc);
  114         if (!cmd) {
  115                 device_printf(sc->mrsas_dev, "Failed to get a free cmd for IOCTL\n");
  116                 return (ENOMEM);
  117         }
  118         /*
  119          * User's IOCTL packet has 2 frames (maximum). Copy those two frames
  120          * into our cmd's frames. cmd->frame's context will get overwritten
  121          * when we copy from user's frames. So set that value alone
  122          * separately
  123          */
  124         memcpy(cmd->frame, user_ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
  125         cmd->frame->hdr.context = cmd->index;
  126         cmd->frame->hdr.pad_0 = 0;
  127         cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
  128             MFI_FRAME_SENSE64);
  129 
  130         /*
  131          * The management interface between applications and the fw uses MFI
  132          * frames. E.g, RAID configuration changes, LD property changes etc
  133          * are accomplishes through different kinds of MFI frames. The driver
  134          * needs to care only about substituting user buffers with kernel
  135          * buffers in SGLs. The location of SGL is embedded in the struct
  136          * iocpacket itself.
  137          */
  138         kern_sge32 = (struct mrsas_sge32 *)
  139             ((uintptr_t)cmd->frame + user_ioc->sgl_off);
  140 
  141         memset(ioctl_data_tag, 0, (sizeof(bus_dma_tag_t) * MAX_IOCTL_SGE));
  142         memset(ioctl_data_dmamap, 0, (sizeof(bus_dmamap_t) * MAX_IOCTL_SGE));
  143         memset(ioctl_data_mem, 0, (sizeof(void *) * MAX_IOCTL_SGE));
  144         memset(ioctl_data_phys_addr, 0, (sizeof(bus_addr_t) * MAX_IOCTL_SGE));
  145 
  146         /*
  147          * For each user buffer, create a mirror buffer and copy in
  148          */
  149         for (i = 0; i < user_ioc->sge_count; i++) {
  150                 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
  151                         if (!user_ioc->sgl[i].iov_len)
  152                                 continue;
  153                         ioctl_data_size = user_ioc->sgl[i].iov_len;
  154 #ifdef COMPAT_FREEBSD32
  155                 } else {
  156                         if (!user_ioc32->sgl[i].iov_len)
  157                                 continue;
  158                         ioctl_data_size = user_ioc32->sgl[i].iov_len;
  159 #endif
  160                 }
  161                 if (bus_dma_tag_create(sc->mrsas_parent_tag,
  162                     1, 0,
  163                     BUS_SPACE_MAXADDR_32BIT,
  164                     BUS_SPACE_MAXADDR,
  165                     NULL, NULL,
  166                     ioctl_data_size,
  167                     1,
  168                     ioctl_data_size,
  169                     BUS_DMA_ALLOCNOW,
  170                     NULL, NULL,
  171                     &ioctl_data_tag[i])) {
  172                         device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n");
  173                         ret = ENOMEM;
  174                         goto out;
  175                 }
  176                 if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i],
  177                     (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) {
  178                         device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
  179                         ret = ENOMEM;
  180                         goto out;
  181                 }
  182                 if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i],
  183                     ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb,
  184                     &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) {
  185                         device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n");
  186                         ret = ENOMEM;
  187                         goto out;
  188                 }
  189                 /* Save the physical address and length */
  190                 kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i];
  191 
  192                 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
  193                         kern_sge32[i].length = user_ioc->sgl[i].iov_len;
  194 
  195                         iov_base_ptrin = user_ioc->sgl[i].iov_base;
  196                         iov_len = user_ioc->sgl[i].iov_len;
  197 #ifdef COMPAT_FREEBSD32
  198                 } else {
  199                         kern_sge32[i].length = user_ioc32->sgl[i].iov_len;
  200 
  201                         iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base);
  202                         iov_len = user_ioc32->sgl[i].iov_len;
  203 #endif
  204                 }
  205 
  206                 /* Copy in data from user space */
  207                 ret = copyin(iov_base_ptrin, ioctl_data_mem[i], iov_len);
  208                 if (ret) {
  209                         device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
  210                         goto out;
  211                 }
  212         }
  213 
  214         ioctl_sense_size = user_ioc->sense_len;
  215 
  216         if (user_ioc->sense_len) {
  217                 if (bus_dma_tag_create(sc->mrsas_parent_tag,
  218                     1, 0,
  219                     BUS_SPACE_MAXADDR_32BIT,
  220                     BUS_SPACE_MAXADDR,
  221                     NULL, NULL,
  222                     ioctl_sense_size,
  223                     1,
  224                     ioctl_sense_size,
  225                     BUS_DMA_ALLOCNOW,
  226                     NULL, NULL,
  227                     &ioctl_sense_tag)) {
  228                         device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n");
  229                         ret = ENOMEM;
  230                         goto out;
  231                 }
  232                 if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem,
  233                     (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) {
  234                         device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense mem\n");
  235                         ret = ENOMEM;
  236                         goto out;
  237                 }
  238                 if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap,
  239                     ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb,
  240                     &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) {
  241                         device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n");
  242                         ret = ENOMEM;
  243                         goto out;
  244                 }
  245                 sense_ptr =
  246                     (unsigned long *)((uintptr_t)cmd->frame + user_ioc->sense_off);
  247                 *sense_ptr = ioctl_sense_phys_addr;
  248         }
  249         /*
  250          * Set the sync_cmd flag so that the ISR knows not to complete this
  251          * cmd to the SCSI mid-layer
  252          */
  253         cmd->sync_cmd = 1;
  254         ret = mrsas_issue_blocked_cmd(sc, cmd);
  255         if (ret == ETIMEDOUT) {
  256                 mrsas_dprint(sc, MRSAS_OCR,
  257                     "IOCTL command is timed out, initiating OCR\n");
  258                 sc->do_timedout_reset = MFI_DCMD_TIMEOUT_OCR;
  259                 ret = EAGAIN;
  260                 goto out;
  261         }
  262         cmd->sync_cmd = 0;
  263 
  264         /*
  265          * copy out the kernel buffers to user buffers
  266          */
  267         for (i = 0; i < user_ioc->sge_count; i++) {
  268                 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
  269                         iov_base_ptrin = user_ioc->sgl[i].iov_base;
  270                         iov_len = user_ioc->sgl[i].iov_len;
  271 #ifdef COMPAT_FREEBSD32
  272                 } else {
  273                         iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base);
  274                         iov_len = user_ioc32->sgl[i].iov_len;
  275 #endif
  276                 }
  277 
  278                 ret = copyout(ioctl_data_mem[i], iov_base_ptrin, iov_len);
  279                 if (ret) {
  280                         device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n");
  281                         goto out;
  282                 }
  283         }
  284 
  285         /*
  286          * copy out the sense
  287          */
  288         if (user_ioc->sense_len) {
  289                 /*
  290                  * sense_buff points to the location that has the user sense
  291                  * buffer address
  292                  */
  293                 sense_ptr = (unsigned long *)((uintptr_t)user_ioc->frame.raw +
  294                     user_ioc->sense_off);
  295                 ret = copyout(ioctl_sense_mem, (unsigned long *)(uintptr_t)*sense_ptr,
  296                     user_ioc->sense_len);
  297                 if (ret) {
  298                         device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n");
  299                         goto out;
  300                 }
  301         }
  302         /*
  303          * Return command status to user space
  304          */
  305         memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status,
  306             sizeof(u_int8_t));
  307 
  308 out:
  309         /*
  310          * Release sense buffer
  311          */
  312         if (user_ioc->sense_len) {
  313                 if (ioctl_sense_phys_addr)
  314                         bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap);
  315                 if (ioctl_sense_mem != NULL)
  316                         bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap);
  317                 if (ioctl_sense_tag != NULL)
  318                         bus_dma_tag_destroy(ioctl_sense_tag);
  319         }
  320         /*
  321          * Release data buffers
  322          */
  323         for (i = 0; i < user_ioc->sge_count; i++) {
  324                 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
  325                         if (!user_ioc->sgl[i].iov_len)
  326                                 continue;
  327 #ifdef COMPAT_FREEBSD32
  328                 } else {
  329                         if (!user_ioc32->sgl[i].iov_len)
  330                                 continue;
  331 #endif
  332                 }
  333                 if (ioctl_data_phys_addr[i])
  334                         bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]);
  335                 if (ioctl_data_mem[i] != NULL)
  336                         bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i],
  337                             ioctl_data_dmamap[i]);
  338                 if (ioctl_data_tag[i] != NULL)
  339                         bus_dma_tag_destroy(ioctl_data_tag[i]);
  340         }
  341         /* Free command */
  342         mrsas_release_mfi_cmd(cmd);
  343 
  344         return (ret);
  345 }
  346 
  347 /*
  348  * mrsas_alloc_mfi_cmds:        Allocates the command packets
  349  * input:                                       Adapter instance soft state
  350  *
  351  * Each IOCTL or passthru command that is issued to the FW are wrapped in a
  352  * local data structure called mrsas_mfi_cmd.  The frame embedded in this
  353  * mrsas_mfi is issued to FW. The array is used only to look up the
  354  * mrsas_mfi_cmd given the context. The free commands are maintained in a
  355  * linked list.
  356  */
  357 int
  358 mrsas_alloc_mfi_cmds(struct mrsas_softc *sc)
  359 {
  360         int i, j;
  361         u_int32_t max_cmd;
  362         struct mrsas_mfi_cmd *cmd;
  363 
  364         max_cmd = MRSAS_MAX_MFI_CMDS;
  365 
  366         /*
  367          * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers.
  368          * Allocate the dynamic array first and then allocate individual
  369          * commands.
  370          */
  371         sc->mfi_cmd_list = malloc(sizeof(struct mrsas_mfi_cmd *) * max_cmd, M_MRSAS, M_NOWAIT);
  372         if (!sc->mfi_cmd_list) {
  373                 device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n");
  374                 return (ENOMEM);
  375         }
  376         memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *) * max_cmd);
  377         for (i = 0; i < max_cmd; i++) {
  378                 sc->mfi_cmd_list[i] = malloc(sizeof(struct mrsas_mfi_cmd),
  379                     M_MRSAS, M_NOWAIT);
  380                 if (!sc->mfi_cmd_list[i]) {
  381                         for (j = 0; j < i; j++)
  382                                 free(sc->mfi_cmd_list[j], M_MRSAS);
  383                         free(sc->mfi_cmd_list, M_MRSAS);
  384                         sc->mfi_cmd_list = NULL;
  385                         return (ENOMEM);
  386                 }
  387         }
  388 
  389         for (i = 0; i < max_cmd; i++) {
  390                 cmd = sc->mfi_cmd_list[i];
  391                 memset(cmd, 0, sizeof(struct mrsas_mfi_cmd));
  392                 cmd->index = i;
  393                 cmd->ccb_ptr = NULL;
  394                 cmd->sc = sc;
  395                 TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
  396         }
  397 
  398         /* create a frame pool and assign one frame to each command */
  399         if (mrsas_create_frame_pool(sc)) {
  400                 device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n");
  401                 /* Free the frames */
  402                 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
  403                         cmd = sc->mfi_cmd_list[i];
  404                         mrsas_free_frame(sc, cmd);
  405                 }
  406                 if (sc->mficmd_frame_tag != NULL)
  407                         bus_dma_tag_destroy(sc->mficmd_frame_tag);
  408                 return (ENOMEM);
  409         }
  410         return (0);
  411 }
  412 
  413 /*
  414  * mrsas_create_frame_pool:     Creates DMA pool for cmd frames
  415  * input:                                       Adapter soft state
  416  *
  417  * Each command packet has an embedded DMA memory buffer that is used for
  418  * filling MFI frame and the SG list that immediately follows the frame. This
  419  * function creates those DMA memory buffers for each command packet by using
  420  * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value
  421  * of context and could cause FW crash.
  422  */
  423 static int
  424 mrsas_create_frame_pool(struct mrsas_softc *sc)
  425 {
  426         int i;
  427         struct mrsas_mfi_cmd *cmd;
  428 
  429         if (bus_dma_tag_create(sc->mrsas_parent_tag,
  430             1, 0,
  431             BUS_SPACE_MAXADDR_32BIT,
  432             BUS_SPACE_MAXADDR,
  433             NULL, NULL,
  434             MRSAS_MFI_FRAME_SIZE,
  435             1,
  436             MRSAS_MFI_FRAME_SIZE,
  437             BUS_DMA_ALLOCNOW,
  438             NULL, NULL,
  439             &sc->mficmd_frame_tag)) {
  440                 device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n");
  441                 return (ENOMEM);
  442         }
  443         for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
  444                 cmd = sc->mfi_cmd_list[i];
  445                 cmd->frame = mrsas_alloc_frame(sc, cmd);
  446                 if (cmd->frame == NULL) {
  447                         device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
  448                         return (ENOMEM);
  449                 }
  450                 /*
  451                  * For MFI controllers.
  452                  * max_num_sge = 60
  453                  * max_sge_sz  = 16 byte (sizeof megasas_sge_skinny)
  454                  * Totl 960 byte (15 MFI frame of 64 byte)
  455                  *
  456                  * Fusion adapter require only 3 extra frame.
  457                  * max_num_sge = 16 (defined as MAX_IOCTL_SGE)
  458                  * max_sge_sz  = 12 byte (sizeof  megasas_sge64)
  459                  * Total 192 byte (3 MFI frame of 64 byte)
  460                  */
  461                 memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE);
  462                 cmd->frame->io.context = cmd->index;
  463                 cmd->frame->io.pad_0 = 0;
  464         }
  465 
  466         return (0);
  467 }
  468 
  469 /*
  470  * mrsas_alloc_frame:   Allocates MFI Frames
  471  * input:                               Adapter soft state
  472  *
  473  * Create bus DMA memory tag and dmamap and load memory for MFI frames. Returns
  474  * virtual memory pointer to allocated region.
  475  */
  476 void   *
  477 mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
  478 {
  479         u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE;
  480 
  481         if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem,
  482             BUS_DMA_NOWAIT, &cmd->frame_dmamap)) {
  483                 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
  484                 return (NULL);
  485         }
  486         if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap,
  487             cmd->frame_mem, frame_size, mrsas_alloc_cb,
  488             &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) {
  489                 device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
  490                 return (NULL);
  491         }
  492         return (cmd->frame_mem);
  493 }
  494 
  495 /*
  496  * mrsas_alloc_cb:      Callback function of bus_dmamap_load()
  497  * input:                       callback argument,
  498  *                                      machine dependent type that describes DMA segments,
  499  *                                      number of segments,
  500  *                                      error code.
  501  *
  502  * This function is for the driver to receive mapping information resultant of
  503  * the bus_dmamap_load(). The information is actually not being used, but the
  504  * address is saved anyway.
  505  */
  506 static void
  507 mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
  508     int nsegs, int error)
  509 {
  510         bus_addr_t *addr;
  511 
  512         addr = arg;
  513         *addr = segs[0].ds_addr;
  514 }
  515 
  516 /*
  517  * mrsas_free_frames:   Frees memory for  MFI frames
  518  * input:                               Adapter soft state
  519  *
  520  * Deallocates MFI frames memory.  Called from mrsas_free_mem() during detach
  521  * and error case during creation of frame pool.
  522  */
  523 void
  524 mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
  525 {
  526         if (cmd->frame_phys_addr)
  527                 bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap);
  528         if (cmd->frame_mem != NULL)
  529                 bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap);
  530 }

Cache object: 3a94f03afc0b9a37b1ee6dfd58207c34


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.