Deleted Added
sdiff udiff text old ( 265555 ) new ( 272737 )
full compact
1/*
2 * Copyright (c) 2014, LSI Corp.
3 * All rights reserved.
4 * Author: Marian Choy
5 * Support: freebsdraid@lsi.com
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 28 unchanged lines hidden (view full) ---

37 *
38 * Send feedback to: <megaraidfbsd@lsi.com>
39 * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035
40 * ATTN: MegaRaid FreeBSD
41 *
42 */
43
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD: head/sys/dev/mrsas/mrsas_ioctl.c 272737 2014-10-08 09:19:35Z kadesai $");
46
47#include <dev/mrsas/mrsas.h>
48#include <dev/mrsas/mrsas_ioctl.h>
49
50/*
51 * Function prototypes
52 */
53int mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
54int mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd);
55void mrsas_free_ioc_cmd(struct mrsas_softc *sc);
56void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
57void * mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
58static int mrsas_create_frame_pool(struct mrsas_softc *sc);
59static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
60 int nsegs, int error);
61
62extern struct mrsas_mfi_cmd* mrsas_get_mfi_cmd(struct mrsas_softc *sc);
63extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
64extern int mrsas_issue_blocked_cmd(struct mrsas_softc *sc,
65 struct mrsas_mfi_cmd *cmd);
66
67/**
68 * mrsas_passthru: Handle pass-through commands
69 * input: Adapter instance soft state
70 * argument pointer
71 *
72 * This function is called from mrsas_ioctl() to handle pass-through and
73 * ioctl commands to Firmware.
74 */
75int mrsas_passthru( struct mrsas_softc *sc, void *arg, u_long ioctlCmd )
76{
77 struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg;
78#ifdef COMPAT_FREEBSD32
79 struct mrsas_iocpacket32 *user_ioc32 = (struct mrsas_iocpacket32 *)arg;
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]; // ioctl data virtual addr
86 bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE]; // ioctl data phys addr
87 bus_dma_tag_t ioctl_sense_tag = 0;
88 bus_dmamap_t ioctl_sense_dmamap = 0;
89 void *ioctl_sense_mem = 0;
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 this
99 * 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
107 /* Validate SGL length */
108 if (user_ioc->sge_count > MAX_IOCTL_SGE) {
109 device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n",
110 __func__, user_ioc->sge_count);
111 return(ENOENT);
112 }
113
114 /* Get a command */

--- 25 unchanged lines hidden (view full) ---

140 */
141 kern_sge32 = (struct mrsas_sge32 *)
142 ((unsigned long)cmd->frame + user_ioc->sgl_off);
143
144 /*
145 * For each user buffer, create a mirror buffer and copy in
146 */
147 for (i=0; i < user_ioc->sge_count; i++) {
148 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
149 if (!user_ioc->sgl[i].iov_len)
150 continue;
151 ioctl_data_size = user_ioc->sgl[i].iov_len;
152#ifdef COMPAT_FREEBSD32
153 } else {
154 if (!user_ioc32->sgl[i].iov_len)
155 continue;
156 ioctl_data_size = user_ioc32->sgl[i].iov_len;
157#endif
158 }
159 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
160 1, 0, // algnmnt, boundary
161 BUS_SPACE_MAXADDR_32BIT,// lowaddr
162 BUS_SPACE_MAXADDR, // highaddr
163 NULL, NULL, // filter, filterarg
164 ioctl_data_size, // maxsize
165 1, // msegments
166 ioctl_data_size, // maxsegsize
167 BUS_DMA_ALLOCNOW, // flags
168 NULL, NULL, // lockfunc, lockarg
169 &ioctl_data_tag[i])) {
170 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n");
171 return (ENOMEM);
172 }
173 if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i],
174 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) {
175 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n");
176 return (ENOMEM);
177 }
178 if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i],
179 ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb,
180 &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) {
181 device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n");
182 return (ENOMEM);
183 }
184
185 /* Save the physical address and length */
186 kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i];
187
188 if (ioctlCmd == MRSAS_IOC_FIRMWARE_PASS_THROUGH64) {
189 kern_sge32[i].length = user_ioc->sgl[i].iov_len;
190
191 iov_base_ptrin = user_ioc->sgl[i].iov_base;
192 iov_len = user_ioc->sgl[i].iov_len;
193#ifdef COMPAT_FREEBSD32
194 } else {
195 kern_sge32[i].length = user_ioc32->sgl[i].iov_len;
196
197 iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base);
198 iov_len = user_ioc32->sgl[i].iov_len;
199#endif
200 }
201
202 /* Copy in data from user space */
203 ret = copyin(iov_base_ptrin, ioctl_data_mem[i], iov_len);
204 if (ret) {
205 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n");
206 goto out;
207 }
208 }
209
210 ioctl_sense_size = user_ioc->sense_len;
211
212 if (user_ioc->sense_len) {
213 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent
214 1, 0, // algnmnt, boundary
215 BUS_SPACE_MAXADDR_32BIT,// lowaddr
216 BUS_SPACE_MAXADDR, // highaddr
217 NULL, NULL, // filter, filterarg
218 ioctl_sense_size, // maxsize
219 1, // msegments

--- 27 unchanged lines hidden (view full) ---

247 cmd->sync_cmd = 1;
248 mrsas_issue_blocked_cmd(sc, cmd);
249 cmd->sync_cmd = 0;
250
251 /*
252 * copy out the kernel buffers to user buffers
253 */
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
259 } else {
260 iov_base_ptrin = PTRIN(user_ioc32->sgl[i].iov_base);
261 iov_len = user_ioc32->sgl[i].iov_len;
262#endif
263 }
264
265 ret = copyout(ioctl_data_mem[i], iov_base_ptrin, iov_len);
266 if (ret) {
267 device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n");
268 goto out;
269 }
270 }
271
272 /*
273 * copy out the sense

--- 39 unchanged lines hidden (view full) ---

313 if (ioctl_data_phys_addr[i])
314 bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]);
315 if (ioctl_data_mem[i] != NULL)
316 bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i],
317 ioctl_data_dmamap[i]);
318 if (ioctl_data_tag[i] != NULL)
319 bus_dma_tag_destroy(ioctl_data_tag[i]);
320 }
321 /* Free command */
322 mrsas_release_mfi_cmd(cmd);
323
324 return(ret);
325}
326
327/**
328 * mrsas_alloc_mfi_cmds: Allocates the command packets

--- 167 unchanged lines hidden ---