diff options
Diffstat (limited to 'drivers/media/video/pwc/pwc-if.c')
| -rw-r--r-- | drivers/media/video/pwc/pwc-if.c | 52 | 
1 files changed, 35 insertions, 17 deletions
| diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 9c0e8d18c2f6..3d81966d8c42 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
| @@ -1196,12 +1196,19 @@ static int pwc_video_open(struct inode *inode, struct file *file) | |||
| 1196 | return 0; | 1196 | return 0; | 
| 1197 | } | 1197 | } | 
| 1198 | 1198 | ||
| 1199 | |||
| 1200 | static void pwc_cleanup(struct pwc_device *pdev) | ||
| 1201 | { | ||
| 1202 | pwc_remove_sysfs_files(pdev->vdev); | ||
| 1203 | video_unregister_device(pdev->vdev); | ||
| 1204 | } | ||
| 1205 | |||
| 1199 | /* Note that all cleanup is done in the reverse order as in _open */ | 1206 | /* Note that all cleanup is done in the reverse order as in _open */ | 
| 1200 | static int pwc_video_close(struct inode *inode, struct file *file) | 1207 | static int pwc_video_close(struct inode *inode, struct file *file) | 
| 1201 | { | 1208 | { | 
| 1202 | struct video_device *vdev = file->private_data; | 1209 | struct video_device *vdev = file->private_data; | 
| 1203 | struct pwc_device *pdev; | 1210 | struct pwc_device *pdev; | 
| 1204 | int i; | 1211 | int i, hint; | 
| 1205 | 1212 | ||
| 1206 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); | 1213 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); | 
| 1207 | 1214 | ||
| @@ -1224,8 +1231,9 @@ static int pwc_video_close(struct inode *inode, struct file *file) | |||
| 1224 | pwc_isoc_cleanup(pdev); | 1231 | pwc_isoc_cleanup(pdev); | 
| 1225 | pwc_free_buffers(pdev); | 1232 | pwc_free_buffers(pdev); | 
| 1226 | 1233 | ||
| 1234 | lock_kernel(); | ||
| 1227 | /* Turn off LEDS and power down camera, but only when not unplugged */ | 1235 | /* Turn off LEDS and power down camera, but only when not unplugged */ | 
| 1228 | if (pdev->error_status != EPIPE) { | 1236 | if (!pdev->unplugged) { | 
| 1229 | /* Turn LEDs off */ | 1237 | /* Turn LEDs off */ | 
| 1230 | if (pwc_set_leds(pdev, 0, 0) < 0) | 1238 | if (pwc_set_leds(pdev, 0, 0) < 0) | 
| 1231 | PWC_DEBUG_MODULE("Failed to set LED on/off time.\n"); | 1239 | PWC_DEBUG_MODULE("Failed to set LED on/off time.\n"); | 
| @@ -1234,9 +1242,19 @@ static int pwc_video_close(struct inode *inode, struct file *file) | |||
| 1234 | if (i < 0) | 1242 | if (i < 0) | 
| 1235 | PWC_ERROR("Failed to power down camera (%d)\n", i); | 1243 | PWC_ERROR("Failed to power down camera (%d)\n", i); | 
| 1236 | } | 1244 | } | 
| 1245 | pdev->vopen--; | ||
| 1246 | PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", i); | ||
| 1247 | } else { | ||
| 1248 | pwc_cleanup(pdev); | ||
| 1249 | /* Free memory (don't set pdev to 0 just yet) */ | ||
| 1250 | kfree(pdev); | ||
| 1251 | /* search device_hint[] table if we occupy a slot, by any chance */ | ||
| 1252 | for (hint = 0; hint < MAX_DEV_HINTS; hint++) | ||
| 1253 | if (device_hint[hint].pdev == pdev) | ||
| 1254 | device_hint[hint].pdev = NULL; | ||
| 1237 | } | 1255 | } | 
| 1238 | pdev->vopen--; | 1256 | unlock_kernel(); | 
| 1239 | PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); | 1257 | |
| 1240 | return 0; | 1258 | return 0; | 
| 1241 | } | 1259 | } | 
| 1242 | 1260 | ||
| @@ -1791,21 +1809,21 @@ static void usb_pwc_disconnect(struct usb_interface *intf) | |||
| 1791 | /* Alert waiting processes */ | 1809 | /* Alert waiting processes */ | 
| 1792 | wake_up_interruptible(&pdev->frameq); | 1810 | wake_up_interruptible(&pdev->frameq); | 
| 1793 | /* Wait until device is closed */ | 1811 | /* Wait until device is closed */ | 
| 1794 | while (pdev->vopen) | 1812 | if(pdev->vopen) { | 
| 1795 | schedule(); | 1813 | pdev->unplugged = 1; | 
| 1796 | /* Device is now closed, so we can safely unregister it */ | 1814 | } else { | 
| 1797 | PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); | 1815 | /* Device is closed, so we can safely unregister it */ | 
| 1798 | pwc_remove_sysfs_files(pdev->vdev); | 1816 | PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); | 
| 1799 | video_unregister_device(pdev->vdev); | 1817 | pwc_cleanup(pdev); | 
| 1800 | 1818 | /* Free memory (don't set pdev to 0 just yet) */ | |
| 1801 | /* Free memory (don't set pdev to 0 just yet) */ | 1819 | kfree(pdev); | 
| 1802 | kfree(pdev); | ||
| 1803 | 1820 | ||
| 1804 | disconnect_out: | 1821 | disconnect_out: | 
| 1805 | /* search device_hint[] table if we occupy a slot, by any chance */ | 1822 | /* search device_hint[] table if we occupy a slot, by any chance */ | 
| 1806 | for (hint = 0; hint < MAX_DEV_HINTS; hint++) | 1823 | for (hint = 0; hint < MAX_DEV_HINTS; hint++) | 
| 1807 | if (device_hint[hint].pdev == pdev) | 1824 | if (device_hint[hint].pdev == pdev) | 
| 1808 | device_hint[hint].pdev = NULL; | 1825 | device_hint[hint].pdev = NULL; | 
| 1826 | } | ||
| 1809 | 1827 | ||
| 1810 | unlock_kernel(); | 1828 | unlock_kernel(); | 
| 1811 | } | 1829 | } | 
