Module: xenomai-abe Branch: analogy Commit: cf02a8150301897faa20cfb3e34b453e35ed083f URL: http://git.xenomai.org/?p=xenomai-abe.git;a=commit;h=cf02a8150301897faa20cfb3e34b453e35ed083f
Author: Alexis Berlemont <alexis.berlem...@gmail.com> Date: Tue Feb 9 00:40:51 2010 +0100 analogy: improve robustness of the detach procedure If a subdevice was busy because of an acquisition, the detach procedure failed and left the device in an incoherent state which needed reboot. This bug was fixed by adding a pre-cleanup function which tests subdevices' status. --- include/analogy/transfer.h | 2 + ksrc/drivers/analogy/device.c | 13 ++++++--- ksrc/drivers/analogy/transfer.c | 53 ++++++++++++++++++++++++++++++-------- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/include/analogy/transfer.h b/include/analogy/transfer.h index e50d574..3d44ac6 100644 --- a/include/analogy/transfer.h +++ b/include/analogy/transfer.h @@ -33,6 +33,7 @@ #define A4L_TSF_BUSY 0 #define A4L_TSF_BULK 1 #define A4L_TSF_MMAP 2 +#define A4L_TSF_CLEAN 3 /* Fields init values */ #define A4L_IRQ_UNUSED (unsigned int)((unsigned short)(~0)) @@ -81,6 +82,7 @@ int a4l_rdproc_transfer(char *page, void a4l_presetup_transfer(a4l_cxt_t * cxt); int a4l_setup_transfer(a4l_cxt_t * cxt); +int a4l_precleanup_transfer(a4l_cxt_t * cxt); int a4l_cleanup_transfer(a4l_cxt_t * cxt); int a4l_reserve_transfer(a4l_cxt_t * cxt, int idx_subd); int a4l_init_transfer(a4l_cxt_t * cxt, a4l_cmd_t * cmd); diff --git a/ksrc/drivers/analogy/device.c b/ksrc/drivers/analogy/device.c index 1b7a012..cd586f7 100644 --- a/ksrc/drivers/analogy/device.c +++ b/ksrc/drivers/analogy/device.c @@ -432,18 +432,21 @@ int a4l_ioctl_devcfg(a4l_cxt_t * cxt, void *arg) if (arg == NULL) { /* Basic checking */ - if (!test_bit - (A4L_DEV_ATTACHED, &(a4l_get_dev(cxt)->flags))) { + if (!test_bit(A4L_DEV_ATTACHED, &(a4l_get_dev(cxt)->flags))) { __a4l_err("a4l_ioctl_devcfg: " "free device, no driver to detach\n"); return -EINVAL; } - /* Removes the related proc file */ + /* Pre-cleanup of the transfer structure, we ensure + that nothing is busy */ + if ((ret = a4l_precleanup_transfer(cxt)) != 0) + return ret; + /* Remove the related proc file */ a4l_proc_detach(cxt); - /* Frees the transfer structure and its related data */ + /* Free the transfer structure and its related data */ if ((ret = a4l_cleanup_transfer(cxt)) != 0) return ret; - /* Frees the device and the driver from each other */ + /* Free the device and the driver from each other */ if ((ret = a4l_device_detach(cxt)) == 0) clear_bit(A4L_DEV_ATTACHED, &(a4l_get_dev(cxt)->flags)); diff --git a/ksrc/drivers/analogy/transfer.c b/ksrc/drivers/analogy/transfer.c index b2c91bd..5239d08 100644 --- a/ksrc/drivers/analogy/transfer.c +++ b/ksrc/drivers/analogy/transfer.c @@ -33,39 +33,70 @@ /* --- Initialization / cleanup / cancel functions --- */ -int a4l_cleanup_transfer(a4l_cxt_t * cxt) +int a4l_precleanup_transfer(a4l_cxt_t * cxt) { a4l_dev_t *dev; a4l_trf_t *tsf; - int i; + int i, err = 0; __a4l_dbg(1, core_dbg, - "a4l_cleanup_transfer: minor=%d\n", + "a4l_precleanup_transfer: minor=%d\n", a4l_get_minor(cxt)); dev = a4l_get_dev(cxt); tsf = &dev->transfer; if (tsf == NULL) { - __a4l_err("a4l_cleanup_transfer: " + __a4l_err("a4l_precleanup_transfer: " "incoherent status, transfer block not reachable\n"); return -ENODEV; } for (i = 0; i < tsf->nb_subd; i++) { - if (test_bit(A4L_TSF_BUSY, &(tsf->status[i]))) { - __a4l_err("a4l_cleanup_transfer: " - "device busy, acquisition occuring\n"); - return -EBUSY; - } if (test_bit(A4L_TSF_MMAP, &(tsf->status[i]))) { - __a4l_err("a4l_cleanup_transfer: " + __a4l_err("a4l_precleanup_transfer: " "device busy, buffer must be unmapped\n"); - return -EPERM; + err = -EPERM; + goto out_error; } + + if (test_and_set_bit(A4L_TSF_BUSY, &(tsf->status[i]))) { + __a4l_err("a4l_precleanup_transfer: " + "device busy, acquisition occuring\n"); + err = -EBUSY; + goto out_error; + } else + set_bit(A4L_TSF_CLEAN, &(tsf->status[i])); } + return 0; + +out_error: + for (i = 0; i < tsf->nb_subd; i++) { + + if (test_bit(A4L_TSF_CLEAN, &(tsf->status[i]))){ + clear_bit(A4L_TSF_BUSY, &(tsf->status[i])); + clear_bit(A4L_TSF_CLEAN, &(tsf->status[i])); + } + } + + return err; +} + +int a4l_cleanup_transfer(a4l_cxt_t * cxt) +{ + a4l_dev_t *dev; + a4l_trf_t *tsf; + int i; + + __a4l_dbg(1, core_dbg, + "a4l_cleanup_transfer: minor=%d\n", + a4l_get_minor(cxt)); + + dev = a4l_get_dev(cxt); + tsf = &dev->transfer; + /* Releases the various buffers */ if (tsf->status != NULL) rtdm_free(tsf->status); _______________________________________________ Xenomai-git mailing list Xenomai-git@gna.org https://mail.gna.org/listinfo/xenomai-git