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

Commit a932f507 authored by Mike Isely's avatar Mike Isely Committed by Mauro Carvalho Chehab
Browse files

V4L/DVB (11159): pvrusb2: Providing means to stop tracking an old i2c module



This implements a temporary mechanism to "untrack" an i2c module from
the old i2c layer.  The v4l2-subdev related code in the driver will
use this to remove a sub-device from the old i2c layer.  In the end,
once the old i2c layer is removed, this will also eventually go away.

Signed-off-by: default avatarMike Isely <isely@pobox.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent e9c64a78
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2020,6 +2020,12 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
						i2caddr);
	}

	/* If we have both old and new i2c layers enabled, make sure that
	   old layer isn't also tracking this module.  This is a debugging
	   aid, in normal situations there's no reason for both mechanisms
	   to be enabled. */
	pvr2_i2c_untrack_subdev(hdw, sd);

	// ?????
	/* Based on module ID, we should remember subdev pointers
	   so that we can send certain custom commands where
+53 −23
Original line number Diff line number Diff line
@@ -421,13 +421,22 @@ void pvr2_i2c_track_attach_inform(struct i2c_client *client)
	if (fl) queue_work(hdw->workqueue,&hdw->worki2csync);
}

static void pvr2_i2c_client_disconnect(struct pvr2_i2c_client *cp)
{
	if (cp->handler && cp->handler->func_table->detach) {
		cp->handler->func_table->detach(cp->handler->func_data);
	}
	list_del(&cp->list);
	kfree(cp);
}

void pvr2_i2c_track_detach_inform(struct i2c_client *client)
{
	struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
	struct pvr2_i2c_client *cp, *ncp;
	unsigned long amask = 0;
	int foundfl = 0;
	mutex_lock(&hdw->i2c_list_lock); do {
	mutex_lock(&hdw->i2c_list_lock);
	hdw->cropcap_stale = !0;
	list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
		if (cp->client == client) {
@@ -435,27 +444,48 @@ void pvr2_i2c_track_detach_inform(struct i2c_client *client)
				  " [client=%s @ 0x%x ctxt=%p]",
				  client->name,
				  client->addr, cp);
				if (cp->handler &&
				    cp->handler->func_table->detach) {
					cp->handler->func_table->detach(
						cp->handler->func_data);
				}
				list_del(&cp->list);
				kfree(cp);
			pvr2_i2c_client_disconnect(cp);
			foundfl = !0;
			continue;
		}
		amask |= cp->ctl_mask;
	}
	hdw->i2c_active_mask = amask;
	} while (0); mutex_unlock(&hdw->i2c_list_lock);
	mutex_unlock(&hdw->i2c_list_lock);
	if (!foundfl) {
		trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=<unknown>]",
			  client->name,
			  client->addr);
			  client->name, client->addr);
	}
}

/* This function is used to remove an i2c client from our tracking
   structure if the client happens to be the specified v4l2 sub-device.
   The idea here is to ensure that sub-devices are not also tracked with
   the old tracking mechanism - it's one or the other not both.  This is
   only for debugging.  In a "real" environment, only one of these two
   mechanisms should even be compiled in.  But by enabling both we can
   incrementally test control of each sub-device. */
void pvr2_i2c_untrack_subdev(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
{
	struct i2c_client *client;
	struct pvr2_i2c_client *cp, *ncp;
	unsigned long amask = 0;
	mutex_lock(&hdw->i2c_list_lock);
	list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
		client = cp->client;
		if (i2c_get_clientdata(client) == sd) {
			trace_i2c("pvr2_i2c_detach (subdev active)"
				  " [client=%s @ 0x%x ctxt=%p]",
				  client->name, client->addr, cp);
			pvr2_i2c_client_disconnect(cp);
			continue;
		}
		amask |= cp->ctl_mask;
	}
	hdw->i2c_active_mask = amask;
	mutex_unlock(&hdw->i2c_list_lock);
}

void pvr2_i2c_track_init(struct pvr2_hdw *hdw)
{
	hdw->i2c_pend_mask = 0;
+5 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@

#include <linux/list.h>
#include <linux/i2c.h>
#include <media/v4l2-device.h>


struct pvr2_hdw;
struct pvr2_i2c_client;
@@ -83,6 +85,9 @@ unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen);
void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *);
const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx);

void pvr2_i2c_untrack_subdev(struct pvr2_hdw *, struct v4l2_subdev *sd);


#endif /* __PVRUSB2_I2C_CORE_H */