From 3c2a0865d06df23f755a7d36a1076965500e1228 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:41:52 -0300 Subject: V4L/DVB (7134): tuner: create a macro for sharing state between hybrid tuner instances Create a macro implementing a standard method to share state amongst multiple instances of a hybrid tuner object. Also, prepare tuner_foo printk macros for the removal of PREFIX Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-i2c.h | 112 ++++++++++++++++++++++++++++++++++------ 1 file changed, 96 insertions(+), 16 deletions(-) diff --git a/drivers/media/video/tuner-i2c.h b/drivers/media/video/tuner-i2c.h index de52e8ffd34..8ec5b41d459 100644 --- a/drivers/media/video/tuner-i2c.h +++ b/drivers/media/video/tuner-i2c.h @@ -26,6 +26,10 @@ struct tuner_i2c_props { u8 addr; struct i2c_adapter *adap; + + /* used for tuner instance management */ + int count; + char *name; }; static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len) @@ -59,29 +63,105 @@ static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, return (ret == 2) ? ilen : ret; } -#define tuner_warn(fmt, arg...) do { \ - printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr, ##arg); \ +/* Callers must declare as a global for the module: + * + * static LIST_HEAD(hybrid_tuner_instance_list); + * + * hybrid_tuner_instance_list should be the third argument + * passed into hybrid_tuner_request_state(). + * + * state structure must contain the following: + * + * struct list_head hybrid_tuner_instance_list; + * struct tuner_i2c_props i2c_props; + * + * hybrid_tuner_instance_list (both within state structure and globally) + * is only required if the driver is using hybrid_tuner_request_state + * and hybrid_tuner_release_state to manage state sharing between + * multiple instances of hybrid tuners. + */ + +#define tuner_printk(kernlvl, i2cprops, fmt, arg...) do { \ + printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name, \ + i2c_adapter_id(i2cprops.adap), \ + i2cprops.addr, ##arg); \ } while (0) -#define tuner_info(fmt, arg...) do { \ - printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ +/* TO DO: convert all callers of these macros to pass in + * struct tuner_i2c_props, then remove the macro wrappers */ + +#define __tuner_warn(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg); \ } while (0) -#define tuner_err(fmt, arg...) do { \ - printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ +#define __tuner_info(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_INFO, i2cprops, fmt, ##arg); \ } while (0) -#define tuner_dbg(fmt, arg...) do { \ +#define __tuner_err(i2cprops, fmt, arg...) do { \ + tuner_printk(KERN_ERR, i2cprops, fmt, ##arg); \ + } while (0) + +#define __tuner_dbg(i2cprops, fmt, arg...) do { \ if ((debug)) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX, \ - i2c_adapter_id(priv->i2c_props.adap), \ - priv->i2c_props.addr , ##arg); \ + tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg); \ } while (0) +#define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg) +#define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg) +#define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg) +#define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg) + +/****************************************************************************/ + +/* The return value of hybrid_tuner_request_state indicates the number of + * instances using this tuner object. + * + * 0 - no instances, indicates an error - kzalloc must have failed + * + * 1 - one instance, indicates that the tuner object was created successfully + * + * 2 (or more) instances, indicates that an existing tuner object was found + */ + +#define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\ +({ \ + int __ret = 0; \ + list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \ + if ((i2c_adapter_id(state->i2c_props.adap) == \ + i2c_adapter_id(i2cadap)) && \ + (state->i2c_props.addr == i2caddr)) { \ + __tuner_info(state->i2c_props, \ + "attaching existing instance\n"); \ + state->i2c_props.count++; \ + __ret = state->i2c_props.count; \ + break; \ + } \ + } \ + if (0 == __ret) { \ + state = kzalloc(sizeof(type), GFP_KERNEL); \ + if (NULL == state) \ + goto __fail; \ + state->i2c_props.addr = i2caddr; \ + state->i2c_props.adap = i2cadap; \ + state->i2c_props.name = devname; \ + __tuner_info(state->i2c_props, \ + "creating new instance\n"); \ + list_add_tail(&state->hybrid_tuner_instance_list, &list);\ + state->i2c_props.count++; \ + __ret = state->i2c_props.count; \ + } \ +__fail: \ + __ret; \ +}) + +#define hybrid_tuner_release_state(state) do { \ + state->i2c_props.count--; \ + if (!state->i2c_props.count) { \ + __tuner_info(state->i2c_props, "destroying instance\n");\ + list_del(&state->hybrid_tuner_instance_list); \ + kfree(state); \ + } \ +} while (0) + #endif /* __TUNER_I2C_H__ */ -- cgit v1.2.3