mrsas_ioctl.c (265555) | mrsas_ioctl.c (272737) |
---|---|
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> | 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 265555 2014-05-07 16:16:49Z ambrisko $"); | 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); | 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); | 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); | 55void mrsas_free_ioc_cmd(struct mrsas_softc *sc); 56void mrsas_free_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); |
57void mrsas_dump_dcmd(struct mrsas_softc *sc, struct mrsas_dcmd_frame* dcmd); 58void mrsas_dump_ioctl(struct mrsas_softc *sc, struct mrsas_iocpacket *user_ioc); | |
59void * mrsas_alloc_frame(struct mrsas_softc *sc, struct mrsas_mfi_cmd *cmd); 60static int mrsas_create_frame_pool(struct mrsas_softc *sc); 61static void mrsas_alloc_cb(void *arg, bus_dma_segment_t *segs, 62 int nsegs, int error); 63 64extern struct mrsas_mfi_cmd* mrsas_get_mfi_cmd(struct mrsas_softc *sc); 65extern void mrsas_release_mfi_cmd(struct mrsas_mfi_cmd *cmd); 66extern int mrsas_issue_blocked_cmd(struct mrsas_softc *sc, 67 struct mrsas_mfi_cmd *cmd); 68 | 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 |
69 | |
70/** | 67/** |
71 * mrsas_dump_ioctl: Print debug output for DCMDs 72 * input: Adapter instance soft state 73 * DCMD frame structure 74 * 75 * This function is called from mrsas_passthru() to print out debug information 76 * in the handling and routing of DCMD commands. 77 */ 78void mrsas_dump_dcmd( struct mrsas_softc *sc, struct mrsas_dcmd_frame* dcmd ) 79{ 80 int i; 81 82 device_printf(sc->mrsas_dev, "dcmd->cmd: 0x%02hhx\n", dcmd->cmd); 83 device_printf(sc->mrsas_dev, "dcmd->cmd_status: 0x%02hhx\n", dcmd->cmd_status); 84 device_printf(sc->mrsas_dev, "dcmd->sge_count: 0x%02hhx\n", dcmd->sge_count); 85 device_printf(sc->mrsas_dev, "dcmd->context: 0x%08x\n", dcmd->context); 86 device_printf(sc->mrsas_dev, "dcmd->flags: 0x%04hx\n", dcmd->flags); 87 device_printf(sc->mrsas_dev, "dcmd->timeout: 0x%04hx\n", dcmd->timeout); 88 device_printf(sc->mrsas_dev, "dcmd->data_xfer_len: 0x%08x\n", dcmd->data_xfer_len); 89 device_printf(sc->mrsas_dev, "dcmd->opcode: 0x%08x\n", dcmd->opcode); 90 device_printf(sc->mrsas_dev, "dcmd->mbox.w[0]: 0x%08x\n", dcmd->mbox.w[0]); 91 device_printf(sc->mrsas_dev, "dcmd->mbox.w[1]: 0x%08x\n", dcmd->mbox.w[1]); 92 device_printf(sc->mrsas_dev, "dcmd->mbox.w[2]: 0x%08x\n", dcmd->mbox.w[2]); 93 for (i=0; i< MIN(MAX_IOCTL_SGE, dcmd->sge_count); i++) { 94 device_printf(sc->mrsas_dev, "sgl[%02d]\n", i); 95 device_printf(sc->mrsas_dev, " sge32[%02d].phys_addr: 0x%08x\n", 96 i, dcmd->sgl.sge32[i].phys_addr); 97 device_printf(sc->mrsas_dev, " sge32[%02d].length: 0x%08x\n", 98 i, dcmd->sgl.sge32[i].length); 99 device_printf(sc->mrsas_dev, " sge64[%02d].phys_addr: 0x%08llx\n", 100 i, (long long unsigned int) dcmd->sgl.sge64[i].phys_addr); 101 device_printf(sc->mrsas_dev, " sge64[%02d].length: 0x%08x\n", 102 i, dcmd->sgl.sge64[i].length); 103 } 104} 105 106/** 107 * mrsas_dump_ioctl: Print debug output for ioctl 108 * input: Adapter instance soft state 109 * iocpacket structure 110 * 111 * This function is called from mrsas_passthru() to print out debug information 112 * in the handling and routing of ioctl commands. 113 */ 114void mrsas_dump_ioctl(struct mrsas_softc *sc, struct mrsas_iocpacket *user_ioc) 115{ 116 union mrsas_frame *in_cmd = (union mrsas_frame *) &(user_ioc->frame.raw); 117 struct mrsas_dcmd_frame* dcmd = (struct mrsas_dcmd_frame *) &(in_cmd->dcmd); 118 int i; 119 120 device_printf(sc->mrsas_dev, 121 "====== In %s() ======================================\n", __func__); 122 device_printf(sc->mrsas_dev, "host_no: 0x%04hx\n", user_ioc->host_no); 123 device_printf(sc->mrsas_dev, " __pad1: 0x%04hx\n", user_ioc->__pad1); 124 device_printf(sc->mrsas_dev, "sgl_off: 0x%08x\n", user_ioc->sgl_off); 125 device_printf(sc->mrsas_dev, "sge_count: 0x%08x\n", user_ioc->sge_count); 126 device_printf(sc->mrsas_dev, "sense_off: 0x%08x\n", user_ioc->sense_off); 127 device_printf(sc->mrsas_dev, "sense_len: 0x%08x\n", user_ioc->sense_len); 128 129 mrsas_dump_dcmd(sc, dcmd); 130 131 for (i=0; i< MIN(MAX_IOCTL_SGE, user_ioc->sge_count); i++) { 132 device_printf(sc->mrsas_dev, "sge[%02d]\n", i); 133 device_printf(sc->mrsas_dev, 134 " iov_base: %p\n", user_ioc->sgl[i].iov_base); 135 device_printf(sc->mrsas_dev, " iov_len: %p\n", 136 (void*)user_ioc->sgl[i].iov_len); 137 } 138 device_printf(sc->mrsas_dev, 139 "==================================================================\n"); 140} 141 142/** | |
143 * mrsas_passthru: Handle pass-through commands 144 * input: Adapter instance soft state 145 * argument pointer 146 * 147 * This function is called from mrsas_ioctl() to handle pass-through and 148 * ioctl commands to Firmware. 149 */ | 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 */ |
150int mrsas_passthru( struct mrsas_softc *sc, void *arg ) | 75int mrsas_passthru( struct mrsas_softc *sc, void *arg, u_long ioctlCmd ) |
151{ 152 struct mrsas_iocpacket *user_ioc = (struct mrsas_iocpacket *)arg; | 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 |
|
153 union mrsas_frame *in_cmd = (union mrsas_frame *) &(user_ioc->frame.raw); 154 struct mrsas_mfi_cmd *cmd = NULL; 155 bus_dma_tag_t ioctl_data_tag[MAX_IOCTL_SGE]; 156 bus_dmamap_t ioctl_data_dmamap[MAX_IOCTL_SGE]; 157 void *ioctl_data_mem[MAX_IOCTL_SGE]; // ioctl data virtual addr 158 bus_addr_t ioctl_data_phys_addr[MAX_IOCTL_SGE]; // ioctl data phys addr 159 bus_dma_tag_t ioctl_sense_tag = 0; 160 bus_dmamap_t ioctl_sense_dmamap = 0; 161 void *ioctl_sense_mem = 0; 162 bus_addr_t ioctl_sense_phys_addr = 0; | 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; |
163 int i, adapter, ioctl_data_size, ioctl_sense_size, ret=0; | 91 int i, ioctl_data_size=0, ioctl_sense_size, ret=0; |
164 struct mrsas_sge32 *kern_sge32; 165 unsigned long *sense_ptr; | 92 struct mrsas_sge32 *kern_sge32; 93 unsigned long *sense_ptr; |
94 uint8_t *iov_base_ptrin=NULL; 95 size_t iov_len=0; |
|
166 | 96 |
167 /* For debug - uncomment the following line for debug output */ 168 //mrsas_dump_ioctl(sc, user_ioc); 169 | |
170 /* 171 * Check for NOP from MegaCli... MegaCli can issue a DCMD of 0. In this 172 * case do nothing and return 0 to it as status. 173 */ 174 if (in_cmd->dcmd.opcode == 0) { 175 device_printf(sc->mrsas_dev, "In %s() Got a NOP\n", __func__); 176 user_ioc->frame.hdr.cmd_status = MFI_STAT_OK; 177 return (0); 178 } 179 | 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 |
180 /* Validate host_no */ 181 adapter = user_ioc->host_no; 182 if (adapter != device_get_unit(sc->mrsas_dev)) { 183 device_printf(sc->mrsas_dev, "In %s() IOCTL not for me!\n", __func__); 184 return(ENOENT); 185 } 186 | |
187 /* Validate SGL length */ 188 if (user_ioc->sge_count > MAX_IOCTL_SGE) { 189 device_printf(sc->mrsas_dev, "In %s() SGL is too long (%d > 8).\n", 190 __func__, user_ioc->sge_count); 191 return(ENOENT); 192 } 193 194 /* Get a command */ --- 25 unchanged lines hidden (view full) --- 220 */ 221 kern_sge32 = (struct mrsas_sge32 *) 222 ((unsigned long)cmd->frame + user_ioc->sgl_off); 223 224 /* 225 * For each user buffer, create a mirror buffer and copy in 226 */ 227 for (i=0; i < user_ioc->sge_count; i++) { | 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++) { |
228 if (!user_ioc->sgl[i].iov_len) 229 continue; 230 ioctl_data_size = user_ioc->sgl[i].iov_len; | 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 } |
231 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent 232 1, 0, // algnmnt, boundary 233 BUS_SPACE_MAXADDR_32BIT,// lowaddr 234 BUS_SPACE_MAXADDR, // highaddr 235 NULL, NULL, // filter, filterarg 236 ioctl_data_size, // maxsize 237 1, // msegments 238 ioctl_data_size, // maxsegsize 239 BUS_DMA_ALLOCNOW, // flags 240 NULL, NULL, // lockfunc, lockarg 241 &ioctl_data_tag[i])) { | 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])) { |
242 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n"); 243 return (ENOMEM); | 170 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data tag\n"); 171 return (ENOMEM); |
244 } 245 if (bus_dmamem_alloc(ioctl_data_tag[i], (void **)&ioctl_data_mem[i], 246 (BUS_DMA_NOWAIT | BUS_DMA_ZERO), &ioctl_data_dmamap[i])) { 247 device_printf(sc->mrsas_dev, "Cannot allocate ioctl data mem\n"); 248 return (ENOMEM); 249 } 250 if (bus_dmamap_load(ioctl_data_tag[i], ioctl_data_dmamap[i], 251 ioctl_data_mem[i], ioctl_data_size, mrsas_alloc_cb, 252 &ioctl_data_phys_addr[i], BUS_DMA_NOWAIT)) { 253 device_printf(sc->mrsas_dev, "Cannot load ioctl data mem\n"); 254 return (ENOMEM); 255 } 256 257 /* Save the physical address and length */ 258 kern_sge32[i].phys_addr = (u_int32_t)ioctl_data_phys_addr[i]; | 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]; |
259 kern_sge32[i].length = user_ioc->sgl[i].iov_len; | |
260 | 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 |
|
261 /* Copy in data from user space */ | 202 /* Copy in data from user space */ |
262 ret = copyin(user_ioc->sgl[i].iov_base, ioctl_data_mem[i], 263 user_ioc->sgl[i].iov_len); | 203 ret = copyin(iov_base_ptrin, ioctl_data_mem[i], iov_len); |
264 if (ret) { | 204 if (ret) { |
265 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n"); 266 goto out; | 205 device_printf(sc->mrsas_dev, "IOCTL copyin failed!\n"); 206 goto out; |
267 } 268 } 269 270 ioctl_sense_size = user_ioc->sense_len; | 207 } 208 } 209 210 ioctl_sense_size = user_ioc->sense_len; |
211 |
|
271 if (user_ioc->sense_len) { 272 if (bus_dma_tag_create( sc->mrsas_parent_tag, // parent 273 1, 0, // algnmnt, boundary 274 BUS_SPACE_MAXADDR_32BIT,// lowaddr 275 BUS_SPACE_MAXADDR, // highaddr 276 NULL, NULL, // filter, filterarg 277 ioctl_sense_size, // maxsize 278 1, // msegments --- 27 unchanged lines hidden (view full) --- 306 cmd->sync_cmd = 1; 307 mrsas_issue_blocked_cmd(sc, cmd); 308 cmd->sync_cmd = 0; 309 310 /* 311 * copy out the kernel buffers to user buffers 312 */ 313 for (i = 0; i < user_ioc->sge_count; i++) { | 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++) { |
314 ret = copyout(ioctl_data_mem[i], user_ioc->sgl[i].iov_base, 315 user_ioc->sgl[i].iov_len); | 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); |
316 if (ret) { 317 device_printf(sc->mrsas_dev, "IOCTL copyout failed!\n"); 318 goto out; 319 } 320 } 321 322 /* 323 * copy out the sense --- 39 unchanged lines hidden (view full) --- 363 if (ioctl_data_phys_addr[i]) 364 bus_dmamap_unload(ioctl_data_tag[i], ioctl_data_dmamap[i]); 365 if (ioctl_data_mem[i] != NULL) 366 bus_dmamem_free(ioctl_data_tag[i], ioctl_data_mem[i], 367 ioctl_data_dmamap[i]); 368 if (ioctl_data_tag[i] != NULL) 369 bus_dma_tag_destroy(ioctl_data_tag[i]); 370 } | 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 } |
371 | |
372 /* Free command */ 373 mrsas_release_mfi_cmd(cmd); 374 375 return(ret); 376} 377 378/** 379 * mrsas_alloc_mfi_cmds: Allocates the command packets --- 167 unchanged lines hidden --- | 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 --- |