* Re: [RFC PATCH v2 4/6] mmc: sdhci: host: add new f_sdh30
From: Mark Rutland @ 2014-06-26 11:03 UTC (permalink / raw)
To: Vincent Yang
Cc: devicetree@vger.kernel.org, andy.green@linaro.org,
patches@linaro.org, anton@enomsg.org, linux-mmc@vger.kernel.org,
chris@printf.net, Vincent.Yang@tw.fujitsu.com,
jaswinder.singh@linaro.org, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1403763812-5495-5-git-send-email-Vincent.Yang@tw.fujitsu.com>
On Thu, Jun 26, 2014 at 07:23:30AM +0100, Vincent Yang wrote:
> This patch adds new host controller driver for
> Fujitsu SDHCI controller f_sdh30.
>
> Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
> ---
> .../devicetree/bindings/mmc/sdhci-fujitsu.txt | 35 +++
> drivers/mmc/host/Kconfig | 7 +
> drivers/mmc/host/Makefile | 1 +
> drivers/mmc/host/sdhci_f_sdh30.c | 346 +++++++++++++++++++++
> drivers/mmc/host/sdhci_f_sdh30.h | 40 +++
> 5 files changed, 429 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt
> create mode 100644 drivers/mmc/host/sdhci_f_sdh30.c
> create mode 100644 drivers/mmc/host/sdhci_f_sdh30.h
>
> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt b/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt
> new file mode 100644
> index 0000000..40add438
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt
> @@ -0,0 +1,35 @@
> +* Fujitsu SDHCI controller
> +
> +This file documents differences between the core properties in mmc.txt
> +and the properties used by the sdhci_f_sdh30 driver.
> +
> +Required properties:
> +- compatible: "fujitsu,f_sdh30"
Please use '-' rather than '_' in compatible strings.
This seems to be the name of the driver. What is the precise name of the
IP block?
> +- voltage-ranges : two cells are required, first cell specifies minimum
> + slot voltage (mV), second cell specifies maximum slot voltage (mV).
> + Several ranges could be specified.
Describe this as a list of pairs, it's confusing otherwise.
I'm not sure I follow what having multiple pairs implies.
> +Optional properties:
> +- gpios: This is one optional gpio for controlling a power mux which
> + switches between two power supplies. 3.3V is selected when gpio is high,
> + and 1.8V is selected when gpio is low. This voltage is used for signal
> + level.
Give this a more descriptive name, like power-mux-gpios. That will match
up with the style of cd-gpios and wp-gpios.
> +- clocks: Must contain an entry for each entry in clock-names. It is a
> + list of phandles and clock-specifier pairs.
> + See ../clocks/clock-bindings.txt for details.
> +- clock-names: Should contain the following two entries:
> + "sd_sd4clk" - clock primarily used for tuning process
> + "sd_bclk" - base clock for sdhci controller
> +
> +Example:
> +
> + sdhci1: sdio@36600000 {
> + compatible = "fujitsu,f_sdh30";
> + reg = <0 0x36600000 0x1000>;
> + interrupts = <0 172 0x4>,
> + <0 173 0x4>;
> + voltage-ranges = <1800 1800 3300 3300>;
Place brackets around each pair to make this clearer:
voltage-ranges = <1800 1800>, <3300 3300>;
[...]
> + if (!of_property_read_u32(pdev->dev.of_node, "vendor-hs200",
> + &priv->vendor_hs200))
> + dev_info(dev, "Applying vendor-hs200 setting\n");
> + else
> + priv->vendor_hs200 = 0;
This wasn't in the binding document, and a grep for "vendor-hs200" in a
v3.16-rc2 tree found me nothing.
Please document this.
> +
> + if (!of_property_read_u32(pdev->dev.of_node, "bus-width", &bus_width)) {
> + if (bus_width == 8) {
> + dev_info(dev, "Applying 8 bit bus width\n");
> + host->mmc->caps |= MMC_CAP_8_BIT_DATA;
> + }
> + }
What if bus-width is not 8, or is not present?
> +
> + ret = mmc_of_parse_voltage(pdev->dev.of_node, &host->ocr_mask);
> + if (ret) {
> + dev_err(dev, "%s: parse voltage error\n", __func__);
> + goto err_voltage;
> + }
> +
> + host->hw_name = DRIVER_NAME;
> + host->ops = &sdhci_f_sdh30_ops;
> + host->irq = irq;
> +
> + host->ioaddr = of_iomap(pdev->dev.of_node, 0);
> + if (!host->ioaddr) {
> + dev_err(dev, "%s: failed to remap registers\n", __func__);
> + ret = -ENXIO;
> + goto err_remap;
> + }
> +
> + priv->clk_sd4 = of_clk_get(pdev->dev.of_node, 0);
> + if (!IS_ERR(priv->clk_sd4)) {
> + ret = clk_prepare_enable(priv->clk_sd4);
> + if (ret < 0) {
> + dev_err(dev, "Failed to enable sd4 clock: %d\n", ret);
> + goto err_clk1;
> + }
> + }
> + priv->clk_b = of_clk_get(pdev->dev.of_node, 1);
> + if (!IS_ERR(priv->clk_b)) {
> + ret = clk_prepare_enable(priv->clk_b);
> + if (ret < 0) {
> + dev_err(dev, "Failed to enable clk_b clock: %d\n", ret);
> + goto err_clk2;
> + }
> + }
Given you gave these names, get these by name rather than index. It's
less surprising and more flexible.
Thanks,
Mark.
^ permalink raw reply
* Re: [PATCH v2 2/2] powerpc: bpf: Fix the broken LD_VLAN_TAG_PRESENT test
From: Denis Kirjanov @ 2014-06-26 15:43 UTC (permalink / raw)
To: Michael Ellerman; +Cc: netdev, linuxppc-dev
In-Reply-To: <1403771455.18572.8.camel@concordia>
On 6/26/14, Michael Ellerman <mpe@ellerman.id.au> wrote:
> On Wed, 2014-06-25 at 21:34 +0400, Denis Kirjanov wrote:
>> We have to return the boolean here if the tag presents
>> or not, not just ANDing the TCI with the mask which results to:
>>
>> [ 709.412097] test_bpf: #18 LD_VLAN_TAG_PRESENT
>> [ 709.412245] ret 4096 != 1
>> [ 709.412332] ret 4096 != 1
>> [ 709.412333] FAIL (2 times)
>
> Hi Denis,
>
> Is this the same version of test_bpf that is in Linus' tree?
You didn't enable the JIT.
> I don't see any fails with that version, am I missing something?
>
> [ 187.690640] test_bpf: #18 LD_VLAN_TAG_PRESENT 46 50 PASS
>
> cheers
>
>
>
^ permalink raw reply
* Re: [PATCH 2/9] drivers: base: support cpu cache information interface to userspace via sysfs
From: Sudeep Holla @ 2014-06-26 18:41 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Rob Herring, Lorenzo Pieralisi, linux-ia64@vger.kernel.org,
linux-s390@vger.kernel.org, Greg Kroah-Hartman,
linux-doc@vger.kernel.org, Heiko Carstens,
linux-kernel@vger.kernel.org, Sudeep Holla, linux390@de.ibm.com,
x86@kernel.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20140625222355.GK32514@n2100.arm.linux.org.uk>
Hi,
On 25/06/14 23:23, Russell King - ARM Linux wrote:
> On Wed, Jun 25, 2014 at 06:30:37PM +0100, Sudeep Holla wrote:
>> +=09=09coherency_line_size: the minimum amount of data that gets transfe=
rred
>
> So, what value to do envision this taking for a CPU where the cache
> line size is 32 bytes, but each cache line has two dirty bits which
> allow it to only evict either the upper or lower 16 bytes depending
> on which are dirty?
>
IIUC most of existing implementations of cacheinfo on various architectures
are representing the cache line size as coherency_line_size, in which case =
I
need fix the definition in this file.
BTW will there be any architectural way of finding such configuration ?
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH 2/9] drivers: base: support cpu cache information interface to userspace via sysfs
From: Russell King - ARM Linux @ 2014-06-26 18:50 UTC (permalink / raw)
To: Sudeep Holla
Cc: Rob Herring, Lorenzo Pieralisi, linux-ia64@vger.kernel.org,
linux-doc@vger.kernel.org, linux-s390@vger.kernel.org,
x86@kernel.org, Heiko Carstens, linux-kernel@vger.kernel.org,
Greg Kroah-Hartman, linux390@de.ibm.com,
linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <53AC695C.2090406@arm.com>
On Thu, Jun 26, 2014 at 07:41:32PM +0100, Sudeep Holla wrote:
> Hi,
>
> On 25/06/14 23:23, Russell King - ARM Linux wrote:
>> On Wed, Jun 25, 2014 at 06:30:37PM +0100, Sudeep Holla wrote:
>>> + coherency_line_size: the minimum amount of data that gets transferred
>>
>> So, what value to do envision this taking for a CPU where the cache
>> line size is 32 bytes, but each cache line has two dirty bits which
>> allow it to only evict either the upper or lower 16 bytes depending
>> on which are dirty?
>>
>
> IIUC most of existing implementations of cacheinfo on various architectures
> are representing the cache line size as coherency_line_size, in which case I
> need fix the definition in this file.
As an example, here's an extract from the SA110 TRM:
StrongARM contains a 16KByte writeback data cache. The DC has 512 lines
of 32 bytes (8 words), arranged as a 32 way set associative cache, and
uses the virtual addresses generated by the processor. A line also
contains the physical address the block was fetched from and two dirty
bits. There is a dirty bit associated with both the first and second
half of the block. When a store hits in the cache the dirty bit
associated with it is set. When a block is evicted from the cache the
dirty bits are used to decide if all, half, or none of the block will
be written back to memory using the physical address stored with the
block. The DC is always reloaded a line at a time (8 words).
> BTW will there be any architectural way of finding such configuration ?
Not that I know of.
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly
improving, and getting towards what was expected from it.
^ permalink raw reply
* Re: [PATCH 2/9] drivers: base: support cpu cache information interface to userspace via sysfs
From: Sudeep Holla @ 2014-06-26 19:03 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Rob Herring, Lorenzo Pieralisi, linux-ia64@vger.kernel.org,
linux-s390@vger.kernel.org, Greg Kroah-Hartman,
linux-doc@vger.kernel.org, Heiko Carstens,
linux-kernel@vger.kernel.org, Sudeep Holla, linux390@de.ibm.com,
x86@kernel.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20140626185005.GA32514@n2100.arm.linux.org.uk>
On 26/06/14 19:50, Russell King - ARM Linux wrote:
> On Thu, Jun 26, 2014 at 07:41:32PM +0100, Sudeep Holla wrote:
>> Hi,
>>
>> On 25/06/14 23:23, Russell King - ARM Linux wrote:
>>> On Wed, Jun 25, 2014 at 06:30:37PM +0100, Sudeep Holla wrote:
>>>> +=09=09coherency_line_size: the minimum amount of data that gets trans=
ferred
>>>
>>> So, what value to do envision this taking for a CPU where the cache
>>> line size is 32 bytes, but each cache line has two dirty bits which
>>> allow it to only evict either the upper or lower 16 bytes depending
>>> on which are dirty?
>>>
>>
>> IIUC most of existing implementations of cacheinfo on various architectu=
res
>> are representing the cache line size as coherency_line_size, in which ca=
se I
>> need fix the definition in this file.
>
> As an example, here's an extract from the SA110 TRM:
>
> StrongARM contains a 16KByte writeback data cache. The DC has 512 lines
> of 32 bytes (8 words), arranged as a 32 way set associative cache, and
> uses the virtual addresses generated by the processor. A line also
> contains the physical address the block was fetched from and two dirty
> bits. There is a dirty bit associated with both the first and second
> half of the block. When a store hits in the cache the dirty bit
> associated with it is set. When a block is evicted from the cache the
> dirty bits are used to decide if all, half, or none of the block will
> be written back to memory using the physical address stored with the
> block. The DC is always reloaded a line at a time (8 words).
>
Thanks for the information. It's interesting that line is referred as block
when referring to 2 dirty bits. I am not sure if this can be mapped to=20
physical_line_partition =3D 2. Thoughts ?
>> BTW will there be any architectural way of finding such configuration ?
>
> Not that I know of.
>
That's bad :)
Regards,
Sudeep
^ permalink raw reply
* Re: OF_DYNAMIC node lifecycle
From: Nathan Fontenot @ 2014-06-26 19:59 UTC (permalink / raw)
To: Grant Likely, Pantelis Antoniou
Cc: devicetree, Steven Rostedt, linuxppc-dev, Tyrel Datwyler,
Thomas Gleixner
In-Reply-To: <20140625202216.16A8AC40AE6@trevor.secretlab.ca>
On 06/25/2014 03:22 PM, Grant Likely wrote:
> On Tue, 24 Jun 2014 15:07:05 -0500, Nathan Fontenot <nfont@austin.ibm.com> wrote:
>> On 06/23/2014 09:58 AM, Grant Likely wrote:
>>> On Thu, 19 Jun 2014 11:33:20 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>>>> Hi Grant,
>>>>
>>>> CCing Thomas Gleixner & Steven Rostedt, since they might have a few
>>>> ideas...
>>>>
>>>> On Jun 18, 2014, at 11:07 PM, Grant Likely wrote:
>>>>
>>>>> Hi Nathan and Tyrel,
>>>>>
>>>>> I'm looking into lifecycle issues on nodes modified by OF_DYNAMIC, and
>>>>> I'm hoping you can help me. Right now, pseries seems to be the only
>>>>> user of OF_DYNAMIC, but making OF_DYNAMIC work has a huge impact on
>>>>> the entire kernel because it requires all DT code to manage reference
>>>>> counting with iterating over nodes. Most users simply get it wrong.
>>>>> Pantelis did some investigation and found that the reference counts on
>>>>> a running kernel are all over the place. I have my doubts that any
>>>>> code really gets it right.
>>>>>
>>>>> The problem is that users need to know when it is appropriate to call
>>>>> of_node_get()/of_node_put(). All list traversals that exit early need
>>>>> an extra call to of_node_put(), and code that is searching for a node
>>>>> in the tree and holding a reference to it needs to call of_node_get().
>>>>>
>>>>
>>>> In hindsight it appears that drivers just can't get the lifecycle right.
>>>> So we need to simplify things.
>>>>
>>>>> I've got a few pseries questions:
>>>>> - What are the changes being requested by pseries firmware? Is it only
>>>>> CPUs and memory nodes, or does it manipulate things all over the tree?
>>>>> - How frequent are the changes? How many changes would be likely over
>>>>> the runtime of the system?
>>>>> - Are you able to verify that removed nodes are actually able to be
>>>>> freed correctly? Do you have any testcases for node removal?
>>>>>
>>>>> I'm thinking very seriously about changing the locking semantics of DT
>>>>> code entirely so that most users never have to worry about
>>>>> of_node_get/put at all. If the DT code is switched to use rcu
>>>>> primitives for tree iteration (which also means making DT code use
>>>>> list_head, something I'm already investigating), then instead of
>>>>> trying to figure out of_node_get/put rules, callers could use
>>>>> rcu_read_lock()/rcu_read_unlock() to protect the region that is
>>>>> searching over nodes, and only call of_node_get() if the node pointer
>>>>> is needed outside the rcu read-side lock.
>>>>>
>>>>> I'd really like to be rid of the node reference counting entirely, but
>>>>> I can't figure out a way of doing that safely, so I'd settle for
>>>>> making it a lot easier to get correct.
>>>>>
>>>>
>>>> Since we're going about changing things, how about that devtree_lock?
>>>
>>> I believe rcu would pretty much eliminate the devtree_lock entirely. All
>>> modifiers would need to grab a mutex to ensure there is only one writer
>>> at any given time, but readers would have free reign to parse the tree
>>> however they like.
>>>
>>> DT writers would have to follow some strict rules about how to handle
>>> nodes that are removed (ie. don't modify or of_node_put() them until
>>> after rcu is syncronized), but the number of writers is very small and
>>> we have control of all of them.
>>>
>>>> We're using a raw_spinlock and we're always taking the lock with
>>>> interrupts disabled.
>>>>
>>>> If we're going to make DT changes frequently during normal runtime
>>>> and not only during boot time, those are bad for any kind of real-time
>>>> performance.
>>>>
>>>> So the question is, do we really have code that access the live tree
>>>> during atomic sections? Is that something we want? Enforcing this
>>>> will make our lives easier, and we'll get the change to replace
>>>> that spinlock with a mutex.
>>>
>>> Yes, I believe the powerpc CPU hotplug code accesses the DT in atomic
>>> sections. I cannot put my finger on the exact code however. Nathan might
>>> know better. But, if I'm right, the whole problem goes away with RCU.
>>
>> I went back through the cpu hotplug code. we do update the DT during cpu
>> hotplug but I don't see it happening during atomic sections.
>>
>> The code is in arch/powerpc/platforms/pseries/dlpar.c
>
> Great, thanks,
>
> By the way, notifiers currently get sent before any updates are applied
> to the tree. I want to change it so that the notifier gets sent
> afterwards. Does that work for you? I've looked through all the users
> and aside from a stupid block of code in arch/powerpc/kernel/prom.c
> which does things that should be done by of_attach_node(), it looks like
> everything should be fine.
This would affect property updates. When doing a property update the
notifier passes a pointer to a struct containing a device node
pointer and a pointer to the new device node property.
I know specifically in memory property updates we grab the current version
of the device tree property and compare it to the 'new' version that
was passed to us.
If you want to do the DT update before calling the notifier that should be
fine for the memory update code and would only require very minimal
updates.
It does look like OF_RECONFIG_UPDATE_PROPERTY is used in a couple of other
places that would need to be investigated.
-Nathan
^ permalink raw reply
* Re: OF_DYNAMIC node lifecycle
From: Nathan Fontenot @ 2014-06-26 20:01 UTC (permalink / raw)
To: Grant Likely, Tyrel Datwyler
Cc: devicetree@vger.kernel.org, Pantelis Antoniou, linuxppc-dev
In-Reply-To: <20140625202446.77687C40AE6@trevor.secretlab.ca>
On 06/25/2014 03:24 PM, Grant Likely wrote:
> On Tue, 24 Jun 2014 15:10:55 -0500, Nathan Fontenot <nfont@austin.ibm.com> wrote:
>> On 06/23/2014 09:48 AM, Grant Likely wrote:
>>> On Thu, 19 Jun 2014 10:26:15 -0500, Nathan Fontenot <nfont@austin.ibm.com> wrote:
>>>> On 06/18/2014 03:07 PM, Grant Likely wrote:
>>>>> Hi Nathan and Tyrel,
>>>>>
>>>>> I'm looking into lifecycle issues on nodes modified by OF_DYNAMIC, and
>>>>> I'm hoping you can help me. Right now, pseries seems to be the only
>>>>> user of OF_DYNAMIC, but making OF_DYNAMIC work has a huge impact on
>>>>> the entire kernel because it requires all DT code to manage reference
>>>>> counting with iterating over nodes. Most users simply get it wrong.
>>>>> Pantelis did some investigation and found that the reference counts on
>>>>> a running kernel are all over the place. I have my doubts that any
>>>>> code really gets it right.
>>>>>
>>>>> The problem is that users need to know when it is appropriate to call
>>>>> of_node_get()/of_node_put(). All list traversals that exit early need
>>>>> an extra call to of_node_put(), and code that is searching for a node
>>>>> in the tree and holding a reference to it needs to call of_node_get().
>>>>>
>>>>> I've got a few pseries questions:
>>>>> - What are the changes being requested by pseries firmware? Is it only
>>>>> CPUs and memory nodes, or does it manipulate things all over the tree?
>>>>
>>>> The short answer, everything.
>>>
>>> :-)
>>>
>>>> For pseries the two big actions that can change the device tree are
>>>> adding/removing resources and partition migration.
>>>>
>>>> The most frequent updates to the device tree happen during resource
>>>> (cpu, memory, and pci/phb) add and remove. During this process we add
>>>> and remove the node and its properties from the device tree.
>>>> - For memory on newer systems this just involves updating the
>>>> ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory property. Older
>>>> firmware levels add and remove the memroy@XXX nodes and their properties.
>>>> - For cpus the cpus/PowerPC,POWERXXXX nodes and its properties are added
>>>> or removed
>>>> - For pci/phb the pci@XXXXX nodes and properties are added/removed.
>>>>
>>>> The less frequent operation of live partition migration (and suspend/resume)
>>>> can update just about anything in the device tree. When this occurs and the
>>>> systems starts after being migrated (or waking up after a suspend) we make
>>>> a call to firmware to get updates to the device tree for the new hardware
>>>> we are running on.
>>>>
>>>>> - How frequent are the changes? How many changes would be likely over
>>>>> the runtime of the system?
>>>>
>>>> This can happen frequently.
>>>
>>> Thanks, that is exactly the information that I want. I'm not so much
>>> concerned with the addition or removal of nodes/properties, which is
>>> actually pretty easy to handle. It is the lifecycle of allocations on
>>> dynamic nodes that causes heartburn.
>>>
>>>>> - Are you able to verify that removed nodes are actually able to be
>>>>> freed correctly? Do you have any testcases for node removal?
>>>>
>>>> I have always tested this by doing resource add/remove, usually cpu and memory
>>>> since it is the easiest.
>>>
>>> Is that just testing the functionality, or do you have tests that check
>>> if the memory gets freed?
>>
>> In general it's just functionality testing.
>>
>>>
>>>>> I'm thinking very seriously about changing the locking semantics of DT
>>>>> code entirely so that most users never have to worry about
>>>>> of_node_get/put at all. If the DT code is switched to use rcu
>>>>> primitives for tree iteration (which also means making DT code use
>>>>> list_head, something I'm already investigating), then instead of
>>>>> trying to figure out of_node_get/put rules, callers could use
>>>>> rcu_read_lock()/rcu_read_unlock() to protect the region that is
>>>>> searching over nodes, and only call of_node_get() if the node pointer
>>>>> is needed outside the rcu read-side lock.
>>>>>
>>>>
>>>> This sounds good. I like just taking the rcu lock around accessing the DT.
>>>> Do we have many places where DT node pointers are held that require
>>>> keeping the of_node_get/put calls? If this did exist perhaps we could
>>>> update those places to look up the DT node every time instead of
>>>> holding on to the pointer. We could just get rid of the reference counting
>>>> altogether then.
>>>
>>> There are a few, but I would be happy to restrict reference counting to
>>> only those locations. Most places will decode the DT data, and then
>>> throw away the reference. We /might/ even be able to do rcu_lock/unlock
>>> around the entire probe path which would make it transparent to all
>>> device drivers.
>>>
>>>>> I'd really like to be rid of the node reference counting entirely, but
>>>>> I can't figure out a way of doing that safely, so I'd settle for
>>>>> making it a lot easier to get correct.
>>>>>
>>>>
>>>> heh! I have often thought about adding reference counting to device tree
>>>> properties.
>>>
>>> You horrible, horrible man.
>>
>> Yes. I are evil :)
>>
>> After looking again the work needed to add reference counts to properties
>> would be huge. The few properties I am concerned with are specific to powerpc
>> so perhaps just adding an arch specific lock around updating those
>> properties would work.
>
> Which code/properties? I'd like to have a look myself.
/ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory
The property is updated in
arch/powerpc/platforms/pseries/hotplug-memory.c:pseries_update_drconf_memory()
-Nathan
^ permalink raw reply
* Re: powerpc: crash with 3.16.0-rc2
From: Sukadev Bhattiprolu @ 2014-06-26 23:52 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, Cedric Le Goater
In-Reply-To: <1403770940.18572.7.camel@concordia>
Michael Ellerman [mpe@ellerman.id.au] wrote:
| > A patch from Michael Ellerman was just merged :
| >
| > powerpc/powernv: Remove OPAL v1 takeover
| >
| > I think it fixes the problem you are seeing.
|
| Yes it should.
It does fix the problem.
^ permalink raw reply
* [PATCH] ibmvfc: fix little endian issues
From: Tyrel Datwyler @ 2014-06-27 0:03 UTC (permalink / raw)
To: linux-scsi; +Cc: brking, linuxppc-dev, linux-kernel, jbottomley, Tyrel Datwyler
Added big endian annotations to relevant data structure fields, and necessary
byte swappings to support little endian builds.
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc.c | 473 +++++++++++++++++++++--------------------
drivers/scsi/ibmvscsi/ibmvfc.h | 268 +++++++++++------------
2 files changed, 374 insertions(+), 367 deletions(-)
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 8dd4768..aaee066 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -166,13 +166,13 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt)
switch (entry->fmt) {
case IBMVFC_CMD_FORMAT:
entry->op_code = vfc_cmd->iu.cdb[0];
- entry->scsi_id = vfc_cmd->tgt_scsi_id;
+ entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id);
entry->lun = scsilun_to_int(&vfc_cmd->iu.lun);
entry->tmf_flags = vfc_cmd->iu.tmf_flags;
- entry->u.start.xfer_len = vfc_cmd->iu.xfer_len;
+ entry->u.start.xfer_len = be32_to_cpu(vfc_cmd->iu.xfer_len);
break;
case IBMVFC_MAD_FORMAT:
- entry->op_code = mad->opcode;
+ entry->op_code = be32_to_cpu(mad->opcode);
break;
default:
break;
@@ -199,18 +199,18 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt)
switch (entry->fmt) {
case IBMVFC_CMD_FORMAT:
entry->op_code = vfc_cmd->iu.cdb[0];
- entry->scsi_id = vfc_cmd->tgt_scsi_id;
+ entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id);
entry->lun = scsilun_to_int(&vfc_cmd->iu.lun);
entry->tmf_flags = vfc_cmd->iu.tmf_flags;
- entry->u.end.status = vfc_cmd->status;
- entry->u.end.error = vfc_cmd->error;
+ entry->u.end.status = be16_to_cpu(vfc_cmd->status);
+ entry->u.end.error = be16_to_cpu(vfc_cmd->error);
entry->u.end.fcp_rsp_flags = vfc_cmd->rsp.flags;
entry->u.end.rsp_code = vfc_cmd->rsp.data.info.rsp_code;
entry->u.end.scsi_status = vfc_cmd->rsp.scsi_status;
break;
case IBMVFC_MAD_FORMAT:
- entry->op_code = mad->opcode;
- entry->u.end.status = mad->status;
+ entry->op_code = be32_to_cpu(mad->opcode);
+ entry->u.end.status = be16_to_cpu(mad->status);
break;
default:
break;
@@ -270,14 +270,14 @@ static int ibmvfc_get_err_result(struct ibmvfc_cmd *vfc_cmd)
{
int err;
struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
- int fc_rsp_len = rsp->fcp_rsp_len;
+ int fc_rsp_len = be32_to_cpu(rsp->fcp_rsp_len);
if ((rsp->flags & FCP_RSP_LEN_VALID) &&
((fc_rsp_len && fc_rsp_len != 4 && fc_rsp_len != 8) ||
rsp->data.info.rsp_code))
return DID_ERROR << 16;
- err = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error);
+ err = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error));
if (err >= 0)
return rsp->scsi_status | (cmd_status[err].result << 16);
return rsp->scsi_status | (DID_ERROR << 16);
@@ -807,7 +807,7 @@ static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code)
evt->cmnd->result = (error_code << 16);
evt->done = ibmvfc_scsi_eh_done;
} else
- evt->xfer_iu->mad_common.status = IBMVFC_MAD_DRIVER_FAILED;
+ evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_DRIVER_FAILED);
list_del(&evt->queue);
del_timer(&evt->timer);
@@ -955,7 +955,7 @@ static void ibmvfc_get_host_speed(struct Scsi_Host *shost)
spin_lock_irqsave(shost->host_lock, flags);
if (vhost->state == IBMVFC_ACTIVE) {
- switch (vhost->login_buf->resp.link_speed / 100) {
+ switch (be64_to_cpu(vhost->login_buf->resp.link_speed) / 100) {
case 1:
fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
break;
@@ -976,7 +976,7 @@ static void ibmvfc_get_host_speed(struct Scsi_Host *shost)
break;
default:
ibmvfc_log(vhost, 3, "Unknown port speed: %lld Gbit\n",
- vhost->login_buf->resp.link_speed / 100);
+ be64_to_cpu(vhost->login_buf->resp.link_speed) / 100);
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break;
}
@@ -1171,21 +1171,21 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
memset(login_info, 0, sizeof(*login_info));
- login_info->ostype = IBMVFC_OS_LINUX;
- login_info->max_dma_len = IBMVFC_MAX_SECTORS << 9;
- login_info->max_payload = sizeof(struct ibmvfc_fcp_cmd_iu);
- login_info->max_response = sizeof(struct ibmvfc_fcp_rsp);
- login_info->partition_num = vhost->partition_number;
- login_info->vfc_frame_version = 1;
- login_info->fcp_version = 3;
- login_info->flags = IBMVFC_FLUSH_ON_HALT;
+ login_info->ostype = cpu_to_be32(IBMVFC_OS_LINUX);
+ login_info->max_dma_len = cpu_to_be64(IBMVFC_MAX_SECTORS << 9);
+ login_info->max_payload = cpu_to_be32(sizeof(struct ibmvfc_fcp_cmd_iu));
+ login_info->max_response = cpu_to_be32(sizeof(struct ibmvfc_fcp_rsp));
+ login_info->partition_num = cpu_to_be32(vhost->partition_number);
+ login_info->vfc_frame_version = cpu_to_be32(1);
+ login_info->fcp_version = cpu_to_be16(3);
+ login_info->flags = cpu_to_be16(IBMVFC_FLUSH_ON_HALT);
if (vhost->client_migrated)
- login_info->flags |= IBMVFC_CLIENT_MIGRATED;
+ login_info->flags |= cpu_to_be16(IBMVFC_CLIENT_MIGRATED);
- login_info->max_cmds = max_requests + IBMVFC_NUM_INTERNAL_REQ;
- login_info->capabilities = IBMVFC_CAN_MIGRATE;
- login_info->async.va = vhost->async_crq.msg_token;
- login_info->async.len = vhost->async_crq.size * sizeof(*vhost->async_crq.msgs);
+ login_info->max_cmds = cpu_to_be32(max_requests + IBMVFC_NUM_INTERNAL_REQ);
+ login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE);
+ login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token);
+ login_info->async.len = cpu_to_be32(vhost->async_crq.size * sizeof(*vhost->async_crq.msgs));
strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME);
strncpy(login_info->device_name,
dev_name(&vhost->host->shost_gendev), IBMVFC_MAX_NAME);
@@ -1225,7 +1225,7 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost)
struct ibmvfc_event *evt = &pool->events[i];
atomic_set(&evt->free, 1);
evt->crq.valid = 0x80;
- evt->crq.ioba = pool->iu_token + (sizeof(*evt->xfer_iu) * i);
+ evt->crq.ioba = cpu_to_be64(pool->iu_token + (sizeof(*evt->xfer_iu) * i));
evt->xfer_iu = pool->iu_storage + i;
evt->vhost = vhost;
evt->ext_list = NULL;
@@ -1310,8 +1310,8 @@ static void ibmvfc_map_sg_list(struct scsi_cmnd *scmd, int nseg,
struct scatterlist *sg;
scsi_for_each_sg(scmd, sg, nseg, i) {
- md[i].va = sg_dma_address(sg);
- md[i].len = sg_dma_len(sg);
+ md[i].va = cpu_to_be64(sg_dma_address(sg));
+ md[i].len = cpu_to_be32(sg_dma_len(sg));
md[i].key = 0;
}
}
@@ -1337,7 +1337,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
sg_mapped = scsi_dma_map(scmd);
if (!sg_mapped) {
- vfc_cmd->flags |= IBMVFC_NO_MEM_DESC;
+ vfc_cmd->flags |= cpu_to_be16(IBMVFC_NO_MEM_DESC);
return 0;
} else if (unlikely(sg_mapped < 0)) {
if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
@@ -1346,10 +1346,10 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
}
if (scmd->sc_data_direction == DMA_TO_DEVICE) {
- vfc_cmd->flags |= IBMVFC_WRITE;
+ vfc_cmd->flags |= cpu_to_be16(IBMVFC_WRITE);
vfc_cmd->iu.add_cdb_len |= IBMVFC_WRDATA;
} else {
- vfc_cmd->flags |= IBMVFC_READ;
+ vfc_cmd->flags |= cpu_to_be16(IBMVFC_READ);
vfc_cmd->iu.add_cdb_len |= IBMVFC_RDDATA;
}
@@ -1358,7 +1358,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
return 0;
}
- vfc_cmd->flags |= IBMVFC_SCATTERLIST;
+ vfc_cmd->flags |= cpu_to_be16(IBMVFC_SCATTERLIST);
if (!evt->ext_list) {
evt->ext_list = dma_pool_alloc(vhost->sg_pool, GFP_ATOMIC,
@@ -1374,8 +1374,8 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
ibmvfc_map_sg_list(scmd, sg_mapped, evt->ext_list);
- data->va = evt->ext_list_token;
- data->len = sg_mapped * sizeof(struct srp_direct_buf);
+ data->va = cpu_to_be64(evt->ext_list_token);
+ data->len = cpu_to_be32(sg_mapped * sizeof(struct srp_direct_buf));
data->key = 0;
return 0;
}
@@ -1404,15 +1404,15 @@ static void ibmvfc_timeout(struct ibmvfc_event *evt)
static int ibmvfc_send_event(struct ibmvfc_event *evt,
struct ibmvfc_host *vhost, unsigned long timeout)
{
- u64 *crq_as_u64 = (u64 *) &evt->crq;
+ __be64 *crq_as_u64 = (__be64 *) &evt->crq;
int rc;
/* Copy the IU into the transfer area */
*evt->xfer_iu = evt->iu;
if (evt->crq.format == IBMVFC_CMD_FORMAT)
- evt->xfer_iu->cmd.tag = (u64)evt;
+ evt->xfer_iu->cmd.tag = cpu_to_be64((u64)evt);
else if (evt->crq.format == IBMVFC_MAD_FORMAT)
- evt->xfer_iu->mad_common.tag = (u64)evt;
+ evt->xfer_iu->mad_common.tag = cpu_to_be64((u64)evt);
else
BUG();
@@ -1428,7 +1428,8 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
mb();
- if ((rc = ibmvfc_send_crq(vhost, crq_as_u64[0], crq_as_u64[1]))) {
+ if ((rc = ibmvfc_send_crq(vhost, be64_to_cpu(crq_as_u64[0]),
+ be64_to_cpu(crq_as_u64[1])))) {
list_del(&evt->queue);
del_timer(&evt->timer);
@@ -1451,7 +1452,7 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
evt->cmnd->result = DID_ERROR << 16;
evt->done = ibmvfc_scsi_eh_done;
} else
- evt->xfer_iu->mad_common.status = IBMVFC_MAD_CRQ_ERROR;
+ evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_CRQ_ERROR);
evt->done(evt);
} else
@@ -1472,7 +1473,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt)
struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
struct scsi_cmnd *cmnd = evt->cmnd;
const char *err = unknown_error;
- int index = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error);
+ int index = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error));
int logerr = 0;
int rsp_code = 0;
@@ -1526,13 +1527,13 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp;
struct scsi_cmnd *cmnd = evt->cmnd;
u32 rsp_len = 0;
- u32 sense_len = rsp->fcp_sense_len;
+ u32 sense_len = be32_to_cpu(rsp->fcp_sense_len);
if (cmnd) {
- if (vfc_cmd->response_flags & IBMVFC_ADAPTER_RESID_VALID)
- scsi_set_resid(cmnd, vfc_cmd->adapter_resid);
+ if (be16_to_cpu(vfc_cmd->response_flags) & IBMVFC_ADAPTER_RESID_VALID)
+ scsi_set_resid(cmnd, be32_to_cpu(vfc_cmd->adapter_resid));
else if (rsp->flags & FCP_RESID_UNDER)
- scsi_set_resid(cmnd, rsp->fcp_resid);
+ scsi_set_resid(cmnd, be32_to_cpu(rsp->fcp_resid));
else
scsi_set_resid(cmnd, 0);
@@ -1540,12 +1541,13 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
cmnd->result = ibmvfc_get_err_result(vfc_cmd);
if (rsp->flags & FCP_RSP_LEN_VALID)
- rsp_len = rsp->fcp_rsp_len;
+ rsp_len = be32_to_cpu(rsp->fcp_rsp_len);
if ((sense_len + rsp_len) > SCSI_SENSE_BUFFERSIZE)
sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len;
if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8)
memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len);
- if ((vfc_cmd->status & IBMVFC_VIOS_FAILURE) && (vfc_cmd->error == IBMVFC_PLOGI_REQUIRED))
+ if ((be16_to_cpu(vfc_cmd->status) & IBMVFC_VIOS_FAILURE) &&
+ (be16_to_cpu(vfc_cmd->error) == IBMVFC_PLOGI_REQUIRED))
ibmvfc_relogin(cmnd->device);
if (!cmnd->result && (!scsi_get_resid(cmnd) || (rsp->flags & FCP_RESID_OVER)))
@@ -1630,19 +1632,19 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
cmnd->scsi_done = done;
vfc_cmd = &evt->iu.cmd;
memset(vfc_cmd, 0, sizeof(*vfc_cmd));
- vfc_cmd->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp);
- vfc_cmd->resp.len = sizeof(vfc_cmd->rsp);
- vfc_cmd->frame_type = IBMVFC_SCSI_FCP_TYPE;
- vfc_cmd->payload_len = sizeof(vfc_cmd->iu);
- vfc_cmd->resp_len = sizeof(vfc_cmd->rsp);
- vfc_cmd->cancel_key = (unsigned long)cmnd->device->hostdata;
- vfc_cmd->tgt_scsi_id = rport->port_id;
- vfc_cmd->iu.xfer_len = scsi_bufflen(cmnd);
+ vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp));
+ vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->rsp));
+ vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE);
+ vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->iu));
+ vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->rsp));
+ vfc_cmd->cancel_key = cpu_to_be32((unsigned long)cmnd->device->hostdata);
+ vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id);
+ vfc_cmd->iu.xfer_len = cpu_to_be32(scsi_bufflen(cmnd));
int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun);
memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len);
if (scsi_populate_tag_msg(cmnd, tag)) {
- vfc_cmd->task_tag = tag[1];
+ vfc_cmd->task_tag = cpu_to_be64(tag[1]);
switch (tag[0]) {
case MSG_SIMPLE_TAG:
vfc_cmd->iu.pri_task_attr = IBMVFC_SIMPLE_TASK;
@@ -1732,12 +1734,12 @@ static int ibmvfc_bsg_timeout(struct fc_bsg_job *job)
tmf = &evt->iu.tmf;
memset(tmf, 0, sizeof(*tmf));
- tmf->common.version = 1;
- tmf->common.opcode = IBMVFC_TMF_MAD;
- tmf->common.length = sizeof(*tmf);
- tmf->scsi_id = port_id;
- tmf->cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY;
- tmf->my_cancel_key = IBMVFC_INTERNAL_CANCEL_KEY;
+ tmf->common.version = cpu_to_be32(1);
+ tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD);
+ tmf->common.length = cpu_to_be16(sizeof(*tmf));
+ tmf->scsi_id = cpu_to_be64(port_id);
+ tmf->cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY);
+ tmf->my_cancel_key = cpu_to_be32(IBMVFC_INTERNAL_CANCEL_KEY);
rc = ibmvfc_send_event(evt, vhost, default_timeout);
if (rc != 0) {
@@ -1789,10 +1791,10 @@ static int ibmvfc_bsg_plogi(struct ibmvfc_host *vhost, unsigned int port_id)
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
plogi = &evt->iu.plogi;
memset(plogi, 0, sizeof(*plogi));
- plogi->common.version = 1;
- plogi->common.opcode = IBMVFC_PORT_LOGIN;
- plogi->common.length = sizeof(*plogi);
- plogi->scsi_id = port_id;
+ plogi->common.version = cpu_to_be32(1);
+ plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN);
+ plogi->common.length = cpu_to_be16(sizeof(*plogi));
+ plogi->scsi_id = cpu_to_be64(port_id);
evt->sync_iu = &rsp_iu;
init_completion(&evt->comp);
@@ -1904,26 +1906,26 @@ static int ibmvfc_bsg_request(struct fc_bsg_job *job)
mad = &evt->iu.passthru;
memset(mad, 0, sizeof(*mad));
- mad->common.version = 1;
- mad->common.opcode = IBMVFC_PASSTHRU;
- mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu);
-
- mad->cmd_ioba.va = (u64)evt->crq.ioba +
- offsetof(struct ibmvfc_passthru_mad, iu);
- mad->cmd_ioba.len = sizeof(mad->iu);
-
- mad->iu.cmd_len = job->request_payload.payload_len;
- mad->iu.rsp_len = job->reply_payload.payload_len;
- mad->iu.flags = fc_flags;
- mad->iu.cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY;
-
- mad->iu.cmd.va = sg_dma_address(job->request_payload.sg_list);
- mad->iu.cmd.len = sg_dma_len(job->request_payload.sg_list);
- mad->iu.rsp.va = sg_dma_address(job->reply_payload.sg_list);
- mad->iu.rsp.len = sg_dma_len(job->reply_payload.sg_list);
- mad->iu.scsi_id = port_id;
- mad->iu.tag = (u64)evt;
- rsp_len = mad->iu.rsp.len;
+ mad->common.version = cpu_to_be32(1);
+ mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU);
+ mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu));
+
+ mad->cmd_ioba.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) +
+ offsetof(struct ibmvfc_passthru_mad, iu));
+ mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu));
+
+ mad->iu.cmd_len = cpu_to_be32(job->request_payload.payload_len);
+ mad->iu.rsp_len = cpu_to_be32(job->reply_payload.payload_len);
+ mad->iu.flags = cpu_to_be32(fc_flags);
+ mad->iu.cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY);
+
+ mad->iu.cmd.va = cpu_to_be64(sg_dma_address(job->request_payload.sg_list));
+ mad->iu.cmd.len = cpu_to_be32(sg_dma_len(job->request_payload.sg_list));
+ mad->iu.rsp.va = cpu_to_be64(sg_dma_address(job->reply_payload.sg_list));
+ mad->iu.rsp.len = cpu_to_be32(sg_dma_len(job->reply_payload.sg_list));
+ mad->iu.scsi_id = cpu_to_be64(port_id);
+ mad->iu.tag = cpu_to_be64((u64)evt);
+ rsp_len = be32_to_cpu(mad->iu.rsp.len);
evt->sync_iu = &rsp_iu;
init_completion(&evt->comp);
@@ -1986,15 +1988,15 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
tmf = &evt->iu.cmd;
memset(tmf, 0, sizeof(*tmf));
- tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp);
- tmf->resp.len = sizeof(tmf->rsp);
- tmf->frame_type = IBMVFC_SCSI_FCP_TYPE;
- tmf->payload_len = sizeof(tmf->iu);
- tmf->resp_len = sizeof(tmf->rsp);
- tmf->cancel_key = (unsigned long)sdev->hostdata;
- tmf->tgt_scsi_id = rport->port_id;
+ tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp));
+ tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp));
+ tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE);
+ tmf->payload_len = cpu_to_be32(sizeof(tmf->iu));
+ tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp));
+ tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
+ tmf->tgt_scsi_id = cpu_to_be64(rport->port_id);
int_to_scsilun(sdev->lun, &tmf->iu.lun);
- tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF);
+ tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF));
tmf->iu.tmf_flags = type;
evt->sync_iu = &rsp_iu;
@@ -2020,8 +2022,8 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
rsp_code = fc_rsp->data.info.rsp_code;
sdev_printk(KERN_ERR, sdev, "%s reset failed: %s (%x:%x) "
- "flags: %x fcp_rsp: %x, scsi_status: %x\n",
- desc, ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error),
+ "flags: %x fcp_rsp: %x, scsi_status: %x\n", desc,
+ ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)),
rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code,
fc_rsp->scsi_status);
rsp_rc = -EIO;
@@ -2185,19 +2187,19 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
tmf = &evt->iu.tmf;
memset(tmf, 0, sizeof(*tmf));
- tmf->common.version = 1;
- tmf->common.opcode = IBMVFC_TMF_MAD;
- tmf->common.length = sizeof(*tmf);
- tmf->scsi_id = rport->port_id;
+ tmf->common.version = cpu_to_be32(1);
+ tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD);
+ tmf->common.length = cpu_to_be16(sizeof(*tmf));
+ tmf->scsi_id = cpu_to_be64(rport->port_id);
int_to_scsilun(sdev->lun, &tmf->lun);
- if (!(vhost->login_buf->resp.capabilities & IBMVFC_CAN_SUPPRESS_ABTS))
+ if (!(be64_to_cpu(vhost->login_buf->resp.capabilities) & IBMVFC_CAN_SUPPRESS_ABTS))
type &= ~IBMVFC_TMF_SUPPRESS_ABTS;
if (vhost->state == IBMVFC_ACTIVE)
- tmf->flags = (type | IBMVFC_TMF_LUA_VALID);
+ tmf->flags = cpu_to_be32((type | IBMVFC_TMF_LUA_VALID));
else
- tmf->flags = ((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID);
- tmf->cancel_key = (unsigned long)sdev->hostdata;
- tmf->my_cancel_key = (unsigned long)starget->hostdata;
+ tmf->flags = cpu_to_be32(((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID));
+ tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
+ tmf->my_cancel_key = cpu_to_be32((unsigned long)starget->hostdata);
evt->sync_iu = &rsp;
init_completion(&evt->comp);
@@ -2217,7 +2219,7 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
sdev_printk(KERN_INFO, sdev, "Cancelling outstanding commands.\n");
wait_for_completion(&evt->comp);
- status = rsp.mad_common.status;
+ status = be16_to_cpu(rsp.mad_common.status);
spin_lock_irqsave(vhost->host->host_lock, flags);
ibmvfc_free_event(evt);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
@@ -2252,7 +2254,7 @@ static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key)
unsigned long cancel_key = (unsigned long)key;
if (evt->crq.format == IBMVFC_CMD_FORMAT &&
- evt->iu.cmd.cancel_key == cancel_key)
+ be32_to_cpu(evt->iu.cmd.cancel_key) == cancel_key)
return 1;
return 0;
}
@@ -2316,15 +2318,15 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
tmf = &evt->iu.cmd;
memset(tmf, 0, sizeof(*tmf));
- tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp);
- tmf->resp.len = sizeof(tmf->rsp);
- tmf->frame_type = IBMVFC_SCSI_FCP_TYPE;
- tmf->payload_len = sizeof(tmf->iu);
- tmf->resp_len = sizeof(tmf->rsp);
- tmf->cancel_key = (unsigned long)sdev->hostdata;
- tmf->tgt_scsi_id = rport->port_id;
+ tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp));
+ tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp));
+ tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE);
+ tmf->payload_len = cpu_to_be32(sizeof(tmf->iu));
+ tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp));
+ tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
+ tmf->tgt_scsi_id = cpu_to_be64(rport->port_id);
int_to_scsilun(sdev->lun, &tmf->iu.lun);
- tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF);
+ tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF));
tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET;
evt->sync_iu = &rsp_iu;
@@ -2380,7 +2382,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) "
"flags: %x fcp_rsp: %x, scsi_status: %x\n",
- ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error),
+ ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)),
rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code,
fc_rsp->scsi_status);
rsp_rc = -EIO;
@@ -2641,14 +2643,14 @@ static const char *ibmvfc_get_link_state(enum ibmvfc_ae_link_state state)
static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
struct ibmvfc_host *vhost)
{
- const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(crq->event);
+ const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(be64_to_cpu(crq->event));
struct ibmvfc_target *tgt;
ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwpn: %llx,"
" node_name: %llx%s\n", desc->desc, crq->scsi_id, crq->wwpn, crq->node_name,
ibmvfc_get_link_state(crq->link_state));
- switch (crq->event) {
+ switch (be64_to_cpu(crq->event)) {
case IBMVFC_AE_RESUME:
switch (crq->link_state) {
case IBMVFC_AE_LS_LINK_DOWN:
@@ -2691,15 +2693,15 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
list_for_each_entry(tgt, &vhost->targets, queue) {
if (!crq->scsi_id && !crq->wwpn && !crq->node_name)
break;
- if (crq->scsi_id && tgt->scsi_id != crq->scsi_id)
+ if (crq->scsi_id && cpu_to_be64(tgt->scsi_id) != crq->scsi_id)
continue;
- if (crq->wwpn && tgt->ids.port_name != crq->wwpn)
+ if (crq->wwpn && cpu_to_be64(tgt->ids.port_name) != crq->wwpn)
continue;
- if (crq->node_name && tgt->ids.node_name != crq->node_name)
+ if (crq->node_name && cpu_to_be64(tgt->ids.node_name) != crq->node_name)
continue;
- if (tgt->need_login && crq->event == IBMVFC_AE_ELS_LOGO)
+ if (tgt->need_login && be64_to_cpu(crq->event) == IBMVFC_AE_ELS_LOGO)
tgt->logo_rcvd = 1;
- if (!tgt->need_login || crq->event == IBMVFC_AE_ELS_PLOGI) {
+ if (!tgt->need_login || be64_to_cpu(crq->event) == IBMVFC_AE_ELS_PLOGI) {
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
ibmvfc_reinit_host(vhost);
}
@@ -2730,7 +2732,7 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
{
long rc;
- struct ibmvfc_event *evt = (struct ibmvfc_event *)crq->ioba;
+ struct ibmvfc_event *evt = (struct ibmvfc_event *)be64_to_cpu(crq->ioba);
switch (crq->valid) {
case IBMVFC_CRQ_INIT_RSP:
@@ -3336,7 +3338,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli;
struct ibmvfc_prli_svc_parms *parms = &rsp->parms;
- u32 status = rsp->common.status;
+ u32 status = be16_to_cpu(rsp->common.status);
int index, level = IBMVFC_DEFAULT_LOG_LEVEL;
vhost->discovery_threads--;
@@ -3347,14 +3349,14 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
parms->type, parms->flags, parms->service_parms);
if (parms->type == IBMVFC_SCSI_FCP_TYPE) {
- index = ibmvfc_get_prli_rsp(parms->flags);
+ index = ibmvfc_get_prli_rsp(be16_to_cpu(parms->flags));
if (prli_rsp[index].logged_in) {
- if (parms->flags & IBMVFC_PRLI_EST_IMG_PAIR) {
+ if (be16_to_cpu(parms->flags) & IBMVFC_PRLI_EST_IMG_PAIR) {
tgt->need_login = 0;
tgt->ids.roles = 0;
- if (parms->service_parms & IBMVFC_PRLI_TARGET_FUNC)
+ if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_TARGET_FUNC)
tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET;
- if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC)
+ if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_INITIATOR_FUNC)
tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR;
tgt->add_rport = 1;
} else
@@ -3373,17 +3375,18 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
break;
case IBMVFC_MAD_FAILED:
default:
- if ((rsp->status & IBMVFC_VIOS_FAILURE) && rsp->error == IBMVFC_PLOGI_REQUIRED)
+ if ((be16_to_cpu(rsp->status) & IBMVFC_VIOS_FAILURE) &&
+ be16_to_cpu(rsp->error) == IBMVFC_PLOGI_REQUIRED)
level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
else if (tgt->logo_rcvd)
level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
- else if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+ else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli);
else
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n",
- ibmvfc_get_cmd_error(rsp->status, rsp->error),
+ ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
rsp->status, rsp->error, status);
break;
};
@@ -3414,14 +3417,14 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt)
evt->tgt = tgt;
prli = &evt->iu.prli;
memset(prli, 0, sizeof(*prli));
- prli->common.version = 1;
- prli->common.opcode = IBMVFC_PROCESS_LOGIN;
- prli->common.length = sizeof(*prli);
- prli->scsi_id = tgt->scsi_id;
+ prli->common.version = cpu_to_be32(1);
+ prli->common.opcode = cpu_to_be32(IBMVFC_PROCESS_LOGIN);
+ prli->common.length = cpu_to_be16(sizeof(*prli));
+ prli->scsi_id = cpu_to_be64(tgt->scsi_id);
prli->parms.type = IBMVFC_SCSI_FCP_TYPE;
- prli->parms.flags = IBMVFC_PRLI_EST_IMG_PAIR;
- prli->parms.service_parms = IBMVFC_PRLI_INITIATOR_FUNC;
+ prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR);
+ prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_INITIATOR_FUNC);
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
if (ibmvfc_send_event(evt, vhost, default_timeout)) {
@@ -3442,7 +3445,7 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt)
struct ibmvfc_target *tgt = evt->tgt;
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_port_login *rsp = &evt->xfer_iu->plogi;
- u32 status = rsp->common.status;
+ u32 status = be16_to_cpu(rsp->common.status);
int level = IBMVFC_DEFAULT_LOG_LEVEL;
vhost->discovery_threads--;
@@ -3472,15 +3475,15 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt)
break;
case IBMVFC_MAD_FAILED:
default:
- if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+ if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi);
else
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
- ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error,
- ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type,
- ibmvfc_get_ls_explain(rsp->fc_explain), rsp->fc_explain, status);
+ ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), rsp->status, rsp->error,
+ ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), rsp->fc_type,
+ ibmvfc_get_ls_explain(be16_to_cpu(rsp->fc_explain)), rsp->fc_explain, status);
break;
};
@@ -3512,10 +3515,10 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *tgt)
evt->tgt = tgt;
plogi = &evt->iu.plogi;
memset(plogi, 0, sizeof(*plogi));
- plogi->common.version = 1;
- plogi->common.opcode = IBMVFC_PORT_LOGIN;
- plogi->common.length = sizeof(*plogi);
- plogi->scsi_id = tgt->scsi_id;
+ plogi->common.version = cpu_to_be32(1);
+ plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN);
+ plogi->common.length = cpu_to_be16(sizeof(*plogi));
+ plogi->scsi_id = cpu_to_be64(tgt->scsi_id);
if (ibmvfc_send_event(evt, vhost, default_timeout)) {
vhost->discovery_threads--;
@@ -3535,7 +3538,7 @@ static void ibmvfc_tgt_implicit_logout_done(struct ibmvfc_event *evt)
struct ibmvfc_target *tgt = evt->tgt;
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_implicit_logout *rsp = &evt->xfer_iu->implicit_logout;
- u32 status = rsp->common.status;
+ u32 status = be16_to_cpu(rsp->common.status);
vhost->discovery_threads--;
ibmvfc_free_event(evt);
@@ -3585,10 +3588,10 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt)
evt->tgt = tgt;
mad = &evt->iu.implicit_logout;
memset(mad, 0, sizeof(*mad));
- mad->common.version = 1;
- mad->common.opcode = IBMVFC_IMPLICIT_LOGOUT;
- mad->common.length = sizeof(*mad);
- mad->old_scsi_id = tgt->scsi_id;
+ mad->common.version = cpu_to_be32(1);
+ mad->common.opcode = cpu_to_be32(IBMVFC_IMPLICIT_LOGOUT);
+ mad->common.length = cpu_to_be16(sizeof(*mad));
+ mad->old_scsi_id = cpu_to_be64(tgt->scsi_id);
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
if (ibmvfc_send_event(evt, vhost, default_timeout)) {
@@ -3616,7 +3619,7 @@ static int ibmvfc_adisc_needs_plogi(struct ibmvfc_passthru_mad *mad,
if (memcmp(&mad->fc_iu.response[4], &tgt->ids.node_name,
sizeof(tgt->ids.node_name)))
return 1;
- if (mad->fc_iu.response[6] != tgt->scsi_id)
+ if (be32_to_cpu(mad->fc_iu.response[6]) != tgt->scsi_id)
return 1;
return 0;
}
@@ -3631,7 +3634,7 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt)
struct ibmvfc_target *tgt = evt->tgt;
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru;
- u32 status = mad->common.status;
+ u32 status = be16_to_cpu(mad->common.status);
u8 fc_reason, fc_explain;
vhost->discovery_threads--;
@@ -3649,10 +3652,10 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt)
case IBMVFC_MAD_FAILED:
default:
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
- fc_reason = (mad->fc_iu.response[1] & 0x00ff0000) >> 16;
- fc_explain = (mad->fc_iu.response[1] & 0x0000ff00) >> 8;
+ fc_reason = (be32_to_cpu(mad->fc_iu.response[1]) & 0x00ff0000) >> 16;
+ fc_explain = (be32_to_cpu(mad->fc_iu.response[1]) & 0x0000ff00) >> 8;
tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
- ibmvfc_get_cmd_error(mad->iu.status, mad->iu.error),
+ ibmvfc_get_cmd_error(be16_to_cpu(mad->iu.status), be16_to_cpu(mad->iu.error)),
mad->iu.status, mad->iu.error,
ibmvfc_get_fc_type(fc_reason), fc_reason,
ibmvfc_get_ls_explain(fc_explain), fc_explain, status);
@@ -3674,22 +3677,22 @@ static void ibmvfc_init_passthru(struct ibmvfc_event *evt)
struct ibmvfc_passthru_mad *mad = &evt->iu.passthru;
memset(mad, 0, sizeof(*mad));
- mad->common.version = 1;
- mad->common.opcode = IBMVFC_PASSTHRU;
- mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu);
- mad->cmd_ioba.va = (u64)evt->crq.ioba +
- offsetof(struct ibmvfc_passthru_mad, iu);
- mad->cmd_ioba.len = sizeof(mad->iu);
- mad->iu.cmd_len = sizeof(mad->fc_iu.payload);
- mad->iu.rsp_len = sizeof(mad->fc_iu.response);
- mad->iu.cmd.va = (u64)evt->crq.ioba +
+ mad->common.version = cpu_to_be32(1);
+ mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU);
+ mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu));
+ mad->cmd_ioba.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) +
+ offsetof(struct ibmvfc_passthru_mad, iu));
+ mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu));
+ mad->iu.cmd_len = cpu_to_be32(sizeof(mad->fc_iu.payload));
+ mad->iu.rsp_len = cpu_to_be32(sizeof(mad->fc_iu.response));
+ mad->iu.cmd.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) +
offsetof(struct ibmvfc_passthru_mad, fc_iu) +
- offsetof(struct ibmvfc_passthru_fc_iu, payload);
- mad->iu.cmd.len = sizeof(mad->fc_iu.payload);
- mad->iu.rsp.va = (u64)evt->crq.ioba +
+ offsetof(struct ibmvfc_passthru_fc_iu, payload));
+ mad->iu.cmd.len = cpu_to_be32(sizeof(mad->fc_iu.payload));
+ mad->iu.rsp.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) +
offsetof(struct ibmvfc_passthru_mad, fc_iu) +
- offsetof(struct ibmvfc_passthru_fc_iu, response);
- mad->iu.rsp.len = sizeof(mad->fc_iu.response);
+ offsetof(struct ibmvfc_passthru_fc_iu, response));
+ mad->iu.rsp.len = cpu_to_be32(sizeof(mad->fc_iu.response));
}
/**
@@ -3748,11 +3751,11 @@ static void ibmvfc_adisc_timeout(struct ibmvfc_target *tgt)
evt->tgt = tgt;
tmf = &evt->iu.tmf;
memset(tmf, 0, sizeof(*tmf));
- tmf->common.version = 1;
- tmf->common.opcode = IBMVFC_TMF_MAD;
- tmf->common.length = sizeof(*tmf);
- tmf->scsi_id = tgt->scsi_id;
- tmf->cancel_key = tgt->cancel_key;
+ tmf->common.version = cpu_to_be32(1);
+ tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD);
+ tmf->common.length = cpu_to_be16(sizeof(*tmf));
+ tmf->scsi_id = cpu_to_be64(tgt->scsi_id);
+ tmf->cancel_key = cpu_to_be32(tgt->cancel_key);
rc = ibmvfc_send_event(evt, vhost, default_timeout);
@@ -3794,16 +3797,16 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
ibmvfc_init_passthru(evt);
mad = &evt->iu.passthru;
- mad->iu.flags = IBMVFC_FC_ELS;
- mad->iu.scsi_id = tgt->scsi_id;
- mad->iu.cancel_key = tgt->cancel_key;
+ mad->iu.flags = cpu_to_be32(IBMVFC_FC_ELS);
+ mad->iu.scsi_id = cpu_to_be64(tgt->scsi_id);
+ mad->iu.cancel_key = cpu_to_be32(tgt->cancel_key);
- mad->fc_iu.payload[0] = IBMVFC_ADISC;
+ mad->fc_iu.payload[0] = cpu_to_be32(IBMVFC_ADISC);
memcpy(&mad->fc_iu.payload[2], &vhost->login_buf->resp.port_name,
sizeof(vhost->login_buf->resp.port_name));
memcpy(&mad->fc_iu.payload[4], &vhost->login_buf->resp.node_name,
sizeof(vhost->login_buf->resp.node_name));
- mad->fc_iu.payload[6] = vhost->login_buf->resp.scsi_id & 0x00ffffff;
+ mad->fc_iu.payload[6] = cpu_to_be32(be64_to_cpu(vhost->login_buf->resp.scsi_id) & 0x00ffffff);
if (timer_pending(&tgt->timer))
mod_timer(&tgt->timer, jiffies + (IBMVFC_ADISC_TIMEOUT * HZ));
@@ -3834,7 +3837,7 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
struct ibmvfc_target *tgt = evt->tgt;
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_query_tgt *rsp = &evt->xfer_iu->query_tgt;
- u32 status = rsp->common.status;
+ u32 status = be16_to_cpu(rsp->common.status);
int level = IBMVFC_DEFAULT_LOG_LEVEL;
vhost->discovery_threads--;
@@ -3842,8 +3845,8 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
switch (status) {
case IBMVFC_MAD_SUCCESS:
tgt_dbg(tgt, "Query Target succeeded\n");
- tgt->new_scsi_id = rsp->scsi_id;
- if (rsp->scsi_id != tgt->scsi_id)
+ tgt->new_scsi_id = be64_to_cpu(rsp->scsi_id);
+ if (be64_to_cpu(rsp->scsi_id) != tgt->scsi_id)
ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
else
ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc);
@@ -3855,19 +3858,20 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt)
break;
case IBMVFC_MAD_FAILED:
default:
- if ((rsp->status & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED &&
- rsp->error == IBMVFC_UNABLE_TO_PERFORM_REQ &&
- rsp->fc_explain == IBMVFC_PORT_NAME_NOT_REG)
+ if ((be16_to_cpu(rsp->status) & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED &&
+ be16_to_cpu(rsp->error) == IBMVFC_UNABLE_TO_PERFORM_REQ &&
+ be16_to_cpu(rsp->fc_explain) == IBMVFC_PORT_NAME_NOT_REG)
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
- else if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+ else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target);
else
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n",
- ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error,
- ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type,
- ibmvfc_get_gs_explain(rsp->fc_explain), rsp->fc_explain, status);
+ ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
+ rsp->status, rsp->error, ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)),
+ rsp->fc_type, ibmvfc_get_gs_explain(be16_to_cpu(rsp->fc_explain)),
+ rsp->fc_explain, status);
break;
};
@@ -3897,10 +3901,10 @@ static void ibmvfc_tgt_query_target(struct ibmvfc_target *tgt)
ibmvfc_init_event(evt, ibmvfc_tgt_query_target_done, IBMVFC_MAD_FORMAT);
query_tgt = &evt->iu.query_tgt;
memset(query_tgt, 0, sizeof(*query_tgt));
- query_tgt->common.version = 1;
- query_tgt->common.opcode = IBMVFC_QUERY_TARGET;
- query_tgt->common.length = sizeof(*query_tgt);
- query_tgt->wwpn = tgt->ids.port_name;
+ query_tgt->common.version = cpu_to_be32(1);
+ query_tgt->common.opcode = cpu_to_be32(IBMVFC_QUERY_TARGET);
+ query_tgt->common.length = cpu_to_be16(sizeof(*query_tgt));
+ query_tgt->wwpn = cpu_to_be64(tgt->ids.port_name);
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
if (ibmvfc_send_event(evt, vhost, default_timeout)) {
@@ -3971,7 +3975,8 @@ static int ibmvfc_alloc_targets(struct ibmvfc_host *vhost)
for (i = 0, rc = 0; !rc && i < vhost->num_targets; i++)
rc = ibmvfc_alloc_target(vhost,
- vhost->disc_buf->scsi_id[i] & IBMVFC_DISC_TGT_SCSI_ID_MASK);
+ be32_to_cpu(vhost->disc_buf->scsi_id[i]) &
+ IBMVFC_DISC_TGT_SCSI_ID_MASK);
return rc;
}
@@ -3985,19 +3990,20 @@ static void ibmvfc_discover_targets_done(struct ibmvfc_event *evt)
{
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_discover_targets *rsp = &evt->xfer_iu->discover_targets;
- u32 mad_status = rsp->common.status;
+ u32 mad_status = be16_to_cpu(rsp->common.status);
int level = IBMVFC_DEFAULT_LOG_LEVEL;
switch (mad_status) {
case IBMVFC_MAD_SUCCESS:
ibmvfc_dbg(vhost, "Discover Targets succeeded\n");
- vhost->num_targets = rsp->num_written;
+ vhost->num_targets = be32_to_cpu(rsp->num_written);
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_ALLOC_TGTS);
break;
case IBMVFC_MAD_FAILED:
level += ibmvfc_retry_host_init(vhost);
ibmvfc_log(vhost, level, "Discover Targets failed: %s (%x:%x)\n",
- ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error);
+ ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
+ rsp->status, rsp->error);
break;
case IBMVFC_MAD_DRIVER_FAILED:
break;
@@ -4024,12 +4030,12 @@ static void ibmvfc_discover_targets(struct ibmvfc_host *vhost)
ibmvfc_init_event(evt, ibmvfc_discover_targets_done, IBMVFC_MAD_FORMAT);
mad = &evt->iu.discover_targets;
memset(mad, 0, sizeof(*mad));
- mad->common.version = 1;
- mad->common.opcode = IBMVFC_DISC_TARGETS;
- mad->common.length = sizeof(*mad);
- mad->bufflen = vhost->disc_buf_sz;
- mad->buffer.va = vhost->disc_buf_dma;
- mad->buffer.len = vhost->disc_buf_sz;
+ mad->common.version = cpu_to_be32(1);
+ mad->common.opcode = cpu_to_be32(IBMVFC_DISC_TARGETS);
+ mad->common.length = cpu_to_be16(sizeof(*mad));
+ mad->bufflen = cpu_to_be32(vhost->disc_buf_sz);
+ mad->buffer.va = cpu_to_be64(vhost->disc_buf_dma);
+ mad->buffer.len = cpu_to_be32(vhost->disc_buf_sz);
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT);
if (!ibmvfc_send_event(evt, vhost, default_timeout))
@@ -4046,7 +4052,7 @@ static void ibmvfc_discover_targets(struct ibmvfc_host *vhost)
static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
{
struct ibmvfc_host *vhost = evt->vhost;
- u32 mad_status = evt->xfer_iu->npiv_login.common.status;
+ u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_login.common.status);
struct ibmvfc_npiv_login_resp *rsp = &vhost->login_buf->resp;
unsigned int npiv_max_sectors;
int level = IBMVFC_DEFAULT_LOG_LEVEL;
@@ -4056,12 +4062,13 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
ibmvfc_free_event(evt);
break;
case IBMVFC_MAD_FAILED:
- if (ibmvfc_retry_cmd(rsp->status, rsp->error))
+ if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)))
level += ibmvfc_retry_host_init(vhost);
else
ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
ibmvfc_log(vhost, level, "NPIV Login failed: %s (%x:%x)\n",
- ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error);
+ ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
+ rsp->status, rsp->error);
ibmvfc_free_event(evt);
return;
case IBMVFC_MAD_CRQ_ERROR:
@@ -4078,7 +4085,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
vhost->client_migrated = 0;
- if (!(rsp->flags & IBMVFC_NATIVE_FC)) {
+ if (!(be32_to_cpu(rsp->flags) & IBMVFC_NATIVE_FC)) {
dev_err(vhost->dev, "Virtual adapter does not support FC. %x\n",
rsp->flags);
ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
@@ -4086,7 +4093,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
return;
}
- if (rsp->max_cmds <= IBMVFC_NUM_INTERNAL_REQ) {
+ if (be32_to_cpu(rsp->max_cmds) <= IBMVFC_NUM_INTERNAL_REQ) {
dev_err(vhost->dev, "Virtual adapter supported queue depth too small: %d\n",
rsp->max_cmds);
ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
@@ -4095,27 +4102,27 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
}
vhost->logged_in = 1;
- npiv_max_sectors = min((uint)(rsp->max_dma_len >> 9), IBMVFC_MAX_SECTORS);
+ npiv_max_sectors = min((uint)(be64_to_cpu(rsp->max_dma_len) >> 9), IBMVFC_MAX_SECTORS);
dev_info(vhost->dev, "Host partition: %s, device: %s %s %s max sectors %u\n",
rsp->partition_name, rsp->device_name, rsp->port_loc_code,
rsp->drc_name, npiv_max_sectors);
- fc_host_fabric_name(vhost->host) = rsp->node_name;
- fc_host_node_name(vhost->host) = rsp->node_name;
- fc_host_port_name(vhost->host) = rsp->port_name;
- fc_host_port_id(vhost->host) = rsp->scsi_id;
+ fc_host_fabric_name(vhost->host) = be64_to_cpu(rsp->node_name);
+ fc_host_node_name(vhost->host) = be64_to_cpu(rsp->node_name);
+ fc_host_port_name(vhost->host) = be64_to_cpu(rsp->port_name);
+ fc_host_port_id(vhost->host) = be64_to_cpu(rsp->scsi_id);
fc_host_port_type(vhost->host) = FC_PORTTYPE_NPIV;
fc_host_supported_classes(vhost->host) = 0;
- if (rsp->service_parms.class1_parms[0] & 0x80000000)
+ if (be32_to_cpu(rsp->service_parms.class1_parms[0]) & 0x80000000)
fc_host_supported_classes(vhost->host) |= FC_COS_CLASS1;
- if (rsp->service_parms.class2_parms[0] & 0x80000000)
+ if (be32_to_cpu(rsp->service_parms.class2_parms[0]) & 0x80000000)
fc_host_supported_classes(vhost->host) |= FC_COS_CLASS2;
- if (rsp->service_parms.class3_parms[0] & 0x80000000)
+ if (be32_to_cpu(rsp->service_parms.class3_parms[0]) & 0x80000000)
fc_host_supported_classes(vhost->host) |= FC_COS_CLASS3;
fc_host_maxframe_size(vhost->host) =
- rsp->service_parms.common.bb_rcv_sz & 0x0fff;
+ be16_to_cpu(rsp->service_parms.common.bb_rcv_sz) & 0x0fff;
- vhost->host->can_queue = rsp->max_cmds - IBMVFC_NUM_INTERNAL_REQ;
+ vhost->host->can_queue = be32_to_cpu(rsp->max_cmds) - IBMVFC_NUM_INTERNAL_REQ;
vhost->host->max_sectors = npiv_max_sectors;
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
wake_up(&vhost->work_wait_q);
@@ -4138,11 +4145,11 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost)
memcpy(vhost->login_buf, &vhost->login_info, sizeof(vhost->login_info));
mad = &evt->iu.npiv_login;
memset(mad, 0, sizeof(struct ibmvfc_npiv_login_mad));
- mad->common.version = 1;
- mad->common.opcode = IBMVFC_NPIV_LOGIN;
- mad->common.length = sizeof(struct ibmvfc_npiv_login_mad);
- mad->buffer.va = vhost->login_buf_dma;
- mad->buffer.len = sizeof(*vhost->login_buf);
+ mad->common.version = cpu_to_be32(1);
+ mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGIN);
+ mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_login_mad));
+ mad->buffer.va = cpu_to_be64(vhost->login_buf_dma);
+ mad->buffer.len = cpu_to_be32(sizeof(*vhost->login_buf));
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT);
@@ -4160,7 +4167,7 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost)
static void ibmvfc_npiv_logout_done(struct ibmvfc_event *evt)
{
struct ibmvfc_host *vhost = evt->vhost;
- u32 mad_status = evt->xfer_iu->npiv_logout.common.status;
+ u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_logout.common.status);
ibmvfc_free_event(evt);
@@ -4199,9 +4206,9 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *vhost)
mad = &evt->iu.npiv_logout;
memset(mad, 0, sizeof(*mad));
- mad->common.version = 1;
- mad->common.opcode = IBMVFC_NPIV_LOGOUT;
- mad->common.length = sizeof(struct ibmvfc_npiv_logout_mad);
+ mad->common.version = cpu_to_be32(1);
+ mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGOUT);
+ mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_logout_mad));
ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_LOGO_WAIT);
@@ -4343,14 +4350,14 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt)
if (rport) {
tgt_dbg(tgt, "rport add succeeded\n");
tgt->rport = rport;
- rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff;
+ rport->maxframe_size = be16_to_cpu(tgt->service_parms.common.bb_rcv_sz) & 0x0fff;
rport->supported_classes = 0;
tgt->target_id = rport->scsi_target_id;
- if (tgt->service_parms.class1_parms[0] & 0x80000000)
+ if (be32_to_cpu(tgt->service_parms.class1_parms[0]) & 0x80000000)
rport->supported_classes |= FC_COS_CLASS1;
- if (tgt->service_parms.class2_parms[0] & 0x80000000)
+ if (be32_to_cpu(tgt->service_parms.class2_parms[0]) & 0x80000000)
rport->supported_classes |= FC_COS_CLASS2;
- if (tgt->service_parms.class3_parms[0] & 0x80000000)
+ if (be32_to_cpu(tgt->service_parms.class3_parms[0]) & 0x80000000)
rport->supported_classes |= FC_COS_CLASS3;
if (rport->rqst_q)
blk_queue_max_segments(rport->rqst_q, 1);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 017a529..8fae032 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -135,12 +135,12 @@ enum ibmvfc_mad_types {
};
struct ibmvfc_mad_common {
- u32 version;
- u32 reserved;
- u32 opcode;
- u16 status;
- u16 length;
- u64 tag;
+ __be32 version;
+ __be32 reserved;
+ __be32 opcode;
+ __be16 status;
+ __be16 length;
+ __be64 tag;
}__attribute__((packed, aligned (8)));
struct ibmvfc_npiv_login_mad {
@@ -155,76 +155,76 @@ struct ibmvfc_npiv_logout_mad {
#define IBMVFC_MAX_NAME 256
struct ibmvfc_npiv_login {
- u32 ostype;
+ __be32 ostype;
#define IBMVFC_OS_LINUX 0x02
- u32 pad;
- u64 max_dma_len;
- u32 max_payload;
- u32 max_response;
- u32 partition_num;
- u32 vfc_frame_version;
- u16 fcp_version;
- u16 flags;
+ __be32 pad;
+ __be64 max_dma_len;
+ __be32 max_payload;
+ __be32 max_response;
+ __be32 partition_num;
+ __be32 vfc_frame_version;
+ __be16 fcp_version;
+ __be16 flags;
#define IBMVFC_CLIENT_MIGRATED 0x01
#define IBMVFC_FLUSH_ON_HALT 0x02
- u32 max_cmds;
- u64 capabilities;
+ __be32 max_cmds;
+ __be64 capabilities;
#define IBMVFC_CAN_MIGRATE 0x01
- u64 node_name;
+ __be64 node_name;
struct srp_direct_buf async;
u8 partition_name[IBMVFC_MAX_NAME];
u8 device_name[IBMVFC_MAX_NAME];
u8 drc_name[IBMVFC_MAX_NAME];
- u64 reserved2[2];
+ __be64 reserved2[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_common_svc_parms {
- u16 fcph_version;
- u16 b2b_credit;
- u16 features;
- u16 bb_rcv_sz; /* upper nibble is BB_SC_N */
- u32 ratov;
- u32 edtov;
+ __be16 fcph_version;
+ __be16 b2b_credit;
+ __be16 features;
+ __be16 bb_rcv_sz; /* upper nibble is BB_SC_N */
+ __be32 ratov;
+ __be32 edtov;
}__attribute__((packed, aligned (4)));
struct ibmvfc_service_parms {
struct ibmvfc_common_svc_parms common;
u8 port_name[8];
u8 node_name[8];
- u32 class1_parms[4];
- u32 class2_parms[4];
- u32 class3_parms[4];
- u32 obsolete[4];
- u32 vendor_version[4];
- u32 services_avail[2];
- u32 ext_len;
- u32 reserved[30];
- u32 clk_sync_qos[2];
+ __be32 class1_parms[4];
+ __be32 class2_parms[4];
+ __be32 class3_parms[4];
+ __be32 obsolete[4];
+ __be32 vendor_version[4];
+ __be32 services_avail[2];
+ __be32 ext_len;
+ __be32 reserved[30];
+ __be32 clk_sync_qos[2];
}__attribute__((packed, aligned (4)));
struct ibmvfc_npiv_login_resp {
- u32 version;
- u16 status;
- u16 error;
- u32 flags;
+ __be32 version;
+ __be16 status;
+ __be16 error;
+ __be32 flags;
#define IBMVFC_NATIVE_FC 0x01
- u32 reserved;
- u64 capabilities;
+ __be32 reserved;
+ __be64 capabilities;
#define IBMVFC_CAN_FLUSH_ON_HALT 0x08
#define IBMVFC_CAN_SUPPRESS_ABTS 0x10
- u32 max_cmds;
- u32 scsi_id_sz;
- u64 max_dma_len;
- u64 scsi_id;
- u64 port_name;
- u64 node_name;
- u64 link_speed;
+ __be32 max_cmds;
+ __be32 scsi_id_sz;
+ __be64 max_dma_len;
+ __be64 scsi_id;
+ __be64 port_name;
+ __be64 node_name;
+ __be64 link_speed;
u8 partition_name[IBMVFC_MAX_NAME];
u8 device_name[IBMVFC_MAX_NAME];
u8 port_loc_code[IBMVFC_MAX_NAME];
u8 drc_name[IBMVFC_MAX_NAME];
struct ibmvfc_service_parms service_parms;
- u64 reserved2;
+ __be64 reserved2;
}__attribute__((packed, aligned (8)));
union ibmvfc_npiv_login_data {
@@ -233,20 +233,20 @@ union ibmvfc_npiv_login_data {
}__attribute__((packed, aligned (8)));
struct ibmvfc_discover_targets_buf {
- u32 scsi_id[1];
+ __be32 scsi_id[1];
#define IBMVFC_DISC_TGT_SCSI_ID_MASK 0x00ffffff
};
struct ibmvfc_discover_targets {
struct ibmvfc_mad_common common;
struct srp_direct_buf buffer;
- u32 flags;
- u16 status;
- u16 error;
- u32 bufflen;
- u32 num_avail;
- u32 num_written;
- u64 reserved[2];
+ __be32 flags;
+ __be16 status;
+ __be16 error;
+ __be32 bufflen;
+ __be32 num_avail;
+ __be32 num_written;
+ __be64 reserved[2];
}__attribute__((packed, aligned (8)));
enum ibmvfc_fc_reason {
@@ -278,32 +278,32 @@ enum ibmvfc_gs_explain {
struct ibmvfc_port_login {
struct ibmvfc_mad_common common;
- u64 scsi_id;
- u16 reserved;
- u16 fc_service_class;
- u32 blksz;
- u32 hdr_per_blk;
- u16 status;
- u16 error; /* also fc_reason */
- u16 fc_explain;
- u16 fc_type;
- u32 reserved2;
+ __be64 scsi_id;
+ __be16 reserved;
+ __be16 fc_service_class;
+ __be32 blksz;
+ __be32 hdr_per_blk;
+ __be16 status;
+ __be16 error; /* also fc_reason */
+ __be16 fc_explain;
+ __be16 fc_type;
+ __be32 reserved2;
struct ibmvfc_service_parms service_parms;
struct ibmvfc_service_parms service_parms_change;
- u64 reserved3[2];
+ __be64 reserved3[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_prli_svc_parms {
u8 type;
#define IBMVFC_SCSI_FCP_TYPE 0x08
u8 type_ext;
- u16 flags;
+ __be16 flags;
#define IBMVFC_PRLI_ORIG_PA_VALID 0x8000
#define IBMVFC_PRLI_RESP_PA_VALID 0x4000
#define IBMVFC_PRLI_EST_IMG_PAIR 0x2000
- u32 orig_pa;
- u32 resp_pa;
- u32 service_parms;
+ __be32 orig_pa;
+ __be32 resp_pa;
+ __be32 service_parms;
#define IBMVFC_PRLI_TASK_RETRY 0x00000200
#define IBMVFC_PRLI_RETRY 0x00000100
#define IBMVFC_PRLI_DATA_OVERLAY 0x00000040
@@ -315,47 +315,47 @@ struct ibmvfc_prli_svc_parms {
struct ibmvfc_process_login {
struct ibmvfc_mad_common common;
- u64 scsi_id;
+ __be64 scsi_id;
struct ibmvfc_prli_svc_parms parms;
u8 reserved[48];
- u16 status;
- u16 error; /* also fc_reason */
- u32 reserved2;
- u64 reserved3[2];
+ __be16 status;
+ __be16 error; /* also fc_reason */
+ __be32 reserved2;
+ __be64 reserved3[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_query_tgt {
struct ibmvfc_mad_common common;
- u64 wwpn;
- u64 scsi_id;
- u16 status;
- u16 error;
- u16 fc_explain;
- u16 fc_type;
- u64 reserved[2];
+ __be64 wwpn;
+ __be64 scsi_id;
+ __be16 status;
+ __be16 error;
+ __be16 fc_explain;
+ __be16 fc_type;
+ __be64 reserved[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_implicit_logout {
struct ibmvfc_mad_common common;
- u64 old_scsi_id;
- u64 reserved[2];
+ __be64 old_scsi_id;
+ __be64 reserved[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_tmf {
struct ibmvfc_mad_common common;
- u64 scsi_id;
+ __be64 scsi_id;
struct scsi_lun lun;
- u32 flags;
+ __be32 flags;
#define IBMVFC_TMF_ABORT_TASK 0x02
#define IBMVFC_TMF_ABORT_TASK_SET 0x04
#define IBMVFC_TMF_LUN_RESET 0x10
#define IBMVFC_TMF_TGT_RESET 0x20
#define IBMVFC_TMF_LUA_VALID 0x40
#define IBMVFC_TMF_SUPPRESS_ABTS 0x80
- u32 cancel_key;
- u32 my_cancel_key;
- u32 pad;
- u64 reserved[2];
+ __be32 cancel_key;
+ __be32 my_cancel_key;
+ __be32 pad;
+ __be64 reserved[2];
}__attribute__((packed, aligned (8)));
enum ibmvfc_fcp_rsp_info_codes {
@@ -366,7 +366,7 @@ enum ibmvfc_fcp_rsp_info_codes {
};
struct ibmvfc_fcp_rsp_info {
- u16 reserved;
+ __be16 reserved;
u8 rsp_code;
u8 reserved2[4];
}__attribute__((packed, aligned (2)));
@@ -388,13 +388,13 @@ union ibmvfc_fcp_rsp_data {
}__attribute__((packed, aligned (8)));
struct ibmvfc_fcp_rsp {
- u64 reserved;
- u16 retry_delay_timer;
+ __be64 reserved;
+ __be16 retry_delay_timer;
u8 flags;
u8 scsi_status;
- u32 fcp_resid;
- u32 fcp_sense_len;
- u32 fcp_rsp_len;
+ __be32 fcp_resid;
+ __be32 fcp_sense_len;
+ __be32 fcp_rsp_len;
union ibmvfc_fcp_rsp_data data;
}__attribute__((packed, aligned (8)));
@@ -429,58 +429,58 @@ struct ibmvfc_fcp_cmd_iu {
#define IBMVFC_RDDATA 0x02
#define IBMVFC_WRDATA 0x01
u8 cdb[IBMVFC_MAX_CDB_LEN];
- u32 xfer_len;
+ __be32 xfer_len;
}__attribute__((packed, aligned (4)));
struct ibmvfc_cmd {
- u64 task_tag;
- u32 frame_type;
- u32 payload_len;
- u32 resp_len;
- u32 adapter_resid;
- u16 status;
- u16 error;
- u16 flags;
- u16 response_flags;
+ __be64 task_tag;
+ __be32 frame_type;
+ __be32 payload_len;
+ __be32 resp_len;
+ __be32 adapter_resid;
+ __be16 status;
+ __be16 error;
+ __be16 flags;
+ __be16 response_flags;
#define IBMVFC_ADAPTER_RESID_VALID 0x01
- u32 cancel_key;
- u32 exchange_id;
+ __be32 cancel_key;
+ __be32 exchange_id;
struct srp_direct_buf ext_func;
struct srp_direct_buf ioba;
struct srp_direct_buf resp;
- u64 correlation;
- u64 tgt_scsi_id;
- u64 tag;
- u64 reserved3[2];
+ __be64 correlation;
+ __be64 tgt_scsi_id;
+ __be64 tag;
+ __be64 reserved3[2];
struct ibmvfc_fcp_cmd_iu iu;
struct ibmvfc_fcp_rsp rsp;
}__attribute__((packed, aligned (8)));
struct ibmvfc_passthru_fc_iu {
- u32 payload[7];
+ __be32 payload[7];
#define IBMVFC_ADISC 0x52000000
- u32 response[7];
+ __be32 response[7];
};
struct ibmvfc_passthru_iu {
- u64 task_tag;
- u32 cmd_len;
- u32 rsp_len;
- u16 status;
- u16 error;
- u32 flags;
+ __be64 task_tag;
+ __be32 cmd_len;
+ __be32 rsp_len;
+ __be16 status;
+ __be16 error;
+ __be32 flags;
#define IBMVFC_FC_ELS 0x01
#define IBMVFC_FC_CT_IU 0x02
- u32 cancel_key;
+ __be32 cancel_key;
#define IBMVFC_PASSTHRU_CANCEL_KEY 0x80000000
#define IBMVFC_INTERNAL_CANCEL_KEY 0x80000001
- u32 reserved;
+ __be32 reserved;
struct srp_direct_buf cmd;
struct srp_direct_buf rsp;
- u64 correlation;
- u64 scsi_id;
- u64 tag;
- u64 reserved2[2];
+ __be64 correlation;
+ __be64 scsi_id;
+ __be64 tag;
+ __be64 reserved2[2];
}__attribute__((packed, aligned (8)));
struct ibmvfc_passthru_mad {
@@ -552,7 +552,7 @@ struct ibmvfc_crq {
volatile u8 valid;
volatile u8 format;
u8 reserved[6];
- volatile u64 ioba;
+ volatile __be64 ioba;
}__attribute__((packed, aligned (8)));
struct ibmvfc_crq_queue {
@@ -572,12 +572,12 @@ struct ibmvfc_async_crq {
volatile u8 valid;
u8 link_state;
u8 pad[2];
- u32 pad2;
- volatile u64 event;
- volatile u64 scsi_id;
- volatile u64 wwpn;
- volatile u64 node_name;
- u64 reserved;
+ __be32 pad2;
+ volatile __be64 event;
+ volatile __be64 scsi_id;
+ volatile __be64 wwpn;
+ volatile __be64 node_name;
+ __be64 reserved;
}__attribute__((packed, aligned (8)));
struct ibmvfc_async_crq_queue {
--
1.8.5.2
^ permalink raw reply related
* Re: BookE "branch taken" behavior vis-a-vis updating the NIP register
From: Sakthi @ 2014-06-27 0:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1384241835150-78036.post@n7.nabble.com>
pegasus,
Were you able to achieve the intended behavior with any of the suggested RFC
patch?
Thanks!
pegasus wrote
> I re-read the link you posted earlier and this time it made more sense to
> me. The kind of questions which are coming into my mind were being
> discussed.
>
> So, off I went and downloaded the latest version of
> arch/powerpc/kernel/traps.c hoping to see those very changes in them.
> However it didn't match one on one with what was written in that thread.
> Ditto for the other files in your patch. Looks like your patch didn't make
> it to upstream but it looks exactly like what I need here. So allow me to
> discuss certain finer points of it, to make sure I understand what it does
> correctly.
>
> In that thread you say
> James Yang wrote
>> BookE ISA's branch taken exception triggers before a branch that will be
>> taken executes. This allows software to examine the branch and the
>> conditions under which it will be taken. It also means software can tell
>> where basic blocks end (at least the ones which are terminated by taken
>> branches).
*
>> There are no architected registers that report the address of the branch
>> instruction after it has executed.
*
>
> My thoughts exactly!
>
> In the first patch's description, you say
> James Yang wrote
>> This patch makes available the unmodified BookE branch taken debug
>> exception through PTRACE_SINGLEBLOCK if the ptrace() addr parameter is
>> set to 2. (The existing behavior of PTRACE_SINGLEBLOCK is retained for
>> any other addr parameter value, e.g., 0.)
*
>> SIGTRAP will be signaled with the NIP pointing to the branch instruction
>> before it has executed. The ptrace-calling program can then examine the
>> program state.
*
>>
/
>> It should then request a PTRACE_SINGLESTEP in order to advance the
>> program to the next instruction or a PTRACE_CONT to resume normal program
>> execution.
/
>> The si_code now also reports TRAP_BRANCH.
> So requesting PTRACE_CONT has to happen inside the SIGTRAP signal handler
> right? So as to advance the branch instruction (and since we are talking
> BookE here, we are dead sure this branch will be taken). Now as for the
> second patch, as far as I can see, implements the same functionality.
> However it makes the change permanent and any tool which is used to the
> NIP pointing to the branch target will be broken.
>
> Anyways, for me either of them will work. But I think the first patch
> makes everyone happy by using the 'addr' field of ptrace. This also means
> I will have to make my (broken) ptrace working which, it seems is not as
> easy adding an enum field as you suggested. May be theres a check
> somewhere in the actual ptrace code which checks for illegal values and
> hence even after adding an enum, it is being reported as illegal in my
> case. However getting that to work is another story.
>
> Please confirm my understanding of your patches and since these patches
> have not made their way to the upstream kernel, will have to use them
> myself directly. By the way, I'm using 2.6.32.10 (you know..the long-term
> kernel) and I couldn't find any of your changes in them but then again I
> couldn't find it in the latest 3.12 version either.
--
View this message in context: http://linuxppc.10917.n7.nabble.com/BookE-branch-taken-behavior-vis-a-vis-updating-the-NIP-register-tp77960p83658.html
Sent from the linuxppc-dev mailing list archive at Nabble.com.
^ permalink raw reply
* Re: [RFC PATCH v2 6/6] mmc: core: add manual resume capability
From: Vincent Yang @ 2014-06-27 2:23 UTC (permalink / raw)
To: Ulf Hansson
Cc: devicetree, Andy Green, patches, Anton Vorontsov, linux-mmc,
chris, Vincent Yang, Jaswinder Singh, linuxppc-dev
In-Reply-To: <8b071848-f7df-4965-bd49-ae05b21ebe2e@email.android.com>
2014-06-26 17:42 GMT+08:00 Ulf Hansson <ulf.hansson@linaro.org>:
>
>
> On 26 juni 2014 08:23:32 CEST, Vincent Yang <vincent.yang.fujitsu@gmail.com> wrote:
>>This patch adds manual resume for some embedded platforms with rootfs
>>stored in SD card. It references CONFIG_MMC_BLOCK_DEFERRED_RESUME in
>>kernel 3.10. It lets host controller driver to manually handle resume
>>by itself.
>>
>>[symptom]
>>This issue is found on mb86s7x platforms with rootfs stored in SD card.
>>It failed to resume form STR suspend mode because SD card cannot be
>>ready
>>in time. It take longer time (e.g., 600ms) to be ready for access.
>>The error log looks like below:
>>
>>root@localhost:~# echo mem > /sys/power/state
>>[ 30.441974] SUSPEND
>>
>>SCB Firmware : Category 01 Version 02.03 Rev. 00_
>> Config : (no configuration)
>>root@localhost:~# [ 30.702976] Buffer I/O error on device mmcblk1p2,
>>logical block 31349
>>[ 30.709678] Buffer I/O error on device mmcblk1p2, logical block
>>168073
>>[ 30.716220] Buffer I/O error on device mmcblk1p2, logical block
>>168074
>>[ 30.722759] Buffer I/O error on device mmcblk1p2, logical block
>>168075
>>[ 30.729456] Buffer I/O error on device mmcblk1p2, logical block
>>31349
>>[ 30.735916] Buffer I/O error on device mmcblk1p2, logical block
>>31350
>>[ 30.742370] Buffer I/O error on device mmcblk1p2, logical block
>>31351
>>[ 30.749025] Buffer I/O error on device mmcblk1p2, logical block
>>168075
>>[ 30.755657] Buffer I/O error on device mmcblk1p2, logical block
>>31351
>>[ 30.763130] Aborting journal on device mmcblk1p2-8.
>>[ 30.768060] JBD2: Error -5 detected when updating journal superblock
>>for mmcblk1p2-8.
>>[ 30.776085] EXT4-fs error (device mmcblk1p2):
>>ext4_journal_check_start:56: Detected aborted journal
>>[ 30.785259] EXT4-fs (mmcblk1p2): Remounting filesystem read-only
>>[ 31.370716] EXT4-fs error (device mmcblk1p2): ext4_find_entry:1309:
>>inode #2490369: comm udevd: reading directory lblock 0
>>[ 31.382485] EXT4-fs error (device mmcblk1p2): ext4_find_entry:1309:
>>inode #1048577: comm udevd: reading directory lblock 0
>>
>>[analysis]
>>In system resume path, mmc_sd_resume() is failed with error code -123
>>because at that time SD card is still not ready on mb86s7x platforms.
>
> So why does it fail? It shouldn't!
>
> I get the impression that you are solving this in the wrong way.
Hi Uffe,
On mb86s7x EVB, power for SD card is completely removed when entering
STR suspend mode (i.e., echo mem > /sys/power/state). When system
starts to resume, it turns on the power for SD card again. However, It take
longer time (e.g., 600ms) to get the power ready.
This is why mmc_sd_resume() failed with error code -123. At that time point,
power for SD card is not ready yet.
At first we fixed it by a simple method of using SDHCI_QUIRK_DELAY_AFTER_POWER:
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 169e17d..ed28896 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1283,7 +1283,7 @@ static void sdhci_set_power(struct sdhci_host
*host, unsigned char mode,
* they can apply clock after applying power
*/
if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
- mdelay(10);
+ mdelay(600);
}
if (host->vmmc) {
However, we found it blocks the system resume path. It can slow down
system resume and also booting.
Therefore, we would like to resume SD card manually and asynchronously
by host controller driver itself. Thus system resume path is not blocked.
Thanks a lot for your review!
Best regards,
Vincent Yang
>
> Kind regards
> Uffe
>
>>
>>[solution]
>>In order to not blocking system resume path, this patch just sets a
>>flag
>>MMC_BUSRESUME_MANUAL_RESUME when this error happened, and then host
>>controller
>>driver can understand it by this flag. Then host controller driver have
>>to
>>resume SD card manually and asynchronously.
>>
>>Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
>>---
>> drivers/mmc/core/core.c | 4 ++
>> drivers/mmc/core/sd.c | 4 ++
>>drivers/mmc/host/sdhci_f_sdh30.c | 89
>>++++++++++++++++++++++++++++++++++++++++
>> include/linux/mmc/host.h | 14 +++++++
>> 4 files changed, 111 insertions(+)
>>
>>diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>>index 764af63..51fce49 100644
>>--- a/drivers/mmc/core/core.c
>>+++ b/drivers/mmc/core/core.c
>>@@ -2648,6 +2648,10 @@ int mmc_pm_notify(struct notifier_block
>>*notify_block,
>> case PM_POST_RESTORE:
>>
>> spin_lock_irqsave(&host->lock, flags);
>>+ if (mmc_bus_manual_resume(host)) {
>>+ spin_unlock_irqrestore(&host->lock, flags);
>>+ break;
>>+ }
>> host->rescan_disable = 0;
>> spin_unlock_irqrestore(&host->lock, flags);
>> _mmc_detect_change(host, 0, false);
>>diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
>>index 0c44510..859390d 100644
>>--- a/drivers/mmc/core/sd.c
>>+++ b/drivers/mmc/core/sd.c
>>@@ -1133,6 +1133,10 @@ static int mmc_sd_resume(struct mmc_host *host)
>>
>> if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
>> err = _mmc_sd_resume(host);
>>+ if ((host->caps2 & MMC_CAP2_MANUAL_RESUME) && err)
>>+ mmc_set_bus_resume_policy(host, 1);
>>+ else
>>+ mmc_set_bus_resume_policy(host, 0);
>> pm_runtime_set_active(&host->card->dev);
>> pm_runtime_mark_last_busy(&host->card->dev);
>> }
>>diff --git a/drivers/mmc/host/sdhci_f_sdh30.c
>>b/drivers/mmc/host/sdhci_f_sdh30.c
>>index 6fae509..67bcff2 100644
>>--- a/drivers/mmc/host/sdhci_f_sdh30.c
>>+++ b/drivers/mmc/host/sdhci_f_sdh30.c
>>@@ -30,6 +30,12 @@
>> #include "../core/core.h"
>>
>> #define DRIVER_NAME "f_sdh30"
>>+#define RESUME_WAIT_COUNT 100
>>+#define RESUME_WAIT_TIME 50
>>+#define RESUME_WAIT_JIFFIES msecs_to_jiffies(RESUME_DETECT_TIME)
>>+#define RESUME_DETECT_COUNT 16
>>+#define RESUME_DETECT_TIME 50
>>+#define RESUME_DETECT_JIFFIES msecs_to_jiffies(RESUME_DETECT_TIME)
>>
>>
>> struct f_sdhost_priv {
>>@@ -38,8 +44,59 @@ struct f_sdhost_priv {
>> int gpio_select_1v8;
>> u32 vendor_hs200;
>> struct device *dev;
>>+ unsigned int quirks; /* Deviations from spec. */
>>+
>>+/* retry to detect mmc device when resume */
>>+#define F_SDH30_QUIRK_RESUME_DETECT_RETRY (1<<0)
>>+
>>+ struct workqueue_struct *resume_detect_wq;
>>+ struct delayed_work resume_detect_work;
>>+ unsigned int resume_detect_count;
>>+ unsigned int resume_wait_count;
>> };
>>
>>+static void sdhci_f_sdh30_resume_detect_work_func(struct work_struct
>>*work)
>>+{
>>+ struct f_sdhost_priv *priv = container_of(work, struct f_sdhost_priv,
>>+ resume_detect_work.work);
>>+ struct sdhci_host *host = dev_get_drvdata(priv->dev);
>>+ int err = 0;
>>+
>>+ if (mmc_bus_manual_resume(host->mmc)) {
>>+ pm_runtime_disable(&host->mmc->card->dev);
>>+ mmc_card_set_suspended(host->mmc->card);
>>+ err = host->mmc->bus_ops->resume(host->mmc);
>>+ if (priv->resume_detect_count-- && err)
>>+ queue_delayed_work(priv->resume_detect_wq,
>>+ &priv->resume_detect_work,
>>+ RESUME_DETECT_JIFFIES);
>>+ else
>>+ pr_debug("%s: resume detection done (count:%d, wait:%d, err:%d)\n",
>>+ mmc_hostname(host->mmc),
>>+ priv->resume_detect_count,
>>+ priv->resume_wait_count, err);
>>+ } else {
>>+ if (priv->resume_wait_count--)
>>+ queue_delayed_work(priv->resume_detect_wq,
>>+ &priv->resume_detect_work,
>>+ RESUME_WAIT_JIFFIES);
>>+ else
>>+ pr_debug("%s: resume done\n", mmc_hostname(host->mmc));
>>+ }
>>+}
>>+
>>+static void sdhci_f_sdh30_resume_detect(struct mmc_host *mmc,
>>+ int detect, int wait)
>>+{
>>+ struct sdhci_host *host = mmc_priv(mmc);
>>+ struct f_sdhost_priv *priv = sdhci_priv(host);
>>+
>>+ priv->resume_detect_count = detect;
>>+ priv->resume_wait_count = wait;
>>+ queue_delayed_work(priv->resume_detect_wq,
>>+ &priv->resume_detect_work, 0);
>>+}
>>+
>> void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
>> {
>> struct f_sdhost_priv *priv = sdhci_priv(host);
>>@@ -146,6 +203,12 @@ static int sdhci_f_sdh30_probe(struct
>>platform_device *pdev)
>> }
>> }
>>
>>+ if (of_find_property(pdev->dev.of_node, "resume-detect-retry", NULL))
>>{
>>+ dev_info(dev, "Applying resume detect retry quirk\n");
>>+ priv->quirks |= F_SDH30_QUIRK_RESUME_DETECT_RETRY;
>>+ host->mmc->caps2 |= MMC_CAP2_MANUAL_RESUME;
>>+ }
>>+
>> ret = mmc_of_parse_voltage(pdev->dev.of_node, &host->ocr_mask);
>> if (ret) {
>> dev_err(dev, "%s: parse voltage error\n", __func__);
>>@@ -197,6 +260,18 @@ static int sdhci_f_sdh30_probe(struct
>>platform_device *pdev)
>> }
>> }
>>
>>+ /* Init workqueue */
>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY) {
>>+ priv->resume_detect_wq = create_workqueue("sdhci_f_sdh30");
>>+ if (priv->resume_detect_wq == NULL) {
>>+ ret = -ENOMEM;
>>+ dev_err(dev, "Failed to create resume detection workqueue\n");
>>+ goto err_init_wq;
>>+ }
>>+ INIT_DELAYED_WORK(&priv->resume_detect_work,
>>+ sdhci_f_sdh30_resume_detect_work_func);
>>+ }
>>+
>> ret = sdhci_add_host(host);
>> if (ret) {
>> dev_err(dev, "%s: host add error\n", __func__);
>>@@ -229,6 +304,9 @@ static int sdhci_f_sdh30_probe(struct
>>platform_device *pdev)
>> return 0;
>>
>> err_add_host:
>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY)
>>+ destroy_workqueue(priv->resume_detect_wq);
>>+err_init_wq:
>> if (gpio_is_valid(priv->gpio_select_1v8)) {
>> gpio_direction_output(priv->gpio_select_1v8, 1);
>> gpio_free(priv->gpio_select_1v8);
>>@@ -268,6 +346,9 @@ static int sdhci_f_sdh30_remove(struct
>>platform_device *pdev)
>> gpio_free(priv->gpio_select_1v8);
>> }
>>
>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY)
>>+ destroy_workqueue(priv->resume_detect_wq);
>>+
>> sdhci_free_host(host);
>> platform_set_drvdata(pdev, NULL);
>>
>>@@ -285,7 +366,15 @@ static int sdhci_f_sdh30_suspend(struct device
>>*dev)
>> static int sdhci_f_sdh30_resume(struct device *dev)
>> {
>> struct sdhci_host *host = dev_get_drvdata(dev);
>>+ struct f_sdhost_priv *priv = sdhci_priv(host);
>>
>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY) {
>>+ pr_debug("%s: start resume detect\n",
>>+ mmc_hostname(host->mmc));
>>+ sdhci_f_sdh30_resume_detect(host->mmc,
>>+ RESUME_DETECT_COUNT,
>>+ RESUME_WAIT_COUNT);
>>+ }
>> return sdhci_resume_host(host);
>> }
>> #endif
>>diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>>index 7960424..55221dd 100644
>>--- a/include/linux/mmc/host.h
>>+++ b/include/linux/mmc/host.h
>>@@ -283,6 +283,7 @@ struct mmc_host {
>> #define MMC_CAP2_HS400 (MMC_CAP2_HS400_1_8V | \
>> MMC_CAP2_HS400_1_2V)
>> #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17)
>>+#define MMC_CAP2_MANUAL_RESUME (1 << 18) /* Resume manually when
>>error */
>>
>> mmc_pm_flag_t pm_caps; /* supported pm features */
>>
>>@@ -338,6 +339,9 @@ struct mmc_host {
>> const struct mmc_bus_ops *bus_ops; /* current bus driver */
>> unsigned int bus_refs; /* reference counter */
>>
>>+ unsigned int bus_resume_flags;
>>+#define MMC_BUSRESUME_MANUAL_RESUME (1 << 0)
>>+
>> unsigned int sdio_irqs;
>> struct task_struct *sdio_irq_thread;
>> bool sdio_irq_pending;
>>@@ -384,6 +388,16 @@ static inline void *mmc_priv(struct mmc_host
>>*host)
>> #define mmc_dev(x) ((x)->parent)
>> #define mmc_classdev(x) (&(x)->class_dev)
>> #define mmc_hostname(x) (dev_name(&(x)->class_dev))
>>+#define mmc_bus_manual_resume(host) ((host)->bus_resume_flags & \
>>+ MMC_BUSRESUME_MANUAL_RESUME)
>>+
>>+static inline void mmc_set_bus_resume_policy(struct mmc_host *host,
>>int manual)
>>+{
>>+ if (manual)
>>+ host->bus_resume_flags |= MMC_BUSRESUME_MANUAL_RESUME;
>>+ else
>>+ host->bus_resume_flags &= ~MMC_BUSRESUME_MANUAL_RESUME;
>>+}
>>
>> int mmc_power_save_host(struct mmc_host *host);
>> int mmc_power_restore_host(struct mmc_host *host);
>
^ permalink raw reply related
* Re: [RFC PATCH v2 4/6] mmc: sdhci: host: add new f_sdh30
From: Vincent Yang @ 2014-06-27 3:32 UTC (permalink / raw)
To: Mark Rutland
Cc: devicetree@vger.kernel.org, andy.green@linaro.org,
patches@linaro.org, anton@enomsg.org, linux-mmc@vger.kernel.org,
chris@printf.net, Vincent.Yang@tw.fujitsu.com,
jaswinder.singh@linaro.org, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20140626110351.GN15240@leverpostej>
2014-06-26 19:03 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> On Thu, Jun 26, 2014 at 07:23:30AM +0100, Vincent Yang wrote:
>> This patch adds new host controller driver for
>> Fujitsu SDHCI controller f_sdh30.
>>
>> Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
>> ---
>> .../devicetree/bindings/mmc/sdhci-fujitsu.txt | 35 +++
>> drivers/mmc/host/Kconfig | 7 +
>> drivers/mmc/host/Makefile | 1 +
>> drivers/mmc/host/sdhci_f_sdh30.c | 346 +++++++++++++++++++++
>> drivers/mmc/host/sdhci_f_sdh30.h | 40 +++
>> 5 files changed, 429 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt
>> create mode 100644 drivers/mmc/host/sdhci_f_sdh30.c
>> create mode 100644 drivers/mmc/host/sdhci_f_sdh30.h
>>
>> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt b/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt
>> new file mode 100644
>> index 0000000..40add438
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt
>> @@ -0,0 +1,35 @@
>> +* Fujitsu SDHCI controller
>> +
>> +This file documents differences between the core properties in mmc.txt
>> +and the properties used by the sdhci_f_sdh30 driver.
>> +
>> +Required properties:
>> +- compatible: "fujitsu,f_sdh30"
>
> Please use '-' rather than '_' in compatible strings.
Hi Mark,
Yes, I'll update it to '-' in next version.
>
> This seems to be the name of the driver. What is the precise name of the
> IP block?
The name of the IP block is "F_SDH30".
That's why it uses "fujitsu,f_sdh30"
>
>> +- voltage-ranges : two cells are required, first cell specifies minimum
>> + slot voltage (mV), second cell specifies maximum slot voltage (mV).
>> + Several ranges could be specified.
>
> Describe this as a list of pairs, it's confusing otherwise.
>
> I'm not sure I follow what having multiple pairs implies.
Yes, I'll update it in next version.
>
>> +Optional properties:
>> +- gpios: This is one optional gpio for controlling a power mux which
>> + switches between two power supplies. 3.3V is selected when gpio is high,
>> + and 1.8V is selected when gpio is low. This voltage is used for signal
>> + level.
>
> Give this a more descriptive name, like power-mux-gpios. That will match
> up with the style of cd-gpios and wp-gpios.
Yes, I'll update it in next version.
>
>> +- clocks: Must contain an entry for each entry in clock-names. It is a
>> + list of phandles and clock-specifier pairs.
>> + See ../clocks/clock-bindings.txt for details.
>> +- clock-names: Should contain the following two entries:
>> + "sd_sd4clk" - clock primarily used for tuning process
>> + "sd_bclk" - base clock for sdhci controller
>> +
>> +Example:
>> +
>> + sdhci1: sdio@36600000 {
>> + compatible = "fujitsu,f_sdh30";
>> + reg = <0 0x36600000 0x1000>;
>> + interrupts = <0 172 0x4>,
>> + <0 173 0x4>;
>> + voltage-ranges = <1800 1800 3300 3300>;
>
> Place brackets around each pair to make this clearer:
>
> voltage-ranges = <1800 1800>, <3300 3300>;
Yes, I'll update it in next version.
>
> [...]
>
>> + if (!of_property_read_u32(pdev->dev.of_node, "vendor-hs200",
>> + &priv->vendor_hs200))
>> + dev_info(dev, "Applying vendor-hs200 setting\n");
>> + else
>> + priv->vendor_hs200 = 0;
>
> This wasn't in the binding document, and a grep for "vendor-hs200" in a
> v3.16-rc2 tree found me nothing.
>
> Please document this.
Yes, it is a setting for a vendor specific register.
I'll update it in next version.
>
>> +
>> + if (!of_property_read_u32(pdev->dev.of_node, "bus-width", &bus_width)) {
>> + if (bus_width == 8) {
>> + dev_info(dev, "Applying 8 bit bus width\n");
>> + host->mmc->caps |= MMC_CAP_8_BIT_DATA;
>> + }
>> + }
>
> What if bus-width is not 8, or is not present?
In both cases, it will not touch host->mmc->caps at all. Then sdhci_add_host()
will handle it and set MMC_CAP_4_BIT_DATA as default:
[...]
/*
* A controller may support 8-bit width, but the board itself
* might not have the pins brought out. Boards that support
* 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in
* their platform code before calling sdhci_add_host(), and we
* won't assume 8-bit width for hosts without that CAP.
*/
if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
mmc->caps |= MMC_CAP_4_BIT_DATA;
[...]
>
>> +
>> + ret = mmc_of_parse_voltage(pdev->dev.of_node, &host->ocr_mask);
>> + if (ret) {
>> + dev_err(dev, "%s: parse voltage error\n", __func__);
>> + goto err_voltage;
>> + }
>> +
>> + host->hw_name = DRIVER_NAME;
>> + host->ops = &sdhci_f_sdh30_ops;
>> + host->irq = irq;
>> +
>> + host->ioaddr = of_iomap(pdev->dev.of_node, 0);
>> + if (!host->ioaddr) {
>> + dev_err(dev, "%s: failed to remap registers\n", __func__);
>> + ret = -ENXIO;
>> + goto err_remap;
>> + }
>> +
>> + priv->clk_sd4 = of_clk_get(pdev->dev.of_node, 0);
>> + if (!IS_ERR(priv->clk_sd4)) {
>> + ret = clk_prepare_enable(priv->clk_sd4);
>> + if (ret < 0) {
>> + dev_err(dev, "Failed to enable sd4 clock: %d\n", ret);
>> + goto err_clk1;
>> + }
>> + }
>> + priv->clk_b = of_clk_get(pdev->dev.of_node, 1);
>> + if (!IS_ERR(priv->clk_b)) {
>> + ret = clk_prepare_enable(priv->clk_b);
>> + if (ret < 0) {
>> + dev_err(dev, "Failed to enable clk_b clock: %d\n", ret);
>> + goto err_clk2;
>> + }
>> + }
>
> Given you gave these names, get these by name rather than index. It's
> less surprising and more flexible.
Yes, I'll update them as below in next version.
- priv->clk_sd4 = of_clk_get(pdev->dev.of_node, 0);
+ priv->clk_sd4 = clk_get(&pdev->dev, "sd_sd4clk");
- priv->clk_b = of_clk_get(pdev->dev.of_node, 1);
+ priv->clk_b = clk_get(&pdev->dev, "sd_bclk");
Thanks a lot for your review!
Best regards,
Vincent Yang
>
> Thanks,
> Mark.
^ permalink raw reply
* Re: [PATCH v2 2/2] powerpc: bpf: Fix the broken LD_VLAN_TAG_PRESENT test
From: Michael Ellerman @ 2014-06-27 5:08 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: netdev, Denis Kirjanov, linuxppc-dev
In-Reply-To: <53ABDB72.9020902@redhat.com>
On Thu, 2014-06-26 at 10:36 +0200, Daniel Borkmann wrote:
> On 06/26/2014 10:30 AM, Michael Ellerman wrote:
> > On Wed, 2014-06-25 at 21:34 +0400, Denis Kirjanov wrote:
> >> We have to return the boolean here if the tag presents
> >> or not, not just ANDing the TCI with the mask which results to:
> >>
> >> [ 709.412097] test_bpf: #18 LD_VLAN_TAG_PRESENT
> >> [ 709.412245] ret 4096 != 1
> >> [ 709.412332] ret 4096 != 1
> >> [ 709.412333] FAIL (2 times)
> >
> > Hi Denis,
> >
> > Is this the same version of test_bpf that is in Linus' tree?
> >
> > I don't see any fails with that version, am I missing something?
> >
> > [ 187.690640] test_bpf: #18 LD_VLAN_TAG_PRESENT 46 50 PASS
>
> Did you try to modprobe test_bpf after enabling JIT, i.e. :
>
> echo 1 > /proc/sys/net/core/bpf_jit_enable
>
> Last time I tested with ppc64, I saw the interpreter passing
> while JIT failed, which the fix above should address.
Right, I thought CONFIG_BPF_JIT=y was sufficient.
But that just makes it available, I need to *also* enable it at runtime.
cheers
^ permalink raw reply
* Re: [RFC PATCH v2 6/6] mmc: core: add manual resume capability
From: Ulf Hansson @ 2014-06-27 9:40 UTC (permalink / raw)
To: Vincent Yang
Cc: devicetree, Andy Green, patches, Anton Vorontsov, linux-mmc,
chris, Vincent Yang, Jaswinder Singh, linuxppc-dev
In-Reply-To: <CAOEd-H2Xtpmj9LAnfX6SwcUSu3W1qvD32YNNPpB4ZQn_HF9-wg@mail.gmail.com>
On 27 juni 2014 04:23:42 CEST, Vincent Yang <vincent.yang.fujitsu@gmail.com> wrote:
>2014-06-26 17:42 GMT+08:00 Ulf Hansson <ulf.hansson@linaro.org>:
>>
>>
>> On 26 juni 2014 08:23:32 CEST, Vincent Yang
><vincent.yang.fujitsu@gmail.com> wrote:
>>>This patch adds manual resume for some embedded platforms with rootfs
>>>stored in SD card. It references CONFIG_MMC_BLOCK_DEFERRED_RESUME in
>>>kernel 3.10. It lets host controller driver to manually handle resume
>>>by itself.
>>>
>>>[symptom]
>>>This issue is found on mb86s7x platforms with rootfs stored in SD
>card.
>>>It failed to resume form STR suspend mode because SD card cannot be
>>>ready
>>>in time. It take longer time (e.g., 600ms) to be ready for access.
>>>The error log looks like below:
>>>
>>>root@localhost:~# echo mem > /sys/power/state
>>>[ 30.441974] SUSPEND
>>>
>>>SCB Firmware : Category 01 Version 02.03 Rev. 00_
>>> Config : (no configuration)
>>>root@localhost:~# [ 30.702976] Buffer I/O error on device
>mmcblk1p2,
>>>logical block 31349
>>>[ 30.709678] Buffer I/O error on device mmcblk1p2, logical block
>>>168073
>>>[ 30.716220] Buffer I/O error on device mmcblk1p2, logical block
>>>168074
>>>[ 30.722759] Buffer I/O error on device mmcblk1p2, logical block
>>>168075
>>>[ 30.729456] Buffer I/O error on device mmcblk1p2, logical block
>>>31349
>>>[ 30.735916] Buffer I/O error on device mmcblk1p2, logical block
>>>31350
>>>[ 30.742370] Buffer I/O error on device mmcblk1p2, logical block
>>>31351
>>>[ 30.749025] Buffer I/O error on device mmcblk1p2, logical block
>>>168075
>>>[ 30.755657] Buffer I/O error on device mmcblk1p2, logical block
>>>31351
>>>[ 30.763130] Aborting journal on device mmcblk1p2-8.
>>>[ 30.768060] JBD2: Error -5 detected when updating journal
>superblock
>>>for mmcblk1p2-8.
>>>[ 30.776085] EXT4-fs error (device mmcblk1p2):
>>>ext4_journal_check_start:56: Detected aborted journal
>>>[ 30.785259] EXT4-fs (mmcblk1p2): Remounting filesystem read-only
>>>[ 31.370716] EXT4-fs error (device mmcblk1p2):
>ext4_find_entry:1309:
>>>inode #2490369: comm udevd: reading directory lblock 0
>>>[ 31.382485] EXT4-fs error (device mmcblk1p2):
>ext4_find_entry:1309:
>>>inode #1048577: comm udevd: reading directory lblock 0
>>>
>>>[analysis]
>>>In system resume path, mmc_sd_resume() is failed with error code -123
>>>because at that time SD card is still not ready on mb86s7x platforms.
>>
>> So why does it fail? It shouldn't!
>>
>> I get the impression that you are solving this in the wrong way.
>
>Hi Uffe,
>On mb86s7x EVB, power for SD card is completely removed when entering
>STR suspend mode (i.e., echo mem > /sys/power/state). When system
>starts to resume, it turns on the power for SD card again. However, It
>take
>longer time (e.g., 600ms) to get the power ready.
>This is why mmc_sd_resume() failed with error code -123. At that time
>point,
>power for SD card is not ready yet.
>
>At first we fixed it by a simple method of using
>SDHCI_QUIRK_DELAY_AFTER_POWER:
>
>diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>index 169e17d..ed28896 100644
>--- a/drivers/mmc/host/sdhci.c
>+++ b/drivers/mmc/host/sdhci.c
>@@ -1283,7 +1283,7 @@ static void sdhci_set_power(struct sdhci_host
>*host, unsigned char mode,
> * they can apply clock after applying power
> */
> if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
>- mdelay(10);
>+ mdelay(600);
> }
If you can't model the power to the card through a regulator, this is what you need to do.
>
> if (host->vmmc) {
>
>However, we found it blocks the system resume path. It can slow down
>system resume and also booting.
>Therefore, we would like to resume SD card manually and asynchronously
>by host controller driver itself. Thus system resume path is not
>blocked.
That is accomplished by using MMC_CAP_RUNTIME_RESUME.
Kind regards
Uffe
>Thanks a lot for your review!
>
>
>Best regards,
>Vincent Yang
>
>>
>> Kind regards
>> Uffe
>>
>>>
>>>[solution]
>>>In order to not blocking system resume path, this patch just sets a
>>>flag
>>>MMC_BUSRESUME_MANUAL_RESUME when this error happened, and then host
>>>controller
>>>driver can understand it by this flag. Then host controller driver
>have
>>>to
>>>resume SD card manually and asynchronously.
>>>
>>>Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
>>>---
>>> drivers/mmc/core/core.c | 4 ++
>>> drivers/mmc/core/sd.c | 4 ++
>>>drivers/mmc/host/sdhci_f_sdh30.c | 89
>>>++++++++++++++++++++++++++++++++++++++++
>>> include/linux/mmc/host.h | 14 +++++++
>>> 4 files changed, 111 insertions(+)
>>>
>>>diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>>>index 764af63..51fce49 100644
>>>--- a/drivers/mmc/core/core.c
>>>+++ b/drivers/mmc/core/core.c
>>>@@ -2648,6 +2648,10 @@ int mmc_pm_notify(struct notifier_block
>>>*notify_block,
>>> case PM_POST_RESTORE:
>>>
>>> spin_lock_irqsave(&host->lock, flags);
>>>+ if (mmc_bus_manual_resume(host)) {
>>>+ spin_unlock_irqrestore(&host->lock, flags);
>>>+ break;
>>>+ }
>>> host->rescan_disable = 0;
>>> spin_unlock_irqrestore(&host->lock, flags);
>>> _mmc_detect_change(host, 0, false);
>>>diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
>>>index 0c44510..859390d 100644
>>>--- a/drivers/mmc/core/sd.c
>>>+++ b/drivers/mmc/core/sd.c
>>>@@ -1133,6 +1133,10 @@ static int mmc_sd_resume(struct mmc_host
>*host)
>>>
>>> if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
>>> err = _mmc_sd_resume(host);
>>>+ if ((host->caps2 & MMC_CAP2_MANUAL_RESUME) && err)
>>>+ mmc_set_bus_resume_policy(host, 1);
>>>+ else
>>>+ mmc_set_bus_resume_policy(host, 0);
>>> pm_runtime_set_active(&host->card->dev);
>>> pm_runtime_mark_last_busy(&host->card->dev);
>>> }
>>>diff --git a/drivers/mmc/host/sdhci_f_sdh30.c
>>>b/drivers/mmc/host/sdhci_f_sdh30.c
>>>index 6fae509..67bcff2 100644
>>>--- a/drivers/mmc/host/sdhci_f_sdh30.c
>>>+++ b/drivers/mmc/host/sdhci_f_sdh30.c
>>>@@ -30,6 +30,12 @@
>>> #include "../core/core.h"
>>>
>>> #define DRIVER_NAME "f_sdh30"
>>>+#define RESUME_WAIT_COUNT 100
>>>+#define RESUME_WAIT_TIME 50
>>>+#define RESUME_WAIT_JIFFIES msecs_to_jiffies(RESUME_DETECT_TIME)
>>>+#define RESUME_DETECT_COUNT 16
>>>+#define RESUME_DETECT_TIME 50
>>>+#define RESUME_DETECT_JIFFIES msecs_to_jiffies(RESUME_DETECT_TIME)
>>>
>>>
>>> struct f_sdhost_priv {
>>>@@ -38,8 +44,59 @@ struct f_sdhost_priv {
>>> int gpio_select_1v8;
>>> u32 vendor_hs200;
>>> struct device *dev;
>>>+ unsigned int quirks; /* Deviations from spec. */
>>>+
>>>+/* retry to detect mmc device when resume */
>>>+#define F_SDH30_QUIRK_RESUME_DETECT_RETRY (1<<0)
>>>+
>>>+ struct workqueue_struct *resume_detect_wq;
>>>+ struct delayed_work resume_detect_work;
>>>+ unsigned int resume_detect_count;
>>>+ unsigned int resume_wait_count;
>>> };
>>>
>>>+static void sdhci_f_sdh30_resume_detect_work_func(struct work_struct
>>>*work)
>>>+{
>>>+ struct f_sdhost_priv *priv = container_of(work, struct
>f_sdhost_priv,
>>>+ resume_detect_work.work);
>>>+ struct sdhci_host *host = dev_get_drvdata(priv->dev);
>>>+ int err = 0;
>>>+
>>>+ if (mmc_bus_manual_resume(host->mmc)) {
>>>+ pm_runtime_disable(&host->mmc->card->dev);
>>>+ mmc_card_set_suspended(host->mmc->card);
>>>+ err = host->mmc->bus_ops->resume(host->mmc);
>>>+ if (priv->resume_detect_count-- && err)
>>>+ queue_delayed_work(priv->resume_detect_wq,
>>>+ &priv->resume_detect_work,
>>>+ RESUME_DETECT_JIFFIES);
>>>+ else
>>>+ pr_debug("%s: resume detection done (count:%d,
>wait:%d, err:%d)\n",
>>>+ mmc_hostname(host->mmc),
>>>+ priv->resume_detect_count,
>>>+ priv->resume_wait_count, err);
>>>+ } else {
>>>+ if (priv->resume_wait_count--)
>>>+ queue_delayed_work(priv->resume_detect_wq,
>>>+ &priv->resume_detect_work,
>>>+ RESUME_WAIT_JIFFIES);
>>>+ else
>>>+ pr_debug("%s: resume done\n",
>mmc_hostname(host->mmc));
>>>+ }
>>>+}
>>>+
>>>+static void sdhci_f_sdh30_resume_detect(struct mmc_host *mmc,
>>>+ int detect, int wait)
>>>+{
>>>+ struct sdhci_host *host = mmc_priv(mmc);
>>>+ struct f_sdhost_priv *priv = sdhci_priv(host);
>>>+
>>>+ priv->resume_detect_count = detect;
>>>+ priv->resume_wait_count = wait;
>>>+ queue_delayed_work(priv->resume_detect_wq,
>>>+ &priv->resume_detect_work, 0);
>>>+}
>>>+
>>> void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
>>> {
>>> struct f_sdhost_priv *priv = sdhci_priv(host);
>>>@@ -146,6 +203,12 @@ static int sdhci_f_sdh30_probe(struct
>>>platform_device *pdev)
>>> }
>>> }
>>>
>>>+ if (of_find_property(pdev->dev.of_node, "resume-detect-retry",
>NULL))
>>>{
>>>+ dev_info(dev, "Applying resume detect retry quirk\n");
>>>+ priv->quirks |= F_SDH30_QUIRK_RESUME_DETECT_RETRY;
>>>+ host->mmc->caps2 |= MMC_CAP2_MANUAL_RESUME;
>>>+ }
>>>+
>>> ret = mmc_of_parse_voltage(pdev->dev.of_node,
>&host->ocr_mask);
>>> if (ret) {
>>> dev_err(dev, "%s: parse voltage error\n", __func__);
>>>@@ -197,6 +260,18 @@ static int sdhci_f_sdh30_probe(struct
>>>platform_device *pdev)
>>> }
>>> }
>>>
>>>+ /* Init workqueue */
>>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY) {
>>>+ priv->resume_detect_wq =
>create_workqueue("sdhci_f_sdh30");
>>>+ if (priv->resume_detect_wq == NULL) {
>>>+ ret = -ENOMEM;
>>>+ dev_err(dev, "Failed to create resume
>detection workqueue\n");
>>>+ goto err_init_wq;
>>>+ }
>>>+ INIT_DELAYED_WORK(&priv->resume_detect_work,
>>>+
>sdhci_f_sdh30_resume_detect_work_func);
>>>+ }
>>>+
>>> ret = sdhci_add_host(host);
>>> if (ret) {
>>> dev_err(dev, "%s: host add error\n", __func__);
>>>@@ -229,6 +304,9 @@ static int sdhci_f_sdh30_probe(struct
>>>platform_device *pdev)
>>> return 0;
>>>
>>> err_add_host:
>>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY)
>>>+ destroy_workqueue(priv->resume_detect_wq);
>>>+err_init_wq:
>>> if (gpio_is_valid(priv->gpio_select_1v8)) {
>>> gpio_direction_output(priv->gpio_select_1v8, 1);
>>> gpio_free(priv->gpio_select_1v8);
>>>@@ -268,6 +346,9 @@ static int sdhci_f_sdh30_remove(struct
>>>platform_device *pdev)
>>> gpio_free(priv->gpio_select_1v8);
>>> }
>>>
>>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY)
>>>+ destroy_workqueue(priv->resume_detect_wq);
>>>+
>>> sdhci_free_host(host);
>>> platform_set_drvdata(pdev, NULL);
>>>
>>>@@ -285,7 +366,15 @@ static int sdhci_f_sdh30_suspend(struct device
>>>*dev)
>>> static int sdhci_f_sdh30_resume(struct device *dev)
>>> {
>>> struct sdhci_host *host = dev_get_drvdata(dev);
>>>+ struct f_sdhost_priv *priv = sdhci_priv(host);
>>>
>>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY) {
>>>+ pr_debug("%s: start resume detect\n",
>>>+ mmc_hostname(host->mmc));
>>>+ sdhci_f_sdh30_resume_detect(host->mmc,
>>>+ RESUME_DETECT_COUNT,
>>>+ RESUME_WAIT_COUNT);
>>>+ }
>>> return sdhci_resume_host(host);
>>> }
>>> #endif
>>>diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>>>index 7960424..55221dd 100644
>>>--- a/include/linux/mmc/host.h
>>>+++ b/include/linux/mmc/host.h
>>>@@ -283,6 +283,7 @@ struct mmc_host {
>>> #define MMC_CAP2_HS400 (MMC_CAP2_HS400_1_8V | \
>>> MMC_CAP2_HS400_1_2V)
>>> #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17)
>>>+#define MMC_CAP2_MANUAL_RESUME (1 << 18) /* Resume manually
>when
>>>error */
>>>
>>> mmc_pm_flag_t pm_caps; /* supported pm
>features */
>>>
>>>@@ -338,6 +339,9 @@ struct mmc_host {
>>> const struct mmc_bus_ops *bus_ops; /* current bus driver
>*/
>>> unsigned int bus_refs; /* reference counter
>*/
>>>
>>>+ unsigned int bus_resume_flags;
>>>+#define MMC_BUSRESUME_MANUAL_RESUME (1 << 0)
>>>+
>>> unsigned int sdio_irqs;
>>> struct task_struct *sdio_irq_thread;
>>> bool sdio_irq_pending;
>>>@@ -384,6 +388,16 @@ static inline void *mmc_priv(struct mmc_host
>>>*host)
>>> #define mmc_dev(x) ((x)->parent)
>>> #define mmc_classdev(x) (&(x)->class_dev)
>>> #define mmc_hostname(x) (dev_name(&(x)->class_dev))
>>>+#define mmc_bus_manual_resume(host) ((host)->bus_resume_flags &
> \
>>>+ MMC_BUSRESUME_MANUAL_RESUME)
>>>+
>>>+static inline void mmc_set_bus_resume_policy(struct mmc_host *host,
>>>int manual)
>>>+{
>>>+ if (manual)
>>>+ host->bus_resume_flags |= MMC_BUSRESUME_MANUAL_RESUME;
>>>+ else
>>>+ host->bus_resume_flags &=
>~MMC_BUSRESUME_MANUAL_RESUME;
>>>+}
>>>
>>> int mmc_power_save_host(struct mmc_host *host);
>>> int mmc_power_restore_host(struct mmc_host *host);
>>
^ permalink raw reply
* Re: [PATCH v2 2/2] powerpc: bpf: Fix the broken LD_VLAN_TAG_PRESENT test
From: Daniel Borkmann @ 2014-06-27 9:46 UTC (permalink / raw)
To: Michael Ellerman; +Cc: netdev, Denis Kirjanov, linuxppc-dev
In-Reply-To: <1403845697.21873.1.camel@concordia>
On 06/27/2014 07:08 AM, Michael Ellerman wrote:
> On Thu, 2014-06-26 at 10:36 +0200, Daniel Borkmann wrote:
>> On 06/26/2014 10:30 AM, Michael Ellerman wrote:
>>> On Wed, 2014-06-25 at 21:34 +0400, Denis Kirjanov wrote:
>>>> We have to return the boolean here if the tag presents
>>>> or not, not just ANDing the TCI with the mask which results to:
>>>>
>>>> [ 709.412097] test_bpf: #18 LD_VLAN_TAG_PRESENT
>>>> [ 709.412245] ret 4096 != 1
>>>> [ 709.412332] ret 4096 != 1
>>>> [ 709.412333] FAIL (2 times)
>>>
>>> Hi Denis,
>>>
>>> Is this the same version of test_bpf that is in Linus' tree?
>>>
>>> I don't see any fails with that version, am I missing something?
>>>
>>> [ 187.690640] test_bpf: #18 LD_VLAN_TAG_PRESENT 46 50 PASS
>>
>> Did you try to modprobe test_bpf after enabling JIT, i.e. :
>>
>> echo 1 > /proc/sys/net/core/bpf_jit_enable
>>
>> Last time I tested with ppc64, I saw the interpreter passing
>> while JIT failed, which the fix above should address.
>
> Right, I thought CONFIG_BPF_JIT=y was sufficient.
>
> But that just makes it available, I need to *also* enable it at runtime.
Yes, it's an extra runtime knob which still needs to be enabled by
the admin for security reasons. This knob also allows you to enable
the debugging interface `echo 2 >/proc/sys/net/core/bpf_jit_enable`
where the disassembly can be read out via: tools/net/bpf_jit_disasm.c
^ permalink raw reply
* Re: [RFC PATCH v2 4/6] mmc: sdhci: host: add new f_sdh30
From: Mark Rutland @ 2014-06-27 10:12 UTC (permalink / raw)
To: Vincent Yang
Cc: devicetree@vger.kernel.org, andy.green@linaro.org,
patches@linaro.org, anton@enomsg.org, linux-mmc@vger.kernel.org,
chris@printf.net, Vincent.Yang@tw.fujitsu.com,
jaswinder.singh@linaro.org, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <CAOEd-H3+MwT3DMqMO0XHaZQqYAN0zaQqRMjC_UjyJn5ZwCaMoQ@mail.gmail.com>
On Fri, Jun 27, 2014 at 04:32:21AM +0100, Vincent Yang wrote:
> 2014-06-26 19:03 GMT+08:00 Mark Rutland <mark.rutland@arm.com>:
> > On Thu, Jun 26, 2014 at 07:23:30AM +0100, Vincent Yang wrote:
> >> This patch adds new host controller driver for
> >> Fujitsu SDHCI controller f_sdh30.
> >>
> >> Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
> >> ---
> >> .../devicetree/bindings/mmc/sdhci-fujitsu.txt | 35 +++
> >> drivers/mmc/host/Kconfig | 7 +
> >> drivers/mmc/host/Makefile | 1 +
> >> drivers/mmc/host/sdhci_f_sdh30.c | 346 +++++++++++++++++++++
> >> drivers/mmc/host/sdhci_f_sdh30.h | 40 +++
> >> 5 files changed, 429 insertions(+)
> >> create mode 100644 Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt
> >> create mode 100644 drivers/mmc/host/sdhci_f_sdh30.c
> >> create mode 100644 drivers/mmc/host/sdhci_f_sdh30.h
> >>
> >> diff --git a/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt b/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt
> >> new file mode 100644
> >> index 0000000..40add438
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt
> >> @@ -0,0 +1,35 @@
> >> +* Fujitsu SDHCI controller
> >> +
> >> +This file documents differences between the core properties in mmc.txt
> >> +and the properties used by the sdhci_f_sdh30 driver.
> >> +
> >> +Required properties:
> >> +- compatible: "fujitsu,f_sdh30"
> >
> > Please use '-' rather than '_' in compatible strings.
>
> Hi Mark,
> Yes, I'll update it to '-' in next version.
>
> >
> > This seems to be the name of the driver. What is the precise name of the
> > IP block?
>
> The name of the IP block is "F_SDH30".
> That's why it uses "fujitsu,f_sdh30"
Hmm. I'd still be tempted to use "fujitsu,f-sdh30".
> >
> > [...]
> >
> >> + if (!of_property_read_u32(pdev->dev.of_node, "vendor-hs200",
> >> + &priv->vendor_hs200))
> >> + dev_info(dev, "Applying vendor-hs200 setting\n");
> >> + else
> >> + priv->vendor_hs200 = 0;
> >
> > This wasn't in the binding document, and a grep for "vendor-hs200" in a
> > v3.16-rc2 tree found me nothing.
> >
> > Please document this.
>
> Yes, it is a setting for a vendor specific register.
> I'll update it in next version.
It would be nice to know exactly what this is. We usually shy clear of
placing register values in dt. I can wait until the next posting if
you're goin to document that.
> >> + if (!of_property_read_u32(pdev->dev.of_node, "bus-width", &bus_width)) {
> >> + if (bus_width == 8) {
> >> + dev_info(dev, "Applying 8 bit bus width\n");
> >> + host->mmc->caps |= MMC_CAP_8_BIT_DATA;
> >> + }
> >> + }
> >
> > What if bus-width is not 8, or is not present?
>
> In both cases, it will not touch host->mmc->caps at all. Then sdhci_add_host()
> will handle it and set MMC_CAP_4_BIT_DATA as default:
>
> [...]
> /*
> * A controller may support 8-bit width, but the board itself
> * might not have the pins brought out. Boards that support
> * 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in
> * their platform code before calling sdhci_add_host(), and we
> * won't assume 8-bit width for hosts without that CAP.
> */
> if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
> mmc->caps |= MMC_CAP_4_BIT_DATA;
Ok, but does it make sense for a dts to have:
bus-width = <1>;
If so, we should presumably do something.
If not, we should at least print a warning that the dtb doesn't make
sense.
Cheers,
Mark.
^ permalink raw reply
* Re: [RFC PATCH v2 6/6] mmc: core: add manual resume capability
From: Vincent Yang @ 2014-06-27 11:00 UTC (permalink / raw)
To: Ulf Hansson
Cc: devicetree@vger.kernel.org, Andy Green, patches@linaro.org,
Anton Vorontsov, linux-mmc@vger.kernel.org, chris@printf.net,
Jaswinder Singh, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <17c3cfc2-ae8c-4d19-8da5-fe40432f565c@email.android.com>
2014-06-27 17:40 GMT+08:00 Ulf Hansson <ulf.hansson@linaro.org>:
>
>
> On 27 juni 2014 04:23:42 CEST, Vincent Yang <vincent.yang.fujitsu@gmail.com> wrote:
>>2014-06-26 17:42 GMT+08:00 Ulf Hansson <ulf.hansson@linaro.org>:
>>>
>>>
>>> On 26 juni 2014 08:23:32 CEST, Vincent Yang
>><vincent.yang.fujitsu@gmail.com> wrote:
>>>>This patch adds manual resume for some embedded platforms with rootfs
>>>>stored in SD card. It references CONFIG_MMC_BLOCK_DEFERRED_RESUME in
>>>>kernel 3.10. It lets host controller driver to manually handle resume
>>>>by itself.
>>>>
>>>>[symptom]
>>>>This issue is found on mb86s7x platforms with rootfs stored in SD
>>card.
>>>>It failed to resume form STR suspend mode because SD card cannot be
>>>>ready
>>>>in time. It take longer time (e.g., 600ms) to be ready for access.
>>>>The error log looks like below:
>>>>
>>>>root@localhost:~# echo mem > /sys/power/state
>>>>[ 30.441974] SUSPEND
>>>>
>>>>SCB Firmware : Category 01 Version 02.03 Rev. 00_
>>>> Config : (no configuration)
>>>>root@localhost:~# [ 30.702976] Buffer I/O error on device
>>mmcblk1p2,
>>>>logical block 31349
>>>>[ 30.709678] Buffer I/O error on device mmcblk1p2, logical block
>>>>168073
>>>>[ 30.716220] Buffer I/O error on device mmcblk1p2, logical block
>>>>168074
>>>>[ 30.722759] Buffer I/O error on device mmcblk1p2, logical block
>>>>168075
>>>>[ 30.729456] Buffer I/O error on device mmcblk1p2, logical block
>>>>31349
>>>>[ 30.735916] Buffer I/O error on device mmcblk1p2, logical block
>>>>31350
>>>>[ 30.742370] Buffer I/O error on device mmcblk1p2, logical block
>>>>31351
>>>>[ 30.749025] Buffer I/O error on device mmcblk1p2, logical block
>>>>168075
>>>>[ 30.755657] Buffer I/O error on device mmcblk1p2, logical block
>>>>31351
>>>>[ 30.763130] Aborting journal on device mmcblk1p2-8.
>>>>[ 30.768060] JBD2: Error -5 detected when updating journal
>>superblock
>>>>for mmcblk1p2-8.
>>>>[ 30.776085] EXT4-fs error (device mmcblk1p2):
>>>>ext4_journal_check_start:56: Detected aborted journal
>>>>[ 30.785259] EXT4-fs (mmcblk1p2): Remounting filesystem read-only
>>>>[ 31.370716] EXT4-fs error (device mmcblk1p2):
>>ext4_find_entry:1309:
>>>>inode #2490369: comm udevd: reading directory lblock 0
>>>>[ 31.382485] EXT4-fs error (device mmcblk1p2):
>>ext4_find_entry:1309:
>>>>inode #1048577: comm udevd: reading directory lblock 0
>>>>
>>>>[analysis]
>>>>In system resume path, mmc_sd_resume() is failed with error code -123
>>>>because at that time SD card is still not ready on mb86s7x platforms.
>>>
>>> So why does it fail? It shouldn't!
>>>
>>> I get the impression that you are solving this in the wrong way.
>>
>>Hi Uffe,
>>On mb86s7x EVB, power for SD card is completely removed when entering
>>STR suspend mode (i.e., echo mem > /sys/power/state). When system
>>starts to resume, it turns on the power for SD card again. However, It
>>take
>>longer time (e.g., 600ms) to get the power ready.
>>This is why mmc_sd_resume() failed with error code -123. At that time
>>point,
>>power for SD card is not ready yet.
>>
>>At first we fixed it by a simple method of using
>>SDHCI_QUIRK_DELAY_AFTER_POWER:
>>
>>diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>index 169e17d..ed28896 100644
>>--- a/drivers/mmc/host/sdhci.c
>>+++ b/drivers/mmc/host/sdhci.c
>>@@ -1283,7 +1283,7 @@ static void sdhci_set_power(struct sdhci_host
>>*host, unsigned char mode,
>> * they can apply clock after applying power
>> */
>> if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
>>- mdelay(10);
>>+ mdelay(600);
>> }
>
> If you can't model the power to the card through a regulator, this is what you need to do.
Hi Uffe,
Yes, I got it.
>
>>
>> if (host->vmmc) {
>>
>>However, we found it blocks the system resume path. It can slow down
>>system resume and also booting.
>>Therefore, we would like to resume SD card manually and asynchronously
>>by host controller driver itself. Thus system resume path is not
>>blocked.
>
> That is accomplished by using MMC_CAP_RUNTIME_RESUME.
Yes, I got it.
Thanks a lot for your review and help.
I will update it in next version.
Best regards,
Vincent Yang
>
> Kind regards
> Uffe
>
>
>>Thanks a lot for your review!
>>
>>
>>Best regards,
>>Vincent Yang
>>
>>>
>>> Kind regards
>>> Uffe
>>>
>>>>
>>>>[solution]
>>>>In order to not blocking system resume path, this patch just sets a
>>>>flag
>>>>MMC_BUSRESUME_MANUAL_RESUME when this error happened, and then host
>>>>controller
>>>>driver can understand it by this flag. Then host controller driver
>>have
>>>>to
>>>>resume SD card manually and asynchronously.
>>>>
>>>>Signed-off-by: Vincent Yang <Vincent.Yang@tw.fujitsu.com>
>>>>---
>>>> drivers/mmc/core/core.c | 4 ++
>>>> drivers/mmc/core/sd.c | 4 ++
>>>>drivers/mmc/host/sdhci_f_sdh30.c | 89
>>>>++++++++++++++++++++++++++++++++++++++++
>>>> include/linux/mmc/host.h | 14 +++++++
>>>> 4 files changed, 111 insertions(+)
>>>>
>>>>diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
>>>>index 764af63..51fce49 100644
>>>>--- a/drivers/mmc/core/core.c
>>>>+++ b/drivers/mmc/core/core.c
>>>>@@ -2648,6 +2648,10 @@ int mmc_pm_notify(struct notifier_block
>>>>*notify_block,
>>>> case PM_POST_RESTORE:
>>>>
>>>> spin_lock_irqsave(&host->lock, flags);
>>>>+ if (mmc_bus_manual_resume(host)) {
>>>>+ spin_unlock_irqrestore(&host->lock, flags);
>>>>+ break;
>>>>+ }
>>>> host->rescan_disable = 0;
>>>> spin_unlock_irqrestore(&host->lock, flags);
>>>> _mmc_detect_change(host, 0, false);
>>>>diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
>>>>index 0c44510..859390d 100644
>>>>--- a/drivers/mmc/core/sd.c
>>>>+++ b/drivers/mmc/core/sd.c
>>>>@@ -1133,6 +1133,10 @@ static int mmc_sd_resume(struct mmc_host
>>*host)
>>>>
>>>> if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
>>>> err = _mmc_sd_resume(host);
>>>>+ if ((host->caps2 & MMC_CAP2_MANUAL_RESUME) && err)
>>>>+ mmc_set_bus_resume_policy(host, 1);
>>>>+ else
>>>>+ mmc_set_bus_resume_policy(host, 0);
>>>> pm_runtime_set_active(&host->card->dev);
>>>> pm_runtime_mark_last_busy(&host->card->dev);
>>>> }
>>>>diff --git a/drivers/mmc/host/sdhci_f_sdh30.c
>>>>b/drivers/mmc/host/sdhci_f_sdh30.c
>>>>index 6fae509..67bcff2 100644
>>>>--- a/drivers/mmc/host/sdhci_f_sdh30.c
>>>>+++ b/drivers/mmc/host/sdhci_f_sdh30.c
>>>>@@ -30,6 +30,12 @@
>>>> #include "../core/core.h"
>>>>
>>>> #define DRIVER_NAME "f_sdh30"
>>>>+#define RESUME_WAIT_COUNT 100
>>>>+#define RESUME_WAIT_TIME 50
>>>>+#define RESUME_WAIT_JIFFIES msecs_to_jiffies(RESUME_DETECT_TIME)
>>>>+#define RESUME_DETECT_COUNT 16
>>>>+#define RESUME_DETECT_TIME 50
>>>>+#define RESUME_DETECT_JIFFIES msecs_to_jiffies(RESUME_DETECT_TIME)
>>>>
>>>>
>>>> struct f_sdhost_priv {
>>>>@@ -38,8 +44,59 @@ struct f_sdhost_priv {
>>>> int gpio_select_1v8;
>>>> u32 vendor_hs200;
>>>> struct device *dev;
>>>>+ unsigned int quirks; /* Deviations from spec. */
>>>>+
>>>>+/* retry to detect mmc device when resume */
>>>>+#define F_SDH30_QUIRK_RESUME_DETECT_RETRY (1<<0)
>>>>+
>>>>+ struct workqueue_struct *resume_detect_wq;
>>>>+ struct delayed_work resume_detect_work;
>>>>+ unsigned int resume_detect_count;
>>>>+ unsigned int resume_wait_count;
>>>> };
>>>>
>>>>+static void sdhci_f_sdh30_resume_detect_work_func(struct work_struct
>>>>*work)
>>>>+{
>>>>+ struct f_sdhost_priv *priv = container_of(work, struct
>>f_sdhost_priv,
>>>>+ resume_detect_work.work);
>>>>+ struct sdhci_host *host = dev_get_drvdata(priv->dev);
>>>>+ int err = 0;
>>>>+
>>>>+ if (mmc_bus_manual_resume(host->mmc)) {
>>>>+ pm_runtime_disable(&host->mmc->card->dev);
>>>>+ mmc_card_set_suspended(host->mmc->card);
>>>>+ err = host->mmc->bus_ops->resume(host->mmc);
>>>>+ if (priv->resume_detect_count-- && err)
>>>>+ queue_delayed_work(priv->resume_detect_wq,
>>>>+ &priv->resume_detect_work,
>>>>+ RESUME_DETECT_JIFFIES);
>>>>+ else
>>>>+ pr_debug("%s: resume detection done (count:%d,
>>wait:%d, err:%d)\n",
>>>>+ mmc_hostname(host->mmc),
>>>>+ priv->resume_detect_count,
>>>>+ priv->resume_wait_count, err);
>>>>+ } else {
>>>>+ if (priv->resume_wait_count--)
>>>>+ queue_delayed_work(priv->resume_detect_wq,
>>>>+ &priv->resume_detect_work,
>>>>+ RESUME_WAIT_JIFFIES);
>>>>+ else
>>>>+ pr_debug("%s: resume done\n",
>>mmc_hostname(host->mmc));
>>>>+ }
>>>>+}
>>>>+
>>>>+static void sdhci_f_sdh30_resume_detect(struct mmc_host *mmc,
>>>>+ int detect, int wait)
>>>>+{
>>>>+ struct sdhci_host *host = mmc_priv(mmc);
>>>>+ struct f_sdhost_priv *priv = sdhci_priv(host);
>>>>+
>>>>+ priv->resume_detect_count = detect;
>>>>+ priv->resume_wait_count = wait;
>>>>+ queue_delayed_work(priv->resume_detect_wq,
>>>>+ &priv->resume_detect_work, 0);
>>>>+}
>>>>+
>>>> void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
>>>> {
>>>> struct f_sdhost_priv *priv = sdhci_priv(host);
>>>>@@ -146,6 +203,12 @@ static int sdhci_f_sdh30_probe(struct
>>>>platform_device *pdev)
>>>> }
>>>> }
>>>>
>>>>+ if (of_find_property(pdev->dev.of_node, "resume-detect-retry",
>>NULL))
>>>>{
>>>>+ dev_info(dev, "Applying resume detect retry quirk\n");
>>>>+ priv->quirks |= F_SDH30_QUIRK_RESUME_DETECT_RETRY;
>>>>+ host->mmc->caps2 |= MMC_CAP2_MANUAL_RESUME;
>>>>+ }
>>>>+
>>>> ret = mmc_of_parse_voltage(pdev->dev.of_node,
>>&host->ocr_mask);
>>>> if (ret) {
>>>> dev_err(dev, "%s: parse voltage error\n", __func__);
>>>>@@ -197,6 +260,18 @@ static int sdhci_f_sdh30_probe(struct
>>>>platform_device *pdev)
>>>> }
>>>> }
>>>>
>>>>+ /* Init workqueue */
>>>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY) {
>>>>+ priv->resume_detect_wq =
>>create_workqueue("sdhci_f_sdh30");
>>>>+ if (priv->resume_detect_wq == NULL) {
>>>>+ ret = -ENOMEM;
>>>>+ dev_err(dev, "Failed to create resume
>>detection workqueue\n");
>>>>+ goto err_init_wq;
>>>>+ }
>>>>+ INIT_DELAYED_WORK(&priv->resume_detect_work,
>>>>+
>>sdhci_f_sdh30_resume_detect_work_func);
>>>>+ }
>>>>+
>>>> ret = sdhci_add_host(host);
>>>> if (ret) {
>>>> dev_err(dev, "%s: host add error\n", __func__);
>>>>@@ -229,6 +304,9 @@ static int sdhci_f_sdh30_probe(struct
>>>>platform_device *pdev)
>>>> return 0;
>>>>
>>>> err_add_host:
>>>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY)
>>>>+ destroy_workqueue(priv->resume_detect_wq);
>>>>+err_init_wq:
>>>> if (gpio_is_valid(priv->gpio_select_1v8)) {
>>>> gpio_direction_output(priv->gpio_select_1v8, 1);
>>>> gpio_free(priv->gpio_select_1v8);
>>>>@@ -268,6 +346,9 @@ static int sdhci_f_sdh30_remove(struct
>>>>platform_device *pdev)
>>>> gpio_free(priv->gpio_select_1v8);
>>>> }
>>>>
>>>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY)
>>>>+ destroy_workqueue(priv->resume_detect_wq);
>>>>+
>>>> sdhci_free_host(host);
>>>> platform_set_drvdata(pdev, NULL);
>>>>
>>>>@@ -285,7 +366,15 @@ static int sdhci_f_sdh30_suspend(struct device
>>>>*dev)
>>>> static int sdhci_f_sdh30_resume(struct device *dev)
>>>> {
>>>> struct sdhci_host *host = dev_get_drvdata(dev);
>>>>+ struct f_sdhost_priv *priv = sdhci_priv(host);
>>>>
>>>>+ if (priv->quirks & F_SDH30_QUIRK_RESUME_DETECT_RETRY) {
>>>>+ pr_debug("%s: start resume detect\n",
>>>>+ mmc_hostname(host->mmc));
>>>>+ sdhci_f_sdh30_resume_detect(host->mmc,
>>>>+ RESUME_DETECT_COUNT,
>>>>+ RESUME_WAIT_COUNT);
>>>>+ }
>>>> return sdhci_resume_host(host);
>>>> }
>>>> #endif
>>>>diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>>>>index 7960424..55221dd 100644
>>>>--- a/include/linux/mmc/host.h
>>>>+++ b/include/linux/mmc/host.h
>>>>@@ -283,6 +283,7 @@ struct mmc_host {
>>>> #define MMC_CAP2_HS400 (MMC_CAP2_HS400_1_8V | \
>>>> MMC_CAP2_HS400_1_2V)
>>>> #define MMC_CAP2_SDIO_IRQ_NOTHREAD (1 << 17)
>>>>+#define MMC_CAP2_MANUAL_RESUME (1 << 18) /* Resume manually
>>when
>>>>error */
>>>>
>>>> mmc_pm_flag_t pm_caps; /* supported pm
>>features */
>>>>
>>>>@@ -338,6 +339,9 @@ struct mmc_host {
>>>> const struct mmc_bus_ops *bus_ops; /* current bus driver
>>*/
>>>> unsigned int bus_refs; /* reference counter
>>*/
>>>>
>>>>+ unsigned int bus_resume_flags;
>>>>+#define MMC_BUSRESUME_MANUAL_RESUME (1 << 0)
>>>>+
>>>> unsigned int sdio_irqs;
>>>> struct task_struct *sdio_irq_thread;
>>>> bool sdio_irq_pending;
>>>>@@ -384,6 +388,16 @@ static inline void *mmc_priv(struct mmc_host
>>>>*host)
>>>> #define mmc_dev(x) ((x)->parent)
>>>> #define mmc_classdev(x) (&(x)->class_dev)
>>>> #define mmc_hostname(x) (dev_name(&(x)->class_dev))
>>>>+#define mmc_bus_manual_resume(host) ((host)->bus_resume_flags &
>> \
>>>>+ MMC_BUSRESUME_MANUAL_RESUME)
>>>>+
>>>>+static inline void mmc_set_bus_resume_policy(struct mmc_host *host,
>>>>int manual)
>>>>+{
>>>>+ if (manual)
>>>>+ host->bus_resume_flags |= MMC_BUSRESUME_MANUAL_RESUME;
>>>>+ else
>>>>+ host->bus_resume_flags &=
>>~MMC_BUSRESUME_MANUAL_RESUME;
>>>>+}
>>>>
>>>> int mmc_power_save_host(struct mmc_host *host);
>>>> int mmc_power_restore_host(struct mmc_host *host);
>>>
>
^ permalink raw reply
* Re: [RFC][PATCH 1/2] dma: imx-sdma: Add device to device support
From: Nicolin Chen @ 2014-06-27 10:58 UTC (permalink / raw)
To: Nicolin Chen, vinod.koul, s.hauer
Cc: mark.rutland, alsa-devel, linux-doc, tiwai, timur, lgirdwood,
b42378, b02247, grant.likely, devicetree, pawel.moll,
ijc+devicetree, b38343, robh+dt, dan.j.williams, perex, rdunlap,
linux-kernel, broonie, galak, dmaengine, linuxppc-dev
In-Reply-To: <42744e778ce8a4b424d5642f86d18ef047bcc7cd.1402653667.git.nicoleotsuka@gmail.com>
On Fri, Jun 13, 2014 at 06:07:04PM +0800, Nicolin Chen wrote:
> This patch adds DEV_TO_DEV support for i.MX SDMA driver to support data
> tranfer between two peripheral FIFOs. The per_2_per script requires two
> peripheral addresses and two DMA requests. So this patch also adds them
> into private structure.
>
> Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>
Excuse me, the patch has been here for two weeks. Could anyone please
give a comment or an Ack on it?
Thank you,
Nicolin
> ---
> drivers/dma/imx-sdma.c | 40 ++++++++++++++++++++++++++++++-----
> include/linux/platform_data/dma-imx.h | 1 +
> 2 files changed, 36 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> index 85561dc..5af1a69 100644
> --- a/drivers/dma/imx-sdma.c
> +++ b/drivers/dma/imx-sdma.c
> @@ -258,8 +258,9 @@ struct sdma_channel {
> struct sdma_buffer_descriptor *bd;
> dma_addr_t bd_phys;
> unsigned int pc_from_device, pc_to_device;
> + unsigned int device_to_device;
> unsigned long flags;
> - dma_addr_t per_address;
> + dma_addr_t per_address, per_address2;
> unsigned long event_mask[2];
> unsigned long watermark_level;
> u32 shp_addr, per_addr;
> @@ -696,6 +697,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
>
> sdmac->pc_from_device = 0;
> sdmac->pc_to_device = 0;
> + sdmac->device_to_device = 0;
>
> switch (peripheral_type) {
> case IMX_DMATYPE_MEMORY:
> @@ -770,6 +772,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
>
> sdmac->pc_from_device = per_2_emi;
> sdmac->pc_to_device = emi_2_per;
> + sdmac->device_to_device = per_2_per;
> }
>
> static int sdma_load_context(struct sdma_channel *sdmac)
> @@ -782,11 +785,12 @@ static int sdma_load_context(struct sdma_channel *sdmac)
> int ret;
> unsigned long flags;
>
> - if (sdmac->direction == DMA_DEV_TO_MEM) {
> + if (sdmac->direction == DMA_DEV_TO_MEM)
> load_address = sdmac->pc_from_device;
> - } else {
> + else if (sdmac->direction == DMA_DEV_TO_DEV)
> + load_address = sdmac->device_to_device;
> + else
> load_address = sdmac->pc_to_device;
> - }
>
> if (load_address < 0)
> return load_address;
> @@ -850,6 +854,12 @@ static int sdma_config_channel(struct sdma_channel *sdmac)
> sdma_event_enable(sdmac, sdmac->event_id0);
> }
>
> + if (sdmac->event_id1) {
> + if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events)
> + return -EINVAL;
> + sdma_event_enable(sdmac, sdmac->event_id1);
> + }
> +
> switch (sdmac->peripheral_type) {
> case IMX_DMATYPE_DSP:
> sdma_config_ownership(sdmac, false, true, true);
> @@ -880,7 +890,12 @@ static int sdma_config_channel(struct sdma_channel *sdmac)
> /* Watermark Level */
> sdmac->watermark_level |= sdmac->watermark_level;
> /* Address */
> - sdmac->shp_addr = sdmac->per_address;
> + if (sdmac->direction == DMA_DEV_TO_DEV) {
> + sdmac->shp_addr = sdmac->per_address2;
> + sdmac->per_addr = sdmac->per_address;
> + } else {
> + sdmac->shp_addr = sdmac->per_address;
> + }
> } else {
> sdmac->watermark_level = 0; /* FIXME: M3_BASE_ADDRESS */
> }
> @@ -974,6 +989,7 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
>
> sdmac->peripheral_type = data->peripheral_type;
> sdmac->event_id0 = data->dma_request;
> + sdmac->event_id1 = data->dma_request2;
>
> clk_enable(sdmac->sdma->clk_ipg);
> clk_enable(sdmac->sdma->clk_ahb);
> @@ -1213,6 +1229,19 @@ static int sdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
> sdmac->watermark_level = dmaengine_cfg->src_maxburst *
> dmaengine_cfg->src_addr_width;
> sdmac->word_size = dmaengine_cfg->src_addr_width;
> + } else if (dmaengine_cfg->direction == DMA_DEV_TO_DEV) {
> + sdmac->per_address = dmaengine_cfg->src_addr;
> + sdmac->per_address2 = dmaengine_cfg->dst_addr;
> + /*
> + * For per_2_per sciprt, register r7 requires two
> + * watermark levels: the lower placed at bits [0-7]
> + * and the higher one placed at bits [16-23].
> + */
> + sdmac->watermark_level =
> + dmaengine_cfg->src_maxburst & 0xff;
> + sdmac->watermark_level |=
> + (dmaengine_cfg->dst_maxburst & 0xff) << 16;
> + sdmac->word_size = dmaengine_cfg->dst_addr_width;
> } else {
> sdmac->per_address = dmaengine_cfg->dst_addr;
> sdmac->watermark_level = dmaengine_cfg->dst_maxburst *
> @@ -1433,6 +1462,7 @@ static struct dma_chan *sdma_xlate(struct of_phandle_args *dma_spec,
> data.dma_request = dma_spec->args[0];
> data.peripheral_type = dma_spec->args[1];
> data.priority = dma_spec->args[2];
> + data.dma_request2 = 0;
>
> return dma_request_channel(mask, sdma_filter_fn, &data);
> }
> diff --git a/include/linux/platform_data/dma-imx.h b/include/linux/platform_data/dma-imx.h
> index 7aa0e89..6a1357d 100644
> --- a/include/linux/platform_data/dma-imx.h
> +++ b/include/linux/platform_data/dma-imx.h
> @@ -51,6 +51,7 @@ enum imx_dma_prio {
>
> struct imx_dma_data {
> int dma_request; /* DMA request line */
> + int dma_request2; /* secondary DMA request line */
> enum sdma_peripheral_type peripheral_type;
> int priority;
> };
> --
> 1.8.4
>
^ permalink raw reply
* Re: OF_DYNAMIC node lifecycle
From: Grant Likely @ 2014-06-27 12:32 UTC (permalink / raw)
To: Nathan Fontenot, Pantelis Antoniou
Cc: devicetree, Steven Rostedt, linuxppc-dev, Tyrel Datwyler,
Thomas Gleixner
In-Reply-To: <53AC7BA3.5030909@austin.ibm.com>
On Thu, 26 Jun 2014 14:59:31 -0500, Nathan Fontenot <nfont@austin.ibm.com> wrote:
> On 06/25/2014 03:22 PM, Grant Likely wrote:
> > On Tue, 24 Jun 2014 15:07:05 -0500, Nathan Fontenot <nfont@austin.ibm.com> wrote:
> >> On 06/23/2014 09:58 AM, Grant Likely wrote:
> >>> On Thu, 19 Jun 2014 11:33:20 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> >>>> Hi Grant,
> >>>>
> >>>> CCing Thomas Gleixner & Steven Rostedt, since they might have a few
> >>>> ideas...
> >>>>
> >>>> On Jun 18, 2014, at 11:07 PM, Grant Likely wrote:
> >>>>
> >>>>> Hi Nathan and Tyrel,
> >>>>>
> >>>>> I'm looking into lifecycle issues on nodes modified by OF_DYNAMIC, and
> >>>>> I'm hoping you can help me. Right now, pseries seems to be the only
> >>>>> user of OF_DYNAMIC, but making OF_DYNAMIC work has a huge impact on
> >>>>> the entire kernel because it requires all DT code to manage reference
> >>>>> counting with iterating over nodes. Most users simply get it wrong.
> >>>>> Pantelis did some investigation and found that the reference counts on
> >>>>> a running kernel are all over the place. I have my doubts that any
> >>>>> code really gets it right.
> >>>>>
> >>>>> The problem is that users need to know when it is appropriate to call
> >>>>> of_node_get()/of_node_put(). All list traversals that exit early need
> >>>>> an extra call to of_node_put(), and code that is searching for a node
> >>>>> in the tree and holding a reference to it needs to call of_node_get().
> >>>>>
> >>>>
> >>>> In hindsight it appears that drivers just can't get the lifecycle right.
> >>>> So we need to simplify things.
> >>>>
> >>>>> I've got a few pseries questions:
> >>>>> - What are the changes being requested by pseries firmware? Is it only
> >>>>> CPUs and memory nodes, or does it manipulate things all over the tree?
> >>>>> - How frequent are the changes? How many changes would be likely over
> >>>>> the runtime of the system?
> >>>>> - Are you able to verify that removed nodes are actually able to be
> >>>>> freed correctly? Do you have any testcases for node removal?
> >>>>>
> >>>>> I'm thinking very seriously about changing the locking semantics of DT
> >>>>> code entirely so that most users never have to worry about
> >>>>> of_node_get/put at all. If the DT code is switched to use rcu
> >>>>> primitives for tree iteration (which also means making DT code use
> >>>>> list_head, something I'm already investigating), then instead of
> >>>>> trying to figure out of_node_get/put rules, callers could use
> >>>>> rcu_read_lock()/rcu_read_unlock() to protect the region that is
> >>>>> searching over nodes, and only call of_node_get() if the node pointer
> >>>>> is needed outside the rcu read-side lock.
> >>>>>
> >>>>> I'd really like to be rid of the node reference counting entirely, but
> >>>>> I can't figure out a way of doing that safely, so I'd settle for
> >>>>> making it a lot easier to get correct.
> >>>>>
> >>>>
> >>>> Since we're going about changing things, how about that devtree_lock?
> >>>
> >>> I believe rcu would pretty much eliminate the devtree_lock entirely. All
> >>> modifiers would need to grab a mutex to ensure there is only one writer
> >>> at any given time, but readers would have free reign to parse the tree
> >>> however they like.
> >>>
> >>> DT writers would have to follow some strict rules about how to handle
> >>> nodes that are removed (ie. don't modify or of_node_put() them until
> >>> after rcu is syncronized), but the number of writers is very small and
> >>> we have control of all of them.
> >>>
> >>>> We're using a raw_spinlock and we're always taking the lock with
> >>>> interrupts disabled.
> >>>>
> >>>> If we're going to make DT changes frequently during normal runtime
> >>>> and not only during boot time, those are bad for any kind of real-time
> >>>> performance.
> >>>>
> >>>> So the question is, do we really have code that access the live tree
> >>>> during atomic sections? Is that something we want? Enforcing this
> >>>> will make our lives easier, and we'll get the change to replace
> >>>> that spinlock with a mutex.
> >>>
> >>> Yes, I believe the powerpc CPU hotplug code accesses the DT in atomic
> >>> sections. I cannot put my finger on the exact code however. Nathan might
> >>> know better. But, if I'm right, the whole problem goes away with RCU.
> >>
> >> I went back through the cpu hotplug code. we do update the DT during cpu
> >> hotplug but I don't see it happening during atomic sections.
> >>
> >> The code is in arch/powerpc/platforms/pseries/dlpar.c
> >
> > Great, thanks,
> >
> > By the way, notifiers currently get sent before any updates are applied
> > to the tree. I want to change it so that the notifier gets sent
> > afterwards. Does that work for you? I've looked through all the users
> > and aside from a stupid block of code in arch/powerpc/kernel/prom.c
> > which does things that should be done by of_attach_node(), it looks like
> > everything should be fine.
>
> This would affect property updates. When doing a property update the
> notifier passes a pointer to a struct containing a device node
> pointer and a pointer to the new device node property.
>
> I know specifically in memory property updates we grab the current version
> of the device tree property and compare it to the 'new' version that
> was passed to us.
>
> If you want to do the DT update before calling the notifier that should be
> fine for the memory update code and would only require very minimal
> updates.
We could change the notifier to include both the old and new values.
I've been thinking about changing the notifier format anyway. With the
addition of bulk changes, it would be more efficient to send a single
notifier for all the changes with a link to the change set instead of
one at a time.
g.
^ permalink raw reply
* Re: OF_DYNAMIC node lifecycle
From: Pantelis Antoniou @ 2014-06-27 12:40 UTC (permalink / raw)
To: Grant Likely
Cc: devicetree, Steven Rostedt, linuxppc-dev, Tyrel Datwyler,
Thomas Gleixner
In-Reply-To: <20140627123251.D0857C40859@trevor.secretlab.ca>
Hi Grant,
On Jun 27, 2014, at 3:32 PM, Grant Likely wrote:
> On Thu, 26 Jun 2014 14:59:31 -0500, Nathan Fontenot =
<nfont@austin.ibm.com> wrote:
>> On 06/25/2014 03:22 PM, Grant Likely wrote:
>>> On Tue, 24 Jun 2014 15:07:05 -0500, Nathan Fontenot =
<nfont@austin.ibm.com> wrote:
>>>> On 06/23/2014 09:58 AM, Grant Likely wrote:
>>>>> On Thu, 19 Jun 2014 11:33:20 +0300, Pantelis Antoniou =
<pantelis.antoniou@konsulko.com> wrote:
>>>>>> Hi Grant,
>>>>>>=20
[snip]
>>=20
>> This would affect property updates. When doing a property update the
>> notifier passes a pointer to a struct containing a device node
>> pointer and a pointer to the new device node property.
>>=20
>> I know specifically in memory property updates we grab the current =
version
>> of the device tree property and compare it to the 'new' version that=20=
>> was passed to us.
>>=20
>> If you want to do the DT update before calling the notifier that =
should be
>> fine for the memory update code and would only require very minimal
>> updates.
>=20
> We could change the notifier to include both the old and new values.
>=20
> I've been thinking about changing the notifier format anyway. With the
> addition of bulk changes, it would be more efficient to send a single
> notifier for all the changes with a link to the change set instead of
> one at a time.
>=20
That one has my vote. We also need a bulk change notifier, and for =
device
driver use, some kind of wrapper for specific node/properties.
At the moment a notification is fired for any change in the tree, we =
might
work something more fine-grained. Like 'watch this node & subnodes', or
'watch this property (or set of properties)'
> g.
Regards
-- Pantelis=
^ permalink raw reply
* Re: OF_DYNAMIC node lifecycle
From: Grant Likely @ 2014-06-27 12:41 UTC (permalink / raw)
To: Nathan Fontenot, Tyrel Datwyler
Cc: devicetree@vger.kernel.org, Pantelis Antoniou, linuxppc-dev
In-Reply-To: <53AC7C2D.3040604@austin.ibm.com>
On Thu, 26 Jun 2014 15:01:49 -0500, Nathan Fontenot <nfont@austin.ibm.com> wrote:
> On 06/25/2014 03:24 PM, Grant Likely wrote:
> > On Tue, 24 Jun 2014 15:10:55 -0500, Nathan Fontenot <nfont@austin.ibm.com> wrote:
> >>>> heh! I have often thought about adding reference counting to device tree
> >>>> properties.
> >>>
> >>> You horrible, horrible man.
> >>
> >> Yes. I are evil :)
> >>
> >> After looking again the work needed to add reference counts to properties
> >> would be huge. The few properties I am concerned with are specific to powerpc
> >> so perhaps just adding an arch specific lock around updating those
> >> properties would work.
> >
> > Which code/properties? I'd like to have a look myself.
>
> /ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory
>
> The property is updated in
> arch/powerpc/platforms/pseries/hotplug-memory.c:pseries_update_drconf_memory()
Specifically, what do you need for the locking? Are you wanting to hold
off additional changes while that function is executing? Pantelis is
adding a mutex for device tree writers. Holding that mutex would prevent
any changes from happening in the tree without affecting readers. Would
that be sufficient?
g.
^ permalink raw reply
* [PATCH] KVM: PPC: BOOK3S: HV: Update compute_tlbie_rb to handle 16MB base page
From: Aneesh Kumar K.V @ 2014-06-27 13:35 UTC (permalink / raw)
To: agraf, benh, paulus; +Cc: linuxppc-dev, kvm, kvm-ppc, Aneesh Kumar K.V
When calculating the lower bits of AVA field, use the shift
count based on the base page size. Also add the missing segment
size and remove stale comment.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/kvm_book3s_64.h | 6 ++++--
arch/powerpc/kvm/book3s_hv.c | 6 ------
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index 66a0a44b62a8..ca7c1688a7b6 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -158,6 +158,8 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
*/
/* This covers 14..54 bits of va*/
rb = (v & ~0x7fUL) << 16; /* AVA field */
+
+ rb |= v >> (62 - 8); /* B field */
/*
* AVA in v had cleared lower 23 bits. We need to derive
* that from pteg index
@@ -188,10 +190,10 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r,
{
int aval_shift;
/*
- * remaining 7bits of AVA/LP fields
+ * remaining bits of AVA/LP fields
* Also contain the rr bits of LP
*/
- rb |= (va_low & 0x7f) << 16;
+ rb |= (va_low << mmu_psize_defs[b_psize].shift) & 0x7ff000;
/*
* Now clear not needed LP bits based on actual psize
*/
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index cbf46eb3f59c..328416f28a55 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1917,12 +1917,6 @@ static void kvmppc_add_seg_page_size(struct kvm_ppc_one_seg_page_size **sps,
(*sps)->page_shift = def->shift;
(*sps)->slb_enc = def->sllp;
(*sps)->enc[0].page_shift = def->shift;
- /*
- * Only return base page encoding. We don't want to return
- * all the supporting pte_enc, because our H_ENTER doesn't
- * support MPSS yet. Once they do, we can start passing all
- * support pte_enc here
- */
(*sps)->enc[0].pte_enc = def->penc[linux_psize];
/*
* Add 16MB MPSS support if host supports it
--
1.9.1
^ permalink raw reply related
* Re: OF_DYNAMIC node lifecycle
From: Nathan Fontenot @ 2014-06-27 14:41 UTC (permalink / raw)
To: Pantelis Antoniou, Grant Likely
Cc: devicetree, Steven Rostedt, linuxppc-dev, Tyrel Datwyler,
Thomas Gleixner
In-Reply-To: <94595B4D-1A58-427C-B9CE-C139048FEDCD@konsulko.com>
On 06/27/2014 07:40 AM, Pantelis Antoniou wrote:
> Hi Grant,
>
> On Jun 27, 2014, at 3:32 PM, Grant Likely wrote:
>
>> On Thu, 26 Jun 2014 14:59:31 -0500, Nathan Fontenot <nfont@austin.ibm.com> wrote:
>>> On 06/25/2014 03:22 PM, Grant Likely wrote:
>>>> On Tue, 24 Jun 2014 15:07:05 -0500, Nathan Fontenot <nfont@austin.ibm.com> wrote:
>>>>> On 06/23/2014 09:58 AM, Grant Likely wrote:
>>>>>> On Thu, 19 Jun 2014 11:33:20 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>>>>>>> Hi Grant,
>>>>>>>
>
> [snip]
>
>>>
>>> This would affect property updates. When doing a property update the
>>> notifier passes a pointer to a struct containing a device node
>>> pointer and a pointer to the new device node property.
>>>
>>> I know specifically in memory property updates we grab the current version
>>> of the device tree property and compare it to the 'new' version that
>>> was passed to us.
>>>
>>> If you want to do the DT update before calling the notifier that should be
>>> fine for the memory update code and would only require very minimal
>>> updates.
>>
>> We could change the notifier to include both the old and new values.
>>
>> I've been thinking about changing the notifier format anyway. With the
>> addition of bulk changes, it would be more efficient to send a single
>> notifier for all the changes with a link to the change set instead of
>> one at a time.
>>
>
> That one has my vote. We also need a bulk change notifier, and for device
> driver use, some kind of wrapper for specific node/properties.
>
> At the moment a notification is fired for any change in the tree, we might
> work something more fine-grained. Like 'watch this node & subnodes', or
> 'watch this property (or set of properties)'
>
Both of these updates would work.
For property updates the only real requirement is that we can get to the new
and the old version of the property value.
I like the idea of being able to watch a single node/property. My experience
is that most code is only interested in updates to a single node or
property. Being able to avoid notifying everyone that has registered a
notifier for DT updates for every change would be nice.
-Nathan
-Nathan
^ permalink raw reply
* Re: OF_DYNAMIC node lifecycle
From: Nathan Fontenot @ 2014-06-27 14:41 UTC (permalink / raw)
To: Grant Likely, Tyrel Datwyler
Cc: devicetree@vger.kernel.org, Pantelis Antoniou, linuxppc-dev
In-Reply-To: <20140627124101.367F7C40E5E@trevor.secretlab.ca>
On 06/27/2014 07:41 AM, Grant Likely wrote:
> On Thu, 26 Jun 2014 15:01:49 -0500, Nathan Fontenot <nfont@austin.ibm.com> wrote:
>> On 06/25/2014 03:24 PM, Grant Likely wrote:
>>> On Tue, 24 Jun 2014 15:10:55 -0500, Nathan Fontenot <nfont@austin.ibm.com> wrote:
>>>>>> heh! I have often thought about adding reference counting to device tree
>>>>>> properties.
>>>>>
>>>>> You horrible, horrible man.
>>>>
>>>> Yes. I are evil :)
>>>>
>>>> After looking again the work needed to add reference counts to properties
>>>> would be huge. The few properties I am concerned with are specific to powerpc
>>>> so perhaps just adding an arch specific lock around updating those
>>>> properties would work.
>>>
>>> Which code/properties? I'd like to have a look myself.
>>
>> /ibm,dynamic-reconfiguration-memory/ibm,dynamic-memory
>>
>> The property is updated in
>> arch/powerpc/platforms/pseries/hotplug-memory.c:pseries_update_drconf_memory()
>
> Specifically, what do you need for the locking? Are you wanting to hold
> off additional changes while that function is executing? Pantelis is
> adding a mutex for device tree writers. Holding that mutex would prevent
> any changes from happening in the tree without affecting readers. Would
> that be sufficient?
That would work.
-Nathan
^ permalink raw reply
* [PATCH 0/5 v4] Read guest last instruction from kvmppc_get_last_inst()
From: Mihai Caraman @ 2014-06-27 22:49 UTC (permalink / raw)
To: kvm-ppc; +Cc: Mihai Caraman, linuxppc-dev, kvm
Read guest last instruction from kvmppc_get_last_inst() allowing the function
to fail in order to emulate again. On bookehv architecture search for
the physical address and kmap it, instead of using Load External PID (lwepx)
instruction. This fixes an infinite loop caused by lwepx's data TLB miss
exception handled in the host and the TODO for execute-but-not-read entries
and TLB eviction.
Mihai Caraman (5):
KVM: PPC: e500mc: Revert "add load inst fixup"
KVM: PPC: Book3e: Add TLBSEL/TSIZE defines for MAS0/1
KVM: PPC: Book3s: Remove kvmppc_read_inst() function
KVM: PPC: Alow kvmppc_get_last_inst() to fail
KVM: PPC: Bookehv: Get vcpu's last instruction for emulation
arch/powerpc/include/asm/kvm_book3s.h | 26 -------
arch/powerpc/include/asm/kvm_booke.h | 5 --
arch/powerpc/include/asm/kvm_ppc.h | 24 +++++++
arch/powerpc/include/asm/mmu-book3e.h | 7 +-
arch/powerpc/kvm/book3s.c | 11 +++
arch/powerpc/kvm/book3s_64_mmu_hv.c | 17 ++---
arch/powerpc/kvm/book3s_paired_singles.c | 38 ++++++----
arch/powerpc/kvm/book3s_pr.c | 116 +++++++++++++++++--------------
arch/powerpc/kvm/booke.c | 47 +++++++++++++
arch/powerpc/kvm/bookehv_interrupts.S | 55 ++-------------
arch/powerpc/kvm/e500_mmu_host.c | 97 ++++++++++++++++++++++++++
arch/powerpc/kvm/emulate.c | 18 +++--
arch/powerpc/kvm/powerpc.c | 10 ++-
13 files changed, 302 insertions(+), 169 deletions(-)
--
1.7.11.7
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox