Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
69db4aa4
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
69db4aa4
编写于
10月 08, 2016
作者:
B
Brian Norris
浏览文件
操作
浏览文件
下载
差异文件
Merge tag '4.9/mtd-pairing-scheme' of github.com:linux-nand/linux
Introduction of the MTD pairing scheme concept.
上级
f5b88de2
477b0229
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
212 addition
and
0 deletion
+212
-0
drivers/mtd/mtdcore.c
drivers/mtd/mtdcore.c
+104
-0
drivers/mtd/mtdpart.c
drivers/mtd/mtdpart.c
+1
-0
include/linux/mtd/mtd.h
include/linux/mtd/mtd.h
+107
-0
未找到文件。
drivers/mtd/mtdcore.c
浏览文件 @
69db4aa4
...
...
@@ -375,6 +375,110 @@ static int mtd_reboot_notifier(struct notifier_block *n, unsigned long state,
return
NOTIFY_DONE
;
}
/**
* mtd_wunit_to_pairing_info - get pairing information of a wunit
* @mtd: pointer to new MTD device info structure
* @wunit: write unit we are interested in
* @info: returned pairing information
*
* Retrieve pairing information associated to the wunit.
* This is mainly useful when dealing with MLC/TLC NANDs where pages can be
* paired together, and where programming a page may influence the page it is
* paired with.
* The notion of page is replaced by the term wunit (write-unit) to stay
* consistent with the ->writesize field.
*
* The @wunit argument can be extracted from an absolute offset using
* mtd_offset_to_wunit(). @info is filled with the pairing information attached
* to @wunit.
*
* From the pairing info the MTD user can find all the wunits paired with
* @wunit using the following loop:
*
* for (i = 0; i < mtd_pairing_groups(mtd); i++) {
* info.pair = i;
* mtd_pairing_info_to_wunit(mtd, &info);
* ...
* }
*/
int
mtd_wunit_to_pairing_info
(
struct
mtd_info
*
mtd
,
int
wunit
,
struct
mtd_pairing_info
*
info
)
{
int
npairs
=
mtd_wunit_per_eb
(
mtd
)
/
mtd_pairing_groups
(
mtd
);
if
(
wunit
<
0
||
wunit
>=
npairs
)
return
-
EINVAL
;
if
(
mtd
->
pairing
&&
mtd
->
pairing
->
get_info
)
return
mtd
->
pairing
->
get_info
(
mtd
,
wunit
,
info
);
info
->
group
=
0
;
info
->
pair
=
wunit
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
mtd_wunit_to_pairing_info
);
/**
* mtd_wunit_to_pairing_info - get wunit from pairing information
* @mtd: pointer to new MTD device info structure
* @info: pairing information struct
*
* Returns a positive number representing the wunit associated to the info
* struct, or a negative error code.
*
* This is the reverse of mtd_wunit_to_pairing_info(), and can help one to
* iterate over all wunits of a given pair (see mtd_wunit_to_pairing_info()
* doc).
*
* It can also be used to only program the first page of each pair (i.e.
* page attached to group 0), which allows one to use an MLC NAND in
* software-emulated SLC mode:
*
* info.group = 0;
* npairs = mtd_wunit_per_eb(mtd) / mtd_pairing_groups(mtd);
* for (info.pair = 0; info.pair < npairs; info.pair++) {
* wunit = mtd_pairing_info_to_wunit(mtd, &info);
* mtd_write(mtd, mtd_wunit_to_offset(mtd, blkoffs, wunit),
* mtd->writesize, &retlen, buf + (i * mtd->writesize));
* }
*/
int
mtd_pairing_info_to_wunit
(
struct
mtd_info
*
mtd
,
const
struct
mtd_pairing_info
*
info
)
{
int
ngroups
=
mtd_pairing_groups
(
mtd
);
int
npairs
=
mtd_wunit_per_eb
(
mtd
)
/
ngroups
;
if
(
!
info
||
info
->
pair
<
0
||
info
->
pair
>=
npairs
||
info
->
group
<
0
||
info
->
group
>=
ngroups
)
return
-
EINVAL
;
if
(
mtd
->
pairing
&&
mtd
->
pairing
->
get_wunit
)
return
mtd
->
pairing
->
get_wunit
(
mtd
,
info
);
return
info
->
pair
;
}
EXPORT_SYMBOL_GPL
(
mtd_pairing_info_to_wunit
);
/**
* mtd_pairing_groups - get the number of pairing groups
* @mtd: pointer to new MTD device info structure
*
* Returns the number of pairing groups.
*
* This number is usually equal to the number of bits exposed by a single
* cell, and can be used in conjunction with mtd_pairing_info_to_wunit()
* to iterate over all pages of a given pair.
*/
int
mtd_pairing_groups
(
struct
mtd_info
*
mtd
)
{
if
(
!
mtd
->
pairing
||
!
mtd
->
pairing
->
ngroups
)
return
1
;
return
mtd
->
pairing
->
ngroups
;
}
EXPORT_SYMBOL_GPL
(
mtd_pairing_groups
);
/**
* add_mtd_device - register an MTD device
* @mtd: pointer to new MTD device info structure
...
...
drivers/mtd/mtdpart.c
浏览文件 @
69db4aa4
...
...
@@ -409,6 +409,7 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
slave
->
mtd
.
oobsize
=
master
->
oobsize
;
slave
->
mtd
.
oobavail
=
master
->
oobavail
;
slave
->
mtd
.
subpage_sft
=
master
->
subpage_sft
;
slave
->
mtd
.
pairing
=
master
->
pairing
;
slave
->
mtd
.
name
=
name
;
slave
->
mtd
.
owner
=
master
->
owner
;
...
...
include/linux/mtd/mtd.h
浏览文件 @
69db4aa4
...
...
@@ -127,6 +127,82 @@ struct mtd_ooblayout_ops {
struct
mtd_oob_region
*
oobfree
);
};
/**
* struct mtd_pairing_info - page pairing information
*
* @pair: pair id
* @group: group id
*
* The term "pair" is used here, even though TLC NANDs might group pages by 3
* (3 bits in a single cell). A pair should regroup all pages that are sharing
* the same cell. Pairs are then indexed in ascending order.
*
* @group is defining the position of a page in a given pair. It can also be
* seen as the bit position in the cell: page attached to bit 0 belongs to
* group 0, page attached to bit 1 belongs to group 1, etc.
*
* Example:
* The H27UCG8T2BTR-BC datasheet describes the following pairing scheme:
*
* group-0 group-1
*
* pair-0 page-0 page-4
* pair-1 page-1 page-5
* pair-2 page-2 page-8
* ...
* pair-127 page-251 page-255
*
*
* Note that the "group" and "pair" terms were extracted from Samsung and
* Hynix datasheets, and might be referenced under other names in other
* datasheets (Micron is describing this concept as "shared pages").
*/
struct
mtd_pairing_info
{
int
pair
;
int
group
;
};
/**
* struct mtd_pairing_scheme - page pairing scheme description
*
* @ngroups: number of groups. Should be related to the number of bits
* per cell.
* @get_info: converts a write-unit (page number within an erase block) into
* mtd_pairing information (pair + group). This function should
* fill the info parameter based on the wunit index or return
* -EINVAL if the wunit parameter is invalid.
* @get_wunit: converts pairing information into a write-unit (page) number.
* This function should return the wunit index pointed by the
* pairing information described in the info argument. It should
* return -EINVAL, if there's no wunit corresponding to the
* passed pairing information.
*
* See mtd_pairing_info documentation for a detailed explanation of the
* pair and group concepts.
*
* The mtd_pairing_scheme structure provides a generic solution to represent
* NAND page pairing scheme. Instead of exposing two big tables to do the
* write-unit <-> (pair + group) conversions, we ask the MTD drivers to
* implement the ->get_info() and ->get_wunit() functions.
*
* MTD users will then be able to query these information by using the
* mtd_pairing_info_to_wunit() and mtd_wunit_to_pairing_info() helpers.
*
* @ngroups is here to help MTD users iterating over all the pages in a
* given pair. This value can be retrieved by MTD users using the
* mtd_pairing_groups() helper.
*
* Examples are given in the mtd_pairing_info_to_wunit() and
* mtd_wunit_to_pairing_info() documentation.
*/
struct
mtd_pairing_scheme
{
int
ngroups
;
int
(
*
get_info
)(
struct
mtd_info
*
mtd
,
int
wunit
,
struct
mtd_pairing_info
*
info
);
int
(
*
get_wunit
)(
struct
mtd_info
*
mtd
,
const
struct
mtd_pairing_info
*
info
);
};
struct
module
;
/* only needed for owner field in mtd_info */
struct
mtd_info
{
...
...
@@ -188,6 +264,9 @@ struct mtd_info {
/* OOB layout description */
const
struct
mtd_ooblayout_ops
*
ooblayout
;
/* NAND pairing scheme, only provided for MLC/TLC NANDs */
const
struct
mtd_pairing_scheme
*
pairing
;
/* the ecc step size. */
unsigned
int
ecc_step_size
;
...
...
@@ -296,6 +375,12 @@ static inline void mtd_set_ooblayout(struct mtd_info *mtd,
mtd
->
ooblayout
=
ooblayout
;
}
static
inline
void
mtd_set_pairing_scheme
(
struct
mtd_info
*
mtd
,
const
struct
mtd_pairing_scheme
*
pairing
)
{
mtd
->
pairing
=
pairing
;
}
static
inline
void
mtd_set_of_node
(
struct
mtd_info
*
mtd
,
struct
device_node
*
np
)
{
...
...
@@ -312,6 +397,11 @@ static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
return
ops
->
mode
==
MTD_OPS_AUTO_OOB
?
mtd
->
oobavail
:
mtd
->
oobsize
;
}
int
mtd_wunit_to_pairing_info
(
struct
mtd_info
*
mtd
,
int
wunit
,
struct
mtd_pairing_info
*
info
);
int
mtd_pairing_info_to_wunit
(
struct
mtd_info
*
mtd
,
const
struct
mtd_pairing_info
*
info
);
int
mtd_pairing_groups
(
struct
mtd_info
*
mtd
);
int
mtd_erase
(
struct
mtd_info
*
mtd
,
struct
erase_info
*
instr
);
int
mtd_point
(
struct
mtd_info
*
mtd
,
loff_t
from
,
size_t
len
,
size_t
*
retlen
,
void
**
virt
,
resource_size_t
*
phys
);
...
...
@@ -397,6 +487,23 @@ static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
return
do_div
(
sz
,
mtd
->
writesize
);
}
static
inline
int
mtd_wunit_per_eb
(
struct
mtd_info
*
mtd
)
{
return
mtd
->
erasesize
/
mtd
->
writesize
;
}
static
inline
int
mtd_offset_to_wunit
(
struct
mtd_info
*
mtd
,
loff_t
offs
)
{
return
mtd_div_by_ws
(
mtd_mod_by_eb
(
offs
,
mtd
),
mtd
);
}
static
inline
loff_t
mtd_wunit_to_offset
(
struct
mtd_info
*
mtd
,
loff_t
base
,
int
wunit
)
{
return
base
+
(
wunit
*
mtd
->
writesize
);
}
static
inline
int
mtd_has_oob
(
const
struct
mtd_info
*
mtd
)
{
return
mtd
->
_read_oob
&&
mtd
->
_write_oob
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录