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 */
49int	mrsas_alloc_mfi_cmds(struct mrsas_softc *sc);
50int	mrsas_passthru(struct mrsas_softc *sc, void *arg, u_long ioctlCmd);
51void	mrsas_free_ioc_cmd(struct mrsas_softc *sc);
52void	mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
53void   *mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd);
54static int mrsas_create_frame_pool(struct mrsas_softc *sc);
55static void
56mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs,
57    int nsegs, int error);
58
59extern struct mrsas_mfi_cmd *mrsas_get_mfi_cmd(struct mrsas_softc *sc);
60extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd);
61extern int
62mrsas_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 */
72int
73mrsas_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	    ((unsigned long)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 *)((unsigned long)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 *)((unsigned long)user_ioc->frame.raw +
294		    user_ioc->sense_off);
295		ret = copyout(ioctl_sense_mem, (unsigned long *)*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
308out:
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 */
357int
358mrsas_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 */
423static int
424mrsas_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 */
476void   *
477mrsas_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 */
506static void
507mrsas_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 */
523void
524mrsas_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}
531