V4L/DVB (8389): videodev: simplify get_index()

Use Hans Verkuil's suggested method of implementing get_index which doesn't
depend on class_for_each_device and instead uses the video_device array. This
simplifies the code and reduces its memory footprint.

Signed-off-by: Brandon Philips <bphilips@suse.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index c24d918..bf12b5f 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -2011,25 +2011,8 @@
 }
 EXPORT_SYMBOL(video_ioctl2);
 
-struct index_info {
-	struct device *dev;
-	unsigned int used[VIDEO_NUM_DEVICES];
-};
-
-static int __fill_index_info(struct device *cd, void *data)
-{
-	struct index_info *info = data;
-	struct video_device *vfd = container_of(cd, struct video_device,
-						class_dev);
-
-	if (info->dev == vfd->dev)
-		info->used[vfd->index] = 1;
-
-	return 0;
-}
-
 /**
- * assign_index - assign stream number based on parent device
+ * get_index - assign stream number based on parent device
  * @vdev: video_device to assign index number to, vdev->dev should be assigned
  * @num: -1 if auto assign, requested number otherwise
  *
@@ -2039,44 +2022,30 @@
  */
 static int get_index(struct video_device *vdev, int num)
 {
-	struct index_info *info;
+	u32 used = 0;
 	int i;
-	int ret = 0;
 
-	if (num >= VIDEO_NUM_DEVICES)
+	if (num >= 32) {
+		printk(KERN_ERR "videodev: %s num is too large\n", __func__);
 		return -EINVAL;
-
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
-
-	info->dev = vdev->dev;
-
-	ret = class_for_each_device(&video_class, info,
-					__fill_index_info);
-
-	if (ret < 0)
-		goto out;
-
-	if (num >= 0) {
-		if (!info->used[num])
-			ret = num;
-		else
-			ret = -ENFILE;
-
-		goto out;
 	}
 
 	for (i = 0; i < VIDEO_NUM_DEVICES; i++) {
-		if (info->used[i])
-			continue;
-		ret = i;
-		goto out;
+		if (video_device[i] != NULL &&
+		    video_device[i] != vdev &&
+		    video_device[i]->dev == vdev->dev) {
+			used |= 1 << video_device[i]->index;
+		}
 	}
 
-out:
-	kfree(info);
-	return ret;
+	if (num >= 0) {
+		if (used & (1 << num))
+			return -ENFILE;
+		return num;
+	}
+
+	i = ffz(used);
+	return i >= 32 ? -ENFILE : i;
 }
 
 static const struct file_operations video_fops;