* Re: [PATCH 1/5] mfd: rk808: Add RK817 and RK809 support
From: kbuild test robot @ 2018-07-23 23:13 UTC (permalink / raw)
To: Tony Xie
Cc: kbuild-all, heiko, broonie, lee.jones, a.zummo, alexandre.belloni,
sboyd, linux-clk, linux-rtc, linux-arm-kernel, linux-rockchip,
devicetree, linux-kernel, chenjh, xsf, zhangqing, huangtao,
tony.xie
In-Reply-To: <1532315945-1094-2-git-send-email-tony.xie@rock-chips.com>
[-- Attachment #1: Type: text/plain, Size: 913 bytes --]
Hi Tony,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on ljones-mfd/for-mfd-next]
[also build test ERROR on v4.18-rc6 next-20180723]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Tony-Xie/mfd-rk808-Add-RK817-and-RK809-support/20180724-040547
base: https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
config: i386-randconfig-a0-201829 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All errors (new ones prefixed by >>):
>> ERROR: "pm_power_off_prepare" [drivers/mfd/rk808.ko] undefined!
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 28749 bytes --]
^ permalink raw reply
* Re: [PATCH v3 1/2] leds: core: Introduce generic pattern interface
From: Bjorn Andersson @ 2018-07-24 0:18 UTC (permalink / raw)
To: David Lechner
Cc: Baolin Wang, Jacek Anaszewski, Pavel Machek, Mark Brown,
Linux LED Subsystem, LKML
In-Reply-To: <2c3a8911-150a-9b25-2a66-a9432047f96b@lechnology.com>
On Sun 15 Jul 18:00 PDT 2018, David Lechner wrote:
> On 07/15/2018 07:22 AM, Jacek Anaszewski wrote:
> > On 07/15/2018 12:39 AM, Pavel Machek wrote:
> > > On Sun 2018-07-15 00:29:25, Pavel Machek wrote:
> > > > On Sun 2018-07-15 00:02:57, Jacek Anaszewski wrote:
> > > > > Hi Pavel,
> > > > >
> > > > > On 07/14/2018 11:20 PM, Pavel Machek wrote:
> > > > > > Hi!
> > > > > >
> > > > > > > > It also drew my attention to the issue of desired pattern sysfs
> > > > > > > > interface semantics on uninitialized pattern. In your implementation
> > > > > > > > user seems to be unable to determine if the pattern is activated
> > > > > > > > or not. We should define the semantics for this use case and
> > > > > > > > describe it in the documentation. Possibly pattern could
> > > > > > > > return alone new line character then.
> > > > > >
> > > > > > Let me take a step back: we have triggers.. like LED blinking.
> > > > > >
> > > > > > How is that going to interact with patterns? We probably want the
> > > > > > patterns to be ignored in that case...?
> > > > > >
> > > > > > Which suggest to me that we should treat patterns as a trigger. I
> > > > > > believe we do something similar with blinking already.
> > > > > >
> > > > > > Then it is easy to determine if pattern is active, and pattern
> > > > > > vs. trigger issue is solved automatically.
> > > > >
> > > > > I'm all for it. I proposed this approach during the previous
> > > > > discussions related to possible pattern interface implementations,
> > > > > but you seemed not to be so enthusiastic in [0].
> > > > >
> > > > > [0] https://lkml.org/lkml/2017/4/7/350
> > > >
> > > > Hmm. Reading my own email now, I can't decipher it.
> > > >
> > > > I believe I meant "changing patterns from kernel in response to events
> > > > is probably overkill"... or something like that.
> > >
> > > Anyway -- to clean up the confusion -- I'd like to see
> > >
> > > echo pattern > trigger
> > > echo "1 2 3 4 5 6 7 8" > somewhere
> >
> > s/somewhere/pattern/
> >
> > pattern trigger should create "pattern" file similarly how ledtrig-timer
> > creates delay_{on|off} files.
> >
>
> I don't think this is the best way. For example, if you want more than one
> LED to have the same pattern, then the patterns will not be synchronized
> between the LEDs. The same things happens now with many of the existing
> triggers. For example, if I have two LEDs side-by-side using the heartbeat
> trigger, they may blink at the same time or they may not, which is not
> very nice. I think we can make something better.
>
> Perhaps a way to do this would be to use configfs to create a pattern
> trigger that can be shared by multiple LEDs. Like this:
>
> mkdir /sys/kernel/config/leds/triggers/my-nice-pattern
> echo "1 2 3 4" > /sys/kernel/config/leds/triggers/my-nice-pattern/pattern
> echo my-nice-pattern > /sys/class/leds/led0/trigger
> echo my-nice-pattern > /sys/class/leds/led1/trigger
>
In the case where you describe this as two different LEDs (to Linux) and
you rely on the two enable-calls to happen fairly quickly I think you
can just as well specify the same pattern in two independent triggers.
This also helps by not providing the illusion of there being any
synchronization between them.
Regards,
Bjorn
^ permalink raw reply
* [PATCH net-next] virtio_net: force_napi_tx module param.
From: Caleb Raitto @ 2018-07-23 23:11 UTC (permalink / raw)
To: mst, jasowang, davem, netdev; +Cc: Caleb Raitto
From: Caleb Raitto <caraitto@google.com>
The driver disables tx napi if it's not certain that completions will
be processed affine with tx service.
Its heuristic doesn't account for some scenarios where it is, such as
when the queue pair count matches the core but not hyperthread count.
Allow userspace to override the heuristic. This is an alternative
solution to that in the linked patch. That added more logic in the
kernel for these cases, but the agreement was that this was better left
to user control.
Do not expand the existing napi_tx variable to a ternary value,
because doing so can break user applications that expect
boolean ('Y'/'N') instead of integer output. Add a new param instead.
Link: https://patchwork.ozlabs.org/patch/725249/
Acked-by: Willem de Bruijn <willemb@google.com>
Acked-by: Jon Olson <jonolson@google.com>
Signed-off-by: Caleb Raitto <caraitto@google.com>
---
drivers/net/virtio_net.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 2ff08bc103a9..d9aca4e90d6b 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -39,10 +39,11 @@
static int napi_weight = NAPI_POLL_WEIGHT;
module_param(napi_weight, int, 0444);
-static bool csum = true, gso = true, napi_tx;
+static bool csum = true, gso = true, napi_tx, force_napi_tx;
module_param(csum, bool, 0444);
module_param(gso, bool, 0444);
module_param(napi_tx, bool, 0644);
+module_param(force_napi_tx, bool, 0644);
/* FIXME: MTU in config. */
#define GOOD_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN)
@@ -1201,7 +1202,7 @@ static void virtnet_napi_tx_enable(struct virtnet_info *vi,
/* Tx napi touches cachelines on the cpu handling tx interrupts. Only
* enable the feature if this is likely affine with the transmit path.
*/
- if (!vi->affinity_hint_set) {
+ if (!vi->affinity_hint_set && !force_napi_tx) {
napi->weight = 0;
return;
}
@@ -2646,7 +2647,7 @@ static int virtnet_alloc_queues(struct virtnet_info *vi)
netif_napi_add(vi->dev, &vi->rq[i].napi, virtnet_poll,
napi_weight);
netif_tx_napi_add(vi->dev, &vi->sq[i].napi, virtnet_poll_tx,
- napi_tx ? napi_weight : 0);
+ (napi_tx || force_napi_tx) ? napi_weight : 0);
sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg));
ewma_pkt_len_init(&vi->rq[i].mrg_avg_pkt_len);
--
2.18.0.233.g985f88cf7e-goog
^ permalink raw reply related
* Re: [PATCH] MIPS: lantiq: Use dma_zalloc_coherent() in dma code
From: Paul Burton @ 2018-07-24 0:13 UTC (permalink / raw)
To: Hauke Mehrtens; +Cc: ralf, jhogan, john, linux-mips, dev
In-Reply-To: <20180721233057.10713-1-hauke@hauke-m.de>
Hi Hauke,
On Sun, Jul 22, 2018 at 01:30:57AM +0200, Hauke Mehrtens wrote:
> Instead of using dma_alloc_coherent() and memset() directly use
> dma_zalloc_coherent().
>
> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
> ---
> arch/mips/lantiq/xway/dma.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
Thanks - applied to mips-next for 4.19.
Paul
^ permalink raw reply
* [PATCH v2 2/2] PCI: NVMe device specific reset quirk
From: Alex Williamson @ 2018-07-24 0:13 UTC (permalink / raw)
To: linux-pci; +Cc: linux-kernel, linux-nvme
In-Reply-To: <20180724000944.7671.64284.stgit@gimli.home>
Take advantage of NVMe devices using a standard interface to quiesce
the controller prior to reset, including device specific delays before
and after that reset. This resolves several NVMe device assignment
scenarios with two different vendors. The Intel DC P3700 controller
has been shown to only work as a VM boot device on the initial VM
startup, failing after reset or reboot, and also fails to initialize
after hot-plug into a VM. Adding a delay after FLR resolves these
cases. The Samsung SM961/PM961 (960 EVO) sometimes fails to return
from FLR with the PCI config space reading back as -1. A reproducible
instance of this behavior is resolved by clearing the enable bit in
the configuration register and waiting for the ready status to clear
(disabling the NVMe controller) prior to FLR.
As all NVMe devices make use of this standard interface and the NVMe
specification also requires PCIe FLR support, we can apply this quirk
to all devices with matching class code.
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1592654
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
drivers/pci/quirks.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e72c8742aafa..bbd029e8d3ae 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -28,6 +28,7 @@
#include <linux/platform_data/x86/apple.h>
#include <linux/pm_runtime.h>
#include <linux/switchtec.h>
+#include <linux/nvme.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
@@ -3669,6 +3670,122 @@ static int reset_chelsio_generic_dev(struct pci_dev *dev, int probe)
#define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156
#define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166
+/* NVMe controller needs delay before testing ready status */
+#define NVME_QUIRK_CHK_RDY_DELAY (1 << 0)
+/* NVMe controller needs post-FLR delay */
+#define NVME_QUIRK_POST_FLR_DELAY (1 << 1)
+
+static const struct pci_device_id nvme_reset_tbl[] = {
+ { PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(0x1c58, 0x0003), /* HGST adapter */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(0x1c58, 0x0023), /* WDC SN200 adapter */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(0x1c5f, 0x0540), /* Memblaze Pblaze4 adapter */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(PCI_VENDOR_ID_SAMSUNG, 0xa821), /* Samsung PM1725 */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(PCI_VENDOR_ID_SAMSUNG, 0xa822), /* Samsung PM1725a */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0953), /* Intel DC P3700 */
+ .driver_data = NVME_QUIRK_POST_FLR_DELAY, },
+ { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
+ { 0 }
+};
+
+/*
+ * The NVMe specification requires that controllers support PCIe FLR, but
+ * but some Samsung SM961/PM961 controllers fail to recover after FLR (-1
+ * config space) unless the device is quiesced prior to FLR. Do this for
+ * all NVMe devices by disabling the controller before reset. Some Intel
+ * controllers also require an additional post-FLR delay or else attempts
+ * to re-enable will timeout, do that here as well with heuristically
+ * determined delay value. Also maintain the delay between disabling and
+ * checking ready status as used by the native NVMe driver.
+ *
+ * NVMe specification: https://nvmexpress.org/resources/specifications/
+ * Revision 1.0e:
+ * Chapter 2: Required and optional PCI config registers
+ * Chapter 3: NVMe control registers
+ * Chapter 7.3: Reset behavior
+ */
+static int reset_nvme(struct pci_dev *dev, int probe)
+{
+ const struct pci_device_id *id;
+ void __iomem *bar;
+ u16 cmd;
+ u32 cfg;
+
+ id = pci_match_id(nvme_reset_tbl, dev);
+ if (!id || !pcie_has_flr(dev) || !pci_resource_start(dev, 0))
+ return -ENOTTY;
+
+ if (probe)
+ return 0;
+
+ bar = pci_iomap(dev, 0, NVME_REG_CC + sizeof(cfg));
+ if (!bar)
+ return -ENOTTY;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY);
+
+ cfg = readl(bar + NVME_REG_CC);
+
+ /* Disable controller if enabled */
+ if (cfg & NVME_CC_ENABLE) {
+ u64 cap = readq(bar + NVME_REG_CAP);
+ unsigned long timeout;
+
+ /*
+ * Per nvme_disable_ctrl() skip shutdown notification as it
+ * could complete commands to the admin queue. We only intend
+ * to quiesce the device before reset.
+ */
+ cfg &= ~(NVME_CC_SHN_MASK | NVME_CC_ENABLE);
+
+ writel(cfg, bar + NVME_REG_CC);
+
+ /* A heuristic value, matches NVME_QUIRK_DELAY_AMOUNT */
+ if (id->driver_data & NVME_QUIRK_CHK_RDY_DELAY)
+ msleep(2300);
+
+ /* Cap register provides max timeout in 500ms increments */
+ timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
+
+ for (;;) {
+ u32 status = readl(bar + NVME_REG_CSTS);
+
+ /* Ready status becomes zero on disable complete */
+ if (!(status & NVME_CSTS_RDY))
+ break;
+
+ msleep(100);
+
+ if (time_after(jiffies, timeout)) {
+ pci_warn(dev, "Timeout waiting for NVMe ready status to clear after disable\n");
+ break;
+ }
+ }
+ }
+
+ pci_iounmap(dev, bar);
+
+ /*
+ * We could use the optional NVM Subsystem Reset here, hardware
+ * supporting this is simply unavailable at the time of this code
+ * to validate in comparison to PCIe FLR. NVMe spec dictates that
+ * NVMe devices shall implement PCIe FLR.
+ */
+ pcie_flr(dev);
+
+ if (id->driver_data & NVME_QUIRK_POST_FLR_DELAY)
+ msleep(250); /* Heuristic based on Intel DC P3700 */
+
+ return 0;
+}
+
static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
reset_intel_82599_sfp_virtfn },
@@ -3678,6 +3795,7 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
reset_ivb_igd },
{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
reset_chelsio_generic_dev },
+ { PCI_ANY_ID, PCI_ANY_ID, reset_nvme },
{ 0 }
};
^ permalink raw reply related
* [PATCH v2 2/2] PCI: NVMe device specific reset quirk
From: Alex Williamson @ 2018-07-24 0:13 UTC (permalink / raw)
To: linux-pci; +Cc: linux-kernel, linux-nvme
In-Reply-To: <20180724000944.7671.64284.stgit@gimli.home>
Take advantage of NVMe devices using a standard interface to quiesce
the controller prior to reset, including device specific delays before
and after that reset. This resolves several NVMe device assignment
scenarios with two different vendors. The Intel DC P3700 controller
has been shown to only work as a VM boot device on the initial VM
startup, failing after reset or reboot, and also fails to initialize
after hot-plug into a VM. Adding a delay after FLR resolves these
cases. The Samsung SM961/PM961 (960 EVO) sometimes fails to return
from FLR with the PCI config space reading back as -1. A reproducible
instance of this behavior is resolved by clearing the enable bit in
the configuration register and waiting for the ready status to clear
(disabling the NVMe controller) prior to FLR.
As all NVMe devices make use of this standard interface and the NVMe
specification also requires PCIe FLR support, we can apply this quirk
to all devices with matching class code.
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1592654
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
drivers/pci/quirks.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e72c8742aafa..bbd029e8d3ae 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -28,6 +28,7 @@
#include <linux/platform_data/x86/apple.h>
#include <linux/pm_runtime.h>
#include <linux/switchtec.h>
+#include <linux/nvme.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
@@ -3669,6 +3670,122 @@ static int reset_chelsio_generic_dev(struct pci_dev *dev, int probe)
#define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156
#define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166
+/* NVMe controller needs delay before testing ready status */
+#define NVME_QUIRK_CHK_RDY_DELAY (1 << 0)
+/* NVMe controller needs post-FLR delay */
+#define NVME_QUIRK_POST_FLR_DELAY (1 << 1)
+
+static const struct pci_device_id nvme_reset_tbl[] = {
+ { PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(0x1c58, 0x0003), /* HGST adapter */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(0x1c58, 0x0023), /* WDC SN200 adapter */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(0x1c5f, 0x0540), /* Memblaze Pblaze4 adapter */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(PCI_VENDOR_ID_SAMSUNG, 0xa821), /* Samsung PM1725 */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(PCI_VENDOR_ID_SAMSUNG, 0xa822), /* Samsung PM1725a */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0953), /* Intel DC P3700 */
+ .driver_data = NVME_QUIRK_POST_FLR_DELAY, },
+ { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
+ { 0 }
+};
+
+/*
+ * The NVMe specification requires that controllers support PCIe FLR, but
+ * but some Samsung SM961/PM961 controllers fail to recover after FLR (-1
+ * config space) unless the device is quiesced prior to FLR. Do this for
+ * all NVMe devices by disabling the controller before reset. Some Intel
+ * controllers also require an additional post-FLR delay or else attempts
+ * to re-enable will timeout, do that here as well with heuristically
+ * determined delay value. Also maintain the delay between disabling and
+ * checking ready status as used by the native NVMe driver.
+ *
+ * NVMe specification: https://nvmexpress.org/resources/specifications/
+ * Revision 1.0e:
+ * Chapter 2: Required and optional PCI config registers
+ * Chapter 3: NVMe control registers
+ * Chapter 7.3: Reset behavior
+ */
+static int reset_nvme(struct pci_dev *dev, int probe)
+{
+ const struct pci_device_id *id;
+ void __iomem *bar;
+ u16 cmd;
+ u32 cfg;
+
+ id = pci_match_id(nvme_reset_tbl, dev);
+ if (!id || !pcie_has_flr(dev) || !pci_resource_start(dev, 0))
+ return -ENOTTY;
+
+ if (probe)
+ return 0;
+
+ bar = pci_iomap(dev, 0, NVME_REG_CC + sizeof(cfg));
+ if (!bar)
+ return -ENOTTY;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY);
+
+ cfg = readl(bar + NVME_REG_CC);
+
+ /* Disable controller if enabled */
+ if (cfg & NVME_CC_ENABLE) {
+ u64 cap = readq(bar + NVME_REG_CAP);
+ unsigned long timeout;
+
+ /*
+ * Per nvme_disable_ctrl() skip shutdown notification as it
+ * could complete commands to the admin queue. We only intend
+ * to quiesce the device before reset.
+ */
+ cfg &= ~(NVME_CC_SHN_MASK | NVME_CC_ENABLE);
+
+ writel(cfg, bar + NVME_REG_CC);
+
+ /* A heuristic value, matches NVME_QUIRK_DELAY_AMOUNT */
+ if (id->driver_data & NVME_QUIRK_CHK_RDY_DELAY)
+ msleep(2300);
+
+ /* Cap register provides max timeout in 500ms increments */
+ timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
+
+ for (;;) {
+ u32 status = readl(bar + NVME_REG_CSTS);
+
+ /* Ready status becomes zero on disable complete */
+ if (!(status & NVME_CSTS_RDY))
+ break;
+
+ msleep(100);
+
+ if (time_after(jiffies, timeout)) {
+ pci_warn(dev, "Timeout waiting for NVMe ready status to clear after disable\n");
+ break;
+ }
+ }
+ }
+
+ pci_iounmap(dev, bar);
+
+ /*
+ * We could use the optional NVM Subsystem Reset here, hardware
+ * supporting this is simply unavailable at the time of this code
+ * to validate in comparison to PCIe FLR. NVMe spec dictates that
+ * NVMe devices shall implement PCIe FLR.
+ */
+ pcie_flr(dev);
+
+ if (id->driver_data & NVME_QUIRK_POST_FLR_DELAY)
+ msleep(250); /* Heuristic based on Intel DC P3700 */
+
+ return 0;
+}
+
static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
reset_intel_82599_sfp_virtfn },
@@ -3678,6 +3795,7 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
reset_ivb_igd },
{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
reset_chelsio_generic_dev },
+ { PCI_ANY_ID, PCI_ANY_ID, reset_nvme },
{ 0 }
};
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply related
* [PATCH v2 2/2] PCI: NVMe device specific reset quirk
From: Alex Williamson @ 2018-07-24 0:13 UTC (permalink / raw)
In-Reply-To: <20180724000944.7671.64284.stgit@gimli.home>
Take advantage of NVMe devices using a standard interface to quiesce
the controller prior to reset, including device specific delays before
and after that reset. This resolves several NVMe device assignment
scenarios with two different vendors. The Intel DC P3700 controller
has been shown to only work as a VM boot device on the initial VM
startup, failing after reset or reboot, and also fails to initialize
after hot-plug into a VM. Adding a delay after FLR resolves these
cases. The Samsung SM961/PM961 (960 EVO) sometimes fails to return
from FLR with the PCI config space reading back as -1. A reproducible
instance of this behavior is resolved by clearing the enable bit in
the configuration register and waiting for the ready status to clear
(disabling the NVMe controller) prior to FLR.
As all NVMe devices make use of this standard interface and the NVMe
specification also requires PCIe FLR support, we can apply this quirk
to all devices with matching class code.
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1592654
Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
---
drivers/pci/quirks.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e72c8742aafa..bbd029e8d3ae 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -28,6 +28,7 @@
#include <linux/platform_data/x86/apple.h>
#include <linux/pm_runtime.h>
#include <linux/switchtec.h>
+#include <linux/nvme.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
@@ -3669,6 +3670,122 @@ static int reset_chelsio_generic_dev(struct pci_dev *dev, int probe)
#define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156
#define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166
+/* NVMe controller needs delay before testing ready status */
+#define NVME_QUIRK_CHK_RDY_DELAY (1 << 0)
+/* NVMe controller needs post-FLR delay */
+#define NVME_QUIRK_POST_FLR_DELAY (1 << 1)
+
+static const struct pci_device_id nvme_reset_tbl[] = {
+ { PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(0x1c58, 0x0003), /* HGST adapter */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(0x1c58, 0x0023), /* WDC SN200 adapter */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(0x1c5f, 0x0540), /* Memblaze Pblaze4 adapter */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(PCI_VENDOR_ID_SAMSUNG, 0xa821), /* Samsung PM1725 */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(PCI_VENDOR_ID_SAMSUNG, 0xa822), /* Samsung PM1725a */
+ .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0953), /* Intel DC P3700 */
+ .driver_data = NVME_QUIRK_POST_FLR_DELAY, },
+ { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
+ { 0 }
+};
+
+/*
+ * The NVMe specification requires that controllers support PCIe FLR, but
+ * but some Samsung SM961/PM961 controllers fail to recover after FLR (-1
+ * config space) unless the device is quiesced prior to FLR. Do this for
+ * all NVMe devices by disabling the controller before reset. Some Intel
+ * controllers also require an additional post-FLR delay or else attempts
+ * to re-enable will timeout, do that here as well with heuristically
+ * determined delay value. Also maintain the delay between disabling and
+ * checking ready status as used by the native NVMe driver.
+ *
+ * NVMe specification: https://nvmexpress.org/resources/specifications/
+ * Revision 1.0e:
+ * Chapter 2: Required and optional PCI config registers
+ * Chapter 3: NVMe control registers
+ * Chapter 7.3: Reset behavior
+ */
+static int reset_nvme(struct pci_dev *dev, int probe)
+{
+ const struct pci_device_id *id;
+ void __iomem *bar;
+ u16 cmd;
+ u32 cfg;
+
+ id = pci_match_id(nvme_reset_tbl, dev);
+ if (!id || !pcie_has_flr(dev) || !pci_resource_start(dev, 0))
+ return -ENOTTY;
+
+ if (probe)
+ return 0;
+
+ bar = pci_iomap(dev, 0, NVME_REG_CC + sizeof(cfg));
+ if (!bar)
+ return -ENOTTY;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY);
+
+ cfg = readl(bar + NVME_REG_CC);
+
+ /* Disable controller if enabled */
+ if (cfg & NVME_CC_ENABLE) {
+ u64 cap = readq(bar + NVME_REG_CAP);
+ unsigned long timeout;
+
+ /*
+ * Per nvme_disable_ctrl() skip shutdown notification as it
+ * could complete commands to the admin queue. We only intend
+ * to quiesce the device before reset.
+ */
+ cfg &= ~(NVME_CC_SHN_MASK | NVME_CC_ENABLE);
+
+ writel(cfg, bar + NVME_REG_CC);
+
+ /* A heuristic value, matches NVME_QUIRK_DELAY_AMOUNT */
+ if (id->driver_data & NVME_QUIRK_CHK_RDY_DELAY)
+ msleep(2300);
+
+ /* Cap register provides max timeout in 500ms increments */
+ timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
+
+ for (;;) {
+ u32 status = readl(bar + NVME_REG_CSTS);
+
+ /* Ready status becomes zero on disable complete */
+ if (!(status & NVME_CSTS_RDY))
+ break;
+
+ msleep(100);
+
+ if (time_after(jiffies, timeout)) {
+ pci_warn(dev, "Timeout waiting for NVMe ready status to clear after disable\n");
+ break;
+ }
+ }
+ }
+
+ pci_iounmap(dev, bar);
+
+ /*
+ * We could use the optional NVM Subsystem Reset here, hardware
+ * supporting this is simply unavailable at the time of this code
+ * to validate in comparison to PCIe FLR. NVMe spec dictates that
+ * NVMe devices shall implement PCIe FLR.
+ */
+ pcie_flr(dev);
+
+ if (id->driver_data & NVME_QUIRK_POST_FLR_DELAY)
+ msleep(250); /* Heuristic based on Intel DC P3700 */
+
+ return 0;
+}
+
static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
reset_intel_82599_sfp_virtfn },
@@ -3678,6 +3795,7 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
reset_ivb_igd },
{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
reset_chelsio_generic_dev },
+ { PCI_ANY_ID, PCI_ANY_ID, reset_nvme },
{ 0 }
};
^ permalink raw reply related
* [PATCH v2 1/2] PCI: Export pcie_has_flr()
From: Alex Williamson @ 2018-07-24 0:13 UTC (permalink / raw)
To: linux-pci; +Cc: linux-kernel, linux-nvme
In-Reply-To: <20180724000944.7671.64284.stgit@gimli.home>
pcie_flr() suggests pcie_has_flr() to ensure that PCIe FLR support is
present prior to calling. pcie_flr() is exported while pcie_has_flr()
is not. Resolve this.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
drivers/pci/pci.c | 3 ++-
include/linux/pci.h | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2bec76c9d9a7..52fe2d72a99c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4071,7 +4071,7 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
* Returns true if the device advertises support for PCIe function level
* resets.
*/
-static bool pcie_has_flr(struct pci_dev *dev)
+bool pcie_has_flr(struct pci_dev *dev)
{
u32 cap;
@@ -4081,6 +4081,7 @@ static bool pcie_has_flr(struct pci_dev *dev)
pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap);
return cap & PCI_EXP_DEVCAP_FLR;
}
+EXPORT_SYMBOL_GPL(pcie_has_flr);
/**
* pcie_flr - initiate a PCIe function level reset
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 04c7ea6ed67b..bbe030d7814f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1092,6 +1092,7 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
enum pci_bus_speed *speed,
enum pcie_link_width *width);
void pcie_print_link_status(struct pci_dev *dev);
+bool pcie_has_flr(struct pci_dev *dev);
int pcie_flr(struct pci_dev *dev);
int __pci_reset_function_locked(struct pci_dev *dev);
int pci_reset_function(struct pci_dev *dev);
^ permalink raw reply related
* [PATCH v2 1/2] PCI: Export pcie_has_flr()
From: Alex Williamson @ 2018-07-24 0:13 UTC (permalink / raw)
To: linux-pci; +Cc: linux-kernel, linux-nvme
In-Reply-To: <20180724000944.7671.64284.stgit@gimli.home>
pcie_flr() suggests pcie_has_flr() to ensure that PCIe FLR support is
present prior to calling. pcie_flr() is exported while pcie_has_flr()
is not. Resolve this.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
drivers/pci/pci.c | 3 ++-
include/linux/pci.h | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2bec76c9d9a7..52fe2d72a99c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4071,7 +4071,7 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
* Returns true if the device advertises support for PCIe function level
* resets.
*/
-static bool pcie_has_flr(struct pci_dev *dev)
+bool pcie_has_flr(struct pci_dev *dev)
{
u32 cap;
@@ -4081,6 +4081,7 @@ static bool pcie_has_flr(struct pci_dev *dev)
pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap);
return cap & PCI_EXP_DEVCAP_FLR;
}
+EXPORT_SYMBOL_GPL(pcie_has_flr);
/**
* pcie_flr - initiate a PCIe function level reset
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 04c7ea6ed67b..bbe030d7814f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1092,6 +1092,7 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
enum pci_bus_speed *speed,
enum pcie_link_width *width);
void pcie_print_link_status(struct pci_dev *dev);
+bool pcie_has_flr(struct pci_dev *dev);
int pcie_flr(struct pci_dev *dev);
int __pci_reset_function_locked(struct pci_dev *dev);
int pci_reset_function(struct pci_dev *dev);
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply related
* [PATCH v2 1/2] PCI: Export pcie_has_flr()
From: Alex Williamson @ 2018-07-24 0:13 UTC (permalink / raw)
In-Reply-To: <20180724000944.7671.64284.stgit@gimli.home>
pcie_flr() suggests pcie_has_flr() to ensure that PCIe FLR support is
present prior to calling. pcie_flr() is exported while pcie_has_flr()
is not. Resolve this.
Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
---
drivers/pci/pci.c | 3 ++-
include/linux/pci.h | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2bec76c9d9a7..52fe2d72a99c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4071,7 +4071,7 @@ static int pci_dev_wait(struct pci_dev *dev, char *reset_type, int timeout)
* Returns true if the device advertises support for PCIe function level
* resets.
*/
-static bool pcie_has_flr(struct pci_dev *dev)
+bool pcie_has_flr(struct pci_dev *dev)
{
u32 cap;
@@ -4081,6 +4081,7 @@ static bool pcie_has_flr(struct pci_dev *dev)
pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap);
return cap & PCI_EXP_DEVCAP_FLR;
}
+EXPORT_SYMBOL_GPL(pcie_has_flr);
/**
* pcie_flr - initiate a PCIe function level reset
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 04c7ea6ed67b..bbe030d7814f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1092,6 +1092,7 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, struct pci_dev **limiting_dev,
enum pci_bus_speed *speed,
enum pcie_link_width *width);
void pcie_print_link_status(struct pci_dev *dev);
+bool pcie_has_flr(struct pci_dev *dev);
int pcie_flr(struct pci_dev *dev);
int __pci_reset_function_locked(struct pci_dev *dev);
int pci_reset_function(struct pci_dev *dev);
^ permalink raw reply related
* [PATCH v2 0/2] PCI: NVMe reset quirk
From: Alex Williamson @ 2018-07-24 0:12 UTC (permalink / raw)
To: linux-pci; +Cc: linux-kernel, linux-nvme
v2: Add bug link, use Samsung vendor ID, add spec references
As discussed in the 2nd patch, at least one NVMe controller sometimes
doesn't like being reset while enabled and another will timeout during
a subsequent re-enable if it happens too quickly after reset.
Introduce a device specific reset quirk for all NVMe class devices so
that we can try to get reliable behavior from them for device
assignment and any other users of the PCI subsystem reset interface.
Patches against current PCI next branch. Thanks,
Alex
---
Alex Williamson (2):
PCI: Export pcie_has_flr()
PCI: NVMe device specific reset quirk
drivers/pci/pci.c | 3 +
drivers/pci/quirks.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/pci.h | 1
3 files changed, 121 insertions(+), 1 deletion(-)
^ permalink raw reply
* [PATCH v2 0/2] PCI: NVMe reset quirk
From: Alex Williamson @ 2018-07-24 0:12 UTC (permalink / raw)
To: linux-pci; +Cc: linux-kernel, linux-nvme
v2: Add bug link, use Samsung vendor ID, add spec references
As discussed in the 2nd patch, at least one NVMe controller sometimes
doesn't like being reset while enabled and another will timeout during
a subsequent re-enable if it happens too quickly after reset.
Introduce a device specific reset quirk for all NVMe class devices so
that we can try to get reliable behavior from them for device
assignment and any other users of the PCI subsystem reset interface.
Patches against current PCI next branch. Thanks,
Alex
---
Alex Williamson (2):
PCI: Export pcie_has_flr()
PCI: NVMe device specific reset quirk
drivers/pci/pci.c | 3 +
drivers/pci/quirks.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/pci.h | 1
3 files changed, 121 insertions(+), 1 deletion(-)
_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply
* [PATCH v2 0/2] PCI: NVMe reset quirk
From: Alex Williamson @ 2018-07-24 0:12 UTC (permalink / raw)
v2: Add bug link, use Samsung vendor ID, add spec references
As discussed in the 2nd patch, at least one NVMe controller sometimes
doesn't like being reset while enabled and another will timeout during
a subsequent re-enable if it happens too quickly after reset.
Introduce a device specific reset quirk for all NVMe class devices so
that we can try to get reliable behavior from them for device
assignment and any other users of the PCI subsystem reset interface.
Patches against current PCI next branch. Thanks,
Alex
---
Alex Williamson (2):
PCI: Export pcie_has_flr()
PCI: NVMe device specific reset quirk
drivers/pci/pci.c | 3 +
drivers/pci/quirks.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/pci.h | 1
3 files changed, 121 insertions(+), 1 deletion(-)
^ permalink raw reply
* Re: [PATCH 2/2] PCI: NVMe device specific reset quirk
From: Alex Williamson @ 2018-07-24 0:11 UTC (permalink / raw)
To: Bjorn Helgaas; +Cc: linux-pci, linux-kernel, linux-nvme
In-Reply-To: <20180723224533.GX128988@bhelgaas-glaptop.roam.corp.google.com>
On Mon, 23 Jul 2018 17:45:33 -0500
Bjorn Helgaas <helgaas@kernel.org> wrote:
> On Mon, Jul 23, 2018 at 04:24:31PM -0600, Alex Williamson wrote:
> > Take advantage of NVMe devices using a standard interface to quiesce
> > the controller prior to reset, including device specific delays before
> > and after that reset. This resolves several NVMe device assignment
> > scenarios with two different vendors. The Intel DC P3700 controller
> > has been shown to only work as a VM boot device on the initial VM
> > startup, failing after reset or reboot, and also fails to initialize
> > after hot-plug into a VM. Adding a delay after FLR resolves these
> > cases. The Samsung SM961/PM961 (960 EVO) sometimes fails to return
> > from FLR with the PCI config space reading back as -1. A reproducible
> > instance of this behavior is resolved by clearing the enable bit in
> > the configuration register and waiting for the ready status to clear
> > (disabling the NVMe controller) prior to FLR.
> >
> > As all NVMe devices make use of this standard interface and the NVMe
> > specification also requires PCIe FLR support, we can apply this quirk
> > to all devices with matching class code.
>
> Do you have any pointers to problem reports or bugzilla entries that
> we could include here?
Yes, https://bugzilla.redhat.com/show_bug.cgi?id=1592654
This only covers the Intel P3700 issue. The Samsung issue has been
reported via a couple bugs, but was not reproducible until recently.
Those bugs were previously closed due to lack of information. I'll add
the above link.
> > Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
> > ---
> > drivers/pci/quirks.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 112 insertions(+)
> >
> > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> > index e72c8742aafa..83853562f220 100644
> > --- a/drivers/pci/quirks.c
> > +++ b/drivers/pci/quirks.c
> > @@ -28,6 +28,7 @@
> > #include <linux/platform_data/x86/apple.h>
> > #include <linux/pm_runtime.h>
> > #include <linux/switchtec.h>
> > +#include <linux/nvme.h>
> > #include <asm/dma.h> /* isa_dma_bridge_buggy */
> > #include "pci.h"
> >
> > @@ -3669,6 +3670,116 @@ static int reset_chelsio_generic_dev(struct pci_dev *dev, int probe)
> > #define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156
> > #define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166
> >
> > +/* NVMe controller needs delay before testing ready status */
> > +#define NVME_QUIRK_CHK_RDY_DELAY (1 << 0)
> > +/* NVMe controller needs post-FLR delay */
> > +#define NVME_QUIRK_POST_FLR_DELAY (1 << 1)
> > +
> > +static const struct pci_device_id nvme_reset_tbl[] = {
> > + { PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(0x1c58, 0x0003), /* HGST adapter */
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(0x1c58, 0x0023), /* WDC SN200 adapter */
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(0x1c5f, 0x0540), /* Memblaze Pblaze4 adapter */
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(0x144d, 0xa821), /* Samsung PM1725 */
>
> We do have PCI_VENDOR_ID_SAMSUNG if you want to use it here. I
> don't see Seagate, HGST, etc.
Oops, cut and pasted those from the nvme driver, I'll use the Samsung
macro.
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(0x144d, 0xa822), /* Samsung PM1725a */
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0953), /* Intel DC P3700 */
> > + .driver_data = NVME_QUIRK_POST_FLR_DELAY, },
> > + { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
> > + { 0 }
> > +};
> > +
> > +/*
> > + * The NVMe specification requires that controllers support PCIe FLR, but
> > + * but some Samsung SM961/PM961 controllers fail to recover after FLR (-1
> > + * config space) unless the device is quiesced prior to FLR. Do this for
> > + * all NVMe devices by disabling the controller before reset. Some Intel
> > + * controllers also require an additional post-FLR delay or else attempts
> > + * to re-enable will timeout, do that here as well with heuristically
> > + * determined delay value. Also maintain the delay between disabling and
> > + * checking ready status as used by the native NVMe driver.
> > + */
> > +static int reset_nvme(struct pci_dev *dev, int probe)
> > +{
> > + const struct pci_device_id *id;
> > + void __iomem *bar;
> > + u16 cmd;
> > + u32 cfg;
> > +
> > + id = pci_match_id(nvme_reset_tbl, dev);
> > + if (!id || !pcie_has_flr(dev) || !pci_resource_start(dev, 0))
> > + return -ENOTTY;
> > +
> > + if (probe)
> > + return 0;
> > +
> > + bar = pci_iomap(dev, 0, NVME_REG_CC + sizeof(cfg));
> > + if (!bar)
> > + return -ENOTTY;
> > +
> > + pci_read_config_word(dev, PCI_COMMAND, &cmd);
> > + pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY);
> > +
> > + cfg = readl(bar + NVME_REG_CC);
>
> Apparently this is part of some NVMe spec and all controllers support
> this? Is there a public reference you could cite for the details?
Yep, I'll add a link in the comments, it's all public. Thanks,
Alex
> > +
> > + /* Disable controller if enabled */
> > + if (cfg & NVME_CC_ENABLE) {
> > + u64 cap = readq(bar + NVME_REG_CAP);
> > + unsigned long timeout;
> > +
> > + /*
> > + * Per nvme_disable_ctrl() skip shutdown notification as it
> > + * could complete commands to the admin queue. We only intend
> > + * to quiesce the device before reset.
> > + */
> > + cfg &= ~(NVME_CC_SHN_MASK | NVME_CC_ENABLE);
> > +
> > + writel(cfg, bar + NVME_REG_CC);
> > +
> > + /* A heuristic value, matches NVME_QUIRK_DELAY_AMOUNT */
> > + if (id->driver_data & NVME_QUIRK_CHK_RDY_DELAY)
> > + msleep(2300);
> > +
> > + /* Cap register provides max timeout in 500ms increments */
> > + timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
> > +
> > + for (;;) {
> > + u32 status = readl(bar + NVME_REG_CSTS);
> > +
> > + /* Ready status becomes zero on disable complete */
> > + if (!(status & NVME_CSTS_RDY))
> > + break;
> > +
> > + msleep(100);
> > +
> > + if (time_after(jiffies, timeout)) {
> > + pci_warn(dev, "Timeout waiting for NVMe ready status to clear after disable\n");
> > + break;
> > + }
> > + }
> > + }
> > +
> > + pci_iounmap(dev, bar);
> > +
> > + /*
> > + * We could use the optional NVM Subsystem Reset here, hardware
> > + * supporting this is simply unavailable at the time of this code
> > + * to validate in comparison to PCIe FLR. NVMe spec dictates that
> > + * NVMe devices shall implement PCIe FLR.
> > + */
> > + pcie_flr(dev);
> > +
> > + if (id->driver_data & NVME_QUIRK_POST_FLR_DELAY)
> > + msleep(250); /* Heuristic based on Intel DC P3700 */
> > +
> > + return 0;
> > +}
> > +
> > static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
> > { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
> > reset_intel_82599_sfp_virtfn },
> > @@ -3678,6 +3789,7 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
> > reset_ivb_igd },
> > { PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
> > reset_chelsio_generic_dev },
> > + { PCI_ANY_ID, PCI_ANY_ID, reset_nvme },
> > { 0 }
> > };
> >
> >
> >
> > _______________________________________________
> > Linux-nvme mailing list
> > Linux-nvme@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply
* [PATCH 2/2] PCI: NVMe device specific reset quirk
From: Alex Williamson @ 2018-07-24 0:11 UTC (permalink / raw)
In-Reply-To: <20180723224533.GX128988@bhelgaas-glaptop.roam.corp.google.com>
On Mon, 23 Jul 2018 17:45:33 -0500
Bjorn Helgaas <helgaas@kernel.org> wrote:
> On Mon, Jul 23, 2018@04:24:31PM -0600, Alex Williamson wrote:
> > Take advantage of NVMe devices using a standard interface to quiesce
> > the controller prior to reset, including device specific delays before
> > and after that reset. This resolves several NVMe device assignment
> > scenarios with two different vendors. The Intel DC P3700 controller
> > has been shown to only work as a VM boot device on the initial VM
> > startup, failing after reset or reboot, and also fails to initialize
> > after hot-plug into a VM. Adding a delay after FLR resolves these
> > cases. The Samsung SM961/PM961 (960 EVO) sometimes fails to return
> > from FLR with the PCI config space reading back as -1. A reproducible
> > instance of this behavior is resolved by clearing the enable bit in
> > the configuration register and waiting for the ready status to clear
> > (disabling the NVMe controller) prior to FLR.
> >
> > As all NVMe devices make use of this standard interface and the NVMe
> > specification also requires PCIe FLR support, we can apply this quirk
> > to all devices with matching class code.
>
> Do you have any pointers to problem reports or bugzilla entries that
> we could include here?
Yes, https://bugzilla.redhat.com/show_bug.cgi?id=1592654
This only covers the Intel P3700 issue. The Samsung issue has been
reported via a couple bugs, but was not reproducible until recently.
Those bugs were previously closed due to lack of information. I'll add
the above link.
> > Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
> > ---
> > drivers/pci/quirks.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 112 insertions(+)
> >
> > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> > index e72c8742aafa..83853562f220 100644
> > --- a/drivers/pci/quirks.c
> > +++ b/drivers/pci/quirks.c
> > @@ -28,6 +28,7 @@
> > #include <linux/platform_data/x86/apple.h>
> > #include <linux/pm_runtime.h>
> > #include <linux/switchtec.h>
> > +#include <linux/nvme.h>
> > #include <asm/dma.h> /* isa_dma_bridge_buggy */
> > #include "pci.h"
> >
> > @@ -3669,6 +3670,116 @@ static int reset_chelsio_generic_dev(struct pci_dev *dev, int probe)
> > #define PCI_DEVICE_ID_INTEL_IVB_M_VGA 0x0156
> > #define PCI_DEVICE_ID_INTEL_IVB_M2_VGA 0x0166
> >
> > +/* NVMe controller needs delay before testing ready status */
> > +#define NVME_QUIRK_CHK_RDY_DELAY (1 << 0)
> > +/* NVMe controller needs post-FLR delay */
> > +#define NVME_QUIRK_POST_FLR_DELAY (1 << 1)
> > +
> > +static const struct pci_device_id nvme_reset_tbl[] = {
> > + { PCI_DEVICE(0x1bb1, 0x0100), /* Seagate Nytro Flash Storage */
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(0x1c58, 0x0003), /* HGST adapter */
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(0x1c58, 0x0023), /* WDC SN200 adapter */
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(0x1c5f, 0x0540), /* Memblaze Pblaze4 adapter */
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(0x144d, 0xa821), /* Samsung PM1725 */
>
> We do have PCI_VENDOR_ID_SAMSUNG if you want to use it here. I
> don't see Seagate, HGST, etc.
Oops, cut and pasted those from the nvme driver, I'll use the Samsung
macro.
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(0x144d, 0xa822), /* Samsung PM1725a */
> > + .driver_data = NVME_QUIRK_CHK_RDY_DELAY, },
> > + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0953), /* Intel DC P3700 */
> > + .driver_data = NVME_QUIRK_POST_FLR_DELAY, },
> > + { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
> > + { 0 }
> > +};
> > +
> > +/*
> > + * The NVMe specification requires that controllers support PCIe FLR, but
> > + * but some Samsung SM961/PM961 controllers fail to recover after FLR (-1
> > + * config space) unless the device is quiesced prior to FLR. Do this for
> > + * all NVMe devices by disabling the controller before reset. Some Intel
> > + * controllers also require an additional post-FLR delay or else attempts
> > + * to re-enable will timeout, do that here as well with heuristically
> > + * determined delay value. Also maintain the delay between disabling and
> > + * checking ready status as used by the native NVMe driver.
> > + */
> > +static int reset_nvme(struct pci_dev *dev, int probe)
> > +{
> > + const struct pci_device_id *id;
> > + void __iomem *bar;
> > + u16 cmd;
> > + u32 cfg;
> > +
> > + id = pci_match_id(nvme_reset_tbl, dev);
> > + if (!id || !pcie_has_flr(dev) || !pci_resource_start(dev, 0))
> > + return -ENOTTY;
> > +
> > + if (probe)
> > + return 0;
> > +
> > + bar = pci_iomap(dev, 0, NVME_REG_CC + sizeof(cfg));
> > + if (!bar)
> > + return -ENOTTY;
> > +
> > + pci_read_config_word(dev, PCI_COMMAND, &cmd);
> > + pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY);
> > +
> > + cfg = readl(bar + NVME_REG_CC);
>
> Apparently this is part of some NVMe spec and all controllers support
> this? Is there a public reference you could cite for the details?
Yep, I'll add a link in the comments, it's all public. Thanks,
Alex
> > +
> > + /* Disable controller if enabled */
> > + if (cfg & NVME_CC_ENABLE) {
> > + u64 cap = readq(bar + NVME_REG_CAP);
> > + unsigned long timeout;
> > +
> > + /*
> > + * Per nvme_disable_ctrl() skip shutdown notification as it
> > + * could complete commands to the admin queue. We only intend
> > + * to quiesce the device before reset.
> > + */
> > + cfg &= ~(NVME_CC_SHN_MASK | NVME_CC_ENABLE);
> > +
> > + writel(cfg, bar + NVME_REG_CC);
> > +
> > + /* A heuristic value, matches NVME_QUIRK_DELAY_AMOUNT */
> > + if (id->driver_data & NVME_QUIRK_CHK_RDY_DELAY)
> > + msleep(2300);
> > +
> > + /* Cap register provides max timeout in 500ms increments */
> > + timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
> > +
> > + for (;;) {
> > + u32 status = readl(bar + NVME_REG_CSTS);
> > +
> > + /* Ready status becomes zero on disable complete */
> > + if (!(status & NVME_CSTS_RDY))
> > + break;
> > +
> > + msleep(100);
> > +
> > + if (time_after(jiffies, timeout)) {
> > + pci_warn(dev, "Timeout waiting for NVMe ready status to clear after disable\n");
> > + break;
> > + }
> > + }
> > + }
> > +
> > + pci_iounmap(dev, bar);
> > +
> > + /*
> > + * We could use the optional NVM Subsystem Reset here, hardware
> > + * supporting this is simply unavailable at the time of this code
> > + * to validate in comparison to PCIe FLR. NVMe spec dictates that
> > + * NVMe devices shall implement PCIe FLR.
> > + */
> > + pcie_flr(dev);
> > +
> > + if (id->driver_data & NVME_QUIRK_POST_FLR_DELAY)
> > + msleep(250); /* Heuristic based on Intel DC P3700 */
> > +
> > + return 0;
> > +}
> > +
> > static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
> > { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
> > reset_intel_82599_sfp_virtfn },
> > @@ -3678,6 +3789,7 @@ static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
> > reset_ivb_igd },
> > { PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
> > reset_chelsio_generic_dev },
> > + { PCI_ANY_ID, PCI_ANY_ID, reset_nvme },
> > { 0 }
> > };
> >
> >
> >
> > _______________________________________________
> > Linux-nvme mailing list
> > Linux-nvme at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-nvme
^ permalink raw reply
* [PATCH v6] media: dvb-frontends: add Socionext MN88443x ISDB-S/T demodulator driver
From: Katsuhiro Suzuki @ 2018-07-24 0:09 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds a frontend driver for the Socionext/Panasonic
MN884434 and MN884433 ISDB-S/T demodulators.
The maximum and minimum frequency of MN88443x comes from
ISDB-S and ISDB-T so frequency range is the following:
- ISDB-S (BS/CS110 IF frequency, Local freq 10.678GHz)
- Min: BS-1: 1032MHz
- Max: ND24: 2070MHz
- ISDB-T
- Min: ch13: 470MHz
- Max: ch62: 770MHz
Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
---
Changes since v5:
- Fix include of header.
Changes since v4:
- Remove SC1501A support.
This driver is written and tested for MN88443x, I misunderstood
spec of SC1501A. SC1501A has not compatibility with MN88443x.
Changes since v3:
- Add symbol rate for ISDB-S
- Describe max/min frequency in Hz (not kHz)
- Depends on Mauro's DVB core fixes
https://patchwork.linuxtv.org/patch/50886/
https://patchwork.linuxtv.org/patch/50887/
https://patchwork.linuxtv.org/patch/50888/
Changes since v2:
- Fix frequency max and min
Changes since v1:
- Fix sparse warning about type of constant
- Use div_s64() instead of divide operator
---
drivers/media/dvb-frontends/Kconfig | 10 +
drivers/media/dvb-frontends/Makefile | 1 +
drivers/media/dvb-frontends/mn88443x.c | 802 +++++++++++++++++++++++++
drivers/media/dvb-frontends/mn88443x.h | 27 +
4 files changed, 840 insertions(+)
create mode 100644 drivers/media/dvb-frontends/mn88443x.c
create mode 100644 drivers/media/dvb-frontends/mn88443x.h
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 9ecaa9d0744a..048285134cdf 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -739,6 +739,16 @@ config DVB_TC90522
Toshiba TC90522 2xISDB-S 8PSK + 2xISDB-T OFDM demodulator.
Say Y when you want to support this frontend.
+config DVB_MN88443X
+ tristate "Socionext MN88443x"
+ depends on DVB_CORE && I2C
+ select REGMAP_I2C
+ default m if !MEDIA_SUBDRV_AUTOSELECT
+ help
+ A driver for Socionext/Panasonic MN884433 and MN884434
+ ISDB-S + ISDB-T demodulator.
+ Say Y when you want to support this frontend.
+
comment "Digital terrestrial only tuners/PLL"
depends on DVB_CORE
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
index 67a783fd5ed0..779dfd027b24 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -125,6 +125,7 @@ obj-$(CONFIG_DVB_AF9033) += af9033.o
obj-$(CONFIG_DVB_AS102_FE) += as102_fe.o
obj-$(CONFIG_DVB_GP8PSK_FE) += gp8psk-fe.o
obj-$(CONFIG_DVB_TC90522) += tc90522.o
+obj-$(CONFIG_DVB_MN88443X) += mn88443x.o
obj-$(CONFIG_DVB_HORUS3A) += horus3a.o
obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o
obj-$(CONFIG_DVB_HELENE) += helene.o
diff --git a/drivers/media/dvb-frontends/mn88443x.c b/drivers/media/dvb-frontends/mn88443x.c
new file mode 100644
index 000000000000..9ec1aeef03d5
--- /dev/null
+++ b/drivers/media/dvb-frontends/mn88443x.c
@@ -0,0 +1,802 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Socionext MN88443x series demodulator driver for ISDB-S/ISDB-T.
+//
+// Copyright (c) 2018 Socionext Inc.
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <media/dvb_math.h>
+
+#include "mn88443x.h"
+
+/* ISDB-S registers */
+#define ATSIDU_S 0x2f
+#define ATSIDL_S 0x30
+#define TSSET_S 0x31
+#define AGCREAD_S 0x5a
+#define CPMON1_S 0x5e
+#define CPMON1_S_FSYNC BIT(5)
+#define CPMON1_S_ERRMON BIT(4)
+#define CPMON1_S_SIGOFF BIT(3)
+#define CPMON1_S_W2LOCK BIT(2)
+#define CPMON1_S_W1LOCK BIT(1)
+#define CPMON1_S_DW1LOCK BIT(0)
+#define TRMON_S 0x60
+#define BERCNFLG_S 0x68
+#define BERCNFLG_S_BERVRDY BIT(5)
+#define BERCNFLG_S_BERVCHK BIT(4)
+#define BERCNFLG_S_BERDRDY BIT(3)
+#define BERCNFLG_S_BERDCHK BIT(2)
+#define CNRDXU_S 0x69
+#define CNRDXL_S 0x6a
+#define CNRDYU_S 0x6b
+#define CNRDYL_S 0x6c
+#define BERVRDU_S 0x71
+#define BERVRDL_S 0x72
+#define DOSET1_S 0x73
+
+/* Primary ISDB-T */
+#define PLLASET1 0x00
+#define PLLASET2 0x01
+#define PLLBSET1 0x02
+#define PLLBSET2 0x03
+#define PLLSET 0x04
+#define OUTCSET 0x08
+#define OUTCSET_CHDRV_8MA 0xff
+#define OUTCSET_CHDRV_4MA 0x00
+#define PLDWSET 0x09
+#define PLDWSET_NORMAL 0x00
+#define PLDWSET_PULLDOWN 0xff
+#define HIZSET1 0x0a
+#define HIZSET2 0x0b
+
+/* Secondary ISDB-T (for MN884434 only) */
+#define RCVSET 0x00
+#define TSSET1_M 0x01
+#define TSSET2_M 0x02
+#define TSSET3_M 0x03
+#define INTACSET 0x08
+#define HIZSET3 0x0b
+
+/* ISDB-T registers */
+#define TSSET1 0x05
+#define TSSET1_TSASEL_MASK GENMASK(4, 3)
+#define TSSET1_TSASEL_ISDBT (0x0 << 3)
+#define TSSET1_TSASEL_ISDBS (0x1 << 3)
+#define TSSET1_TSASEL_NONE (0x2 << 3)
+#define TSSET1_TSBSEL_MASK GENMASK(2, 1)
+#define TSSET1_TSBSEL_ISDBS (0x0 << 1)
+#define TSSET1_TSBSEL_ISDBT (0x1 << 1)
+#define TSSET1_TSBSEL_NONE (0x2 << 1)
+#define TSSET2 0x06
+#define TSSET3 0x07
+#define TSSET3_INTASEL_MASK GENMASK(7, 6)
+#define TSSET3_INTASEL_T (0x0 << 6)
+#define TSSET3_INTASEL_S (0x1 << 6)
+#define TSSET3_INTASEL_NONE (0x2 << 6)
+#define TSSET3_INTBSEL_MASK GENMASK(5, 4)
+#define TSSET3_INTBSEL_S (0x0 << 4)
+#define TSSET3_INTBSEL_T (0x1 << 4)
+#define TSSET3_INTBSEL_NONE (0x2 << 4)
+#define OUTSET2 0x0d
+#define PWDSET 0x0f
+#define PWDSET_OFDMPD_MASK GENMASK(3, 2)
+#define PWDSET_OFDMPD_DOWN BIT(3)
+#define PWDSET_PSKPD_MASK GENMASK(1, 0)
+#define PWDSET_PSKPD_DOWN BIT(1)
+#define CLKSET1_T 0x11
+#define MDSET_T 0x13
+#define MDSET_T_MDAUTO_MASK GENMASK(7, 4)
+#define MDSET_T_MDAUTO_AUTO (0xf << 4)
+#define MDSET_T_MDAUTO_MANUAL (0x0 << 4)
+#define MDSET_T_FFTS_MASK GENMASK(3, 2)
+#define MDSET_T_FFTS_MODE1 (0x0 << 2)
+#define MDSET_T_FFTS_MODE2 (0x1 << 2)
+#define MDSET_T_FFTS_MODE3 (0x2 << 2)
+#define MDSET_T_GI_MASK GENMASK(1, 0)
+#define MDSET_T_GI_1_32 (0x0 << 0)
+#define MDSET_T_GI_1_16 (0x1 << 0)
+#define MDSET_T_GI_1_8 (0x2 << 0)
+#define MDSET_T_GI_1_4 (0x3 << 0)
+#define MDASET_T 0x14
+#define ADCSET1_T 0x20
+#define ADCSET1_T_REFSEL_MASK GENMASK(1, 0)
+#define ADCSET1_T_REFSEL_2V (0x3 << 0)
+#define ADCSET1_T_REFSEL_1_5V (0x2 << 0)
+#define ADCSET1_T_REFSEL_1V (0x1 << 0)
+#define NCOFREQU_T 0x24
+#define NCOFREQM_T 0x25
+#define NCOFREQL_T 0x26
+#define FADU_T 0x27
+#define FADM_T 0x28
+#define FADL_T 0x29
+#define AGCSET2_T 0x2c
+#define AGCSET2_T_IFPOLINV_INC BIT(0)
+#define AGCSET2_T_RFPOLINV_INC BIT(1)
+#define AGCV3_T 0x3e
+#define MDRD_T 0xa2
+#define MDRD_T_SEGID_MASK GENMASK(5, 4)
+#define MDRD_T_SEGID_13 (0x0 << 4)
+#define MDRD_T_SEGID_1 (0x1 << 4)
+#define MDRD_T_SEGID_3 (0x2 << 4)
+#define MDRD_T_FFTS_MASK GENMASK(3, 2)
+#define MDRD_T_FFTS_MODE1 (0x0 << 2)
+#define MDRD_T_FFTS_MODE2 (0x1 << 2)
+#define MDRD_T_FFTS_MODE3 (0x2 << 2)
+#define MDRD_T_GI_MASK GENMASK(1, 0)
+#define MDRD_T_GI_1_32 (0x0 << 0)
+#define MDRD_T_GI_1_16 (0x1 << 0)
+#define MDRD_T_GI_1_8 (0x2 << 0)
+#define MDRD_T_GI_1_4 (0x3 << 0)
+#define SSEQRD_T 0xa3
+#define SSEQRD_T_SSEQSTRD_MASK GENMASK(3, 0)
+#define SSEQRD_T_SSEQSTRD_RESET (0x0 << 0)
+#define SSEQRD_T_SSEQSTRD_TUNING (0x1 << 0)
+#define SSEQRD_T_SSEQSTRD_AGC (0x2 << 0)
+#define SSEQRD_T_SSEQSTRD_SEARCH (0x3 << 0)
+#define SSEQRD_T_SSEQSTRD_CLOCK_SYNC (0x4 << 0)
+#define SSEQRD_T_SSEQSTRD_FREQ_SYNC (0x8 << 0)
+#define SSEQRD_T_SSEQSTRD_FRAME_SYNC (0x9 << 0)
+#define SSEQRD_T_SSEQSTRD_SYNC (0xa << 0)
+#define SSEQRD_T_SSEQSTRD_LOCK (0xb << 0)
+#define AGCRDU_T 0xa8
+#define AGCRDL_T 0xa9
+#define CNRDU_T 0xbe
+#define CNRDL_T 0xbf
+#define BERFLG_T 0xc0
+#define BERFLG_T_BERDRDY BIT(7)
+#define BERFLG_T_BERDCHK BIT(6)
+#define BERFLG_T_BERVRDYA BIT(5)
+#define BERFLG_T_BERVCHKA BIT(4)
+#define BERFLG_T_BERVRDYB BIT(3)
+#define BERFLG_T_BERVCHKB BIT(2)
+#define BERFLG_T_BERVRDYC BIT(1)
+#define BERFLG_T_BERVCHKC BIT(0)
+#define BERRDU_T 0xc1
+#define BERRDM_T 0xc2
+#define BERRDL_T 0xc3
+#define BERLENRDU_T 0xc4
+#define BERLENRDL_T 0xc5
+#define ERRFLG_T 0xc6
+#define ERRFLG_T_BERDOVF BIT(7)
+#define ERRFLG_T_BERVOVFA BIT(6)
+#define ERRFLG_T_BERVOVFB BIT(5)
+#define ERRFLG_T_BERVOVFC BIT(4)
+#define ERRFLG_T_NERRFA BIT(3)
+#define ERRFLG_T_NERRFB BIT(2)
+#define ERRFLG_T_NERRFC BIT(1)
+#define ERRFLG_T_NERRF BIT(0)
+#define DOSET1_T 0xcf
+
+#define CLK_LOW 4000000
+#define CLK_DIRECT 20200000
+#define CLK_MAX 25410000
+
+#define S_T_FREQ 8126984 /* 512 / 63 MHz */
+
+struct mn88443x_spec {
+ bool primary;
+};
+
+struct mn88443x_priv {
+ const struct mn88443x_spec *spec;
+
+ struct dvb_frontend fe;
+ struct clk *mclk;
+ struct gpio_desc *reset_gpio;
+ u32 clk_freq;
+ u32 if_freq;
+
+ /* Common */
+ bool use_clkbuf;
+
+ /* ISDB-S */
+ struct i2c_client *client_s;
+ struct regmap *regmap_s;
+
+ /* ISDB-T */
+ struct i2c_client *client_t;
+ struct regmap *regmap_t;
+};
+
+static void mn88443x_cmn_power_on(struct mn88443x_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ clk_prepare_enable(chip->mclk);
+
+ gpiod_set_value_cansleep(chip->reset_gpio, 1);
+ usleep_range(100, 1000);
+ gpiod_set_value_cansleep(chip->reset_gpio, 0);
+
+ if (chip->spec->primary) {
+ regmap_write(r_t, OUTCSET, OUTCSET_CHDRV_8MA);
+ regmap_write(r_t, PLDWSET, PLDWSET_NORMAL);
+ regmap_write(r_t, HIZSET1, 0x80);
+ regmap_write(r_t, HIZSET2, 0xe0);
+ } else {
+ regmap_write(r_t, HIZSET3, 0x8f);
+ }
+}
+
+static void mn88443x_cmn_power_off(struct mn88443x_priv *chip)
+{
+ gpiod_set_value_cansleep(chip->reset_gpio, 1);
+
+ clk_disable_unprepare(chip->mclk);
+}
+
+static void mn88443x_s_sleep(struct mn88443x_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK,
+ PWDSET_PSKPD_DOWN);
+}
+
+static void mn88443x_s_wake(struct mn88443x_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_PSKPD_MASK, 0);
+}
+
+static void mn88443x_s_tune(struct mn88443x_priv *chip,
+ struct dtv_frontend_properties *c)
+{
+ struct regmap *r_s = chip->regmap_s;
+
+ regmap_write(r_s, ATSIDU_S, c->stream_id >> 8);
+ regmap_write(r_s, ATSIDL_S, c->stream_id);
+ regmap_write(r_s, TSSET_S, 0);
+}
+
+static int mn88443x_s_read_status(struct mn88443x_priv *chip,
+ struct dtv_frontend_properties *c,
+ enum fe_status *status)
+{
+ struct regmap *r_s = chip->regmap_s;
+ u32 cpmon, tmpu, tmpl, flg;
+ u64 tmp;
+
+ /* Sync detection */
+ regmap_read(r_s, CPMON1_S, &cpmon);
+
+ *status = 0;
+ if (cpmon & CPMON1_S_FSYNC)
+ *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ if (cpmon & CPMON1_S_W2LOCK)
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+ /* Signal strength */
+ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_SIGNAL) {
+ u32 agc;
+
+ regmap_read(r_s, AGCREAD_S, &tmpu);
+ agc = tmpu << 8;
+
+ c->strength.len = 1;
+ c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+ c->strength.stat[0].uvalue = agc;
+ }
+
+ /* C/N rate */
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_VITERBI) {
+ u32 cnr = 0, x, y, d;
+ u64 d_3 = 0;
+
+ regmap_read(r_s, CNRDXU_S, &tmpu);
+ regmap_read(r_s, CNRDXL_S, &tmpl);
+ x = (tmpu << 8) | tmpl;
+ regmap_read(r_s, CNRDYU_S, &tmpu);
+ regmap_read(r_s, CNRDYL_S, &tmpl);
+ y = (tmpu << 8) | tmpl;
+
+ /* CNR[dB]: 10 * log10(D) - 30.74 / D^3 - 3 */
+ /* D = x^2 / (2^15 * y - x^2) */
+ d = (y << 15) - x * x;
+ if (d > 0) {
+ /* (2^4 * D)^3 = 2^12 * D^3 */
+ /* 3.074 * 2^(12 + 24) = 211243671486 */
+ d_3 = div_u64(16 * x * x, d);
+ d_3 = d_3 * d_3 * d_3;
+ if (d_3)
+ d_3 = div_u64(211243671486ULL, d_3);
+ }
+
+ if (d_3) {
+ /* 0.3 * 2^24 = 5033164 */
+ tmp = (s64)2 * intlog10(x) - intlog10(abs(d)) - d_3
+ - 5033164;
+ cnr = div_u64(tmp * 10000, 1 << 24);
+ }
+
+ if (cnr) {
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].uvalue = cnr;
+ }
+ }
+
+ /* BER */
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ regmap_read(r_s, BERCNFLG_S, &flg);
+
+ if ((*status & FE_HAS_VITERBI) && (flg & BERCNFLG_S_BERVRDY)) {
+ u32 bit_err, bit_cnt;
+
+ regmap_read(r_s, BERVRDU_S, &tmpu);
+ regmap_read(r_s, BERVRDL_S, &tmpl);
+ bit_err = (tmpu << 8) | tmpl;
+ bit_cnt = (1 << 13) * 204;
+
+ if (bit_cnt) {
+ c->post_bit_error.len = 1;
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue = bit_err;
+ c->post_bit_count.len = 1;
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].uvalue = bit_cnt;
+ }
+ }
+
+ return 0;
+}
+
+static void mn88443x_t_sleep(struct mn88443x_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK,
+ PWDSET_OFDMPD_DOWN);
+}
+
+static void mn88443x_t_wake(struct mn88443x_priv *chip)
+{
+ struct regmap *r_t = chip->regmap_t;
+
+ regmap_update_bits(r_t, PWDSET, PWDSET_OFDMPD_MASK, 0);
+}
+
+static bool mn88443x_t_is_valid_clk(u32 adckt, u32 if_freq)
+{
+ if (if_freq == DIRECT_IF_57MHZ) {
+ if (adckt >= CLK_DIRECT && adckt <= 21000000)
+ return true;
+ if (adckt >= 25300000 && adckt <= CLK_MAX)
+ return true;
+ } else if (if_freq == DIRECT_IF_44MHZ) {
+ if (adckt >= 25000000 && adckt <= CLK_MAX)
+ return true;
+ } else if (if_freq >= LOW_IF_4MHZ && if_freq < DIRECT_IF_44MHZ) {
+ if (adckt >= CLK_DIRECT && adckt <= CLK_MAX)
+ return true;
+ }
+
+ return false;
+}
+
+static int mn88443x_t_set_freq(struct mn88443x_priv *chip)
+{
+ struct device *dev = &chip->client_s->dev;
+ struct regmap *r_t = chip->regmap_t;
+ s64 adckt, nco, ad_t;
+ u32 m, v;
+
+ /* Clock buffer (but not supported) or XTAL */
+ if (chip->clk_freq >= CLK_LOW && chip->clk_freq < CLK_DIRECT) {
+ chip->use_clkbuf = true;
+ regmap_write(r_t, CLKSET1_T, 0x07);
+
+ adckt = 0;
+ } else {
+ chip->use_clkbuf = false;
+ regmap_write(r_t, CLKSET1_T, 0x00);
+
+ adckt = chip->clk_freq;
+ }
+ if (!mn88443x_t_is_valid_clk(adckt, chip->if_freq)) {
+ dev_err(dev, "Invalid clock, CLK:%d, ADCKT:%lld, IF:%d\n",
+ chip->clk_freq, adckt, chip->if_freq);
+ return -EINVAL;
+ }
+
+ /* Direct IF or Low IF */
+ if (chip->if_freq == DIRECT_IF_57MHZ ||
+ chip->if_freq == DIRECT_IF_44MHZ)
+ nco = adckt * 2 - chip->if_freq;
+ else
+ nco = -((s64)chip->if_freq);
+ nco = div_s64(nco << 24, adckt);
+ ad_t = div_s64(adckt << 22, S_T_FREQ);
+
+ regmap_write(r_t, NCOFREQU_T, nco >> 16);
+ regmap_write(r_t, NCOFREQM_T, nco >> 8);
+ regmap_write(r_t, NCOFREQL_T, nco);
+ regmap_write(r_t, FADU_T, ad_t >> 16);
+ regmap_write(r_t, FADM_T, ad_t >> 8);
+ regmap_write(r_t, FADL_T, ad_t);
+
+ /* Level of IF */
+ m = ADCSET1_T_REFSEL_MASK;
+ v = ADCSET1_T_REFSEL_1_5V;
+ regmap_update_bits(r_t, ADCSET1_T, m, v);
+
+ /* Polarity of AGC */
+ v = AGCSET2_T_IFPOLINV_INC | AGCSET2_T_RFPOLINV_INC;
+ regmap_update_bits(r_t, AGCSET2_T, v, v);
+
+ /* Lower output level of AGC */
+ regmap_write(r_t, AGCV3_T, 0x00);
+
+ regmap_write(r_t, MDSET_T, 0xfa);
+
+ return 0;
+}
+
+static void mn88443x_t_tune(struct mn88443x_priv *chip,
+ struct dtv_frontend_properties *c)
+{
+ struct regmap *r_t = chip->regmap_t;
+ u32 m, v;
+
+ m = MDSET_T_MDAUTO_MASK | MDSET_T_FFTS_MASK | MDSET_T_GI_MASK;
+ v = MDSET_T_MDAUTO_AUTO | MDSET_T_FFTS_MODE3 | MDSET_T_GI_1_8;
+ regmap_update_bits(r_t, MDSET_T, m, v);
+
+ regmap_write(r_t, MDASET_T, 0);
+}
+
+static int mn88443x_t_read_status(struct mn88443x_priv *chip,
+ struct dtv_frontend_properties *c,
+ enum fe_status *status)
+{
+ struct regmap *r_t = chip->regmap_t;
+ u32 seqrd, st, flg, tmpu, tmpm, tmpl;
+ u64 tmp;
+
+ /* Sync detection */
+ regmap_read(r_t, SSEQRD_T, &seqrd);
+ st = seqrd & SSEQRD_T_SSEQSTRD_MASK;
+
+ *status = 0;
+ if (st >= SSEQRD_T_SSEQSTRD_SYNC)
+ *status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ if (st >= SSEQRD_T_SSEQSTRD_FRAME_SYNC)
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+ /* Signal strength */
+ c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_SIGNAL) {
+ u32 agc;
+
+ regmap_read(r_t, AGCRDU_T, &tmpu);
+ regmap_read(r_t, AGCRDL_T, &tmpl);
+ agc = (tmpu << 8) | tmpl;
+
+ c->strength.len = 1;
+ c->strength.stat[0].scale = FE_SCALE_RELATIVE;
+ c->strength.stat[0].uvalue = agc;
+ }
+
+ /* C/N rate */
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ if (*status & FE_HAS_VITERBI) {
+ u32 cnr;
+
+ regmap_read(r_t, CNRDU_T, &tmpu);
+ regmap_read(r_t, CNRDL_T, &tmpl);
+
+ if (tmpu || tmpl) {
+ /* CNR[dB]: 10 * (log10(65536 / value) + 0.2) */
+ /* intlog10(65536) = 80807124, 0.2 * 2^24 = 3355443 */
+ tmp = (u64)80807124 - intlog10((tmpu << 8) | tmpl)
+ + 3355443;
+ cnr = div_u64(tmp * 10000, 1 << 24);
+ } else {
+ cnr = 0;
+ }
+
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].uvalue = cnr;
+ }
+
+ /* BER */
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ regmap_read(r_t, BERFLG_T, &flg);
+
+ if ((*status & FE_HAS_VITERBI) && (flg & BERFLG_T_BERVRDYA)) {
+ u32 bit_err, bit_cnt;
+
+ regmap_read(r_t, BERRDU_T, &tmpu);
+ regmap_read(r_t, BERRDM_T, &tmpm);
+ regmap_read(r_t, BERRDL_T, &tmpl);
+ bit_err = (tmpu << 16) | (tmpm << 8) | tmpl;
+
+ regmap_read(r_t, BERLENRDU_T, &tmpu);
+ regmap_read(r_t, BERLENRDL_T, &tmpl);
+ bit_cnt = ((tmpu << 8) | tmpl) * 203 * 8;
+
+ if (bit_cnt) {
+ c->post_bit_error.len = 1;
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue = bit_err;
+ c->post_bit_count.len = 1;
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].uvalue = bit_cnt;
+ }
+ }
+
+ return 0;
+}
+
+static int mn88443x_sleep(struct dvb_frontend *fe)
+{
+ struct mn88443x_priv *chip = fe->demodulator_priv;
+
+ mn88443x_s_sleep(chip);
+ mn88443x_t_sleep(chip);
+
+ return 0;
+}
+
+static int mn88443x_set_frontend(struct dvb_frontend *fe)
+{
+ struct mn88443x_priv *chip = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+ struct regmap *r_s = chip->regmap_s;
+ struct regmap *r_t = chip->regmap_t;
+ u8 tssel = 0, intsel = 0;
+
+ if (c->delivery_system == SYS_ISDBS) {
+ mn88443x_s_wake(chip);
+ mn88443x_t_sleep(chip);
+
+ tssel = TSSET1_TSASEL_ISDBS;
+ intsel = TSSET3_INTASEL_S;
+ } else if (c->delivery_system == SYS_ISDBT) {
+ mn88443x_s_sleep(chip);
+ mn88443x_t_wake(chip);
+
+ mn88443x_t_set_freq(chip);
+
+ tssel = TSSET1_TSASEL_ISDBT;
+ intsel = TSSET3_INTASEL_T;
+ }
+
+ regmap_update_bits(r_t, TSSET1,
+ TSSET1_TSASEL_MASK | TSSET1_TSBSEL_MASK,
+ tssel | TSSET1_TSBSEL_NONE);
+ regmap_write(r_t, TSSET2, 0);
+ regmap_update_bits(r_t, TSSET3,
+ TSSET3_INTASEL_MASK | TSSET3_INTBSEL_MASK,
+ intsel | TSSET3_INTBSEL_NONE);
+
+ regmap_write(r_t, DOSET1_T, 0x95);
+ regmap_write(r_s, DOSET1_S, 0x80);
+
+ if (c->delivery_system == SYS_ISDBS)
+ mn88443x_s_tune(chip, c);
+ else if (c->delivery_system == SYS_ISDBT)
+ mn88443x_t_tune(chip, c);
+
+ if (fe->ops.tuner_ops.set_params) {
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 1);
+ fe->ops.tuner_ops.set_params(fe);
+ if (fe->ops.i2c_gate_ctrl)
+ fe->ops.i2c_gate_ctrl(fe, 0);
+ }
+
+ return 0;
+}
+
+static int mn88443x_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *s)
+{
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ s->min_delay_ms = 850;
+
+ if (c->delivery_system == SYS_ISDBS) {
+ s->max_drift = 30000 * 2 + 1;
+ s->step_size = 30000;
+ } else if (c->delivery_system == SYS_ISDBT) {
+ s->max_drift = 142857 * 2 + 1;
+ s->step_size = 142857 * 2;
+ }
+
+ return 0;
+}
+
+static int mn88443x_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+ struct mn88443x_priv *chip = fe->demodulator_priv;
+ struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+ if (c->delivery_system == SYS_ISDBS)
+ return mn88443x_s_read_status(chip, c, status);
+
+ if (c->delivery_system == SYS_ISDBT)
+ return mn88443x_t_read_status(chip, c, status);
+
+ return -EINVAL;
+}
+
+static const struct dvb_frontend_ops mn88443x_ops = {
+ .delsys = { SYS_ISDBS, SYS_ISDBT },
+ .info = {
+ .name = "Socionext MN88443x",
+ .frequency_min_hz = 470 * MHz,
+ .frequency_max_hz = 2071 * MHz,
+ .symbol_rate_min = 28860000,
+ .symbol_rate_max = 28860000,
+ .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
+ FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
+ },
+
+ .sleep = mn88443x_sleep,
+ .set_frontend = mn88443x_set_frontend,
+ .get_tune_settings = mn88443x_get_tune_settings,
+ .read_status = mn88443x_read_status,
+};
+
+static const struct regmap_config regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_NONE,
+};
+
+static int mn88443x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct mn88443x_config *conf = client->dev.platform_data;
+ struct mn88443x_priv *chip;
+ struct device *dev = &client->dev;
+ int ret;
+
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ if (dev->of_node)
+ chip->spec = of_device_get_match_data(dev);
+ else
+ chip->spec = (struct mn88443x_spec *)id->driver_data;
+ if (!chip->spec)
+ return -EINVAL;
+
+ chip->mclk = devm_clk_get(dev, "mclk");
+ if (IS_ERR(chip->mclk) && !conf) {
+ dev_err(dev, "Failed to request mclk: %ld\n",
+ PTR_ERR(chip->mclk));
+ return PTR_ERR(chip->mclk);
+ }
+
+ ret = of_property_read_u32(dev->of_node, "if-frequency",
+ &chip->if_freq);
+ if (ret && !conf) {
+ dev_err(dev, "Failed to load IF frequency: %d.\n", ret);
+ return ret;
+ }
+
+ chip->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(chip->reset_gpio)) {
+ dev_err(dev, "Failed to request reset_gpio: %ld\n",
+ PTR_ERR(chip->reset_gpio));
+ return PTR_ERR(chip->reset_gpio);
+ }
+
+ if (conf) {
+ chip->mclk = conf->mclk;
+ chip->if_freq = conf->if_freq;
+ chip->reset_gpio = conf->reset_gpio;
+
+ *conf->fe = &chip->fe;
+ }
+
+ chip->client_s = client;
+ chip->regmap_s = devm_regmap_init_i2c(chip->client_s, ®map_config);
+ if (IS_ERR(chip->regmap_s))
+ return PTR_ERR(chip->regmap_s);
+
+ /*
+ * Chip has two I2C addresses for each satellite/terrestrial system.
+ * ISDB-T uses address ISDB-S + 4, so we register a dummy client.
+ */
+ chip->client_t = i2c_new_dummy(client->adapter, client->addr + 4);
+ if (!chip->client_t)
+ return -ENODEV;
+
+ chip->regmap_t = devm_regmap_init_i2c(chip->client_t, ®map_config);
+ if (IS_ERR(chip->regmap_t)) {
+ ret = PTR_ERR(chip->regmap_t);
+ goto err_i2c_t;
+ }
+
+ chip->clk_freq = clk_get_rate(chip->mclk);
+
+ memcpy(&chip->fe.ops, &mn88443x_ops, sizeof(mn88443x_ops));
+ chip->fe.demodulator_priv = chip;
+ i2c_set_clientdata(client, chip);
+
+ mn88443x_cmn_power_on(chip);
+ mn88443x_s_sleep(chip);
+ mn88443x_t_sleep(chip);
+
+ return 0;
+
+err_i2c_t:
+ i2c_unregister_device(chip->client_t);
+
+ return ret;
+}
+
+static int mn88443x_remove(struct i2c_client *client)
+{
+ struct mn88443x_priv *chip = i2c_get_clientdata(client);
+
+ mn88443x_cmn_power_off(chip);
+
+ i2c_unregister_device(chip->client_t);
+
+ return 0;
+}
+
+static const struct mn88443x_spec mn88443x_spec_pri = {
+ .primary = true,
+};
+
+static const struct mn88443x_spec mn88443x_spec_sec = {
+ .primary = false,
+};
+
+static const struct of_device_id mn88443x_of_match[] = {
+ { .compatible = "socionext,mn884433", .data = &mn88443x_spec_pri, },
+ { .compatible = "socionext,mn884434-0", .data = &mn88443x_spec_pri, },
+ { .compatible = "socionext,mn884434-1", .data = &mn88443x_spec_sec, },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mn88443x_of_match);
+
+static const struct i2c_device_id mn88443x_i2c_id[] = {
+ { "mn884433", (kernel_ulong_t)&mn88443x_spec_pri },
+ { "mn884434-0", (kernel_ulong_t)&mn88443x_spec_pri },
+ { "mn884434-1", (kernel_ulong_t)&mn88443x_spec_sec },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, mn88443x_i2c_id);
+
+static struct i2c_driver mn88443x_driver = {
+ .driver = {
+ .name = "mn88443x",
+ .of_match_table = of_match_ptr(mn88443x_of_match),
+ },
+ .probe = mn88443x_probe,
+ .remove = mn88443x_remove,
+ .id_table = mn88443x_i2c_id,
+};
+
+module_i2c_driver(mn88443x_driver);
+
+MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
+MODULE_DESCRIPTION("Socionext MN88443x series demodulator driver.");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/dvb-frontends/mn88443x.h b/drivers/media/dvb-frontends/mn88443x.h
new file mode 100644
index 000000000000..b19aaf6a1ea3
--- /dev/null
+++ b/drivers/media/dvb-frontends/mn88443x.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Socionext MN88443x series demodulator driver for ISDB-S/ISDB-T.
+ *
+ * Copyright (c) 2018 Socionext Inc.
+ */
+
+#ifndef MN88443X_H
+#define MN88443X_H
+
+#include <media/dvb_frontend.h>
+
+/* ISDB-T IF frequency */
+#define DIRECT_IF_57MHZ 57000000
+#define DIRECT_IF_44MHZ 44000000
+#define LOW_IF_4MHZ 4000000
+
+struct mn88443x_config {
+ struct clk *mclk;
+ u32 if_freq;
+ struct gpio_desc *reset_gpio;
+
+ /* Everything after that is returned by the driver. */
+ struct dvb_frontend **fe;
+};
+
+#endif /* MN88443X_H */
--
2.18.0
^ permalink raw reply related
* [PATCH v5] media: dvb-frontends: add Socionext MN88443x ISDB-S/T demodulator driver
From: Katsuhiro Suzuki @ 2018-07-24 0:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201807240508.gpMy7uIR%fengguang.wu@intel.com>
Ugh, sorry. I'll fix it...
Regards,
--
Katsuhiro Suzuki
> -----Original Message-----
> From: kbuild test robot <lkp@intel.com>
> Sent: Tuesday, July 24, 2018 7:15 AM
> To: Suzuki, Katsuhiro/?? ?? <suzuki.katsuhiro@socionext.com>
> Cc: kbuild-all at 01.org; Mauro Carvalho Chehab <mchehab+samsung@kernel.org>;
> linux-media at vger.kernel.org; Masami Hiramatsu <masami.hiramatsu@linaro.org>;
> Jassi Brar <jaswinder.singh@linaro.org>; linux-arm-kernel at lists.infradead.org;
> linux-kernel at vger.kernel.org; Suzuki, Katsuhiro/?? ??
> <suzuki.katsuhiro@socionext.com>
> Subject: Re: [PATCH v5] media: dvb-frontends: add Socionext MN88443x ISDB-S/T
> demodulator driver
>
> Hi Katsuhiro,
>
> I love your patch! Yet something to improve:
>
> [auto build test ERROR on linuxtv-media/master]
> [also build test ERROR on v4.18-rc6 next-20180723]
> [if your patch is applied to the wrong git tree, please drop us a note to help
improve
> the system]
>
> url:
> https://github.com/0day-ci/linux/commits/Katsuhiro-Suzuki/media-dvb-frontends-a
> dd-Socionext-MN88443x-ISDB-S-T-demodulator-driver/20180724-050011
> base: git://linuxtv.org/media_tree.git master
> config: i386-randconfig-i1-201829 (attached as .config)
> compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
> reproduce:
> # save the attached .config to linux build tree
> make ARCH=i386
>
> All errors (new ones prefixed by >>):
>
> >> drivers/media/dvb-frontends/mn88443x.c:15:10: fatal error: sc1501a.h: No
such
> file or directory
> #include "sc1501a.h"
> ^~~~~~~~~~~
> compilation terminated.
>
> vim +15 drivers/media/dvb-frontends/mn88443x.c
>
> 14
> > 15 #include "sc1501a.h"
> 16
>
> ---
> 0-DAY kernel test infrastructure Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply
* Re: [Qemu-devel] [PATCH] qga-win: Handle fstrim for OSes lower than Win8
From: Michael Roth @ 2018-07-24 0:06 UTC (permalink / raw)
To: Sameeh Jubran; +Cc: QEMU Developers, Yan Vugenfirer
In-Reply-To: <CAKPgXcF64Bq+xfFRojYwHS-s3HjNS8s=1Lix4C9Z16Y5Ez3yCg@mail.gmail.com>
Quoting Sameeh Jubran (2018-07-17 00:46:27)
> I'v successfully compiled the previous patch on Fedora 27, but it seems to be
> failing on RHEL, You can apply this patch instead which avoids using the
> versionhelpers header:
Thanks, applied to qga tree:
https://github.com/mdroth/qemu/commits/qga
I went ahead with the GetVersionEx() version since it's also used
elsewhere in qga code. I needed to fix up the version check to be
(major > 6) || (major == 6 && minor >= 2) since that seems to align
with what's documented here:
https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_osversioninfoa
> ---
> qga/commands-win32.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/qga/commands-win32.c b/qga/commands-win32.c
> index fb91f5d..e688e71 100644
> --- a/qga/commands-win32.c
> +++ b/qga/commands-win32.c
> @@ -846,6 +846,17 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error
> **errp)
> GuestFilesystemTrimResponse *resp;
> HANDLE handle;
> WCHAR guid[MAX_PATH] = L"";
> + OSVERSIONINFO osvi;
> + BOOL bIsWindows8orLater;
> +
> + ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
> + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
> + GetVersionEx(&osvi);
> + bIsWindows8orLater = ((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion >
> = 2));
> + if (!bIsWindows8orLater) {
> + error_setg(errp, "fstrim is only supported for Win8+");
> + return NULL;
> + }
>
> handle = FindFirstVolumeW(guid, ARRAYSIZE(guid));
> if (handle == INVALID_HANDLE_VALUE) {
> --
> 2.8.1.185.gdc0db2c
>
>
> On Mon, Jul 16, 2018 at 11:10 PM, Michael Roth <mdroth@linux.vnet.ibm.com>
> wrote:
>
> Quoting Sameeh Jubran (2018-06-24 07:45:40)
> > From: Sameeh Jubran <sjubran@redhat.com>
> >
> > The defrag.exe tool which is used for executing the fstrim command
> > on Windows doesn't support retrim for OSes lower than Win8. This
> > commit handles this case and returns a suitable error.
> >
> > Output of fstrim before this commit:
> > {"execute":"guest-fstrim"}
> > {"return": {"paths": [{"path": "C:\\", "error": "An invalid command line
> option
> > was specified. (0x89000008)"}, {"path": "F:\\", "error": "An invalid
> command
> > line option was specified. (0x89000008)"}, {"path": "S:\\", "error": "An
> > invalid command line option was specified. (0x89000008)"}]}}
> >
> > Reported on:
> > https://bugzilla.redhat.com/show_bug.cgi?id=1594113
> >
> > Signed-off-by: Sameeh Jubran <sjubran@redhat.com>
> > ---
> > qga/commands-win32.c | 6 ++++++
> > 1 file changed, 6 insertions(+)
> >
> > diff --git a/qga/commands-win32.c b/qga/commands-win32.c
> > index d79974f212..0bdcd9dd38 100644
> > --- a/qga/commands-win32.c
> > +++ b/qga/commands-win32.c
> > @@ -30,6 +30,7 @@
> > #include <lm.h>
> > #include <wtsapi32.h>
> > #include <wininet.h>
> > +#include <versionhelpers.h>
>
> I have this queued locally but the mingw64 build environment I've been
> using (fc20) doesn't support this header and I'm running into some odd
> null pointer / 0xc0000005 / access violation issues with the binary
> generated in newer tool chains. I'll send a pull for this next week when
> I can get it tested.
>
> What build envionment are you using?
>
> >
> > #include "qga/guest-agent-core.h"
> > #include "qga/vss-win32.h"
> > @@ -852,6 +853,11 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum,
> Error **errp)
> > HANDLE handle;
> > WCHAR guid[MAX_PATH] = L"";
> >
> > + if (!IsWindows8OrGreater()) {
> > + error_setg(errp, "fstrim is only supported for Win8+");
> > + return NULL;
> > + }
> > +
> > handle = FindFirstVolumeW(guid, ARRAYSIZE(guid));
> > if (handle == INVALID_HANDLE_VALUE) {
> > error_setg_win32(errp, GetLastError(), "failed to find any
> volume");
> > --
> > 2.13.6
> >
>
>
>
>
> --
> Respectfully,
> Sameeh Jubran
> Linkedin
> Software Engineer @ Daynix.
^ permalink raw reply
* Re: [Qemu-devel] [PATCH v2 06/18] qga: process_event() simplification and leak fix
From: Michael Roth @ 2018-07-24 0:03 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel; +Cc: armbru
In-Reply-To: <20180719184111.5129-7-marcandre.lureau@redhat.com>
Quoting Marc-André Lureau (2018-07-19 13:40:59)
> json_parser_parse_err() may return something else than a QDict, in
> which case we loose the object. Let's keep track of the original
> object to avoid leaks.
>
> When an error occurs, "qdict" contains the response, but we still
> check the "execute" key there. Untangle a bit this code, by having a
> clear error path.
>
> CC: Michael Roth <mdroth@linux.vnet.ibm.com>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
Thanks, I've gone ahead and queued this one for 3.0/stable:
https://github.com/mdroth/qemu/commits/qga
> ---
> qga/main.c | 54 +++++++++++++++++++++++++++---------------------------
> 1 file changed, 27 insertions(+), 27 deletions(-)
>
> diff --git a/qga/main.c b/qga/main.c
> index 537cc0e162..87372d40ef 100644
> --- a/qga/main.c
> +++ b/qga/main.c
> @@ -600,42 +600,42 @@ static void process_command(GAState *s, QDict *req)
> static void process_event(JSONMessageParser *parser, GQueue *tokens)
> {
> GAState *s = container_of(parser, GAState, parser);
> - QDict *qdict;
> + QObject *obj;
> + QDict *req, *rsp;
> Error *err = NULL;
> int ret;
>
> g_assert(s && parser);
>
> g_debug("process_event: called");
> - qdict = qobject_to(QDict, json_parser_parse_err(tokens, NULL, &err));
> - if (err || !qdict) {
> - qobject_unref(qdict);
> - if (!err) {
> - g_warning("failed to parse event: unknown error");
> - error_setg(&err, QERR_JSON_PARSING);
> - } else {
> - g_warning("failed to parse event: %s", error_get_pretty(err));
> - }
> - qdict = qmp_error_response(err);
> + obj = json_parser_parse_err(tokens, NULL, &err);
> + if (err) {
> + goto err;
> }
> -
> - /* handle host->guest commands */
> - if (qdict_haskey(qdict, "execute")) {
> - process_command(s, qdict);
> - } else {
> - if (!qdict_haskey(qdict, "error")) {
> - qobject_unref(qdict);
> - g_warning("unrecognized payload format");
> - error_setg(&err, QERR_UNSUPPORTED);
> - qdict = qmp_error_response(err);
> - }
> - ret = send_response(s, qdict);
> - if (ret < 0) {
> - g_warning("error sending error response: %s", strerror(-ret));
> - }
> + req = qobject_to(QDict, obj);
> + if (!req) {
> + error_setg(&err, QERR_JSON_PARSING);
> + goto err;
> + }
> + if (!qdict_haskey(req, "execute")) {
> + g_warning("unrecognized payload format");
> + error_setg(&err, QERR_UNSUPPORTED);
> + goto err;
> }
>
> - qobject_unref(qdict);
> + process_command(s, req);
> + qobject_unref(obj);
> + return;
> +
> +err:
> + g_warning("failed to parse event: %s", error_get_pretty(err));
> + rsp = qmp_error_response(err);
> + ret = send_response(s, rsp);
> + if (ret < 0) {
> + g_warning("error sending error response: %s", strerror(-ret));
> + }
> + qobject_unref(rsp);
> + qobject_unref(obj);
> }
>
> /* false return signals GAChannel to close the current client connection */
> --
> 2.18.0.129.ge3331758f1
>
^ permalink raw reply
* [Qemu-devel] [PULL for-3.0 2/2] qga: process_event() simplification and leak fix
From: Michael Roth @ 2018-07-24 0:01 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau, qemu-stable
In-Reply-To: <20180724000126.21787-1-mdroth@linux.vnet.ibm.com>
From: Marc-André Lureau <marcandre.lureau@redhat.com>
json_parser_parse_err() may return something else than a QDict, in
which case we loose the object. Let's keep track of the original
object to avoid leaks.
When an error occurs, "qdict" contains the response, but we still
check the "execute" key there. Untangle a bit this code, by having a
clear error path.
CC: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
qga/main.c | 54 +++++++++++++++++++++++++++---------------------------
1 file changed, 27 insertions(+), 27 deletions(-)
diff --git a/qga/main.c b/qga/main.c
index 537cc0e162..87372d40ef 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -600,42 +600,42 @@ static void process_command(GAState *s, QDict *req)
static void process_event(JSONMessageParser *parser, GQueue *tokens)
{
GAState *s = container_of(parser, GAState, parser);
- QDict *qdict;
+ QObject *obj;
+ QDict *req, *rsp;
Error *err = NULL;
int ret;
g_assert(s && parser);
g_debug("process_event: called");
- qdict = qobject_to(QDict, json_parser_parse_err(tokens, NULL, &err));
- if (err || !qdict) {
- qobject_unref(qdict);
- if (!err) {
- g_warning("failed to parse event: unknown error");
- error_setg(&err, QERR_JSON_PARSING);
- } else {
- g_warning("failed to parse event: %s", error_get_pretty(err));
- }
- qdict = qmp_error_response(err);
+ obj = json_parser_parse_err(tokens, NULL, &err);
+ if (err) {
+ goto err;
}
-
- /* handle host->guest commands */
- if (qdict_haskey(qdict, "execute")) {
- process_command(s, qdict);
- } else {
- if (!qdict_haskey(qdict, "error")) {
- qobject_unref(qdict);
- g_warning("unrecognized payload format");
- error_setg(&err, QERR_UNSUPPORTED);
- qdict = qmp_error_response(err);
- }
- ret = send_response(s, qdict);
- if (ret < 0) {
- g_warning("error sending error response: %s", strerror(-ret));
- }
+ req = qobject_to(QDict, obj);
+ if (!req) {
+ error_setg(&err, QERR_JSON_PARSING);
+ goto err;
+ }
+ if (!qdict_haskey(req, "execute")) {
+ g_warning("unrecognized payload format");
+ error_setg(&err, QERR_UNSUPPORTED);
+ goto err;
}
- qobject_unref(qdict);
+ process_command(s, req);
+ qobject_unref(obj);
+ return;
+
+err:
+ g_warning("failed to parse event: %s", error_get_pretty(err));
+ rsp = qmp_error_response(err);
+ ret = send_response(s, rsp);
+ if (ret < 0) {
+ g_warning("error sending error response: %s", strerror(-ret));
+ }
+ qobject_unref(rsp);
+ qobject_unref(obj);
}
/* false return signals GAChannel to close the current client connection */
--
2.17.1
^ permalink raw reply related
* [Qemu-devel] [PULL for-3.0 1/2] qga-win: Handle fstrim for OSes lower than Win8
From: Michael Roth @ 2018-07-24 0:01 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Sameeh Jubran
In-Reply-To: <20180724000126.21787-1-mdroth@linux.vnet.ibm.com>
From: Sameeh Jubran <sjubran@redhat.com>
The defrag.exe tool which is used for executing the fstrim command
on Windows doesn't support retrim for OSes lower than Win8. This
commit handles this case and returns a suitable error.
Output of fstrim before this commit:
{"execute":"guest-fstrim"}
{"return": {"paths": [{"path": "C:\\", "error": "An invalid command line option
was specified. (0x89000008)"}, {"path": "F:\\", "error": "An invalid command
line option was specified. (0x89000008)"}, {"path": "S:\\", "error": "An
invalid command line option was specified. (0x89000008)"}]}}
Reported on:
https://bugzilla.redhat.com/show_bug.cgi?id=1594113
Signed-off-by: Sameeh Jubran <sjubran@redhat.com>
* use alternative version query code proposed by Sameeh
* fix up version check logic
* avoid CamelCase variable names when possible
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
qga/commands-win32.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 318d760a74..98d9735389 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -865,6 +865,19 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp)
GuestFilesystemTrimResponse *resp;
HANDLE handle;
WCHAR guid[MAX_PATH] = L"";
+ OSVERSIONINFO osvi;
+ BOOL win8_or_later;
+
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&osvi);
+ win8_or_later = (osvi.dwMajorVersion > 6 ||
+ ((osvi.dwMajorVersion == 6) &&
+ (osvi.dwMinorVersion >= 2)));
+ if (!win8_or_later) {
+ error_setg(errp, "fstrim is only supported for Win8+");
+ return NULL;
+ }
handle = FindFirstVolumeW(guid, ARRAYSIZE(guid));
if (handle == INVALID_HANDLE_VALUE) {
--
2.17.1
^ permalink raw reply related
* [Qemu-devel] [PULL for-3.0 0/2] qemu-ga patch queue for hard-freeze
From: Michael Roth @ 2018-07-24 0:01 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell
The following changes since commit 4eecc2e212bae7308d8582d99f665dfc253c9dda:
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20180723' into staging (2018-07-23 19:24:05 +0100)
are available in the Git repository at:
git://github.com/mdroth/qemu.git tags/qga-pull-2018-07-23-tag
for you to fetch changes up to ae7da1e5f658ea21d96e565514de20ff2cf24fa1:
qga: process_event() simplification and leak fix (2018-07-23 18:54:26 -0500)
----------------------------------------------------------------
qemu-ga patch queue for hard-freeze
* fix leak in qga main loop error path
* better error reporting when Windows version doesn't support fstrim
----------------------------------------------------------------
Marc-André Lureau (1):
qga: process_event() simplification and leak fix
Sameeh Jubran (1):
qga-win: Handle fstrim for OSes lower than Win8
qga/commands-win32.c | 13 +++++++++++++
qga/main.c | 54 ++++++++++++++++++++++++++--------------------------
2 files changed, 40 insertions(+), 27 deletions(-)
^ permalink raw reply
* Re: [PATCH 06/15] MIPS: dts: img: pistachio_marduk: Add 6Lowpan node
From: Paul Burton @ 2018-07-24 0:06 UTC (permalink / raw)
To: Andreas Färber, Rob Herring
Cc: linux-mips, Ralf Baechle, James Hogan, linux-kernel,
Rahul Bedarkar, James Hartley, Mark Rutland, devicetree,
Harry Morris, Stefan Schmidt, Marcel Holtmann, David Gibson
In-Reply-To: <20180722212010.3979-7-afaerber@suse.de>
Hi Andreas,
On Sun, Jul 22, 2018 at 11:20:01PM +0200, Andreas Färber wrote:
> diff --git a/arch/mips/boot/dts/img/pistachio_marduk.dts b/arch/mips/boot/dts/img/pistachio_marduk.dts
> index d723b68084c9..b0b6b534a41f 100644
> --- a/arch/mips/boot/dts/img/pistachio_marduk.dts
> +++ b/arch/mips/boot/dts/img/pistachio_marduk.dts
> @@ -158,6 +158,20 @@
> <&gpio1 12 GPIO_ACTIVE_HIGH>,
> <&gpio1 13 GPIO_ACTIVE_HIGH>,
> <&gpio1 14 GPIO_ACTIVE_HIGH>;
> +
> + ca8210: sixlowpan@4 {
> + compatible = "cascoda,ca8210";
> + reg = <4>;
> + spi-max-frequency = <3000000>;
> + spi-cpol;
> + reset-gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;
> + irq-gpio = <&gpio2 12 GPIO_ACTIVE_HIGH>;
> +
> + extclock-enable;
> + extclock-freq = <16000000>;
> + extclock-gpio = <2>; /* spiuart_clk */
> + #clock-cells = <0>;
> + };
dtc complains about the extclock-gpio property because it expects a
property named *-gpio to contain a gpio-list:
DTC arch/mips/boot/dts/img/pistachio_marduk.dtb
arch/mips/boot/dts/img/pistachio_marduk.dtb: Warning (gpios_property):
/spi@18100f00/sixlowpan@4: Missing property '#gpio-cells' in node
/clk@18144000 or bad phandle (referred from extclock-gpio[0])
Rob, perhaps this should be added as a second false-positive case in
dtc's prop_is_gpio()?
Thanks,
Paul
^ permalink raw reply
* Re: [PATCH v4] iio: chemical: Add support for Bosch BME680 sensor
From: Himanshu Jha @ 2018-07-23 23:02 UTC (permalink / raw)
To: David Frey; +Cc: Daniel Baluta, Linux Kernel Mailing List, linux-iio
In-Reply-To: <a1c8c770-18b4-1722-2672-ee0e8abab611@sierrawireless.com>
On Mon, Jul 23, 2018 at 03:16:10PM -0700, David Frey wrote:
> On 7/22/2018 3:21 PM, Himanshu Jha wrote:
> >On Sat, Jul 21, 2018 at 08:45:34PM +0300, Daniel Baluta wrote:
> >>On Sat, Jul 21, 2018 at 6:43 PM, Andy Shevchenko
> >><andy.shevchenko@gmail.com> wrote:
> >>>On Sat, Jul 21, 2018 at 6:36 PM, Himanshu Jha
> >>><himanshujha199640@gmail.com> wrote:
> >>>
> >>>>>>+ /* Look up table 1 for the possible gas range values */
> >>>>>>+ u32 lookupTable1[16] = {2147483647u, 2147483647u, 2147483647u,
> >>>>>>+ 2147483647u, 2147483647u, 2126008810u,
> >>>>>>+ 2147483647u, 2130303777u, 2147483647u,
> >>>>>>+ 2147483647u, 2143188679u, 2136746228u,
> >>>>>>+ 2147483647u, 2126008810u, 2147483647u,
> >>>>>>+ 2147483647u};
> >>>
> >>>This one needs perhaps a bit of though, but...
> >>>
> >>>>>>+ /* Look up table 2 for the possible gas range values */
> >>>>>>+ u32 lookupTable2[16] = {4096000000u, 2048000000u, 1024000000u,
> >>>>>>+ 512000000u, 255744255u, 127110228u, 64000000u,
> >>>>>>+ 32258064u, 16016016u, 8000000u, 4000000u,
> >>>>>>+ 2000000u, 1000000u, 500000u, 250000u, 125000u};
> >>>
> >>>...this one obviously just a not needed one. You may replace it with a
> >>>one constant and simple calculation to get either value (index from
> >>>value, or value from index).
> >>
> >>Indeed this can be reduce to:
> >>
> >>125.000 << (15 - idx).
> >>
> >>The real question here is if we approximate 255.744.255u to 256.00.00u how
> >>much different is the result. Being a gas sensor I think it is very
> >>hard to appreciate.
> >>
> >>We can go with this formula + adding a comment with the table with the
> >>exact coefficients.
> >
> >So, I have planned to use this 125000 << (15 - idx) equation with
> >approximating the array members.
> >
> >About the difference in results we would get after approximating isn't
> >much of a problem IMHO because gas sensor is primarily used for IAQ, and
> >IAQ is relative to the resistance reading.
> >
> >For eg:
> >
> >Resistance(ohm) IAQ
> >value < 30K Very bad
> >30k < value < 50k worse
> >50k < value < 70k bad
> >...
> >..
> >so on..
> >
> >So, what I simply imply is the scale will be adjusted and nothing else
> >changes, unlike if it had been pressure, temperature, humidity.
> >
> >The IAQ implementation is userspace application suggesting
> >good/bad/ugly air quality.
> >
> >And since we know David Frey is planning to use this sensor in his
> >product mangOH board.
> >
> >So, David, how are you planning to use the gas sensing part in your
> >product ? RGB leds, buzzer, alarm ?
> >
> >Thanks Andy for the suggestion :)
> >
>
> My understanding is that the Bosch BSEC (Bosch Sensortec Environmental
> Cluster - https://www.bosch-sensortec.com/bst/products/all_products/bsec)
> software calculates the indoor air quality (IAQ) which is presented in
> the range of 0 to 500. BSEC is proprietary, pre-compiled static
> library. I don't know how they derive the IAQ, but it seems that it
> could be based on smoothing outlying gas resistance values and integrating
> other values such as temperature, humidity and pressure.
> Unless this driver can somehow produce IAQ values of equal or greater
> reliability to the BSEC library, then I would prefer that it just
> present the raw gas resistance value so that a user can write a program
> to feed the sensor data into BSEC.
>
> mangOH isn't really a traditional product. It's an open hardware board
> designed around Sierra Wireless cellular modules that run Linux. So I
> don't have any specific use case in mind, but I want to enable our users
> (and thus future products) to make use of air quality measurements.
I tested the gas sensor with the new bitshifting equation and didn't find any
discrepancy in the resistance readings.
Even I don't know how Bosch implements IAQ algorithm, but one thing I
got around testing the sensor was that the air quality is inversely
proportional to resistance value.
[You can try it yourself, by spraying deodrant/aerosol sprays around the sensor ;)]
But we shouldn't be worried about such issues since these should be handled
fine with the userspace application and depends on the implementation.
We only need to focus on exporting data.
Anyway, thanks again for your time!
--
Himanshu Jha
Undergraduate Student
Department of Electronics & Communication
Guru Tegh Bahadur Institute of Technology
^ permalink raw reply
* Re: [PATCH 7/7] libxfs: remove crc32 functions
From: Eric Sandeen @ 2018-07-23 22:55 UTC (permalink / raw)
To: Darrick J. Wong, sandeen; +Cc: linux-xfs
In-Reply-To: <152728634020.22515.16684194597988861920.stgit@magnolia>
On 5/25/18 3:12 PM, Darrick J. Wong wrote:
> From: Darrick J. Wong <darrick.wong@oracle.com>
>
> XFS uses crc32c, not crc32. Remove the unnecessary crc32 code, which
> decreases binary size by the 8K crc32 table.
Getting back to this ...
The files have diverged a bit since the initial lift from the kernel.
Commenting out to keep things diffable is a bit pointless now, due
to that divergence (for example, the crc32test stuff has been moved
out to its own file, a big swath of code.)
So, I think we should make a decision about whether we want to try
to keep this in sync with the kernel, or just let it drift.
If the former, I'd go with an #if 0 but only after syncing things
up again.
If the latter, just nuke the unused code, if we ever need the crc32c
variants we can re-lift them from the kernel. I'd still take a brief
look at whether there's anything that needs to be synced in an ad-hoc
fashion.
I guess right now I'm feeling inclined to go with the former, and
even add the crc32 file(s) to the libxfs-diff and/or libxfs-apply
scripts, if we plan to keep them more in sync.
I'd accept either plan, really - but there's no reason to comment
out or #ifdef code to keep it around if it doesn't even necessarily
match kernelspace anymore.
-Eric
> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
> ---
> include/libxfs.h | 3 ---
> libxfs/crc32.c | 16 ++++++++++------
> libxfs/gen_crc32table.c | 8 +++++++-
> libxfs/libxfs_priv.h | 3 ---
> 4 files changed, 17 insertions(+), 13 deletions(-)
>
>
> diff --git a/include/libxfs.h b/include/libxfs.h
> index fbaae089..109866de 100644
> --- a/include/libxfs.h
> +++ b/include/libxfs.h
> @@ -43,10 +43,7 @@
>
>
> /* CRC stuff, buffer API dependent on it */
> -extern uint32_t crc32_le(uint32_t crc, unsigned char const *p, size_t len);
> extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len);
> -
> -#define crc32(c,p,l) crc32_le((c),(unsigned char const *)(p),(l))
> #define crc32c(c,p,l) crc32c_le((c),(unsigned char const *)(p),(l))
>
> #include "xfs_cksum.h"
> diff --git a/libxfs/crc32.c b/libxfs/crc32.c
> index 783d62e9..8fe5c42c 100644
> --- a/libxfs/crc32.c
> +++ b/libxfs/crc32.c
> @@ -176,20 +176,26 @@ static inline u32 __pure crc32_le_generic(u32 crc, unsigned char const *p,
> }
>
> #if CRC_LE_BITS == 1
> +/*
> + * not used by xfs.
> u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
> {
> return crc32_le_generic(crc, p, len, NULL, CRCPOLY_LE);
> }
> + */
...
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.