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: Mike Isely <isely@pobox.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
e9c64a78db
commit
a932f50746
@@ -2020,6 +2020,12 @@ static void pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
|
|||||||
i2caddr);
|
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
|
/* Based on module ID, we should remember subdev pointers
|
||||||
so that we can send certain custom commands where
|
so that we can send certain custom commands where
|
||||||
|
@@ -421,41 +421,71 @@ void pvr2_i2c_track_attach_inform(struct i2c_client *client)
|
|||||||
if (fl) queue_work(hdw->workqueue,&hdw->worki2csync);
|
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)
|
void pvr2_i2c_track_detach_inform(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
|
struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
|
||||||
struct pvr2_i2c_client *cp, *ncp;
|
struct pvr2_i2c_client *cp, *ncp;
|
||||||
unsigned long amask = 0;
|
unsigned long amask = 0;
|
||||||
int foundfl = 0;
|
int foundfl = 0;
|
||||||
mutex_lock(&hdw->i2c_list_lock); do {
|
mutex_lock(&hdw->i2c_list_lock);
|
||||||
hdw->cropcap_stale = !0;
|
hdw->cropcap_stale = !0;
|
||||||
list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
|
list_for_each_entry_safe(cp, ncp, &hdw->i2c_clients, list) {
|
||||||
if (cp->client == client) {
|
if (cp->client == client) {
|
||||||
trace_i2c("pvr2_i2c_detach"
|
trace_i2c("pvr2_i2c_detach"
|
||||||
" [client=%s @ 0x%x ctxt=%p]",
|
" [client=%s @ 0x%x ctxt=%p]",
|
||||||
client->name,
|
client->name,
|
||||||
client->addr,cp);
|
client->addr, cp);
|
||||||
if (cp->handler &&
|
pvr2_i2c_client_disconnect(cp);
|
||||||
cp->handler->func_table->detach) {
|
foundfl = !0;
|
||||||
cp->handler->func_table->detach(
|
continue;
|
||||||
cp->handler->func_data);
|
|
||||||
}
|
|
||||||
list_del(&cp->list);
|
|
||||||
kfree(cp);
|
|
||||||
foundfl = !0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
amask |= cp->ctl_mask;
|
|
||||||
}
|
}
|
||||||
hdw->i2c_active_mask = amask;
|
amask |= cp->ctl_mask;
|
||||||
} while (0); mutex_unlock(&hdw->i2c_list_lock);
|
}
|
||||||
|
hdw->i2c_active_mask = amask;
|
||||||
|
mutex_unlock(&hdw->i2c_list_lock);
|
||||||
if (!foundfl) {
|
if (!foundfl) {
|
||||||
trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=<unknown>]",
|
trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=<unknown>]",
|
||||||
client->name,
|
client->name, client->addr);
|
||||||
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)
|
void pvr2_i2c_track_init(struct pvr2_hdw *hdw)
|
||||||
{
|
{
|
||||||
hdw->i2c_pend_mask = 0;
|
hdw->i2c_pend_mask = 0;
|
||||||
|
@@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
|
#include <media/v4l2-device.h>
|
||||||
|
|
||||||
|
|
||||||
struct pvr2_hdw;
|
struct pvr2_hdw;
|
||||||
struct pvr2_i2c_client;
|
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 *);
|
void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *);
|
||||||
const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx);
|
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 */
|
#endif /* __PVRUSB2_I2C_CORE_H */
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user