2 * Copyright (c) 2014, LSI Corp. All rights reserved. Author: Marian Choy
3 * Support: freebsdraid@lsi.com
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer. 2. Redistributions
11 * in binary form must reproduce the above copyright notice, this list of
12 * conditions and the following disclaimer in the documentation and/or other
13 * materials provided with the distribution. 3. Neither the name of the
14 * <ORGANIZATION> nor the names of its contributors may be used to endorse or
15 * promote products derived from this software without specific prior written
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * The views and conclusions contained in the software and documentation are
31 * those of the authors and should not be interpreted as representing
32 * official policies,either expressed or implied, of the FreeBSD Project.
34 * Send feedback to: <megaraidfbsd@lsi.com> Mail to: LSI Corporation, 1621
35 * Barber Lane, Milpitas, CA 95035 ATTN: MegaRaid FreeBSD
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
42 #include <dev/mrsas/mrsas.h>
43 #include <dev/mrsas/mrsas_ioctl.h>
48 int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
49 int mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd);
50 void mrsas_free_ioc_cmd(struct mrsas_softc *sc);
51 void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
52 void *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
53 static int mrsas_create_frame_pool(struct mrsas_softc *sc);
55 mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
56 int nsegs, int error);
58 extern struct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc);
59 extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
61 mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
62 struct mrsas_mfi_cmd *cmd);
65 * mrsas_passthru: Handle pass-through commands
66 * input: Adapter instance soft state argument pointer
68 * This function is called from mrsas_ioctl() to handle pass-through and ioctl
69 * commands to Firmware.
72 mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd)
74 struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
76 #ifdef COMPAT_FREEBSD32
77 struct mrsas_iocpacket32 *user_ioc32 = (struct mrsas_iocpacket32 *)arg;
80 union mrsas_frame *in_cmd = (union mrsas_frame *)&(user_ioc->frame.raw);
81 struct mrsas_mfi_cmd *cmd = NULL;
82 bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE];
83 bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE];
84 void *ioctl_data_mem[MAX_IOCTL_SGE];
85 bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE];
86 bus_dma_tag_t ioctl_sense_tag = 0;
87 bus_dmamap_t ioctl_sense_dmamap = 0;
88 void *ioctl_sense_mem = 0;
89 bus_addr_t ioctl_sense_phys_addr = 0;
90 int i, ioctl_data_size = 0, ioctl_sense_size, ret = 0;
91 struct mrsas_sge32 *kern_sge32;
92 unsigned long *sense_ptr;
93 uint8_t *iov_base_ptrin = NULL;
97 * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0. In
98 * this case do nothing and return 0 to it as status.
100 if (in_cmd->dcmd.opcode == 0) {
101 device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__);
102 user_ioc->frame.hdr.cmd_status = MFI_STAT_OK;
105 /* Validate SGL length */
106 if (user_ioc->sge_count > MAX_IOCTL_SGE) {
107 device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n",
108 __func__, user_ioc->sge_count);
112 cmd = mrsas_get_mfi_cmd(sc);
114 device_printf(sc->mrsas_dev, "Failed to get a free cmd for IOCTL\n");
118 * User's IOCTL packet has 2 frames (maximum). Copy those two frames
119 * into our cmd's frames. cmd->frame's context will get overwritten
120 * when we copy from user's frames. So set that value alone
123 memcpy(cmd->frame, user_ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
124 cmd->frame->hdr.context = cmd->index;
125 cmd->frame->hdr.pad_0 = 0;
126 cmd->frame->hdr.flags &= ~(MFI_FRAME_IEEE | MFI_FRAME_SGL64 |
130 * The management interface between applications and the fw uses MFI
131 * frames. E.g, RAID configuration changes, LD property changes etc
132 * are accomplishes through different kinds of MFI frames. The driver
133 * needs to care only about substituting user buffers with kernel
134 * buffers in SGLs. The location of SGL is embedded in the struct
137 kern_sge32 = (struct mrsas_sge32 *)
138 ((unsigned long)cmd->frame + user_ioc->sgl_off);
141 * For each user buffer, create a mirror buffer and copy in
143 for (i = 0; i < user_ioc->sge_count; i++) {
144 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
145 if (!user_ioc->sgl[i].iov_len)
147 ioctl_data_size = user_ioc->sgl[i].iov_len;
148 #ifdef COMPAT_FREEBSD32
150 if (!user_ioc32->sgl[i].iov_len)
152 ioctl_data_size = user_ioc32->sgl[i].iov_len;
155 if (bus_dma_tag_create(sc->mrsas_parent_tag,
157 BUS_SPACE_MAXADDR_32BIT,
165 &ioctl_data_tag[i])) {
166 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n");
170 if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i],
171 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) {
172 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
176 if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i],
177 ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb,
178 &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) {
179 device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n");
183 /* Save the physical address and length */
184 kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i];
186 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
187 kern_sge32[i].length = user_ioc->sgl[i].iov_len;
189 iov_base_ptrin = user_ioc->sgl[i].iov_base;
190 iov_len = user_ioc->sgl[i].iov_len;
191 #ifdef COMPAT_FREEBSD32
193 kern_sge32[i].length = user_ioc32->sgl[i].iov_len;
195 iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base);
196 iov_len = user_ioc32->sgl[i].iov_len;
200 /* Copy in data from user space */
201 ret = copyin(iov_base_ptrin, ioctl_data_mem[i], iov_len);
203 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
208 ioctl_sense_size = user_ioc->sense_len;
210 if (user_ioc->sense_len) {
211 if (bus_dma_tag_create(sc->mrsas_parent_tag,
213 BUS_SPACE_MAXADDR_32BIT,
222 device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense tag\n");
226 if (bus_dmamem_alloc(ioctl_sense_tag, (void **)&ioctl_sense_mem,
227 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_sense_dmamap)) {
228 device_printf(sc->mrsas_dev, "Cannot allocate ioctl sense mem\n");
232 if (bus_dmamap_load(ioctl_sense_tag, ioctl_sense_dmamap,
233 ioctl_sense_mem, ioctl_sense_size, mrsas_alloc_cb,
234 &ioctl_sense_phys_addr, BUS_DMA_NOWAIT)) {
235 device_printf(sc->mrsas_dev, "Cannot load ioctl sense mem\n");
240 (unsigned long *)((unsigned long)cmd->frame + user_ioc->sense_off);
241 sense_ptr = ioctl_sense_mem;
244 * Set the sync_cmd flag so that the ISR knows not to complete this
245 * cmd to the SCSI mid-layer
248 mrsas_issue_blocked_cmd(sc, cmd);
252 * copy out the kernel buffers to user buffers
254 for (i = 0; i < user_ioc->sge_count; i++) {
255 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
256 iov_base_ptrin = user_ioc->sgl[i].iov_base;
257 iov_len = user_ioc->sgl[i].iov_len;
258 #ifdef COMPAT_FREEBSD32
260 iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base);
261 iov_len = user_ioc32->sgl[i].iov_len;
265 ret = copyout(ioctl_data_mem[i], iov_base_ptrin, iov_len);
267 device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n");
275 if (user_ioc->sense_len) {
277 * sense_buff points to the location that has the user sense
280 sense_ptr = (unsigned long *)((unsigned long)user_ioc->frame.raw +
281 user_ioc->sense_off);
282 ret = copyout(ioctl_sense_mem, (unsigned long *)*sense_ptr,
283 user_ioc->sense_len);
285 device_printf(sc->mrsas_dev, "IOCTL sense copyout failed!\n");
290 * Return command status to user space
292 memcpy(&user_ioc->frame.hdr.cmd_status, &cmd->frame->hdr.cmd_status,
297 * Release sense buffer
299 if (ioctl_sense_phys_addr)
300 bus_dmamap_unload(ioctl_sense_tag, ioctl_sense_dmamap);
301 if (ioctl_sense_mem != NULL)
302 bus_dmamem_free(ioctl_sense_tag, ioctl_sense_mem, ioctl_sense_dmamap);
303 if (ioctl_sense_tag != NULL)
304 bus_dma_tag_destroy(ioctl_sense_tag);
307 * Release data buffers
309 for (i = 0; i < user_ioc->sge_count; i++) {
310 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
311 if (!user_ioc->sgl[i].iov_len)
313 #ifdef COMPAT_FREEBSD32
315 if (!user_ioc32->sgl[i].iov_len)
319 if (ioctl_data_phys_addr[i])
320 bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]);
321 if (ioctl_data_mem[i] != NULL)
322 bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i],
323 ioctl_data_dmamap[i]);
324 if (ioctl_data_tag[i] != NULL)
325 bus_dma_tag_destroy(ioctl_data_tag[i]);
328 mrsas_release_mfi_cmd(cmd);
334 * mrsas_alloc_mfi_cmds: Allocates the command packets
335 * input: Adapter instance soft state
337 * Each IOCTL or passthru command that is issued to the FW are wrapped in a
338 * local data structure called mrsas_mfi_cmd. The frame embedded in this
339 * mrsas_mfi is issued to FW. The array is used only to look up the
340 * mrsas_mfi_cmd given the context. The free commands are maintained in a
344 mrsas_alloc_mfi_cmds(struct mrsas_softc *sc)
348 struct mrsas_mfi_cmd *cmd;
350 max_cmd = MRSAS_MAX_MFI_CMDS;
353 * sc->mfi_cmd_list is an array of struct mrsas_mfi_cmd pointers.
354 * Allocate the dynamic array first and then allocate individual
357 sc->mfi_cmd_list = malloc(sizeof(struct mrsas_mfi_cmd *) * max_cmd, M_MRSAS, M_NOWAIT);
358 if (!sc->mfi_cmd_list) {
359 device_printf(sc->mrsas_dev, "Cannot alloc memory for mfi_cmd cmd_list.\n");
362 memset(sc->mfi_cmd_list, 0, sizeof(struct mrsas_mfi_cmd *) * max_cmd);
363 for (i = 0; i < max_cmd; i++) {
364 sc->mfi_cmd_list[i] = malloc(sizeof(struct mrsas_mfi_cmd),
366 if (!sc->mfi_cmd_list[i]) {
367 for (j = 0; j < i; j++)
368 free(sc->mfi_cmd_list[j], M_MRSAS);
369 free(sc->mfi_cmd_list, M_MRSAS);
370 sc->mfi_cmd_list = NULL;
375 for (i = 0; i < max_cmd; i++) {
376 cmd = sc->mfi_cmd_list[i];
377 memset(cmd, 0, sizeof(struct mrsas_mfi_cmd));
381 TAILQ_INSERT_TAIL(&(sc->mrsas_mfi_cmd_list_head), cmd, next);
384 /* create a frame pool and assign one frame to each command */
385 if (mrsas_create_frame_pool(sc)) {
386 device_printf(sc->mrsas_dev, "Cannot allocate DMA frame pool.\n");
387 /* Free the frames */
388 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
389 cmd = sc->mfi_cmd_list[i];
390 mrsas_free_frame(sc, cmd);
392 if (sc->mficmd_frame_tag != NULL)
393 bus_dma_tag_destroy(sc->mficmd_frame_tag);
400 * mrsas_create_frame_pool: Creates DMA pool for cmd frames
401 * input: Adapter soft state
403 * Each command packet has an embedded DMA memory buffer that is used for
404 * filling MFI frame and the SG list that immediately follows the frame. This
405 * function creates those DMA memory buffers for each command packet by using
406 * PCI pool facility. pad_0 is initialized to 0 to prevent corrupting value
407 * of context and could cause FW crash.
410 mrsas_create_frame_pool(struct mrsas_softc *sc)
413 struct mrsas_mfi_cmd *cmd;
415 if (bus_dma_tag_create(sc->mrsas_parent_tag,
417 BUS_SPACE_MAXADDR_32BIT,
420 MRSAS_MFI_FRAME_SIZE,
422 MRSAS_MFI_FRAME_SIZE,
425 &sc->mficmd_frame_tag)) {
426 device_printf(sc->mrsas_dev, "Cannot create MFI frame tag\n");
429 for (i = 0; i < MRSAS_MAX_MFI_CMDS; i++) {
430 cmd = sc->mfi_cmd_list[i];
431 cmd->frame = mrsas_alloc_frame(sc, cmd);
432 if (cmd->frame == NULL) {
433 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
436 memset(cmd->frame, 0, MRSAS_MFI_FRAME_SIZE);
437 cmd->frame->io.context = cmd->index;
438 cmd->frame->io.pad_0 = 0;
445 * mrsas_alloc_frame: Allocates MFI Frames
446 * input: Adapter soft state
448 * Create bus DMA memory tag and dmamap and load memory for MFI frames. Returns
449 * virtual memory pointer to allocated region.
452 mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
454 u_int32_t frame_size = MRSAS_MFI_FRAME_SIZE;
456 if (bus_dmamem_alloc(sc->mficmd_frame_tag, (void **)&cmd->frame_mem,
457 BUS_DMA_NOWAIT, &cmd->frame_dmamap)) {
458 device_printf(sc->mrsas_dev, "Cannot alloc MFI frame memory\n");
461 if (bus_dmamap_load(sc->mficmd_frame_tag, cmd->frame_dmamap,
462 cmd->frame_mem, frame_size, mrsas_alloc_cb,
463 &cmd->frame_phys_addr, BUS_DMA_NOWAIT)) {
464 device_printf(sc->mrsas_dev, "Cannot load IO request memory\n");
467 return (cmd->frame_mem);
471 * mrsas_alloc_cb: Callback function of bus_dmamap_load()
472 * input: callback argument,
473 * machine dependent type that describes DMA segments,
474 * number of segments,
477 * This function is for the driver to receive mapping information resultant of
478 * the bus_dmamap_load(). The information is actually not being used, but the
479 * address is saved anyway.
482 mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
483 int nsegs, int error)
488 *addr = segs[0].ds_addr;
492 * mrsas_free_frames: Frees memory for MFI frames
493 * input: Adapter soft state
495 * Deallocates MFI frames memory. Called from mrsas_free_mem() during detach
496 * and error case during creation of frame pool.
499 mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd)
501 if (cmd->frame_phys_addr)
502 bus_dmamap_unload(sc->mficmd_frame_tag, cmd->frame_dmamap);
503 if (cmd->frame_mem != NULL)
504 bus_dmamem_free(sc->mficmd_frame_tag, cmd->frame_mem, cmd->frame_dmamap);