blob: 01aa2c29fc195e46dd3874f882a7e1a65f2eb688 [file] [log] [blame]
#ifndef __BACKPORT_IDR_H
#define __BACKPORT_IDR_H
/* some versions have a broken idr header */
#include <linux/spinlock.h>
#include_next <linux/idr.h>
#include <linux/version.h>
#if LINUX_VERSION_IS_LESS(3,1,0)
#define ida_simple_get LINUX_BACKPORT(ida_simple_get)
int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
gfp_t gfp_mask);
#define ida_simple_remove LINUX_BACKPORT(ida_simple_remove)
void ida_simple_remove(struct ida *ida, unsigned int id);
#endif
#if LINUX_VERSION_IS_LESS(3,9,0)
#include <linux/errno.h>
/**
* backport of idr idr_alloc() usage
*
* This backports a patch series send by Tejun Heo:
* https://lkml.org/lkml/2013/2/2/159
*/
static inline void compat_idr_destroy(struct idr *idp)
{
idr_remove_all(idp);
idr_destroy(idp);
}
#define idr_destroy(idp) compat_idr_destroy(idp)
static inline int idr_alloc(struct idr *idr, void *ptr, int start, int end,
gfp_t gfp_mask)
{
int id, ret;
do {
if (!idr_pre_get(idr, gfp_mask))
return -ENOMEM;
ret = idr_get_new_above(idr, ptr, start, &id);
if (!ret && id > end) {
idr_remove(idr, id);
ret = -ENOSPC;
}
} while (ret == -EAGAIN);
return ret ? ret : id;
}
static inline void idr_preload(gfp_t gfp_mask)
{
}
static inline void idr_preload_end(void)
{
}
#endif
#ifndef idr_for_each_entry
#define idr_for_each_entry(idp, entry, id) \
for (id = 0; ((entry) = idr_get_next(idp, &(id))) != NULL; ++id)
#endif
#if LINUX_VERSION_IS_LESS(4, 11, 0)
static inline void *backport_idr_remove(struct idr *idr, int id)
{
void *item = idr_find(idr, id);
idr_remove(idr, id);
return item;
}
#define idr_remove backport_idr_remove
#endif
#endif /* __BACKPORT_IDR_H */