Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 98522a7b authored by Jean-Francois Moine's avatar Jean-Francois Moine Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (9689): gspca: Memory leak when disconnect while streaming.



As a side effect, the sd routine stop0 is called on disconnect.
This permits the subdriver to free its resources.

Signed-off-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 818a557e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -846,10 +846,13 @@ static int sd_start(struct gspca_dev *gspca_dev)
	return 0;
}

/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
	int retry = 50;

	if (!gspca_dev->present)
		return;
	reg_w_val(gspca_dev, 0x0000, 0x00);
	reg_r(gspca_dev, 0x0002, 1);
	reg_w_val(gspca_dev, 0x0053, 0x00);
+8 −0
Original line number Diff line number Diff line
@@ -276,6 +276,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
	/* Stop the state machine */
	if (dev->state != FPIX_NOP)
		wait_for_completion(&dev->can_close);
}

/* called on streamoff with alt 0 and disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
	struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;

	usb_free_urb(dev->control_urb);
	dev->control_urb = NULL;
@@ -385,6 +391,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
error:
	/* Free the ressources */
	sd_stopN(gspca_dev);
	sd_stop0(gspca_dev);
	return ret;
}

@@ -425,6 +432,7 @@ static const struct sd_desc sd_desc = {
	.init = sd_init,
	.start = sd_start,
	.stopN = sd_stopN,
	.stop0 = sd_stop0,
};

/* -- device connect -- */
+8 −9
Original line number Diff line number Diff line
@@ -646,8 +646,8 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
{
	gspca_dev->streaming = 0;
	atomic_set(&gspca_dev->nevent, 0);
	if (gspca_dev->present) {
		if (gspca_dev->sd_desc->stopN)
	if (gspca_dev->present
	    && gspca_dev->sd_desc->stopN)
		gspca_dev->sd_desc->stopN(gspca_dev);
	destroy_urbs(gspca_dev);
	gspca_set_alt0(gspca_dev);
@@ -655,7 +655,6 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
		gspca_dev->sd_desc->stop0(gspca_dev);
	PDEBUG(D_STREAM, "stream off OK");
}
}

static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
{
+1 −1
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ struct sd_desc {
	cam_pkt_op pkt_scan;
/* optional operations */
	cam_v_op stopN;		/* called on stream off - main alt */
	cam_v_op stop0;		/* called on stream off - alt 0 */
	cam_v_op stop0;		/* called on stream off & disconnect - alt 0 */
	cam_v_op dq_callback;	/* called when a frame has been dequeued */
	cam_jpg_op get_jcomp;
	cam_jpg_op set_jcomp;
+3 −0
Original line number Diff line number Diff line
@@ -749,10 +749,13 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
	reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
}

/* called on streamoff with alt 0 and on disconnect */
static void sd_stop0(struct gspca_dev *gspca_dev)
{
	struct sd *sd = (struct sd *) gspca_dev;

	if (!gspca_dev->present)
		return;
	if (sd->sensor == SENSOR_PAC7302) {
		reg_w(gspca_dev, 0xff, 0x01);
		reg_w(gspca_dev, 0x78, 0x40);
Loading