On Mon, 4 May 2015, Bryan O'Donoghue wrote:
+++ b/arch/x86/include/asm/esram.h
This should be in platform/quark/....
+++ b/arch/x86/platform/intel-quark/esram.c
+#define phys_to_esram(x) ((x) >> PAGE_SHIFT)
There is a single usage size for this lousy documented magic.
+struct esram_page {
+ u32 id;
+ struct list_head list;
+ phys_addr_t addr;
Please tab align the struct member names as you did below.
+};
+
+/**
+ * struct esram_dev
+ *
+ * Structre to represent module state/data/etc.
+ */
+struct esram_dev {
+ struct dentry *dbg;
So dbgfs is a hard requirement for this to work?
+ */
+static int esram_dbgfs_state_show(struct seq_file *s, void *unused)
+{
+ struct esram_dev *edev = &esram_dev;
+ u32 data;
+ u32 reg = (u32)s->private;
You really like to waste lines. What's wrong with:
u32 data, reg = .....
+/**
+ * esram_dump_fault - dump eSRAM registers and BUG().
+ *
+ * @return:
Sigh. Please generate kernel docs from your file to catch all those
function comment failures.
+
+ /* Show the page state. */
+ iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MMESRAM_READ, ep->id, &pgd);
+ pr_err("fault @ page %d state 0x%08x\n", ep->id, pgd);
+
+ /* Get state. */
+ iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ, ESRAMCTRL_REG, &pgc);
+ iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ, ESRAMPGBLOCK_REG, &pgb);
+ pr_err("page-control=0x%08x, page-block=0x%08x\n", pgc, pgb);
+
+ BUG();
So we force BUG() here. Why?
+/**
+ * esram_page_enable - Enable an eSRAM page spinning for page to become ready.
+ *
+ * @param ep: struct esram_page carries data to program to register.
+ * @return zero on success < 0 on error.
+ */
+static int esram_page_enable(struct esram_page *ep)
+{
+ int ret = 0;
+
+ /* Enable a busy page => EINVAL, return IOSF error as necessary. */
Why is EINVAL a good return code if the page is busy?
+ ret = esram_page_busy(ep);
+ if (ret)
+ return ret < 0 ? ret : -EINVAL;
+
+ /* Enable page overlay - with automatic flush on S3 entry. */
+ ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MMESRAM_WRITE, ep->id,
+ ESRAMPGCTRL_FLUSH_PAGE_EN | ESRAMPGCTRL_EN |
+ phys_to_esram(ep->addr));
+ if (ret)
+ return ret;
+
+ /* Busy bit true is good, ret < 0 means IOSF read error. */
+ ret = esram_page_busy(ep);
+ if (ret)
+ ret = 0;
+
+ return ret;
Why not just return 0 unconitionally?
+ if (pte == NULL || !(pte_write(*pte))) {
+ pr_err("invalid address for overlay %pa\n", &ep->addr);
+ return -ENOMEM;
+ }
Also what makes sure that the mapping is not going away under you?
Nothing, but the whole thing is not required at all. Because you map a
kernel buffer from init(), so these half baken sanity checks are
really useless.
> At init() time I can see how that works, on resume() rather not.
+
+ /* eSRAM does not autopopulate so save the contents. */
+ memcpy(&edev->cbuf, vaddr, PAGE_SIZE);
+ ret = esram_page_enable(ep);
+ if (ret) {
+ esram_dump_fault(ep);
+ goto err;
return ret perhaps?
+ }
+
+ /* Overlay complete, repopulate the eSRAM page with original data. */
+ memcpy((void *)vaddr, &esram_dev.cbuf, PAGE_SIZE);
So the caller must ensure that the DRAM content cannot change between
the two memcpys, right? Otherwise you end up with inconsistent data.
+ /* Calculate # of pages silicon supports. */
+ edev->num_bytes = ESRAMCTRL_SIZE(ctrl);
+ edev->total_pages = edev->num_bytes / PAGE_SIZE;
+ if (edev->total_pages == 0)
+ return -ENOMEM;
+
+ /* Get an array of esram pages. */
+ edev->pages = kzalloc(edev->total_pages *
+ sizeof(struct esram_page), GFP_KERNEL);
+ if (IS_ERR(edev->pages)) {
+ ret = PTR_ERR(edev->pages);
+ goto err;
+ }
+
+ /* Make an area for the gen_pool to operate from. */
+ edev->overlay = kmalloc(edev->num_bytes, GFP_KERNEL);
This better be page aligned, right? How's that guaranteed?
+ if (ret) {
+ esram_dump_fault(ep);
+ ret = ret < 0 ? ret : -ENOMEM;
This return value juggling is really horrible and hard to follow.
+ goto err;
+ }
+
+ /* Overlay. */
+ ret = esram_map_page(edev, ep);
+ if (ret)
+ goto err;
What undoes already established mappings?
+static void __exit esram_exit(void)
+{
+ struct esram_dev *edev = &esram_dev;
Again. What happens to the mappings?