mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-07 23:28:55 +00:00
mtd: Replace static array of devices with an idr structure
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
4d1ee80f3a
commit
b520e412fa
3 changed files with 74 additions and 76 deletions
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/mtd/compatmac.h>
|
#include <linux/mtd/compatmac.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
|
#include <linux/idr.h>
|
||||||
|
|
||||||
#include <linux/mtd/mtd.h>
|
#include <linux/mtd/mtd.h>
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
@ -33,13 +34,18 @@ static struct class mtd_class = {
|
||||||
.resume = mtd_cls_resume,
|
.resume = mtd_cls_resume,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static DEFINE_IDR(mtd_idr);
|
||||||
|
|
||||||
/* These are exported solely for the purpose of mtd_blkdevs.c. You
|
/* These are exported solely for the purpose of mtd_blkdevs.c. You
|
||||||
should not use them for _anything_ else */
|
should not use them for _anything_ else */
|
||||||
DEFINE_MUTEX(mtd_table_mutex);
|
DEFINE_MUTEX(mtd_table_mutex);
|
||||||
struct mtd_info *mtd_table[MAX_MTD_DEVICES];
|
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(mtd_table_mutex);
|
EXPORT_SYMBOL_GPL(mtd_table_mutex);
|
||||||
EXPORT_SYMBOL_GPL(mtd_table);
|
|
||||||
|
struct mtd_info *__mtd_next_device(int i)
|
||||||
|
{
|
||||||
|
return idr_get_next(&mtd_idr, &i);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(__mtd_next_device);
|
||||||
|
|
||||||
static LIST_HEAD(mtd_notifiers);
|
static LIST_HEAD(mtd_notifiers);
|
||||||
|
|
||||||
|
@ -235,13 +241,13 @@ static struct device_type mtd_devtype = {
|
||||||
* Add a device to the list of MTD devices present in the system, and
|
* Add a device to the list of MTD devices present in the system, and
|
||||||
* notify each currently active MTD 'user' of its arrival. Returns
|
* notify each currently active MTD 'user' of its arrival. Returns
|
||||||
* zero on success or 1 on failure, which currently will only happen
|
* zero on success or 1 on failure, which currently will only happen
|
||||||
* if the number of present devices exceeds MAX_MTD_DEVICES (i.e. 16)
|
* if there is insufficient memory or a sysfs error.
|
||||||
* or there's a sysfs error.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int add_mtd_device(struct mtd_info *mtd)
|
int add_mtd_device(struct mtd_info *mtd)
|
||||||
{
|
{
|
||||||
int i;
|
struct mtd_notifier *not;
|
||||||
|
int i, error;
|
||||||
|
|
||||||
if (!mtd->backing_dev_info) {
|
if (!mtd->backing_dev_info) {
|
||||||
switch (mtd->type) {
|
switch (mtd->type) {
|
||||||
|
@ -260,70 +266,73 @@ int add_mtd_device(struct mtd_info *mtd)
|
||||||
BUG_ON(mtd->writesize == 0);
|
BUG_ON(mtd->writesize == 0);
|
||||||
mutex_lock(&mtd_table_mutex);
|
mutex_lock(&mtd_table_mutex);
|
||||||
|
|
||||||
for (i=0; i < MAX_MTD_DEVICES; i++)
|
do {
|
||||||
if (!mtd_table[i]) {
|
if (!idr_pre_get(&mtd_idr, GFP_KERNEL))
|
||||||
struct mtd_notifier *not;
|
goto fail_locked;
|
||||||
|
error = idr_get_new(&mtd_idr, mtd, &i);
|
||||||
|
} while (error == -EAGAIN);
|
||||||
|
|
||||||
mtd_table[i] = mtd;
|
if (error)
|
||||||
mtd->index = i;
|
goto fail_locked;
|
||||||
mtd->usecount = 0;
|
|
||||||
|
|
||||||
if (is_power_of_2(mtd->erasesize))
|
mtd->index = i;
|
||||||
mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
|
mtd->usecount = 0;
|
||||||
else
|
|
||||||
mtd->erasesize_shift = 0;
|
|
||||||
|
|
||||||
if (is_power_of_2(mtd->writesize))
|
if (is_power_of_2(mtd->erasesize))
|
||||||
mtd->writesize_shift = ffs(mtd->writesize) - 1;
|
mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
|
||||||
else
|
else
|
||||||
mtd->writesize_shift = 0;
|
mtd->erasesize_shift = 0;
|
||||||
|
|
||||||
mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
|
if (is_power_of_2(mtd->writesize))
|
||||||
mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
|
mtd->writesize_shift = ffs(mtd->writesize) - 1;
|
||||||
|
else
|
||||||
|
mtd->writesize_shift = 0;
|
||||||
|
|
||||||
/* Some chips always power up locked. Unlock them now */
|
mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
|
||||||
if ((mtd->flags & MTD_WRITEABLE)
|
mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
|
||||||
&& (mtd->flags & MTD_POWERUP_LOCK) && mtd->unlock) {
|
|
||||||
if (mtd->unlock(mtd, 0, mtd->size))
|
|
||||||
printk(KERN_WARNING
|
|
||||||
"%s: unlock failed, "
|
|
||||||
"writes may not work\n",
|
|
||||||
mtd->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Caller should have set dev.parent to match the
|
/* Some chips always power up locked. Unlock them now */
|
||||||
* physical device.
|
if ((mtd->flags & MTD_WRITEABLE)
|
||||||
*/
|
&& (mtd->flags & MTD_POWERUP_LOCK) && mtd->unlock) {
|
||||||
mtd->dev.type = &mtd_devtype;
|
if (mtd->unlock(mtd, 0, mtd->size))
|
||||||
mtd->dev.class = &mtd_class;
|
printk(KERN_WARNING
|
||||||
mtd->dev.devt = MTD_DEVT(i);
|
"%s: unlock failed, writes may not work\n",
|
||||||
dev_set_name(&mtd->dev, "mtd%d", i);
|
mtd->name);
|
||||||
dev_set_drvdata(&mtd->dev, mtd);
|
}
|
||||||
if (device_register(&mtd->dev) != 0) {
|
|
||||||
mtd_table[i] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MTD_DEVT(i))
|
/* Caller should have set dev.parent to match the
|
||||||
device_create(&mtd_class, mtd->dev.parent,
|
* physical device.
|
||||||
MTD_DEVT(i) + 1,
|
*/
|
||||||
NULL, "mtd%dro", i);
|
mtd->dev.type = &mtd_devtype;
|
||||||
|
mtd->dev.class = &mtd_class;
|
||||||
|
mtd->dev.devt = MTD_DEVT(i);
|
||||||
|
dev_set_name(&mtd->dev, "mtd%d", i);
|
||||||
|
dev_set_drvdata(&mtd->dev, mtd);
|
||||||
|
if (device_register(&mtd->dev) != 0)
|
||||||
|
goto fail_added;
|
||||||
|
|
||||||
DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name);
|
if (MTD_DEVT(i))
|
||||||
/* No need to get a refcount on the module containing
|
device_create(&mtd_class, mtd->dev.parent,
|
||||||
the notifier, since we hold the mtd_table_mutex */
|
MTD_DEVT(i) + 1,
|
||||||
list_for_each_entry(not, &mtd_notifiers, list)
|
NULL, "mtd%dro", i);
|
||||||
not->add(mtd);
|
|
||||||
|
|
||||||
mutex_unlock(&mtd_table_mutex);
|
DEBUG(0, "mtd: Giving out device %d to %s\n", i, mtd->name);
|
||||||
/* We _know_ we aren't being removed, because
|
/* No need to get a refcount on the module containing
|
||||||
our caller is still holding us here. So none
|
the notifier, since we hold the mtd_table_mutex */
|
||||||
of this try_ nonsense, and no bitching about it
|
list_for_each_entry(not, &mtd_notifiers, list)
|
||||||
either. :) */
|
not->add(mtd);
|
||||||
__module_get(THIS_MODULE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
mutex_unlock(&mtd_table_mutex);
|
||||||
|
/* We _know_ we aren't being removed, because
|
||||||
|
our caller is still holding us here. So none
|
||||||
|
of this try_ nonsense, and no bitching about it
|
||||||
|
either. :) */
|
||||||
|
__module_get(THIS_MODULE);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail_added:
|
||||||
|
idr_remove(&mtd_idr, i);
|
||||||
|
fail_locked:
|
||||||
mutex_unlock(&mtd_table_mutex);
|
mutex_unlock(&mtd_table_mutex);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -344,7 +353,7 @@ int del_mtd_device (struct mtd_info *mtd)
|
||||||
|
|
||||||
mutex_lock(&mtd_table_mutex);
|
mutex_lock(&mtd_table_mutex);
|
||||||
|
|
||||||
if (mtd_table[mtd->index] != mtd) {
|
if (idr_find(&mtd_idr, mtd->index) != mtd) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
} else if (mtd->usecount) {
|
} else if (mtd->usecount) {
|
||||||
printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n",
|
printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n",
|
||||||
|
@ -360,7 +369,7 @@ int del_mtd_device (struct mtd_info *mtd)
|
||||||
list_for_each_entry(not, &mtd_notifiers, list)
|
list_for_each_entry(not, &mtd_notifiers, list)
|
||||||
not->remove(mtd);
|
not->remove(mtd);
|
||||||
|
|
||||||
mtd_table[mtd->index] = NULL;
|
idr_remove(&mtd_idr, mtd->index);
|
||||||
|
|
||||||
module_put(THIS_MODULE);
|
module_put(THIS_MODULE);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -448,8 +457,8 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (num >= 0 && num < MAX_MTD_DEVICES) {
|
} else if (num >= 0) {
|
||||||
ret = mtd_table[num];
|
ret = idr_find(&mtd_idr, num);
|
||||||
if (mtd && mtd != ret)
|
if (mtd && mtd != ret)
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,7 @@
|
||||||
should not use them for _anything_ else */
|
should not use them for _anything_ else */
|
||||||
|
|
||||||
extern struct mutex mtd_table_mutex;
|
extern struct mutex mtd_table_mutex;
|
||||||
extern struct mtd_info *mtd_table[MAX_MTD_DEVICES];
|
extern struct mtd_info *__mtd_next_device(int i);
|
||||||
|
|
||||||
static inline struct mtd_info *__mtd_next_device(int i)
|
|
||||||
{
|
|
||||||
while (i < MAX_MTD_DEVICES) {
|
|
||||||
if (mtd_table[i])
|
|
||||||
return mtd_table[i];
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define mtd_for_each_device(mtd) \
|
#define mtd_for_each_device(mtd) \
|
||||||
for ((mtd) = __mtd_next_device(0); \
|
for ((mtd) = __mtd_next_device(0); \
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
#define MTD_CHAR_MAJOR 90
|
#define MTD_CHAR_MAJOR 90
|
||||||
#define MTD_BLOCK_MAJOR 31
|
#define MTD_BLOCK_MAJOR 31
|
||||||
#define MAX_MTD_DEVICES 32
|
|
||||||
|
|
||||||
#define MTD_ERASE_PENDING 0x01
|
#define MTD_ERASE_PENDING 0x01
|
||||||
#define MTD_ERASING 0x02
|
#define MTD_ERASING 0x02
|
||||||
|
|
Loading…
Add table
Reference in a new issue