From: Bryan O'Donoghue <pure.logic@nexus-software.ie>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: mingo@redhat.com, hpa@zytor.com, x86@kernel.org,
dvhart@infradead.org, andy.schevchenko@gmail.com,
boon.leong.ong@intel.com, linux-kernel@vger.kernel.org,
platform-driver-x86@vger.kernel.org, derek.browne@intel.com,
josef.ahmad@intel.com, erik.nyquist@intel.com
Subject: Re: [PATCH 1/2] x86/quark: Add Quark embedded SRAM support
Date: Tue, 05 May 2015 06:48:07 -0700 [thread overview]
Message-ID: <5548CA17.1030002@nexus-software.ie> (raw)
In-Reply-To: <alpine.DEB.2.11.1505041608530.4225@nanos>
On 04/05/15 08:00, Thomas Gleixner wrote:
> 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
No problem.
>> +#define phys_to_esram(x) ((x) >> PAGE_SHIFT)
>
> There is a single usage size for this lousy documented magic.
Hmm - OK I'll add a comment like "stuff the address field of the eSRAM
page register" or similar.
>> +struct esram_page {
>> + u32 id;
>> + struct list_head list;
>> + phys_addr_t addr;
>
> Please tab align the struct member names as you did below.
OK
>> +};
>> +
>> +/**
>> + * 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?
No it's not. I had an awful hard time making a kernel without dbgfs but,
I'll add an #ifdef for the field
>> + */
>> +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 = .....
Hmm, I had feedback when doing the IMR code *not* to do that, so kept
that pattern for eSRAM. More than happy to rationalize the line-count here.
>> +/**
>> + * esram_dump_fault - dump eSRAM registers and BUG().
>> + *
>> + * @return:
>
> Sigh. Please generate kernel docs from your file to catch all those
> function comment failures.
Hmm - OK - I've missed a trick here clearly - I'll check.
>> +
>> + /* 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?
A nice way to generate a backtrace which was useful to the BSP version
of this code since BSP version supported deallocation of eSRAM pages and
had a /sysfs interface to add/remove mappings.
With the version I'm proposing here, we could just as easily not BUG()
at all.
>> +/**
>> + * 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?
You're right ENOMEM is more logical.
>
>> + 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?
That should be if (ret < 0) we need to transmit iosf bus errors upwards.
>
>> + 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.
The BSP code was checking for memory as ro or rw and flipping the bit in
the page to make it r/w so the memcpy() could continue.
You're right though since the data comes from a kzalloc() there's no
point in validating it further.
>
>> +
>> + /* 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.
> At init() time I can see how that works, on resume() rather not.
Yes absolutely true. eSRAM is not self populating - ideally you'd want
memory transactions to be stopped until the eSRAM had populated itself.
During init this is safe. The resume callback is done via syscore_ops so
the resume path should be called with interrupts off.
memcpy(&edev->cbuf, vaddr, PAGE_SIZE);
ret = esram_page_enable(ep);
if (ret) {
esram_dump_fault(ep);
goto err;
}
memcpy((void *)vaddr, &esram_dev.cbuf, PAGE_SIZE);
>> + /* 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?
The silicon guarantees that by returning the size of eSRAM in 4k pages.
329676_QuarkDatasheet.pdf : 12.7.4.37 : ESRAMCTRL
24:16 07Fh
RO eSRAM Size (eSRAM_SIZE): eSRAM size in 4k pages ( 0 means 1)
>> + if (ret) {
>> + esram_dump_fault(ep);
>> + ret = ret < 0 ? ret : -ENOMEM;
>
> This return value juggling is really horrible and hard to follow.
NP - I'll change it.
>> + goto err;
>> + }
>> +
>> + /* Overlay. */
>> + ret = esram_map_page(edev, ep);
>> + if (ret)
>> + goto err;
>
> What undoes already established mappings?
Nothing - unmap() is not supported by silicon. Disabling a mapping once
it's been setup is not supported.
>> +static void __exit esram_exit(void)
>> +{
>> + struct esram_dev *edev = &esram_dev;
>
> Again. What happens to the mappings?
Stay as-is. So in fact I shouldn't be doing any kfree()'s on already
mapped pages.
I'll change that too.
Thanks for the review.
Bryan
next prev parent reply other threads:[~2015-05-05 13:48 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-04 2:17 [PATCH 0/2] x86/quark: Add eSRAM driver and test code Bryan O'Donoghue
2015-05-04 2:17 ` [PATCH 1/2] x86/quark: Add Quark embedded SRAM support Bryan O'Donoghue
2015-05-04 15:00 ` Thomas Gleixner
2015-05-05 13:48 ` Bryan O'Donoghue [this message]
2015-05-05 20:07 ` Darren Hart
2015-05-05 22:19 ` H. Peter Anvin
2015-05-05 8:44 ` Paul Bolle
2015-05-05 13:03 ` Bryan O'Donoghue
2015-05-06 9:58 ` Ingo Molnar
2015-05-06 15:46 ` Bryan O'Donoghue
2015-05-04 2:17 ` [PATCH 2/2] x86/quark: Add Quark embedded SRAM self-test Bryan O'Donoghue
2015-05-05 8:34 ` Paul Bolle
2015-05-06 10:02 ` Ingo Molnar
2015-05-06 14:27 ` Bryan O'Donoghue
2015-05-06 10:08 ` Ingo Molnar
2015-05-06 9:52 ` [PATCH 0/2] x86/quark: Add eSRAM driver and test code Ingo Molnar
2015-05-06 15:27 ` Bryan O'Donoghue
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5548CA17.1030002@nexus-software.ie \
--to=pure.logic@nexus-software.ie \
--cc=andy.schevchenko@gmail.com \
--cc=boon.leong.ong@intel.com \
--cc=derek.browne@intel.com \
--cc=dvhart@infradead.org \
--cc=erik.nyquist@intel.com \
--cc=hpa@zytor.com \
--cc=josef.ahmad@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=platform-driver-x86@vger.kernel.org \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.