bif: bif-core: add BIF object matching support

Update the BIF slave matching criteria so that BIF consumer
drivers can find BIF slaves which contain BIF objects of a
certain type.  Also add functions which allow consumers to get
handles for the BIF objects which match specified search
criteria.

Change-Id: Ice7042ecb3829db8f5601d91940c5f7bef383d3d
Signed-off-by: David Collins <collinsd@codeaurora.org>
This commit is contained in:
David Collins 2013-09-23 11:51:16 -07:00
parent 356ab1e444
commit 5bfb07eada
3 changed files with 251 additions and 15 deletions

View File

@ -235,10 +235,10 @@ registration order.
Get/put handle for a BIF slave:
-------------------------------
int bif_slave_match_count(const struct bif_ctrl *ctrl,
int bif_slave_match_count(struct bif_ctrl *ctrl,
const struct bif_match_criteria *match_criteria);
struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
unsigned int id, const struct bif_match_criteria *match_criteria);
void bif_slave_put(struct bif_slave *slave);
@ -293,7 +293,6 @@ int bif_ctrl_notifier_register(struct bif_ctrl *ctrl,
int bif_ctrl_notifier_unregister(struct bif_ctrl *ctrl,
struct notifier_block *nb);
Read or write BIF slave registers:
----------------------------------
@ -315,6 +314,20 @@ Raw NVM writing may be needed in order to intialize the NVM BIF object list.
However, its use can be dangerous as it can overwrite existing objects in the
list and make the list unparsable.
BIF object search in slave non-volatile memory:
-----------------------------------------------
int bif_object_match_count(struct bif_slave *slave,
const struct bif_obj_match_criteria *match_criteria);
struct bif_object *bif_object_match_get(struct bif_slave *slave,
unsigned int id, const struct bif_obj_match_criteria *match_criteria);
void bif_object_put(struct bif_object *object);
bif_object_match_count() and bif_object_match_get() can be used together in
order to retrieve the set of BIF objects within a slave which match certain
criteria. bif_object_put() is used to free the memory allocated by
bif_object_match_get().
Get or set the BIF bus state or period:
---------------------------------------

View File

@ -1526,16 +1526,29 @@ void bif_ctrl_put(struct bif_ctrl *ctrl)
}
EXPORT_SYMBOL(bif_ctrl_put);
static bool bif_slave_object_match(const struct bif_object *object,
const struct bif_match_criteria *criteria)
{
return (object->type == criteria->obj_type)
&& (object->version == criteria->obj_version
|| !(criteria->match_mask & BIF_MATCH_OBJ_VERSION))
&& (object->manufacturer_id == criteria->obj_manufacturer_id
|| !(criteria->match_mask & BIF_MATCH_OBJ_MANUFACTURER_ID));
}
/*
* Returns true if all parameters are matched, otherwise false.
* function_type and function_version mean that their exists some function in
* the slave which has the specified type and subtype. ctrl == NULL is treated
* as a wildcard.
*/
static bool bif_slave_match(const struct bif_ctrl *ctrl,
static bool bif_slave_match(struct bif_ctrl *ctrl,
struct bif_slave_dev *sdev, const struct bif_match_criteria *criteria)
{
int i, type, version;
struct bif_object *object;
bool function_found = false;
bool object_found = false;
if (ctrl && (ctrl->bdev != sdev->bdev))
return false;
@ -1563,10 +1576,29 @@ static bool bif_slave_match(const struct bif_ctrl *ctrl,
if (type == criteria->function_type &&
(version == criteria->function_version
|| !(criteria->match_mask
& BIF_MATCH_FUNCTION_VERSION)))
return true;
& BIF_MATCH_FUNCTION_VERSION))) {
function_found = true;
break;
}
}
return false;
if (!function_found)
return false;
}
if (criteria->match_mask & BIF_MATCH_OBJ_TYPE) {
if (!sdev->nvm_function)
return false;
bif_ctrl_lock(ctrl);
list_for_each_entry(object, &sdev->nvm_function->object_list,
list) {
if (bif_slave_object_match(object, criteria)) {
object_found = true;
break;
}
}
bif_ctrl_unlock(ctrl);
if (!object_found)
return false;
}
return true;
@ -1579,7 +1611,7 @@ static bool bif_slave_match(const struct bif_ctrl *ctrl,
* @ctrl: BIF controller consumer handle
* @match_criteria: Matching criteria used to filter slaves
*/
int bif_slave_match_count(const struct bif_ctrl *ctrl,
int bif_slave_match_count(struct bif_ctrl *ctrl,
const struct bif_match_criteria *match_criteria)
{
struct bif_slave_dev *sdev;
@ -1610,7 +1642,7 @@ EXPORT_SYMBOL(bif_slave_match_count);
*
* Returns a BIF slave handle if successful or an ERR_PTR if not.
*/
struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
unsigned int id, const struct bif_match_criteria *match_criteria)
{
struct bif_slave_dev *sdev;
@ -1699,6 +1731,135 @@ int bif_slave_find_function(struct bif_slave *slave, u8 function, u8 *version,
}
EXPORT_SYMBOL(bif_slave_find_function);
static bool bif_object_match(const struct bif_object *object,
const struct bif_obj_match_criteria *criteria)
{
return (object->type == criteria->type
|| !(criteria->match_mask & BIF_OBJ_MATCH_TYPE))
&& (object->version == criteria->version
|| !(criteria->match_mask & BIF_OBJ_MATCH_VERSION))
&& (object->manufacturer_id == criteria->manufacturer_id
|| !(criteria->match_mask & BIF_OBJ_MATCH_MANUFACTURER_ID));
}
/**
* bif_object_match_count() - returns the number of objects associated with the
* specified BIF slave which fit the matching criteria
* @slave: BIF slave handle
* @match_criteria: Matching criteria used to filter objects
*/
int bif_object_match_count(struct bif_slave *slave,
const struct bif_obj_match_criteria *match_criteria)
{
struct bif_object *object;
int count = 0;
if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(match_criteria)) {
pr_err("Invalid pointer input.\n");
return -EINVAL;
}
if (!slave->sdev->nvm_function)
return 0;
bif_slave_ctrl_lock(slave);
list_for_each_entry(object, &slave->sdev->nvm_function->object_list,
list) {
if (bif_object_match(object, match_criteria))
count++;
}
bif_slave_ctrl_unlock(slave);
return count;
}
EXPORT_SYMBOL(bif_object_match_count);
/**
* bif_object_match_get() - get a BIF object handle for the id'th object found
* in the non-volatile memory of the specified BIF slave
* which fits the matching criteria
* @slave: BIF slave handle
* @id: Index into the set of matching objects
* @match_criteria: Matching criteria used to filter objects
*
* id must be in range [0, bif_object_match_count(slave, match_criteria) - 1].
*
* Returns a BIF object handle if successful or an ERR_PTR if not. This handle
* must be freed using bif_object_put() when it is no longer needed.
*/
struct bif_object *bif_object_match_get(struct bif_slave *slave,
unsigned int id, const struct bif_obj_match_criteria *match_criteria)
{
struct bif_object *object;
struct bif_object *object_found = NULL;
struct bif_object *object_consumer = ERR_PTR(-ENODEV);
int count = 0;
if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(match_criteria)) {
pr_err("Invalid pointer input.\n");
return ERR_PTR(-EINVAL);
}
if (!slave->sdev->nvm_function)
return object_consumer;
bif_slave_ctrl_lock(slave);
list_for_each_entry(object, &slave->sdev->nvm_function->object_list,
list) {
if (bif_object_match(object, match_criteria))
count++;
if (count == id + 1) {
object_found = object;
break;
}
}
if (object_found) {
object_consumer = kmemdup(object_found,
sizeof(*object_consumer), GFP_KERNEL);
if (!object_consumer) {
pr_err("out of memory\n");
object_consumer = ERR_PTR(-ENOMEM);
goto done;
}
object_consumer->data = kmemdup(object_found->data,
object_found->length - 8, GFP_KERNEL);
if (!object_consumer->data) {
pr_err("out of memory\n");
kfree(object_consumer);
object_consumer = ERR_PTR(-ENOMEM);
goto done;
}
/*
* Use prev pointer in consumer struct to point to original
* struct in the internal linked list.
*/
object_consumer->list.prev = &object_found->list;
}
done:
bif_slave_ctrl_unlock(slave);
return object_consumer;
}
EXPORT_SYMBOL(bif_object_match_get);
/**
* bif_object_put() - frees the memory allocated for a BIF object pointer
* returned by bif_object_match_get()
* @object: BIF object to free
*/
void bif_object_put(struct bif_object *object)
{
if (object)
kfree(object->data);
kfree(object);
}
EXPORT_SYMBOL(bif_object_put);
/**
* bif_slave_read() - read contiguous memory values from a BIF slave
* @slave: BIF slave handle

View File

@ -311,10 +311,11 @@ enum bif_mipi_object_type {
* @type: Object type
* @version: Object version
* @manufacturer_id: Manufacturer ID number allocated by MIPI
* @length: Length of the entire object including header and CRC
* @length: Length of the entire object including header and CRC;
* data length == total length - 8.
* @data: Raw byte data found in the object
* @crc: CRC of the object calculated using CRC-CCITT
* @list: Linked-list connection parameter
* @list: Linked-list connection parameter; internal use only
* @addr: BIF slave address correspond to the start of the object
*
* manufacturer_id == 0x0000 if MIPI type and version.
@ -415,6 +416,9 @@ enum bif_bus_event {
#define BIF_MATCH_FUNCTION_TYPE BIT(2)
#define BIF_MATCH_FUNCTION_VERSION BIT(3)
#define BIF_MATCH_IGNORE_PRESENCE BIT(4)
#define BIF_MATCH_OBJ_TYPE BIT(5)
#define BIF_MATCH_OBJ_VERSION BIT(6)
#define BIF_MATCH_OBJ_MANUFACTURER_ID BIT(7)
/**
* struct bif_match_criteria - specifies the matching criteria that a BIF
@ -431,6 +435,17 @@ enum bif_bus_event {
* @ignore_presence: If true, then slaves that are currently not present
* will be successfully matched against. By default, only
* present slaves can be matched.
* @obj_type: Defines the type of a BIF object found in the
* non-volatile memory of a slave.
* @obj_version: Defines the version of a BIF object found in the
* non-volatile memory of a slave.
* @obj_manufacturer_id: Manufacturer ID of a BIF object found in the
* non-volatile memory of a slave.
*
* If function_type and function_verion are both specified, then they must both
* match for a single BIF function. If obj_type and obj_version or
* obj_manufacturer_id are specified, then all must match for a single BIF
* object.
*/
struct bif_match_criteria {
u32 match_mask;
@ -439,6 +454,34 @@ struct bif_match_criteria {
u8 function_type;
u8 function_version;
bool ignore_presence;
u8 obj_type;
u8 obj_version;
u16 obj_manufacturer_id;
};
/* Mask values to be ORed for use in bif_obj_match_criteria.match_mask. */
#define BIF_OBJ_MATCH_TYPE BIT(0)
#define BIF_OBJ_MATCH_VERSION BIT(1)
#define BIF_OBJ_MATCH_MANUFACTURER_ID BIT(2)
/**
* struct bif_obj_match_criteria - specifies the matching criteria that a BIF
* consumer uses to find an appropriate BIF data object
* within a slave
* @match_mask: Mask value specifying which parameters to match upon.
* This value should be some ORed combination of
* BIF_OBJ_MATCH_* specified above.
* @type: Defines the type of the object. The type may be either
* MIPI or manufacturer defined.
* @version: Defines the version of the object. The version may be
* either MIPI or manufacturer defined.
* @manufacturer_id: Manufacturer ID number allocated by MIPI.
*/
struct bif_obj_match_criteria {
u32 match_mask;
u8 type;
u8 version;
u16 manufacturer_id;
};
/**
@ -486,10 +529,10 @@ void bif_ctrl_put(struct bif_ctrl *ctrl);
int bif_ctrl_signal_battery_changed(struct bif_ctrl *ctrl);
int bif_slave_match_count(const struct bif_ctrl *ctrl,
int bif_slave_match_count(struct bif_ctrl *ctrl,
const struct bif_match_criteria *match_criteria);
struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
unsigned int id, const struct bif_match_criteria *match_criteria);
void bif_slave_put(struct bif_slave *slave);
@ -505,6 +548,14 @@ struct bif_ctrl *bif_get_ctrl_handle(struct bif_slave *slave);
int bif_slave_find_function(struct bif_slave *slave, u8 function, u8 *version,
u16 *function_pointer);
int bif_object_match_count(struct bif_slave *slave,
const struct bif_obj_match_criteria *match_criteria);
struct bif_object *bif_object_match_get(struct bif_slave *slave,
unsigned int id, const struct bif_obj_match_criteria *match_criteria);
void bif_object_put(struct bif_object *object);
int bif_slave_read(struct bif_slave *slave, u16 addr, u8 *buf, int len);
int bif_slave_write(struct bif_slave *slave, u16 addr, u8 *buf, int len);
@ -563,11 +614,11 @@ static inline void bif_ctrl_put(struct bif_ctrl *ctrl) { return; }
static inline int bif_ctrl_signal_battery_changed(struct bif_ctrl *ctrl)
{ return -EPERM; }
static inline int bif_slave_match_count(const struct bif_ctrl *ctrl,
static inline int bif_slave_match_count(struct bif_ctrl *ctrl,
const struct bif_match_criteria *match_criteria)
{ return -EPERM; }
static inline struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
static inline struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
unsigned int id, const struct bif_match_criteria *match_criteria)
{ return ERR_PTR(-EPERM); }
@ -588,6 +639,17 @@ static inline int bif_slave_find_function(struct bif_slave *slave, u8 function,
u8 *version, u16 *function_pointer)
{ return -EPERM; }
static inline int bif_object_match_count(struct bif_slave *slave,
const struct bif_obj_match_criteria *match_criteria)
{ return -EPERM; }
static inline struct bif_object *bif_object_match_get(struct bif_slave *slave,
unsigned int id, const struct bif_obj_match_criteria *match_criteria)
{ return ERR_PTR(-EPERM); }
static inline void bif_object_put(struct bif_object *object)
{}
static inline int bif_slave_read(struct bif_slave *slave, u16 addr, u8 *buf,
int len)
{ return -EPERM; }