[PATCH 1/1] Blackfin OTP Char Driver: add writing support of OTP - Kernel

This is a discussion on [PATCH 1/1] Blackfin OTP Char Driver: add writing support of OTP - Kernel ; From: Mike Frysinger Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- drivers/char/bfin-otp.c | 166 +++++++++++++++++++++++++++++++++++----------- 1 files changed, 126 insertions(+), 40 deletions(-) diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c index 0a01329..ab30147 100644 --- a/drivers/char/bfin-otp.c +++ b/drivers/char/bfin-otp.c @@ -1,6 +1,5 @@ /* * Blackfin On-Chip ...

+ Reply to Thread
Results 1 to 7 of 7

Thread: [PATCH 1/1] Blackfin OTP Char Driver: add writing support of OTP

  1. [PATCH 1/1] Blackfin OTP Char Driver: add writing support of OTP

    From: Mike Frysinger

    Signed-off-by: Mike Frysinger
    Signed-off-by: Bryan Wu
    ---
    drivers/char/bfin-otp.c | 166 +++++++++++++++++++++++++++++++++++-----------
    1 files changed, 126 insertions(+), 40 deletions(-)

    diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c
    index 0a01329..ab30147 100644
    --- a/drivers/char/bfin-otp.c
    +++ b/drivers/char/bfin-otp.c
    @@ -1,6 +1,5 @@
    /*
    * Blackfin On-Chip OTP Memory Interface
    - * Supports BF52x/BF54x
    *
    * Copyright 2007-2008 Analog Devices Inc.
    *
    @@ -17,8 +16,10 @@
    #include
    #include
    #include
    +#include

    #include
    +#include
    #include

    #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args)
    @@ -30,39 +31,6 @@

    static DEFINE_MUTEX(bfin_otp_lock);

    -/* OTP Boot ROM functions */
    -#define _BOOTROM_OTP_COMMAND 0xEF000018
    -#define _BOOTROM_OTP_READ 0xEF00001A
    -#define _BOOTROM_OTP_WRITE 0xEF00001C
    -
    -static u32 (* const otp_command)(u32 command, u32 value) = (void *)_BOOTROM_OTP_COMMAND;
    -static u32 (* const otp_read)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_READ;
    -static u32 (* const otp_write)(u32 page, u32 flags, u64 *page_content) = (void *)_BOOTROM_OTP_WRITE;
    -
    -/* otp_command(): defines for "command" */
    -#define OTP_INIT 0x00000001
    -#define OTP_CLOSE 0x00000002
    -
    -/* otp_{read,write}(): defines for "flags" */
    -#define OTP_LOWER_HALF 0x00000000 /* select upper/lower 64-bit half (bit 0) */
    -#define OTP_UPPER_HALF 0x00000001
    -#define OTP_NO_ECC 0x00000010 /* do not use ECC */
    -#define OTP_LOCK 0x00000020 /* sets page protection bit for page */
    -#define OTP_ACCESS_READ 0x00001000
    -#define OTP_ACCESS_READWRITE 0x00002000
    -
    -/* Return values for all functions */
    -#define OTP_SUCCESS 0x00000000
    -#define OTP_MASTER_ERROR 0x001
    -#define OTP_WRITE_ERROR 0x003
    -#define OTP_READ_ERROR 0x005
    -#define OTP_ACC_VIO_ERROR 0x009
    -#define OTP_DATA_MULT_ERROR 0x011
    -#define OTP_ECC_MULT_ERROR 0x021
    -#define OTP_PREV_WR_ERROR 0x041
    -#define OTP_DATA_SB_WARN 0x100
    -#define OTP_ECC_SB_WARN 0x200
    -
    /**
    * bfin_otp_read - Read OTP pages
    *
    @@ -86,9 +54,11 @@ static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count,
    page = *pos / (sizeof(u64) * 2);
    while (bytes_done < count) {
    flags = (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF);
    - stamp("processing page %i (%s)", page, (flags == OTP_UPPER_HALF ? "upper" : "lower"));
    - ret = otp_read(page, flags, &content);
    + stamp("processing page %i (0x%x:%s)", page, flags,
    + (flags & OTP_UPPER_HALF ? "upper" : "lower"));
    + ret = bfrom_OtpRead(page, flags, &content);
    if (ret & OTP_MASTER_ERROR) {
    + stamp("error from otp: 0x%x", ret);
    bytes_done = -EIO;
    break;
    }
    @@ -96,7 +66,7 @@ static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count,
    bytes_done = -EFAULT;
    break;
    }
    - if (flags == OTP_UPPER_HALF)
    + if (flags & OTP_UPPER_HALF)
    ++page;
    bytes_done += sizeof(content);
    *pos += sizeof(content);
    @@ -108,14 +78,53 @@ static ssize_t bfin_otp_read(struct file *file, char __user *buff, size_t count,
    }

    #ifdef CONFIG_BFIN_OTP_WRITE_ENABLE
    +static bool allow_writes;
    +
    +/**
    + * bfin_otp_init_timing - setup OTP timing parameters
    + *
    + * Required before doing any write operation. Algorithms from HRM.
    + */
    +static u32 bfin_otp_init_timing(void)
    +{
    + u32 tp1, tp2, tp3, timing;
    +
    + tp1 = get_sclk() / 1000000;
    + tp2 = (2 * get_sclk() / 10000000) << 8;
    + tp3 = (0x1401) << 15;
    + timing = tp1 | tp2 | tp3;
    + if (bfrom_OtpCommand(OTP_INIT, timing))
    + return 0;
    +
    + return timing;
    +}
    +
    +/**
    + * bfin_otp_deinit_timing - set timings to only allow reads
    + *
    + * Should be called after all writes are done.
    + */
    +static void bfin_otp_deinit_timing(u32 timing)
    +{
    + /* mask bits [31:15] so that any attempts to write fail */
    + bfrom_OtpCommand(OTP_CLOSE, 0);
    + bfrom_OtpCommand(OTP_INIT, timing & ~(-1 << 15));
    + bfrom_OtpCommand(OTP_CLOSE, 0);
    +}
    +
    /**
    - * bfin_otp_write - Write OTP pages
    + * bfin_otp_write - write OTP pages
    *
    * All writes must be in half page chunks (half page == 64 bits).
    */
    static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t count, loff_t *pos)
    {
    - stampit();
    + ssize_t bytes_done;
    + u32 timing, page, base_flags, flags, ret;
    + u64 content;
    +
    + if (!allow_writes)
    + return -EACCES;

    if (count % sizeof(u64))
    return -EMSGSIZE;
    @@ -123,18 +132,95 @@ static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t
    if (mutex_lock_interruptible(&bfin_otp_lock))
    return -ERESTARTSYS;

    - /* need otp_init() documentation before this can be implemented */
    + stampit();
    +
    + timing = bfin_otp_init_timing();
    + if (timing == 0) {
    + mutex_unlock(&bfin_otp_lock);
    + return -EIO;
    + }
    +
    + base_flags = OTP_CHECK_FOR_PREV_WRITE;
    +
    + bytes_done = 0;
    + page = *pos / (sizeof(u64) * 2);
    + while (bytes_done < count) {
    + flags = base_flags | (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF);
    + stamp("processing page %i (0x%x:%s) from %p", page, flags,
    + (flags & OTP_UPPER_HALF ? "upper" : "lower"), buff + bytes_done);
    + if (copy_from_user(&content, buff + bytes_done, sizeof(content))) {
    + bytes_done = -EFAULT;
    + break;
    + }
    + ret = bfrom_OtpWrite(page, flags, &content);
    + if (ret & OTP_MASTER_ERROR) {
    + stamp("error from otp: 0x%x", ret);
    + bytes_done = -EIO;
    + break;
    + }
    + if (flags & OTP_UPPER_HALF)
    + ++page;
    + bytes_done += sizeof(content);
    + *pos += sizeof(content);
    + }
    +
    + bfin_otp_deinit_timing(timing);

    mutex_unlock(&bfin_otp_lock);

    + return bytes_done;
    +}
    +
    +static int bfin_otp_ioctl(struct inode *inode, struct file *filp,
    + unsigned cmd, unsigned long arg)
    +{
    + stampit();
    +
    + switch (cmd) {
    + case OTPLOCK: {
    + u32 timing;
    + int ret = -EIO;
    +
    + if (!allow_writes)
    + return -EACCES;
    +
    + if (mutex_lock_interruptible(&bfin_otp_lock))
    + return -ERESTARTSYS;
    +
    + timing = bfin_otp_init_timing();
    + if (timing) {
    + u32 otp_result = bfrom_OtpWrite(arg, OTP_LOCK, NULL);
    + stamp("locking page %i resulted in 0x%x", arg, otp_result);
    + if (!(otp_result & OTP_MASTER_ERROR))
    + ret = 0;
    +
    + bfin_otp_deinit_timing(timing);
    + }
    +
    + mutex_unlock(&bfin_otp_lock);
    +
    + return ret;
    + }
    +
    + case MEMLOCK:
    + allow_writes = false;
    + return 0;
    +
    + case MEMUNLOCK:
    + allow_writes = true;
    + return 0;
    + }
    +
    return -EINVAL;
    }
    #else
    # define bfin_otp_write NULL
    +# define bfin_otp_ioctl NULL
    #endif

    static struct file_operations bfin_otp_fops = {
    .owner = THIS_MODULE,
    + .ioctl = bfin_otp_ioctl,
    .read = bfin_otp_read,
    .write = bfin_otp_write,
    };
    --
    1.5.6
    --
    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/

  2. Re: [PATCH 1/1] Blackfin OTP Char Driver: add writing support of OTP

    On 10/13/2008 11:13 AM, Bryan Wu wrote:
    > From: Mike Frysinger


    Some changelog please.

    > Signed-off-by: Mike Frysinger
    > Signed-off-by: Bryan Wu
    > ---

    [...]
    > @@ -123,18 +132,95 @@ static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t
    > if (mutex_lock_interruptible(&bfin_otp_lock))
    > return -ERESTARTSYS;
    >
    > - /* need otp_init() documentation before this can be implemented */
    > + stampit();
    > +
    > + timing = bfin_otp_init_timing();
    > + if (timing == 0) {
    > + mutex_unlock(&bfin_otp_lock);
    > + return -EIO;
    > + }
    > +
    > + base_flags = OTP_CHECK_FOR_PREV_WRITE;
    > +
    > + bytes_done = 0;
    > + page = *pos / (sizeof(u64) * 2);
    > + while (bytes_done < count) {
    > + flags = base_flags | (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF);
    > + stamp("processing page %i (0x%x:%s) from %p", page, flags,
    > + (flags & OTP_UPPER_HALF ? "upper" : "lower"), buff + bytes_done);
    > + if (copy_from_user(&content, buff + bytes_done, sizeof(content))) {
    > + bytes_done = -EFAULT;
    > + break;
    > + }
    > + ret = bfrom_OtpWrite(page, flags, &content);
    > + if (ret & OTP_MASTER_ERROR) {
    > + stamp("error from otp: 0x%x", ret);
    > + bytes_done = -EIO;
    > + break;
    > + }
    > + if (flags & OTP_UPPER_HALF)
    > + ++page;
    > + bytes_done += sizeof(content);
    > + *pos += sizeof(content);


    What happens to pos if it fails later?

    > + }
    > +
    > + bfin_otp_deinit_timing(timing);
    >
    > mutex_unlock(&bfin_otp_lock);
    >
    > + return bytes_done;
    > +}
    > +
    > +static int bfin_otp_ioctl(struct inode *inode, struct file *filp,
    > + unsigned cmd, unsigned long arg)
    > +{
    > + stampit();
    > +
    > + switch (cmd) {
    > + case OTPLOCK: {
    > + u32 timing;
    > + int ret = -EIO;
    > +
    > + if (!allow_writes)
    > + return -EACCES;
    > +
    > + if (mutex_lock_interruptible(&bfin_otp_lock))
    > + return -ERESTARTSYS;
    > +
    > + timing = bfin_otp_init_timing();
    > + if (timing) {
    > + u32 otp_result = bfrom_OtpWrite(arg, OTP_LOCK, NULL);
    > + stamp("locking page %i resulted in 0x%x", arg, otp_result);
    > + if (!(otp_result & OTP_MASTER_ERROR))
    > + ret = 0;
    > +
    > + bfin_otp_deinit_timing(timing);
    > + }
    > +
    > + mutex_unlock(&bfin_otp_lock);
    > +
    > + return ret;
    > + }
    > +
    > + case MEMLOCK:
    > + allow_writes = false;
    > + return 0;
    > +
    > + case MEMUNLOCK:
    > + allow_writes = true;
    > + return 0;


    Please switch to unlocked_ioctl. It should be pretty easy. You should change
    (and check) allow_writes under the mutex anyway.

    > + }
    > +
    > return -EINVAL;

    --
    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/

  3. Re: [PATCH 1/1] Blackfin OTP Char Driver: add writing support of OTP

    On Mon, Oct 13, 2008 at 05:37, Jiri Slaby wrote:
    > On 10/13/2008 11:13 AM, Bryan Wu wrote:
    >> From: Mike Frysinger

    >
    > Some changelog please.


    i implemented write support. like the subject says ... not sure what
    else to say.

    >> @@ -123,18 +132,95 @@ static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t
    >> if (mutex_lock_interruptible(&bfin_otp_lock))
    >> return -ERESTARTSYS;
    >>
    >> - /* need otp_init() documentation before this can be implemented */
    >> + stampit();
    >> +
    >> + timing = bfin_otp_init_timing();
    >> + if (timing == 0) {
    >> + mutex_unlock(&bfin_otp_lock);
    >> + return -EIO;
    >> + }
    >> +
    >> + base_flags = OTP_CHECK_FOR_PREV_WRITE;
    >> +
    >> + bytes_done = 0;
    >> + page = *pos / (sizeof(u64) * 2);
    >> + while (bytes_done < count) {
    >> + flags = base_flags | (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF);
    >> + stamp("processing page %i (0x%x:%s) from %p", page, flags,
    >> + (flags & OTP_UPPER_HALF ? "upper" : "lower"), buff + bytes_done);
    >> + if (copy_from_user(&content, buff + bytes_done, sizeof(content))) {
    >> + bytes_done = -EFAULT;
    >> + break;
    >> + }
    >> + ret = bfrom_OtpWrite(page, flags, &content);
    >> + if (ret & OTP_MASTER_ERROR) {
    >> + stamp("error from otp: 0x%x", ret);
    >> + bytes_done = -EIO;
    >> + break;
    >> + }
    >> + if (flags & OTP_UPPER_HALF)
    >> + ++page;
    >> + bytes_done += sizeof(content);
    >> + *pos += sizeof(content);

    >
    > What happens to pos if it fails later?


    there is no state maintained in the hardware. the pos gets updated
    only when a half-page actually gets processed. so there is no
    "later".

    >> +static int bfin_otp_ioctl(struct inode *inode, struct file *filp,
    >> + unsigned cmd, unsigned long arg)
    >> +{
    >> + stampit();
    >> +
    >> + switch (cmd) {
    >> + case OTPLOCK: {
    >> + u32 timing;
    >> + int ret = -EIO;
    >> +
    >> + if (!allow_writes)
    >> + return -EACCES;
    >> +
    >> + if (mutex_lock_interruptible(&bfin_otp_lock))
    >> + return -ERESTARTSYS;
    >> +
    >> + timing = bfin_otp_init_timing();
    >> + if (timing) {
    >> + u32 otp_result = bfrom_OtpWrite(arg, OTP_LOCK, NULL);
    >> + stamp("locking page %i resulted in 0x%x", arg, otp_result);
    >> + if (!(otp_result & OTP_MASTER_ERROR))
    >> + ret = 0;
    >> +
    >> + bfin_otp_deinit_timing(timing);
    >> + }
    >> +
    >> + mutex_unlock(&bfin_otp_lock);
    >> +
    >> + return ret;
    >> + }
    >> +
    >> + case MEMLOCK:
    >> + allow_writes = false;
    >> + return 0;
    >> +
    >> + case MEMUNLOCK:
    >> + allow_writes = true;
    >> + return 0;

    >
    > Please switch to unlocked_ioctl. It should be pretty easy.


    will do, thanks

    > You should change (and check) allow_writes under the mutex anyway.


    not really. the mutex is to restrict access to the OTP hardware, not
    driver state. because there is none. access to allow_writes is
    atomic in the hardware anyways.

    thanks for the review
    -mike
    --
    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/

  4. Re: [PATCH 1/1] Blackfin OTP Char Driver: add writing support of OTP

    On Mon, Oct 13, 2008 at 05:59, Jiri Slaby wrote:
    > On 10/13/2008 11:43 AM, Mike Frysinger wrote:
    >> On Mon, Oct 13, 2008 at 05:37, Jiri Slaby wrote:
    >>> On 10/13/2008 11:13 AM, Bryan Wu wrote:
    >>>> @@ -123,18 +132,95 @@ static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t
    >>>> if (mutex_lock_interruptible(&bfin_otp_lock))
    >>>> return -ERESTARTSYS;
    >>>>
    >>>> - /* need otp_init() documentation before this can be implemented */
    >>>> + stampit();
    >>>> +
    >>>> + timing = bfin_otp_init_timing();
    >>>> + if (timing == 0) {
    >>>> + mutex_unlock(&bfin_otp_lock);
    >>>> + return -EIO;
    >>>> + }
    >>>> +
    >>>> + base_flags = OTP_CHECK_FOR_PREV_WRITE;
    >>>> +
    >>>> + bytes_done = 0;
    >>>> + page = *pos / (sizeof(u64) * 2);
    >>>> + while (bytes_done < count) {
    >>>> + flags = base_flags | (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF);
    >>>> + stamp("processing page %i (0x%x:%s) from %p", page, flags,
    >>>> + (flags & OTP_UPPER_HALF ? "upper" : "lower"), buff + bytes_done);
    >>>> + if (copy_from_user(&content, buff + bytes_done, sizeof(content))) {
    >>>> + bytes_done = -EFAULT;
    >>>> + break;
    >>>> + }
    >>>> + ret = bfrom_OtpWrite(page, flags, &content);
    >>>> + if (ret & OTP_MASTER_ERROR) {
    >>>> + stamp("error from otp: 0x%x", ret);
    >>>> + bytes_done = -EIO;
    >>>> + break;
    >>>> + }
    >>>> + if (flags & OTP_UPPER_HALF)
    >>>> + ++page;
    >>>> + bytes_done += sizeof(content);
    >>>> + *pos += sizeof(content);
    >>>
    >>> What happens to pos if it fails later?

    >>
    >> there is no state maintained in the hardware. the pos gets updated
    >> only when a half-page actually gets processed. so there is no
    >> "later".

    >
    > Sure there is. Next iteration of the loop. I.e. what happens if bfrom_OtpWrite
    > fails for the second time?


    the pos gets updated every time a half-page gets processed. so if you
    call write() and tell it to write 128 bytes, but you get an error half
    way through, the pos points right at the place where the error
    occurred. i dont get what you're asking.

    >>> You should change (and check) allow_writes under the mutex anyway.

    >>
    >> not really. the mutex is to restrict access to the OTP hardware, not
    >> driver state. because there is none. access to allow_writes is
    >> atomic in the hardware anyways.

    >
    > Yeah, the assignment/check is.
    >
    > But is this OK to you:
    > PROCESS 1 PROCESS 2
    > lock
    > set allow_writes
    > write
    > check allow_writes
    > be interrupted
    > whatever
    > unlock
    > unset allow_writes
    > sleep
    > mutex lock
    > the processing...


    i dont see a problem here. there is no loss of data, hardware
    failure, software crashes, etc... in other words, there is no
    misbehavior.
    -mike
    --
    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/

  5. Re: [PATCH 1/1] Blackfin OTP Char Driver: add writing support of OTP

    On 10/13/2008 11:43 AM, Mike Frysinger wrote:
    > On Mon, Oct 13, 2008 at 05:37, Jiri Slaby wrote:
    >> On 10/13/2008 11:13 AM, Bryan Wu wrote:
    >>> @@ -123,18 +132,95 @@ static ssize_t bfin_otp_write(struct file *filp, const char __user *buff, size_t
    >>> if (mutex_lock_interruptible(&bfin_otp_lock))
    >>> return -ERESTARTSYS;
    >>>
    >>> - /* need otp_init() documentation before this can be implemented */
    >>> + stampit();
    >>> +
    >>> + timing = bfin_otp_init_timing();
    >>> + if (timing == 0) {
    >>> + mutex_unlock(&bfin_otp_lock);
    >>> + return -EIO;
    >>> + }
    >>> +
    >>> + base_flags = OTP_CHECK_FOR_PREV_WRITE;
    >>> +
    >>> + bytes_done = 0;
    >>> + page = *pos / (sizeof(u64) * 2);
    >>> + while (bytes_done < count) {
    >>> + flags = base_flags | (*pos % (sizeof(u64) * 2) ? OTP_UPPER_HALF : OTP_LOWER_HALF);
    >>> + stamp("processing page %i (0x%x:%s) from %p", page, flags,
    >>> + (flags & OTP_UPPER_HALF ? "upper" : "lower"), buff + bytes_done);
    >>> + if (copy_from_user(&content, buff + bytes_done, sizeof(content))) {
    >>> + bytes_done = -EFAULT;
    >>> + break;
    >>> + }
    >>> + ret = bfrom_OtpWrite(page, flags, &content);
    >>> + if (ret & OTP_MASTER_ERROR) {
    >>> + stamp("error from otp: 0x%x", ret);
    >>> + bytes_done = -EIO;
    >>> + break;
    >>> + }
    >>> + if (flags & OTP_UPPER_HALF)
    >>> + ++page;
    >>> + bytes_done += sizeof(content);
    >>> + *pos += sizeof(content);

    >> What happens to pos if it fails later?

    >
    > there is no state maintained in the hardware. the pos gets updated
    > only when a half-page actually gets processed. so there is no
    > "later".


    Sure there is. Next iteration of the loop. I.e. what happens if bfrom_OtpWrite
    fails for the second time?

    >> You should change (and check) allow_writes under the mutex anyway.

    >
    > not really. the mutex is to restrict access to the OTP hardware, not
    > driver state. because there is none. access to allow_writes is
    > atomic in the hardware anyways.


    Yeah, the assignment/check is.

    But is this OK to you:
    PROCESS 1 PROCESS 2
    lock
    set allow_writes
    write
    check allow_writes
    be interrupted
    whatever
    unlock
    unset allow_writes
    sleep
    mutex lock
    the processing...
    --
    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/

  6. Re: [PATCH 1/1] Blackfin OTP Char Driver: add writing support of OTP

    On 10/13/2008 12:07 PM, Mike Frysinger wrote:
    > the pos gets updated every time a half-page gets processed. so if you
    > call write() and tell it to write 128 bytes, but you get an error half
    > way through, the pos points right at the place where the error
    > occurred. i dont get what you're asking.


    Ah, OK, that's because I don't know exactly what should happen if a write fails.
    I though userspace expects the state of the fd to not be touched.

    >> But is this OK to you:
    >> PROCESS 1 PROCESS 2
    >> lock
    >> set allow_writes
    >> write
    >> check allow_writes
    >> be interrupted
    >> whatever
    >> unlock
    >> unset allow_writes
    >> sleep
    >> mutex lock
    >> the processing...

    >
    > i dont see a problem here. there is no loss of data, hardware
    > failure, software crashes, etc... in other words, there is no
    > misbehavior.


    I see no purpose of allow_writes then. Why is it there? I don't need to call
    memlock if anybody else did and I raced with him. Also when somebody else
    unlocks after finishing of writes I can start failing in the middle of my writes
    -- this doesn't have anything to do with locking, but with the design, the one
    global variable.
    --
    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/

  7. Re: [PATCH 1/1] Blackfin OTP Char Driver: add writing support of OTP

    On Mon, Oct 13, 2008 at 06:35, Jiri Slaby wrote:
    > On 10/13/2008 12:07 PM, Mike Frysinger wrote:
    >>> But is this OK to you:
    >>> PROCESS 1 PROCESS 2
    >>> lock
    >>> set allow_writes
    >>> write
    >>> check allow_writes
    >>> be interrupted
    >>> whatever
    >>> unlock
    >>> unset allow_writes
    >>> sleep
    >>> mutex lock
    >>> the processing...

    >>
    >> i dont see a problem here. there is no loss of data, hardware
    >> failure, software crashes, etc... in other words, there is no
    >> misbehavior.

    >
    > I see no purpose of allow_writes then. Why is it there? I don't need to call
    > memlock if anybody else did and I raced with him. Also when somebody else
    > unlocks after finishing of writes I can start failing in the middle of my writes
    > -- this doesn't have anything to do with locking, but with the design, the one
    > global variable.


    the write bit is per-device, not per-process. so the fact you've
    narrowed down a race condition to two instructions doesnt matter, the
    behavior is the same. one process can unlock the hardware while
    another process (which did not unlock) now has access. or vice versa.
    the lock is to prevent in inadvertent writes. considering such
    inadvertent writes could make the processor unbootable, it's a simple
    safety measure which is quite common when dealing with storage
    technology like this (just look at some of the other drivers in the
    char subdir). an application that wants to write must first enable
    write access, do the write, and then disable write access. the
    scenario you describe isnt a realistic use case, so no point in
    accounting for it. OTP writes are very rare outside of development if
    they occur at all (which is why there's a Kconfig option to just
    disable it completely).
    -mike
    --
    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/

+ Reply to Thread