All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
To: Alexey Kardashevskiy <aik@ozlabs.ru>,
	npiggin@gmail.com, paulus@samba.org,  mpe@ellerman.id.au
Cc: oohall@gmail.com, linuxppc-dev@lists.ozlabs.org
Subject: Re: [PATCH] powerpc/nvdimm: Add support for multibyte read/write for metadata
Date: Thu, 06 Jun 2019 18:19:52 +0530	[thread overview]
Message-ID: <87blzaho9b.fsf@linux.ibm.com> (raw)
In-Reply-To: <fcb825c4-39fe-5c0f-0eed-764723295d54@ozlabs.ru>

Alexey Kardashevskiy <aik@ozlabs.ru> writes:

> On 02/06/2019 14:43, Aneesh Kumar K.V wrote:
>> SCM_READ/WRITE_MEATADATA hcall supports multibyte read/write. This patch
>> updates the metadata read/write to use 1, 2, 4 or 8 byte read/write as
>> mentioned in PAPR document.
>> 
>> READ/WRITE_METADATA hcall supports the 1, 2, 4, or 8 bytes read/write.
>> For other values hcall results H_P3.
>> 
>> Hypervisor stores the metadata contents in big-endian format and in-order
>> to enable read/write in different granularity, we need to switch the contents
>> to big-endian before calling HCALL.
>> 
>> Based on an patch from Oliver O'Halloran <oohall@gmail.com>
>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
>> ---
>>  arch/powerpc/platforms/pseries/papr_scm.c | 104 +++++++++++++++++-----
>>  1 file changed, 82 insertions(+), 22 deletions(-)
>> 
>> diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
>> index 0176ce66673f..e33cebb8ee6c 100644
>> --- a/arch/powerpc/platforms/pseries/papr_scm.c
>> +++ b/arch/powerpc/platforms/pseries/papr_scm.c
>> @@ -97,42 +97,102 @@ static int drc_pmem_unbind(struct papr_scm_priv *p)
>>  }
>>  
>>  static int papr_scm_meta_get(struct papr_scm_priv *p,
>> -			struct nd_cmd_get_config_data_hdr *hdr)
>> +			     struct nd_cmd_get_config_data_hdr *hdr)
>>  {
>>  	unsigned long data[PLPAR_HCALL_BUFSIZE];
>> +	unsigned long offset, data_offset;
>> +	int len, read;
>>  	int64_t ret;
>>  
>> -	if (hdr->in_offset >= p->metadata_size || hdr->in_length != 1)
>> +	if ((hdr->in_offset + hdr->in_length) >= p->metadata_size)
>>  		return -EINVAL;
>>  
>> -	ret = plpar_hcall(H_SCM_READ_METADATA, data, p->drc_index,
>> -			hdr->in_offset, 1);
>> -
>> -	if (ret == H_PARAMETER) /* bad DRC index */
>> -		return -ENODEV;
>> -	if (ret)
>> -		return -EINVAL; /* other invalid parameter */
>> -
>> -	hdr->out_buf[0] = data[0] & 0xff;
>> -
>> +	for (len = hdr->in_length; len; len -= read) {
>> +
>> +		data_offset = hdr->in_length - len;
>> +		offset = hdr->in_offset + data_offset;
>> +
>> +		if (len >= 8)
>> +			read = 8;
>> +		else if (len >= 4)
>> +			read = 4;
>> +		else if ( len >= 2)
>
> Do not need a space before "len".

Will fix in next update

>
>
>> +			read = 2;
>> +		else
>> +			read = 1;
>> +
>> +		ret = plpar_hcall(H_SCM_READ_METADATA, data, p->drc_index,
>> +				  offset, read);
>> +
>> +		if (ret == H_PARAMETER) /* bad DRC index */
>> +			return -ENODEV;
>> +		if (ret)
>> +			return -EINVAL; /* other invalid parameter */
>> +
>> +		switch (read) {
>> +		case 8:
>> +			*(uint64_t *)(hdr->out_buf + data_offset) = be64_to_cpu(data[0]);
>> +			break;
>> +		case 4:
>> +			*(uint32_t *)(hdr->out_buf + data_offset) = be32_to_cpu(data[0] & 0xffffffff);
>> +			break;
>> +
>> +		case 2:
>> +			*(uint16_t *)(hdr->out_buf + data_offset) = be16_to_cpu(data[0] & 0xffff);
>> +			break;
>> +
>> +		case 1:
>> +			*(uint32_t *)(hdr->out_buf + data_offset) = (data[0] & 0xff);
>
>
> Memory corruption, should be uint8_t*.

Good catch. That also resulted in an error on big endian kernel. Will
fix that in next update
>
>
>> +			break;
>> +		}
>> +	}
>>  	return 0;
>>  }
>>  
>>  static int papr_scm_meta_set(struct papr_scm_priv *p,
>> -			struct nd_cmd_set_config_hdr *hdr)
>> +			     struct nd_cmd_set_config_hdr *hdr)
>>  {
>> +	unsigned long offset, data_offset;
>> +	int len, wrote;
>> +	unsigned long data;
>> +	__be64 data_be;
>>  	int64_t ret;
>>  
>> -	if (hdr->in_offset >= p->metadata_size || hdr->in_length != 1)
>> +	if ((hdr->in_offset + hdr->in_length) >= p->metadata_size)
>>  		return -EINVAL;
>>  
>> -	ret = plpar_hcall_norets(H_SCM_WRITE_METADATA,
>> -			p->drc_index, hdr->in_offset, hdr->in_buf[0], 1);
>> -
>> -	if (ret == H_PARAMETER) /* bad DRC index */
>> -		return -ENODEV;
>> -	if (ret)
>> -		return -EINVAL; /* other invalid parameter */
>> +	for (len = hdr->in_length; len; len -= wrote) {
>> +
>> +		data_offset = hdr->in_length - len;
>> +		offset = hdr->in_offset + data_offset;
>> +
>> +		if (len >= 8) {
>> +			data = *(uint64_t *)(hdr->in_buf + data_offset);
>> +			data_be = cpu_to_be64(data);
>> +			wrote = 8;
>> +		} else if (len >= 4) {
>> +			data = *(uint32_t *)(hdr->in_buf + data_offset);
>> +			data &= 0xffffffff;
>
>
> Why do you need &0xffffffff here and below (&0xffff, &0xff)? uint32_t is
> unsigned type so the sign bit won't be extended.

Sure. I just want to make sure we don't take extra data. For now I will
keep it as it is and let Michael Ellerman decide to drop that?

>
>
>> +			data_be = cpu_to_be32(data);
>> +			wrote = 4;
>> +		} else if (len >= 2) {
>> +			data = *(uint16_t *)(hdr->in_buf + data_offset);
>> +			data &= 0xffff;
>> +			data_be = cpu_to_be16(data);
>> +			wrote = 2;
>> +		} else {
>> +			data_be = *(uint8_t *)(hdr->in_buf + data_offset);
>> +			data_be &= 0xff;
>> +			wrote = 1;
>> +		}
>> +
>> +		ret = plpar_hcall_norets(H_SCM_WRITE_METADATA, p->drc_index,
>> +					 offset, data_be, wrote);
>> +		if (ret == H_PARAMETER) /* bad DRC index */
>> +			return -ENODEV;
>> +		if (ret)
>> +			return -EINVAL; /* other invalid parameter */
>> +	}
>>  
>>  	return 0;
>>  }
>> @@ -154,7 +214,7 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
>>  		get_size_hdr = buf;
>>  
>>  		get_size_hdr->status = 0;
>> -		get_size_hdr->max_xfer = 1;
>> +		get_size_hdr->max_xfer = 8;
>>  		get_size_hdr->config_size = p->metadata_size;
>>  		*cmd_rc = 0;
>>  		break;
>> 
>
> -- 
> Alexey

Thanks for the review
-aneesh


      reply	other threads:[~2019-06-06 12:52 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-02  4:43 [PATCH] powerpc/nvdimm: Add support for multibyte read/write for metadata Aneesh Kumar K.V
2019-06-03  0:25 ` Oliver
2019-06-04  9:06   ` Aneesh Kumar K.V
2019-06-05 10:51     ` Michael Ellerman
2019-06-06 12:50       ` Aneesh Kumar K.V
2019-06-05  8:02 ` Alexey Kardashevskiy
2019-06-06 12:49   ` Aneesh Kumar K.V [this message]

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=87blzaho9b.fsf@linux.ibm.com \
    --to=aneesh.kumar@linux.ibm.com \
    --cc=aik@ozlabs.ru \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=mpe@ellerman.id.au \
    --cc=npiggin@gmail.com \
    --cc=oohall@gmail.com \
    --cc=paulus@samba.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.