[PATCH v2 00/16] DocG3 fixes and write support

November 10th, 2011 - 03:10 am ET by Robert Jarzmik | Report spam
This patchset is aimed at :
- fixing 5 glitches in the driver
- add several new functions

The added functions are :
- add block erase capability
- add write page capability
- add powerdown and powerup
- add multiple floor support
- add ECC support
- add docg3 modes support
- add protection support (DPS areas)

The ECC part should especially be reviewed by Ivan and Mike,
as this is their work (patch "add ECC correction code").

Since V1, Ivan's and Mike's comments have been taken into
account, and nandtest/nanddump/nandwrite testing has been
done, with and without bitflipped data.

Moreover, 3 new patches have been added:
- fix reading oob+data without correction
This was triggered by the bitflipped pages tests, and
fixes cases where we want to read corrupted data.
- add docg3 modes support
This actually fixes the read part, as we now read in
"normal" mode by default rather than in "reliable"
mode. This is mandatory for nandtest to work, because of
the "even/odd pages logical AND".
- add protection support
This is an evolution to be able to access the whole chip
in protected chips, as they are in smartphones.

Happy review.

Robert

Robert Jarzmik (16):
mtd/docg3: fix debug log verbosity
mtd/docg3: fix tracing of IO in writeb
mtd/docg3: fix protection areas reading
mtd/docg3: fix BCH registers
mtd/docg3: fix reading oob+data without correction
mtd/docg3: add multiple floor support
mtd/docg3: add OOB layout to mtdinfo
mtd/docg3: add registers for erasing and writing
mtd/docg3: add OOB buffer to device structure
mtd/docg3: add write functions
mtd/docg3: add erase functions
mtd/docg3: map erase and write functions
mtd/docg3: add ECC correction code
mtd/docg3: add suspend and resume
mtd/docg3: add fast mode
mtd/docg3: add protection areas sysfs access

drivers/mtd/devices/Kconfig | 9 +
drivers/mtd/devices/docg3.c | 1451 ++++++++++++++++++++++++++++++++++++-
drivers/mtd/devices/docg3.h | 64 ++-
3 files changed, 1299 insertions(+), 225 deletions(-)

1.7.5.4

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
email Follow the discussionReplies 30 repliesReplies Make a reply

Replies

#1 Robert Jarzmik
November 10th, 2011 - 03:10 am ET | Report spam
As each docg3 chip has 2 protection areas (DPS0 and DPS1),
and because theses areas can prevent user access to the chip
data, add for each floor the sysfs entries which insert the
protection key into the right DPS.

Signed-off-by: Robert Jarzmik

drivers/mtd/devices/docg3.c | 121 +++++++++++++++++++++++++++++++++++++++++++
drivers/mtd/devices/docg3.h | 13 +++++
2 files changed, 134 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index 35df377..d7df311 100644
a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -1513,6 +1513,123 @@ static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
return ret;
}

+static struct docg3 *sysfs_dev2docg3(struct device *dev,
+ struct device_attribute *attr)
+{
+ int floor;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mtd_info **docg3_floors = platform_get_drvdata(pdev);
+
+ floor = attr->attr.name[1] - '0';
+ if (floor < 0 || floor >= DOC_MAX_NBFLOORS)
+ return NULL;
+ else
+ return docg3_floors[floor]->priv;
+}
+
+static ssize_t dps0_is_key_locked(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
+ int dps0;
+
+ doc_set_device_id(docg3, docg3->device_id);
+ dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS);
+ doc_set_device_id(docg3, 0);
+
+ return sprintf(buf, "%d", !(dps0 & DOC_DPS_KEY_OK));
+}
+
+static ssize_t dps1_is_key_locked(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
+ int dps1;
+
+ doc_set_device_id(docg3, docg3->device_id);
+ dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS);
+ doc_set_device_id(docg3, 0);
+
+ return sprintf(buf, "%d", !(dps1 & DOC_DPS_KEY_OK));
+}
+
+static ssize_t dps0_insert_key(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
+ int i;
+
+ if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
+ return -EINVAL;
+
+ doc_set_device_id(docg3, docg3->device_id);
+ for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
+ doc_writeb(docg3, buf[i], DOC_DPS0_KEY);
+ doc_set_device_id(docg3, 0);
+ return count;
+}
+
+static ssize_t dps1_insert_key(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
+ int i;
+
+ if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
+ return -EINVAL;
+
+ doc_set_device_id(docg3, docg3->device_id);
+ for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
+ doc_writeb(docg3, buf[i], DOC_DPS1_KEY);
+ doc_set_device_id(docg3, 0);
+ return count;
+}
+
+#define FLOOR_SYSFS(id) { \
+ __ATTR(f##id##_dps0_is_keylocked, S_IRUGO, dps0_is_key_locked, NULL), \
+ __ATTR(f##id##_dps1_is_keylocked, S_IRUGO, dps1_is_key_locked, NULL), \
+ __ATTR(f##id##_dps0_protection_key, S_IWUGO, NULL, dps0_insert_key), \
+ __ATTR(f##id##_dps1_protection_key, S_IWUGO, NULL, dps1_insert_key), \
+}
+
+static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = {
+ FLOOR_SYSFS(0), FLOOR_SYSFS(1), FLOOR_SYSFS(2), FLOOR_SYSFS(3)
+};
+
+static int doc_register_sysfs(struct platform_device *pdev,
+ struct mtd_info **floors)
+{
+ int ret = 0, floor, i = 0;
+ struct device *dev = &pdev->dev;
+
+ for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && floors[floor];
+ floor++)
+ for (i = 0; !ret && i < 4; i++)
+ ret = device_create_file(dev, &doc_sys_attrs[floor][i]);
+ if (!ret)
+ return 0;
+ do {
+ while (--i >= 0)
+ device_remove_file(dev, &doc_sys_attrs[floor][i]);
+ i = 4;
+ } while (--floor >= 0);
+ return ret;
+}
+
+static void doc_unregister_sysfs(struct platform_device *pdev,
+ struct mtd_info **floors)
+{
+ struct device *dev = &pdev->dev;
+ int floor, i;
+
+ for (floor = 0; floor < DOC_MAX_NBFLOORS && floors[floor];
+ floor++)
+ for (i = 0; i < 4; i++)
+ device_remove_file(dev, &doc_sys_attrs[floor][i]);
+}
+
/*
* Debug sysfs entries
*/
@@ -1927,6 +2044,9 @@ static int __init docg3_probe(struct platform_device *pdev)
found++;
}

+ ret = doc_register_sysfs(pdev, docg3_floors);
+ if (ret)
+ goto err_probe;
if (!found)
goto notfound;

@@ -1963,6 +2083,7 @@ static int __exit docg3_release(struct platform_device *pdev)
void __iomem *base = docg3->base;
int floor;

+ doc_unregister_sysfs(pdev, docg3_floors);
doc_dbg_unregister(docg3);
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
if (docg3_floors[floor])
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h
index 07182f9..a349915 100644
a/drivers/mtd/devices/docg3.h
+++ b/drivers/mtd/devices/docg3.h
@@ -118,6 +118,8 @@
#define DOC_BCH_SYNDROM(idx) (0x1048 + (idx << 0))

#define DOC_PROTECTION 0x1056
+#define DOC_DPS0_KEY 0x105c
+#define DOC_DPS1_KEY 0x105e
#define DOC_DPS0_ADDRLOW 0x1060
#define DOC_DPS0_ADDRHIGH 0x1062
#define DOC_DPS1_ADDRLOW 0x1064
@@ -252,6 +254,17 @@
#define DOC_PLANES_STATUS_PLANE0_KO 0x02
#define DOC_PLANES_STATUS_PLANE1_KO 0x04

+/*
+ * DPS key management
+ *
+ * Each floor of docg3 has 2 protection areas: DPS0 and DPS1. These areas span
+ * across block boundaries, and define whether these blocks can be read or
+ * written.
+ * The definition is dynamically stored in page 0 of blocks (2,3) for DPS0, and
+ * page 0 of blocks (4,5) for DPS1.
+ */
+#define DOC_LAYOUT_DPS_KEY_LENGTH 8
+
/**
* struct docg3 - DiskOnChip driver private data
* @dev: the device currently under control
1.7.5.4

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Similar topics