On Sun, Feb 15, 2015 at 08:53:08PM +0000, Miod Vallat wrote: > This ought to fix this problem:
This looks reasonable but needs a tweak if you want to keep the existing behavior. In the existing code, it has this section above the copyout(): rw_enter_write(&sc->sc_lock); if (request == SDIOCEXECMMC) error = sdmmc_mmc_command(sc, &cmd); else error = sdmmc_app_command(sc, &cmd); rw_exit(&sc->sc_lock); if (error && !cmd.c_error) cmd.c_error = error; and returns 0 even if error is non-zero. With this diff, it will either return the result of those functions or the result of copyout depending on whether ucmd->c_data is non-zero. Using the result of copyout is intentional, but not the result from sdmmc_{mmc,app}_command(). Could you set error=0 after the above chunk or use a new variable? Also, one of the new lines has space indents rather than a tab. > Index: sdmmc.c > =================================================================== > RCS file: /cvs/src/sys/dev/sdmmc/sdmmc.c,v > retrieving revision 1.36 > diff -u -p -r1.36 sdmmc.c > --- sdmmc.c 1 Nov 2014 16:32:06 -0000 1.36 > +++ sdmmc.c 15 Feb 2015 20:52:08 -0000 > @@ -749,7 +749,7 @@ sdmmc_ioctl(struct device *self, u_long > struct sdmmc_command *ucmd; > struct sdmmc_command cmd; > void *data; > - int error; > + int error = 0; > > switch (request) { > #ifdef SDMMC_DEBUG > @@ -784,8 +784,9 @@ sdmmc_ioctl(struct device *self, u_long > M_WAITOK | M_CANFAIL); > if (data == NULL) > return ENOMEM; > - if (copyin(ucmd->c_data, data, ucmd->c_datalen)) > - return EFAULT; > + error = copyin(ucmd->c_data, data, ucmd->c_datalen); > + if (error != 0) > + goto exec_done; > > cmd.c_data = data; > cmd.c_datalen = ucmd->c_datalen; > @@ -804,10 +805,10 @@ sdmmc_ioctl(struct device *self, u_long > ucmd->c_flags = cmd.c_flags; > ucmd->c_error = cmd.c_error; > > - if (ucmd->c_data && copyout(data, ucmd->c_data, > - ucmd->c_datalen)) > - return EFAULT; > + if (ucmd->c_data) > + error = copyout(data, ucmd->c_data, ucmd->c_datalen); > > +exec_done: > if (ucmd->c_data) > free(data, M_TEMP, 0); > break; > @@ -815,7 +816,7 @@ sdmmc_ioctl(struct device *self, u_long > default: > return ENOTTY; > } > - return 0; > + return error; > } > #endif > >