aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiquel Raynal <miquel.raynal@bootlin.com>2018-07-14 08:42:00 -0400
committerBoris Brezillon <boris.brezillon@bootlin.com>2018-07-18 10:44:03 -0400
commit89fd23efa0d7934ed9ec93c77486a047759d6543 (patch)
tree11b41cd18ba7b52650af60dfa380ec27c165594e
parent5f7a01e222635cba7e4889ad4ebd891835e8b2eb (diff)
mtd: Fallback to ->_read/write() when ->_read/write_oob() is missing
Some MTD sublayers/drivers are implementing ->_read/write() and not ->_read/write_oob(). While for NAND devices both are usually valid, for NOR devices, using the _oob variant has no real meaning. But, as the MTD layer is supposed to hide as much as possible the flash complexity to the user, there is no reason to error out while it is just a matter of rewritting things internally. Add a fallback on mtd->_read() (resp. mtd->_write()) when the user calls mtd_read_oob() (resp. mtd_write_oob()) while mtd->_read_oob() (resp. mtd->_write_oob) is not implemented. There is already a fallback on the _oob variant if the former is used. Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-rw-r--r--drivers/mtd/mtdcore.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 42395df06be9..97ac219c082e 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1155,21 +1155,29 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
1155{ 1155{
1156 int ret_code; 1156 int ret_code;
1157 ops->retlen = ops->oobretlen = 0; 1157 ops->retlen = ops->oobretlen = 0;
1158 if (!mtd->_read_oob)
1159 return -EOPNOTSUPP;
1160 1158
1161 ret_code = mtd_check_oob_ops(mtd, from, ops); 1159 ret_code = mtd_check_oob_ops(mtd, from, ops);
1162 if (ret_code) 1160 if (ret_code)
1163 return ret_code; 1161 return ret_code;
1164 1162
1165 ledtrig_mtd_activity(); 1163 ledtrig_mtd_activity();
1164
1165 /* Check the validity of a potential fallback on mtd->_read */
1166 if (!mtd->_read_oob && (!mtd->_read || ops->oobbuf))
1167 return -EOPNOTSUPP;
1168
1169 if (mtd->_read_oob)
1170 ret_code = mtd->_read_oob(mtd, from, ops);
1171 else
1172 ret_code = mtd->_read(mtd, from, ops->len, &ops->retlen,
1173 ops->datbuf);
1174
1166 /* 1175 /*
1167 * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics 1176 * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics
1168 * similar to mtd->_read(), returning a non-negative integer 1177 * similar to mtd->_read(), returning a non-negative integer
1169 * representing max bitflips. In other cases, mtd->_read_oob() may 1178 * representing max bitflips. In other cases, mtd->_read_oob() may
1170 * return -EUCLEAN. In all cases, perform similar logic to mtd_read(). 1179 * return -EUCLEAN. In all cases, perform similar logic to mtd_read().
1171 */ 1180 */
1172 ret_code = mtd->_read_oob(mtd, from, ops);
1173 if (unlikely(ret_code < 0)) 1181 if (unlikely(ret_code < 0))
1174 return ret_code; 1182 return ret_code;
1175 if (mtd->ecc_strength == 0) 1183 if (mtd->ecc_strength == 0)
@@ -1184,8 +1192,7 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
1184 int ret; 1192 int ret;
1185 1193
1186 ops->retlen = ops->oobretlen = 0; 1194 ops->retlen = ops->oobretlen = 0;
1187 if (!mtd->_write_oob) 1195
1188 return -EOPNOTSUPP;
1189 if (!(mtd->flags & MTD_WRITEABLE)) 1196 if (!(mtd->flags & MTD_WRITEABLE))
1190 return -EROFS; 1197 return -EROFS;
1191 1198
@@ -1194,7 +1201,16 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
1194 return ret; 1201 return ret;
1195 1202
1196 ledtrig_mtd_activity(); 1203 ledtrig_mtd_activity();
1197 return mtd->_write_oob(mtd, to, ops); 1204
1205 /* Check the validity of a potential fallback on mtd->_write */
1206 if (!mtd->_write_oob && (!mtd->_write || ops->oobbuf))
1207 return -EOPNOTSUPP;
1208
1209 if (mtd->_write_oob)
1210 return mtd->_write_oob(mtd, to, ops);
1211 else
1212 return mtd->_write(mtd, to, ops->len, &ops->retlen,
1213 ops->datbuf);
1198} 1214}
1199EXPORT_SYMBOL_GPL(mtd_write_oob); 1215EXPORT_SYMBOL_GPL(mtd_write_oob);
1200 1216