]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - drivers/mtd/mtdcore.c
MTD: Add MTD paritioning infrastructure
[karo-tx-uboot.git] / drivers / mtd / mtdcore.c
1 /*
2  * Core registration and callback routines for MTD
3  * drivers and users.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9
10 #include <linux/mtd/mtd.h>
11 #include <linux/mtd/compat.h>
12 #include <ubi_uboot.h>
13
14 struct mtd_info *mtd_table[MAX_MTD_DEVICES];
15
16 int add_mtd_device(struct mtd_info *mtd)
17 {
18         int i;
19
20         BUG_ON(mtd->writesize == 0);
21
22         for (i = 0; i < MAX_MTD_DEVICES; i++)
23                 if (!mtd_table[i]) {
24                         mtd_table[i] = mtd;
25                         mtd->index = i;
26                         mtd->usecount = 0;
27
28                         printf("mtd: Giving out device %d to %s\n",
29                                 i, mtd->name);
30                         /* No need to get a refcount on the module containing
31                            the notifier, since we hold the mtd_table_mutex */
32
33                         /* We _know_ we aren't being removed, because
34                            our caller is still holding us here. So none
35                            of this try_ nonsense, and no bitching about it
36                            either. :) */
37                         return 0;
38                 }
39
40         return 1;
41 }
42
43 /**
44  *      del_mtd_device - unregister an MTD device
45  *      @mtd: pointer to MTD device info structure
46  *
47  *      Remove a device from the list of MTD devices present in the system,
48  *      and notify each currently active MTD 'user' of its departure.
49  *      Returns zero on success or 1 on failure, which currently will happen
50  *      if the requested device does not appear to be present in the list.
51  */
52 int del_mtd_device(struct mtd_info *mtd)
53 {
54         int ret;
55
56         if (mtd_table[mtd->index] != mtd) {
57                 ret = -ENODEV;
58         } else if (mtd->usecount) {
59                 printk(KERN_NOTICE "Removing MTD device #%d (%s)"
60                                 " with use count %d\n",
61                                 mtd->index, mtd->name, mtd->usecount);
62                 ret = -EBUSY;
63         } else {
64                 /* No need to get a refcount on the module containing
65                  * the notifier, since we hold the mtd_table_mutex */
66                 mtd_table[mtd->index] = NULL;
67
68                 ret = 0;
69         }
70
71         return ret;
72 }
73
74 /**
75  *      get_mtd_device - obtain a validated handle for an MTD device
76  *      @mtd: last known address of the required MTD device
77  *      @num: internal device number of the required MTD device
78  *
79  *      Given a number and NULL address, return the num'th entry in the device
80  *      table, if any.  Given an address and num == -1, search the device table
81  *      for a device with that address and return if it's still present. Given
82  *      both, return the num'th driver only if its address matches. Return
83  *      error code if not.
84  */
85 struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
86 {
87         struct mtd_info *ret = NULL;
88         int i, err = -ENODEV;
89
90         if (num == -1) {
91                 for (i = 0; i < MAX_MTD_DEVICES; i++)
92                         if (mtd_table[i] == mtd)
93                                 ret = mtd_table[i];
94         } else if (num < MAX_MTD_DEVICES) {
95                 ret = mtd_table[num];
96                 if (mtd && mtd != ret)
97                         ret = NULL;
98         }
99
100         if (!ret)
101                 goto out_unlock;
102
103         ret->usecount++;
104         return ret;
105
106 out_unlock:
107         return ERR_PTR(err);
108 }
109
110 /**
111  *      get_mtd_device_nm - obtain a validated handle for an MTD device by
112  *      device name
113  *      @name: MTD device name to open
114  *
115  *      This function returns MTD device description structure in case of
116  *      success and an error code in case of failure.
117  */
118 struct mtd_info *get_mtd_device_nm(const char *name)
119 {
120         int i, err = -ENODEV;
121         struct mtd_info *mtd = NULL;
122
123         for (i = 0; i < MAX_MTD_DEVICES; i++) {
124                 if (mtd_table[i] && !strcmp(name, mtd_table[i]->name)) {
125                         mtd = mtd_table[i];
126                         break;
127                 }
128         }
129
130         if (!mtd)
131                 goto out_unlock;
132
133         mtd->usecount++;
134         return mtd;
135
136 out_unlock:
137         return ERR_PTR(err);
138 }
139
140 void put_mtd_device(struct mtd_info *mtd)
141 {
142         int c;
143
144         c = --mtd->usecount;
145         BUG_ON(c < 0);
146 }