[PATCH V6 4/5] LPC: Support the device-tree LPC host on Hip06/Hip07
John Garry
john.garry at huawei.com
Tue Jan 31 03:49:56 PST 2017
>>>> + * The port size of legacy I/O devices is normally less than 0x400.
>>>> + * Defining the I/O range size as 0x400 here should be sufficient for
>>>> + * all peripherals under one bus.
>>>> + */
>>>
>>> This comment doesn't make a lot of sense. What is the limit? Is there a
>>> hardware limit?
>>>
>>> We don't dynamically allocate devices on the lpc bus, so why imply a
>>> limit at all?
>>>
>>
>> IIRC from previously asking Zhichang this before, this is the upper
>> range we can address devices on the LPC bus. But the value was 0x1000
>> then.
>
> Well, all devices that we want to address are defined by firmware (via
> device tree or dsdt). So I'm not quite sure what this arbitrary limit
> buys us.
>
Will check with Zhichang.
>>
>>>> +#define LPC_BUS_IO_SIZE 0x400
>>>> +
<snip>
>>>> + ret = 0;
>>>> + cnt_per_trans = (para->csize == 1) ? opcnt : para->csize;
>>>> + for (; opcnt && !ret; cnt_per_trans = para->csize) {
>>>> + unsigned long flags;
>>>> +
>>>> + /* whole operation must be atomic */
>>>> + spin_lock_irqsave(&lpcdev->cycle_lock, flags);
>>>
>>> Ouch. This is going to kill your RT jitter. Is there no better way?
>>>
>>
>> Obviously the bus register driving is non-atomic, so we need some way to
>> lock out.
>>
>> I think that it is not so critical for low-speed/infrequent-access bus.
>>
>> If we were going to use virtual UART in the BMC on the LPC bus then we
>> could consider more.
>
> Well, it basically means that an arbitrary daemon running in user space
> that checks your temperature readings via the ipmi interface could
> create a lot of jitter. That could be very critical if you want to use
> this hardware for real time critical applications, such as telecom.
>
> I bet that if you leave it like that and postpone the decision to fix it
> to "later", in 1 or 2 years you will cause someone weeks of debugging to
> track down why their voip gateway loses packets from time to time.
>
>>
We need to consider this more. There may a way to access the registers
and drive the bus without requiring a lock, but I doubt it.
Note: I think that we could make some readl/writel relaxed, which would
help.
>>>> +
>>>> + writel(cnt_per_trans, lpcdev->membase + LPC_REG_OP_LEN);
>>>> +
>>>> + writel(cmd_word, lpcdev->membase + LPC_REG_CMD);
>>>> +
>>>> + writel(ptaddr, lpcdev->membase + LPC_REG_ADDR);
>>>> +
>>>> + writel(START_WORK, lpcdev->membase + LPC_REG_START);
>>>> +
>>>> + /* whether the operation is finished */
>>>> + ret = wait_lpc_idle(lpcdev->membase, waitcnt);
>>>> + if (!ret) {
>>>> + opcnt -= cnt_per_trans;
>>>> + for (; cnt_per_trans--; buf++)
>>>> + *buf = readl(lpcdev->membase + LPC_REG_RDATA);
>>>> + }
>>>> +
>>>> + spin_unlock_irqrestore(&lpcdev->cycle_lock, flags);
>>>> + }
>>>> +
>>>> + return ret;
>>>> +}
<snip>
>>>> + * hisilpc_comm_in - read/input the data from the I/O peripheral
>>>> + * through LPC.
>>>> + * @devobj: pointer to the device information relevant to LPC
>>>> controller.
>>>> + * @pio: the target I/O port address.
>>>> + * @dlen: the data length required to read from the target I/O port.
>>>> + *
>>>> + * when succeed, the data read back is stored in buffer pointed by
>>>> inbuf.
>>>> + * For inb, return the data read from I/O or -1 when error occur.
>>>> + */
>>>> +static u64 hisilpc_comm_in(void *devobj, unsigned long pio, size_t
>>>> dlen)
>>>> +{
>>>> + struct hisilpc_dev *lpcdev = devobj;
>>>> + struct lpc_cycle_para iopara;
>>>> + u32 rd_data;
>>>
>>> rd_data needs to be initialized to 0. Otherwise it may contain stale
>>> stack contents and corrupt non-32bit dlen returns.
>>>
>>
>> I think so, since we read into this value byte-by-byte. We also seem to
>> return a 32b value but should return 64b value according to the
>> prototype.
>
> IIRC LPC (well, PIO) doesn't support bigger requests than 32bit. At
> least I can't think of an x86 instruction that would allow bigger
> transactions. So there's no need to make it 64bit. However, the question
> is why the prototype is 64bit then. Hm. :)
>
> Maybe the prototype should be only 32bit.
>
Will check with Zhichang.
>>
>>>> + unsigned char *newbuf;
>>>> + int ret = 0;
>>>> + unsigned long ptaddr;
>>>> +
>>>> + if (!lpcdev || !dlen || dlen > LPC_MAX_DULEN || (dlen & (dlen
>>>> - 1)))
>>>> + return -1;
>>>
>>> Isn't this -EINVAL?
>>
>> Not sure. This value is returned directly to the inb/outb caller, which
>> would not check this value for error.
>>
>> It could be argued that the checking is paranoia. If not, we should
>> treat the failure as a more severe event.
>
> Oh, I see. In that case -1 makes a lot of sense since it's the default
> read value on x86 for unallocated space.
>
> This probably deserves a comment (and/or maybe a #define)
>
We can add a comment
>
> Alex
>
> .
>
More information about the linux-arm-kernel
mailing list