Re: [PATCH v2] net: dsa: b53: constify b53_io_ops structures

2016-08-09 Thread David Miller
From: Julia Lawall 
Date: Tue,  9 Aug 2016 19:09:45 +0200

> The b53_io_ops structures are never modified, so declare them as const.
> 
> Done with the help of Coccinelle.
> 
> Signed-off-by: Julia Lawall 
> 
> ---
> v2: Refer to the right structure in the commit message

Applied to net-next, thanks.


Re: [PATCH v2] net: dsa: b53: constify b53_io_ops structures

2016-08-09 Thread David Miller
From: Julia Lawall 
Date: Tue,  9 Aug 2016 19:09:45 +0200

> The b53_io_ops structures are never modified, so declare them as const.
> 
> Done with the help of Coccinelle.
> 
> Signed-off-by: Julia Lawall 
> 
> ---
> v2: Refer to the right structure in the commit message

Applied to net-next, thanks.


Re: [tpmdd-devel] [PATCH] tpm: fix cacheline alignment for DMA-able buffers

2016-08-09 Thread Jason Gunthorpe
On Tue, Aug 09, 2016 at 08:18:00AM -0700, Dmitry Torokhov wrote:

>Well, the main reason was simplicity and invasiveness of the
>change.

Well, it isn't simple, because the proposed patches have had subtle
problems with DMA. Simple is to use a guaranteed dma-able allocation
for DMA memory and stop trying to over optimize.

Jason


Re: [PATCH] dm9000: Fix irq trigger type setup on non-dt platforms

2016-08-09 Thread David Miller
From: Robert Jarzmik 
Date: Tue, 09 Aug 2016 19:20:44 +0200

> Sylwester Nawrocki  writes:
> 
>> Commit b5a099c67a1c36b "net: ethernet: davicom: fix devicetree irq
>> resource" causes an interrupt storm after the ethernet interface
>> is activated on S3C24XX platform (ARM non-dt), due to the interrupt
>> trigger type not being set properly.
>>
>> It seems, after adding parsing of IRQ flags in commit 7085a7401ba54e92b
>> "drivers: platform: parse IRQ flags from resources", there is no path
>> for non-dt platforms where irq_set_type callback could be invoked when
>> we don't pass the trigger type flags to the request_irq() call.
>>
>> In case of a board where the regression is seen the interrupt trigger
>> type flags are passed through a platform device's resource and it is
>> not currently handled properly without passing the irq trigger type
>> flags to the request_irq() call.  In case of OF an of_irq_get() call
>> within platform_get_irq() function seems to be ensuring required irq_chip
>> setup, but there is no equivalent code for non OF/ACPI platforms.
>>
>> This patch mostly restores irq trigger type setting code which has been
>> removed in commit ("net: ethernet: davicom: fix devicetree irq resource").
>>
>> Fixes: b5a099c67a1c36b913 ("net: ethernet: davicom: fix devicetree irq 
>> resource")
>>
>> Signed-off-by: Sylwester Nawrocki 
>> ---
>>
>> Perhaps instead the core could be configuring the irqchip automatically as it
>> is done for OF/ACPI cases. I had doubts though if trying to make such changes
>> for a bug fix patch was the right thing to do.
> Hi Sylvester,
> 
> You're right, and I came to the same conclusion a bit earlier, in [1], but I
> didn't notice my FAI didn't actually send the mail. Your analysis of the core 
> in
> non-OF/ACPI case is the reason I didn't post a patch for dm9000 ... I was
> overconfident in finding a reason in irq core code within a couple of days.
> 
> Therefore:
> Acked-by: Robert Jarzmik 

Applied.


Re: [tpmdd-devel] [PATCH] tpm: fix cacheline alignment for DMA-able buffers

2016-08-09 Thread Jason Gunthorpe
On Tue, Aug 09, 2016 at 08:18:00AM -0700, Dmitry Torokhov wrote:

>Well, the main reason was simplicity and invasiveness of the
>change.

Well, it isn't simple, because the proposed patches have had subtle
problems with DMA. Simple is to use a guaranteed dma-able allocation
for DMA memory and stop trying to over optimize.

Jason


Re: [PATCH] dm9000: Fix irq trigger type setup on non-dt platforms

2016-08-09 Thread David Miller
From: Robert Jarzmik 
Date: Tue, 09 Aug 2016 19:20:44 +0200

> Sylwester Nawrocki  writes:
> 
>> Commit b5a099c67a1c36b "net: ethernet: davicom: fix devicetree irq
>> resource" causes an interrupt storm after the ethernet interface
>> is activated on S3C24XX platform (ARM non-dt), due to the interrupt
>> trigger type not being set properly.
>>
>> It seems, after adding parsing of IRQ flags in commit 7085a7401ba54e92b
>> "drivers: platform: parse IRQ flags from resources", there is no path
>> for non-dt platforms where irq_set_type callback could be invoked when
>> we don't pass the trigger type flags to the request_irq() call.
>>
>> In case of a board where the regression is seen the interrupt trigger
>> type flags are passed through a platform device's resource and it is
>> not currently handled properly without passing the irq trigger type
>> flags to the request_irq() call.  In case of OF an of_irq_get() call
>> within platform_get_irq() function seems to be ensuring required irq_chip
>> setup, but there is no equivalent code for non OF/ACPI platforms.
>>
>> This patch mostly restores irq trigger type setting code which has been
>> removed in commit ("net: ethernet: davicom: fix devicetree irq resource").
>>
>> Fixes: b5a099c67a1c36b913 ("net: ethernet: davicom: fix devicetree irq 
>> resource")
>>
>> Signed-off-by: Sylwester Nawrocki 
>> ---
>>
>> Perhaps instead the core could be configuring the irqchip automatically as it
>> is done for OF/ACPI cases. I had doubts though if trying to make such changes
>> for a bug fix patch was the right thing to do.
> Hi Sylvester,
> 
> You're right, and I came to the same conclusion a bit earlier, in [1], but I
> didn't notice my FAI didn't actually send the mail. Your analysis of the core 
> in
> non-OF/ACPI case is the reason I didn't post a patch for dm9000 ... I was
> overconfident in finding a reason in irq core code within a couple of days.
> 
> Therefore:
> Acked-by: Robert Jarzmik 

Applied.


[PATCH 1/2] net: ethernet: renesas: sh_eth: use phydev from struct net_device

2016-08-09 Thread Philippe Reynes
The private structure contain a pointer to phydev, but the structure
net_device already contain such pointer. So we can remove the pointer
phy_dev in the private structure, and update the driver to use the
one contained in struct net_device.

Signed-off-by: Philippe Reynes 
---
 drivers/net/ethernet/renesas/sh_eth.c |   29 -
 drivers/net/ethernet/renesas/sh_eth.h |1 -
 2 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/renesas/sh_eth.c 
b/drivers/net/ethernet/renesas/sh_eth.c
index 799d58d..901ed36 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1723,7 +1723,7 @@ out:
 static void sh_eth_adjust_link(struct net_device *ndev)
 {
struct sh_eth_private *mdp = netdev_priv(ndev);
-   struct phy_device *phydev = mdp->phydev;
+   struct phy_device *phydev = ndev->phydev;
int new_state = 0;
 
if (phydev->link) {
@@ -1800,22 +1800,19 @@ static int sh_eth_phy_init(struct net_device *ndev)
 
phy_attached_info(phydev);
 
-   mdp->phydev = phydev;
-
return 0;
 }
 
 /* PHY control start function */
 static int sh_eth_phy_start(struct net_device *ndev)
 {
-   struct sh_eth_private *mdp = netdev_priv(ndev);
int ret;
 
ret = sh_eth_phy_init(ndev);
if (ret)
return ret;
 
-   phy_start(mdp->phydev);
+   phy_start(ndev->phydev);
 
return 0;
 }
@@ -1827,11 +1824,11 @@ static int sh_eth_get_settings(struct net_device *ndev,
unsigned long flags;
int ret;
 
-   if (!mdp->phydev)
+   if (!ndev->phydev)
return -ENODEV;
 
spin_lock_irqsave(>lock, flags);
-   ret = phy_ethtool_gset(mdp->phydev, ecmd);
+   ret = phy_ethtool_gset(ndev->phydev, ecmd);
spin_unlock_irqrestore(>lock, flags);
 
return ret;
@@ -1844,7 +1841,7 @@ static int sh_eth_set_settings(struct net_device *ndev,
unsigned long flags;
int ret;
 
-   if (!mdp->phydev)
+   if (!ndev->phydev)
return -ENODEV;
 
spin_lock_irqsave(>lock, flags);
@@ -1852,7 +1849,7 @@ static int sh_eth_set_settings(struct net_device *ndev,
/* disable tx and rx */
sh_eth_rcv_snd_disable(ndev);
 
-   ret = phy_ethtool_sset(mdp->phydev, ecmd);
+   ret = phy_ethtool_sset(ndev->phydev, ecmd);
if (ret)
goto error_exit;
 
@@ -2067,11 +2064,11 @@ static int sh_eth_nway_reset(struct net_device *ndev)
unsigned long flags;
int ret;
 
-   if (!mdp->phydev)
+   if (!ndev->phydev)
return -ENODEV;
 
spin_lock_irqsave(>lock, flags);
-   ret = phy_start_aneg(mdp->phydev);
+   ret = phy_start_aneg(ndev->phydev);
spin_unlock_irqrestore(>lock, flags);
 
return ret;
@@ -2408,10 +2405,9 @@ static int sh_eth_close(struct net_device *ndev)
sh_eth_dev_exit(ndev);
 
/* PHY Disconnect */
-   if (mdp->phydev) {
-   phy_stop(mdp->phydev);
-   phy_disconnect(mdp->phydev);
-   mdp->phydev = NULL;
+   if (ndev->phydev) {
+   phy_stop(ndev->phydev);
+   phy_disconnect(ndev->phydev);
}
 
free_irq(ndev->irq, ndev);
@@ -2429,8 +2425,7 @@ static int sh_eth_close(struct net_device *ndev)
 /* ioctl to device function */
 static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 {
-   struct sh_eth_private *mdp = netdev_priv(ndev);
-   struct phy_device *phydev = mdp->phydev;
+   struct phy_device *phydev = ndev->phydev;
 
if (!netif_running(ndev))
return -EINVAL;
diff --git a/drivers/net/ethernet/renesas/sh_eth.h 
b/drivers/net/ethernet/renesas/sh_eth.h
index c62380e..d050f37 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -518,7 +518,6 @@ struct sh_eth_private {
/* MII transceiver section. */
u32 phy_id; /* PHY ID */
struct mii_bus *mii_bus;/* MDIO bus control */
-   struct phy_device *phydev;  /* PHY device control */
int link;
phy_interface_t phy_interface;
int msg_enable;
-- 
1.7.4.4



[PATCH 1/2] net: ethernet: renesas: sh_eth: use phydev from struct net_device

2016-08-09 Thread Philippe Reynes
The private structure contain a pointer to phydev, but the structure
net_device already contain such pointer. So we can remove the pointer
phy_dev in the private structure, and update the driver to use the
one contained in struct net_device.

Signed-off-by: Philippe Reynes 
---
 drivers/net/ethernet/renesas/sh_eth.c |   29 -
 drivers/net/ethernet/renesas/sh_eth.h |1 -
 2 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/renesas/sh_eth.c 
b/drivers/net/ethernet/renesas/sh_eth.c
index 799d58d..901ed36 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1723,7 +1723,7 @@ out:
 static void sh_eth_adjust_link(struct net_device *ndev)
 {
struct sh_eth_private *mdp = netdev_priv(ndev);
-   struct phy_device *phydev = mdp->phydev;
+   struct phy_device *phydev = ndev->phydev;
int new_state = 0;
 
if (phydev->link) {
@@ -1800,22 +1800,19 @@ static int sh_eth_phy_init(struct net_device *ndev)
 
phy_attached_info(phydev);
 
-   mdp->phydev = phydev;
-
return 0;
 }
 
 /* PHY control start function */
 static int sh_eth_phy_start(struct net_device *ndev)
 {
-   struct sh_eth_private *mdp = netdev_priv(ndev);
int ret;
 
ret = sh_eth_phy_init(ndev);
if (ret)
return ret;
 
-   phy_start(mdp->phydev);
+   phy_start(ndev->phydev);
 
return 0;
 }
@@ -1827,11 +1824,11 @@ static int sh_eth_get_settings(struct net_device *ndev,
unsigned long flags;
int ret;
 
-   if (!mdp->phydev)
+   if (!ndev->phydev)
return -ENODEV;
 
spin_lock_irqsave(>lock, flags);
-   ret = phy_ethtool_gset(mdp->phydev, ecmd);
+   ret = phy_ethtool_gset(ndev->phydev, ecmd);
spin_unlock_irqrestore(>lock, flags);
 
return ret;
@@ -1844,7 +1841,7 @@ static int sh_eth_set_settings(struct net_device *ndev,
unsigned long flags;
int ret;
 
-   if (!mdp->phydev)
+   if (!ndev->phydev)
return -ENODEV;
 
spin_lock_irqsave(>lock, flags);
@@ -1852,7 +1849,7 @@ static int sh_eth_set_settings(struct net_device *ndev,
/* disable tx and rx */
sh_eth_rcv_snd_disable(ndev);
 
-   ret = phy_ethtool_sset(mdp->phydev, ecmd);
+   ret = phy_ethtool_sset(ndev->phydev, ecmd);
if (ret)
goto error_exit;
 
@@ -2067,11 +2064,11 @@ static int sh_eth_nway_reset(struct net_device *ndev)
unsigned long flags;
int ret;
 
-   if (!mdp->phydev)
+   if (!ndev->phydev)
return -ENODEV;
 
spin_lock_irqsave(>lock, flags);
-   ret = phy_start_aneg(mdp->phydev);
+   ret = phy_start_aneg(ndev->phydev);
spin_unlock_irqrestore(>lock, flags);
 
return ret;
@@ -2408,10 +2405,9 @@ static int sh_eth_close(struct net_device *ndev)
sh_eth_dev_exit(ndev);
 
/* PHY Disconnect */
-   if (mdp->phydev) {
-   phy_stop(mdp->phydev);
-   phy_disconnect(mdp->phydev);
-   mdp->phydev = NULL;
+   if (ndev->phydev) {
+   phy_stop(ndev->phydev);
+   phy_disconnect(ndev->phydev);
}
 
free_irq(ndev->irq, ndev);
@@ -2429,8 +2425,7 @@ static int sh_eth_close(struct net_device *ndev)
 /* ioctl to device function */
 static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 {
-   struct sh_eth_private *mdp = netdev_priv(ndev);
-   struct phy_device *phydev = mdp->phydev;
+   struct phy_device *phydev = ndev->phydev;
 
if (!netif_running(ndev))
return -EINVAL;
diff --git a/drivers/net/ethernet/renesas/sh_eth.h 
b/drivers/net/ethernet/renesas/sh_eth.h
index c62380e..d050f37 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -518,7 +518,6 @@ struct sh_eth_private {
/* MII transceiver section. */
u32 phy_id; /* PHY ID */
struct mii_bus *mii_bus;/* MDIO bus control */
-   struct phy_device *phydev;  /* PHY device control */
int link;
phy_interface_t phy_interface;
int msg_enable;
-- 
1.7.4.4



[PATCH 2/2] net: ethernet: renesas: sh_eth: use new api ethtool_{get|set}_link_ksettings

2016-08-09 Thread Philippe Reynes
The ethtool api {get|set}_settings is deprecated.
We move this driver to new api {get|set}_link_ksettings.

Signed-off-by: Philippe Reynes 
---
 drivers/net/ethernet/renesas/sh_eth.c |   18 +-
 1 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/renesas/sh_eth.c 
b/drivers/net/ethernet/renesas/sh_eth.c
index 901ed36..1f8240a 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1817,8 +1817,8 @@ static int sh_eth_phy_start(struct net_device *ndev)
return 0;
 }
 
-static int sh_eth_get_settings(struct net_device *ndev,
-  struct ethtool_cmd *ecmd)
+static int sh_eth_get_link_ksettings(struct net_device *ndev,
+struct ethtool_link_ksettings *cmd)
 {
struct sh_eth_private *mdp = netdev_priv(ndev);
unsigned long flags;
@@ -1828,14 +1828,14 @@ static int sh_eth_get_settings(struct net_device *ndev,
return -ENODEV;
 
spin_lock_irqsave(>lock, flags);
-   ret = phy_ethtool_gset(ndev->phydev, ecmd);
+   ret = phy_ethtool_ksettings_get(ndev->phydev, cmd);
spin_unlock_irqrestore(>lock, flags);
 
return ret;
 }
 
-static int sh_eth_set_settings(struct net_device *ndev,
-  struct ethtool_cmd *ecmd)
+static int sh_eth_set_link_ksettings(struct net_device *ndev,
+const struct ethtool_link_ksettings *cmd)
 {
struct sh_eth_private *mdp = netdev_priv(ndev);
unsigned long flags;
@@ -1849,11 +1849,11 @@ static int sh_eth_set_settings(struct net_device *ndev,
/* disable tx and rx */
sh_eth_rcv_snd_disable(ndev);
 
-   ret = phy_ethtool_sset(ndev->phydev, ecmd);
+   ret = phy_ethtool_ksettings_set(ndev->phydev, cmd);
if (ret)
goto error_exit;
 
-   if (ecmd->duplex == DUPLEX_FULL)
+   if (cmd->base.duplex == DUPLEX_FULL)
mdp->duplex = 1;
else
mdp->duplex = 0;
@@ -2195,8 +2195,6 @@ static int sh_eth_set_ringparam(struct net_device *ndev,
 }
 
 static const struct ethtool_ops sh_eth_ethtool_ops = {
-   .get_settings   = sh_eth_get_settings,
-   .set_settings   = sh_eth_set_settings,
.get_regs_len   = sh_eth_get_regs_len,
.get_regs   = sh_eth_get_regs,
.nway_reset = sh_eth_nway_reset,
@@ -2208,6 +2206,8 @@ static const struct ethtool_ops sh_eth_ethtool_ops = {
.get_sset_count = sh_eth_get_sset_count,
.get_ringparam  = sh_eth_get_ringparam,
.set_ringparam  = sh_eth_set_ringparam,
+   .get_link_ksettings = sh_eth_get_link_ksettings,
+   .set_link_ksettings = sh_eth_set_link_ksettings,
 };
 
 /* network device open function */
-- 
1.7.4.4



[PATCH 2/2] net: ethernet: renesas: sh_eth: use new api ethtool_{get|set}_link_ksettings

2016-08-09 Thread Philippe Reynes
The ethtool api {get|set}_settings is deprecated.
We move this driver to new api {get|set}_link_ksettings.

Signed-off-by: Philippe Reynes 
---
 drivers/net/ethernet/renesas/sh_eth.c |   18 +-
 1 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/renesas/sh_eth.c 
b/drivers/net/ethernet/renesas/sh_eth.c
index 901ed36..1f8240a 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1817,8 +1817,8 @@ static int sh_eth_phy_start(struct net_device *ndev)
return 0;
 }
 
-static int sh_eth_get_settings(struct net_device *ndev,
-  struct ethtool_cmd *ecmd)
+static int sh_eth_get_link_ksettings(struct net_device *ndev,
+struct ethtool_link_ksettings *cmd)
 {
struct sh_eth_private *mdp = netdev_priv(ndev);
unsigned long flags;
@@ -1828,14 +1828,14 @@ static int sh_eth_get_settings(struct net_device *ndev,
return -ENODEV;
 
spin_lock_irqsave(>lock, flags);
-   ret = phy_ethtool_gset(ndev->phydev, ecmd);
+   ret = phy_ethtool_ksettings_get(ndev->phydev, cmd);
spin_unlock_irqrestore(>lock, flags);
 
return ret;
 }
 
-static int sh_eth_set_settings(struct net_device *ndev,
-  struct ethtool_cmd *ecmd)
+static int sh_eth_set_link_ksettings(struct net_device *ndev,
+const struct ethtool_link_ksettings *cmd)
 {
struct sh_eth_private *mdp = netdev_priv(ndev);
unsigned long flags;
@@ -1849,11 +1849,11 @@ static int sh_eth_set_settings(struct net_device *ndev,
/* disable tx and rx */
sh_eth_rcv_snd_disable(ndev);
 
-   ret = phy_ethtool_sset(ndev->phydev, ecmd);
+   ret = phy_ethtool_ksettings_set(ndev->phydev, cmd);
if (ret)
goto error_exit;
 
-   if (ecmd->duplex == DUPLEX_FULL)
+   if (cmd->base.duplex == DUPLEX_FULL)
mdp->duplex = 1;
else
mdp->duplex = 0;
@@ -2195,8 +2195,6 @@ static int sh_eth_set_ringparam(struct net_device *ndev,
 }
 
 static const struct ethtool_ops sh_eth_ethtool_ops = {
-   .get_settings   = sh_eth_get_settings,
-   .set_settings   = sh_eth_set_settings,
.get_regs_len   = sh_eth_get_regs_len,
.get_regs   = sh_eth_get_regs,
.nway_reset = sh_eth_nway_reset,
@@ -2208,6 +2206,8 @@ static const struct ethtool_ops sh_eth_ethtool_ops = {
.get_sset_count = sh_eth_get_sset_count,
.get_ringparam  = sh_eth_get_ringparam,
.set_ringparam  = sh_eth_set_ringparam,
+   .get_link_ksettings = sh_eth_get_link_ksettings,
+   .set_link_ksettings = sh_eth_set_link_ksettings,
 };
 
 /* network device open function */
-- 
1.7.4.4



[PATCH 1/4] befs: dump inode_size superblock information

2016-08-09 Thread Luis de Bethencourt
befs_dump_super_block() wasn't giving the inode_size information when
dumping all elements of the superblock. Add this element to have complete
information of the superblock.

Signed-off-by: Luis de Bethencourt 
---

Hi,

This is a series of superblock information related changes.

Thanks,
Luis

 fs/befs/debug.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fs/befs/debug.c b/fs/befs/debug.c
index 4de7cff..85c1339 100644
--- a/fs/befs/debug.c
+++ b/fs/befs/debug.c
@@ -169,6 +169,7 @@ befs_dump_super_block(const struct super_block *sb, 
befs_super_block * sup)
 
befs_debug(sb, "  num_blocks %llu", fs64_to_cpu(sb, sup->num_blocks));
befs_debug(sb, "  used_blocks %llu", fs64_to_cpu(sb, sup->used_blocks));
+   befs_debug(sb, "  inode_size %u", fs32_to_cpu(sb, sup->inode_size));
 
befs_debug(sb, "  magic2 %08x", fs32_to_cpu(sb, sup->magic2));
befs_debug(sb, "  blocks_per_ag %u",
-- 
2.5.1



[PATCH 1/4] befs: dump inode_size superblock information

2016-08-09 Thread Luis de Bethencourt
befs_dump_super_block() wasn't giving the inode_size information when
dumping all elements of the superblock. Add this element to have complete
information of the superblock.

Signed-off-by: Luis de Bethencourt 
---

Hi,

This is a series of superblock information related changes.

Thanks,
Luis

 fs/befs/debug.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fs/befs/debug.c b/fs/befs/debug.c
index 4de7cff..85c1339 100644
--- a/fs/befs/debug.c
+++ b/fs/befs/debug.c
@@ -169,6 +169,7 @@ befs_dump_super_block(const struct super_block *sb, 
befs_super_block * sup)
 
befs_debug(sb, "  num_blocks %llu", fs64_to_cpu(sb, sup->num_blocks));
befs_debug(sb, "  used_blocks %llu", fs64_to_cpu(sb, sup->used_blocks));
+   befs_debug(sb, "  inode_size %u", fs32_to_cpu(sb, sup->inode_size));
 
befs_debug(sb, "  magic2 %08x", fs32_to_cpu(sb, sup->magic2));
befs_debug(sb, "  blocks_per_ag %u",
-- 
2.5.1



[PATCH 4/4] befs: fix style issues in super.c

2016-08-09 Thread Luis de Bethencourt
Fixing the following checkpatch.pl error:

ERROR: "foo * bar" should be "foo *bar"
+befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)

And the following warnings:

WARNING: suspect code indent for conditional statements (8, 12)
+   if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_LE)
+   befs_sb->byte_order = BEFS_BYTESEX_LE;

WARNING: suspect code indent for conditional statements (8, 12)
+   else if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_BE)
+   befs_sb->byte_order = BEFS_BYTESEX_BE;

WARNING: break quoted strings at a space character
+   befs_error(sb, "blocksize(%u) cannot be larger"
+  "than system pagesize(%lu)", befs_sb->block_size,

WARNING: line over 80 characters
+   if (befs_sb->log_start != befs_sb->log_end || befs_sb->flags == 
BEFS_DIRTY) {

Signed-off-by: Luis de Bethencourt 
---

Fixing these because I was touching this code area.

Thanks,
Luis

 fs/befs/super.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/befs/super.c b/fs/befs/super.c
index 80b93c0..7c50025 100644
--- a/fs/befs/super.c
+++ b/fs/befs/super.c
@@ -18,15 +18,15 @@
  * of the befs superblock
  */
 int
-befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)
+befs_load_sb(struct super_block *sb, befs_super_block *disk_sb)
 {
struct befs_sb_info *befs_sb = BEFS_SB(sb);
 
/* Check the byte order of the filesystem */
if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_LE)
-   befs_sb->byte_order = BEFS_BYTESEX_LE;
+   befs_sb->byte_order = BEFS_BYTESEX_LE;
else if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_BE)
-   befs_sb->byte_order = BEFS_BYTESEX_BE;
+   befs_sb->byte_order = BEFS_BYTESEX_BE;
 
befs_sb->magic1 = fs32_to_cpu(sb, disk_sb->magic1);
befs_sb->magic2 = fs32_to_cpu(sb, disk_sb->magic2);
@@ -82,7 +82,7 @@ befs_check_sb(struct super_block *sb)
}
 
if (befs_sb->block_size > PAGE_SIZE) {
-   befs_error(sb, "blocksize(%u) cannot be larger"
+   befs_error(sb, "blocksize(%u) cannot be larger "
   "than system pagesize(%lu)", befs_sb->block_size,
   PAGE_SIZE);
return BEFS_ERR;
@@ -106,10 +106,11 @@ befs_check_sb(struct super_block *sb)
if ((1 << befs_sb->ag_shift) != befs_sb->blocks_per_ag)
befs_error(sb, "ag_shift disagrees with blocks_per_ag.");
 
-   if (befs_sb->log_start != befs_sb->log_end || befs_sb->flags == 
BEFS_DIRTY) {
+   if (befs_sb->log_start != befs_sb->log_end ||
+   befs_sb->flags == BEFS_DIRTY) {
befs_error(sb, "Filesystem not clean! There are blocks in the "
-  "journal. You must boot into BeOS and mount this 
volume "
-  "to make it clean.");
+  "journal. You must boot into BeOS and mount this "
+  "volume to make it clean.");
return BEFS_ERR;
}
 
-- 
2.5.1



[PATCH 3/4] befs: fix comment style

2016-08-09 Thread Luis de Bethencourt
The description of befs_load_sb was confusing the kernel-doc system since,
because it starts with /**, it thinks it will document the function with
kernel-doc formatting. Which it isn't.

Fix other comment style issues in the file while we are at it.

Signed-off-by: Luis de Bethencourt 
---
 fs/befs/super.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/fs/befs/super.c b/fs/befs/super.c
index c36745d..80b93c0 100644
--- a/fs/befs/super.c
+++ b/fs/befs/super.c
@@ -13,13 +13,9 @@
 #include "befs.h"
 #include "super.h"
 
-/**
+/*
  * befs_load_sb -- Read from disk and properly byteswap all the fields
  * of the befs superblock
- *
- *
- *
- *
  */
 int
 befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)
@@ -93,8 +89,8 @@ befs_check_sb(struct super_block *sb)
}
 
/*
-  * block_shift and block_size encode the same information
-  * in different ways as a consistency check.
+* block_shift and block_size encode the same information
+* in different ways as a consistency check.
 */
 
if ((1 << befs_sb->block_shift) != befs_sb->block_size) {
-- 
2.5.1



[PATCH 3/4] befs: fix comment style

2016-08-09 Thread Luis de Bethencourt
The description of befs_load_sb was confusing the kernel-doc system since,
because it starts with /**, it thinks it will document the function with
kernel-doc formatting. Which it isn't.

Fix other comment style issues in the file while we are at it.

Signed-off-by: Luis de Bethencourt 
---
 fs/befs/super.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/fs/befs/super.c b/fs/befs/super.c
index c36745d..80b93c0 100644
--- a/fs/befs/super.c
+++ b/fs/befs/super.c
@@ -13,13 +13,9 @@
 #include "befs.h"
 #include "super.h"
 
-/**
+/*
  * befs_load_sb -- Read from disk and properly byteswap all the fields
  * of the befs superblock
- *
- *
- *
- *
  */
 int
 befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)
@@ -93,8 +89,8 @@ befs_check_sb(struct super_block *sb)
}
 
/*
-  * block_shift and block_size encode the same information
-  * in different ways as a consistency check.
+* block_shift and block_size encode the same information
+* in different ways as a consistency check.
 */
 
if ((1 << befs_sb->block_shift) != befs_sb->block_size) {
-- 
2.5.1



[PATCH 4/4] befs: fix style issues in super.c

2016-08-09 Thread Luis de Bethencourt
Fixing the following checkpatch.pl error:

ERROR: "foo * bar" should be "foo *bar"
+befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)

And the following warnings:

WARNING: suspect code indent for conditional statements (8, 12)
+   if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_LE)
+   befs_sb->byte_order = BEFS_BYTESEX_LE;

WARNING: suspect code indent for conditional statements (8, 12)
+   else if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_BE)
+   befs_sb->byte_order = BEFS_BYTESEX_BE;

WARNING: break quoted strings at a space character
+   befs_error(sb, "blocksize(%u) cannot be larger"
+  "than system pagesize(%lu)", befs_sb->block_size,

WARNING: line over 80 characters
+   if (befs_sb->log_start != befs_sb->log_end || befs_sb->flags == 
BEFS_DIRTY) {

Signed-off-by: Luis de Bethencourt 
---

Fixing these because I was touching this code area.

Thanks,
Luis

 fs/befs/super.c | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/befs/super.c b/fs/befs/super.c
index 80b93c0..7c50025 100644
--- a/fs/befs/super.c
+++ b/fs/befs/super.c
@@ -18,15 +18,15 @@
  * of the befs superblock
  */
 int
-befs_load_sb(struct super_block *sb, befs_super_block * disk_sb)
+befs_load_sb(struct super_block *sb, befs_super_block *disk_sb)
 {
struct befs_sb_info *befs_sb = BEFS_SB(sb);
 
/* Check the byte order of the filesystem */
if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_LE)
-   befs_sb->byte_order = BEFS_BYTESEX_LE;
+   befs_sb->byte_order = BEFS_BYTESEX_LE;
else if (disk_sb->fs_byte_order == BEFS_BYTEORDER_NATIVE_BE)
-   befs_sb->byte_order = BEFS_BYTESEX_BE;
+   befs_sb->byte_order = BEFS_BYTESEX_BE;
 
befs_sb->magic1 = fs32_to_cpu(sb, disk_sb->magic1);
befs_sb->magic2 = fs32_to_cpu(sb, disk_sb->magic2);
@@ -82,7 +82,7 @@ befs_check_sb(struct super_block *sb)
}
 
if (befs_sb->block_size > PAGE_SIZE) {
-   befs_error(sb, "blocksize(%u) cannot be larger"
+   befs_error(sb, "blocksize(%u) cannot be larger "
   "than system pagesize(%lu)", befs_sb->block_size,
   PAGE_SIZE);
return BEFS_ERR;
@@ -106,10 +106,11 @@ befs_check_sb(struct super_block *sb)
if ((1 << befs_sb->ag_shift) != befs_sb->blocks_per_ag)
befs_error(sb, "ag_shift disagrees with blocks_per_ag.");
 
-   if (befs_sb->log_start != befs_sb->log_end || befs_sb->flags == 
BEFS_DIRTY) {
+   if (befs_sb->log_start != befs_sb->log_end ||
+   befs_sb->flags == BEFS_DIRTY) {
befs_error(sb, "Filesystem not clean! There are blocks in the "
-  "journal. You must boot into BeOS and mount this 
volume "
-  "to make it clean.");
+  "journal. You must boot into BeOS and mount this "
+  "volume to make it clean.");
return BEFS_ERR;
}
 
-- 
2.5.1



[PATCH 2/4] befs: add check for ag_shift in superblock

2016-08-09 Thread Luis de Bethencourt
ag_shift and blocks_per_ag contain the same information in different ways,
same as block_shift and block_size do. It is worth checking this two are
consistent, but since blocks_per_ag isn't documented as mandatory to use
some implementations of befs don't enforce this, so making it non-fatal if
they don't match and just having it as a warning.

Signed-off-by: Luis de Bethencourt 
---
 fs/befs/super.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/fs/befs/super.c b/fs/befs/super.c
index dc13df8..c36745d 100644
--- a/fs/befs/super.c
+++ b/fs/befs/super.c
@@ -103,6 +103,13 @@ befs_check_sb(struct super_block *sb)
return BEFS_ERR;
}
 
+
+   /* ag_shift also encodes the same information as blocks_per_ag in a
+* different way, non-fatal consistency check
+*/
+   if ((1 << befs_sb->ag_shift) != befs_sb->blocks_per_ag)
+   befs_error(sb, "ag_shift disagrees with blocks_per_ag.");
+
if (befs_sb->log_start != befs_sb->log_end || befs_sb->flags == 
BEFS_DIRTY) {
befs_error(sb, "Filesystem not clean! There are blocks in the "
   "journal. You must boot into BeOS and mount this 
volume "
-- 
2.5.1



[PATCH 2/4] befs: add check for ag_shift in superblock

2016-08-09 Thread Luis de Bethencourt
ag_shift and blocks_per_ag contain the same information in different ways,
same as block_shift and block_size do. It is worth checking this two are
consistent, but since blocks_per_ag isn't documented as mandatory to use
some implementations of befs don't enforce this, so making it non-fatal if
they don't match and just having it as a warning.

Signed-off-by: Luis de Bethencourt 
---
 fs/befs/super.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/fs/befs/super.c b/fs/befs/super.c
index dc13df8..c36745d 100644
--- a/fs/befs/super.c
+++ b/fs/befs/super.c
@@ -103,6 +103,13 @@ befs_check_sb(struct super_block *sb)
return BEFS_ERR;
}
 
+
+   /* ag_shift also encodes the same information as blocks_per_ag in a
+* different way, non-fatal consistency check
+*/
+   if ((1 << befs_sb->ag_shift) != befs_sb->blocks_per_ag)
+   befs_error(sb, "ag_shift disagrees with blocks_per_ag.");
+
if (befs_sb->log_start != befs_sb->log_end || befs_sb->flags == 
BEFS_DIRTY) {
befs_error(sb, "Filesystem not clean! There are blocks in the "
   "journal. You must boot into BeOS and mount this 
volume "
-- 
2.5.1



[Patch v4 9/9] arm64: Update device tree for Layerscape SoCs

2016-08-09 Thread York Sun
Add DDR memory controller nodes to enable EDAC driver.

Signed-off-by: York Sun 

---
Change log
  v4: no change
  v3: no change
  v2: no change

 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi |  7 +++
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 14 ++
 2 files changed, 21 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index de0323b..cb33f23 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -196,6 +196,13 @@
bus-width = <4>;
};
 
+   ddr: memory-controller@108 {
+   compatible = "fsl,qoriq-memory-controller";
+   reg = <0x0 0x108 0x0 0x1000>;
+   interrupts = <0 144 0x4>;
+   big-endian;
+   };
+
dspi0: dspi@210 {
compatible = "fsl,ls1043a-dspi", 
"fsl,ls1021a-v1.0-dspi";
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 3187c82..3221e5c 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -689,4 +689,18 @@
interrupts = <0 12 4>;
};
};
+
+   ddr1: memory-controller@108 {
+   compatible = "fsl,qoriq-memory-controller";
+   reg = <0x0 0x108 0x0 0x1000>;
+   interrupts = <0 17 0x4>;
+   little-endian;
+   };
+
+   ddr2: memory-controller@109 {
+   compatible = "fsl,qoriq-memory-controller";
+   reg = <0x0 0x109 0x0 0x1000>;
+   interrupts = <0 18 0x4>;
+   little-endian;
+   };
 };
-- 
2.7.4



[Patch v4 9/9] arm64: Update device tree for Layerscape SoCs

2016-08-09 Thread York Sun
Add DDR memory controller nodes to enable EDAC driver.

Signed-off-by: York Sun 

---
Change log
  v4: no change
  v3: no change
  v2: no change

 arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi |  7 +++
 arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi | 14 ++
 2 files changed, 21 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index de0323b..cb33f23 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -196,6 +196,13 @@
bus-width = <4>;
};
 
+   ddr: memory-controller@108 {
+   compatible = "fsl,qoriq-memory-controller";
+   reg = <0x0 0x108 0x0 0x1000>;
+   interrupts = <0 144 0x4>;
+   big-endian;
+   };
+
dspi0: dspi@210 {
compatible = "fsl,ls1043a-dspi", 
"fsl,ls1021a-v1.0-dspi";
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi 
b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index 3187c82..3221e5c 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -689,4 +689,18 @@
interrupts = <0 12 4>;
};
};
+
+   ddr1: memory-controller@108 {
+   compatible = "fsl,qoriq-memory-controller";
+   reg = <0x0 0x108 0x0 0x1000>;
+   interrupts = <0 17 0x4>;
+   little-endian;
+   };
+
+   ddr2: memory-controller@109 {
+   compatible = "fsl,qoriq-memory-controller";
+   reg = <0x0 0x109 0x0 0x1000>;
+   interrupts = <0 18 0x4>;
+   little-endian;
+   };
 };
-- 
2.7.4



[Patch v4 8/9] driver/edac/layerscape_edac: Add Layerscape EDAC support

2016-08-09 Thread York Sun
Add DDR EDAC for ARM-based compatible controllers. Both big-endian
and little-endian are supported, as specified in device tree.

Signed-off-by: York Sun 

---
Change log
  v4: Drop adding atomic_scrub() for arm64
  Drop NO_IRQ
  v3: no change
  v2: Create new driver using shared DDR object

 arch/arm64/Kconfig.platforms   |  1 +
 drivers/edac/Kconfig   |  7 +
 drivers/edac/Makefile  |  3 ++
 drivers/edac/fsl_ddr_edac.c|  2 +-
 drivers/edac/layerscape_edac.c | 67 ++
 5 files changed, 79 insertions(+), 1 deletion(-)
 create mode 100644 drivers/edac/layerscape_edac.c

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 7ef1d05..185a215 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -41,6 +41,7 @@ config ARCH_EXYNOS
 
 config ARCH_LAYERSCAPE
bool "ARMv8 based Freescale Layerscape SoC family"
+   select EDAC_SUPPORT
help
  This enables support for the Freescale Layerscape SoC family.
 
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 6ca7474..f1ac4e2 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -258,6 +258,13 @@ config EDAC_MPC85XX
  Support for error detection and correction on the Freescale
  MPC8349, MPC8560, MPC8540, MPC8548, T4240
 
+config EDAC_LAYERSCAPE
+   tristate "Freescale Layerscape DDR"
+   depends on EDAC_MM_EDAC && ARCH_LAYERSCAPE
+   help
+ Support for error detection and correction on Freescale memory
+ controllers on Layerscape SoCs.
+
 config EDAC_MV64X60
tristate "Marvell MV64x60"
depends on EDAC_MM_EDAC && MV64X60
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index ee047a4..910dc83 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -54,6 +54,9 @@ obj-$(CONFIG_EDAC_PASEMI) += pasemi_edac.o
 mpc85xx_edac_mod-y := fsl_ddr_edac.o mpc85xx_edac.o
 obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac_mod.o
 
+layerscape_edac_mod-y  := fsl_ddr_edac.o layerscape_edac.o
+obj-$(CONFIG_EDAC_LAYERSCAPE)  += layerscape_edac_mod.o
+
 obj-$(CONFIG_EDAC_MV64X60) += mv64x60_edac.o
 obj-$(CONFIG_EDAC_CELL)+= cell_edac.o
 obj-$(CONFIG_EDAC_PPC4XX)  += ppc4xx_edac.o
diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c
index d8ce1f6..afade14 100644
--- a/drivers/edac/fsl_ddr_edac.c
+++ b/drivers/edac/fsl_ddr_edac.c
@@ -26,6 +26,7 @@
 
 #include 
 #include 
+#include 
 #include "edac_module.h"
 #include "edac_core.h"
 #include "fsl_ddr_edac.h"
@@ -478,7 +479,6 @@ int fsl_mc_err_probe(struct platform_device *op)
 
pdata = mci->pvt_info;
pdata->name = "fsl_mc_err";
-   pdata->irq = NO_IRQ;
mci->pdev = >dev;
pdata->edac_idx = edac_mc_idx++;
dev_set_drvdata(mci->pdev, mci);
diff --git a/drivers/edac/layerscape_edac.c b/drivers/edac/layerscape_edac.c
new file mode 100644
index 000..6ba771d
--- /dev/null
+++ b/drivers/edac/layerscape_edac.c
@@ -0,0 +1,67 @@
+/*
+ * Freescale Memory Controller kernel module
+ *
+ * Derived from mpc85xx_edac.c
+ * Author: Dave Jiang 
+ *
+ * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include "edac_core.h"
+#include "fsl_ddr_edac.h"
+
+static const struct of_device_id fsl_ddr_mc_err_of_match[] = {
+   { .compatible = "fsl,qoriq-memory-controller", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, fsl_ddr_mc_err_of_match);
+
+static struct platform_driver fsl_ddr_mc_err_driver = {
+   .probe = fsl_mc_err_probe,
+   .remove = fsl_mc_err_remove,
+   .driver = {
+   .name = "fsl_ddr_mc_err",
+   .of_match_table = fsl_ddr_mc_err_of_match,
+   },
+};
+
+static int __init fsl_ddr_mc_init(void)
+{
+   int res = 0;
+
+   /* make sure error reporting method is sane */
+   switch (edac_op_state) {
+   case EDAC_OPSTATE_POLL:
+   case EDAC_OPSTATE_INT:
+   break;
+   default:
+   edac_op_state = EDAC_OPSTATE_INT;
+   break;
+   }
+
+   res = platform_driver_register(_ddr_mc_err_driver);
+   if (res) {
+   pr_err("Layerscape EDAC: MC fails to register\n");
+   return res;
+   }
+
+   return 0;
+}
+
+module_init(fsl_ddr_mc_init);
+
+static void __exit fsl_ddr_mc_exit(void)
+{
+   platform_driver_unregister(_ddr_mc_err_driver);
+}
+
+module_exit(fsl_ddr_mc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Montavista Software, Inc.");
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state,
+"EDAC Error Reporting state: 0=Poll, 2=Interrupt");
-- 
2.7.4



[Patch v4 8/9] driver/edac/layerscape_edac: Add Layerscape EDAC support

2016-08-09 Thread York Sun
Add DDR EDAC for ARM-based compatible controllers. Both big-endian
and little-endian are supported, as specified in device tree.

Signed-off-by: York Sun 

---
Change log
  v4: Drop adding atomic_scrub() for arm64
  Drop NO_IRQ
  v3: no change
  v2: Create new driver using shared DDR object

 arch/arm64/Kconfig.platforms   |  1 +
 drivers/edac/Kconfig   |  7 +
 drivers/edac/Makefile  |  3 ++
 drivers/edac/fsl_ddr_edac.c|  2 +-
 drivers/edac/layerscape_edac.c | 67 ++
 5 files changed, 79 insertions(+), 1 deletion(-)
 create mode 100644 drivers/edac/layerscape_edac.c

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 7ef1d05..185a215 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -41,6 +41,7 @@ config ARCH_EXYNOS
 
 config ARCH_LAYERSCAPE
bool "ARMv8 based Freescale Layerscape SoC family"
+   select EDAC_SUPPORT
help
  This enables support for the Freescale Layerscape SoC family.
 
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 6ca7474..f1ac4e2 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -258,6 +258,13 @@ config EDAC_MPC85XX
  Support for error detection and correction on the Freescale
  MPC8349, MPC8560, MPC8540, MPC8548, T4240
 
+config EDAC_LAYERSCAPE
+   tristate "Freescale Layerscape DDR"
+   depends on EDAC_MM_EDAC && ARCH_LAYERSCAPE
+   help
+ Support for error detection and correction on Freescale memory
+ controllers on Layerscape SoCs.
+
 config EDAC_MV64X60
tristate "Marvell MV64x60"
depends on EDAC_MM_EDAC && MV64X60
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index ee047a4..910dc83 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -54,6 +54,9 @@ obj-$(CONFIG_EDAC_PASEMI) += pasemi_edac.o
 mpc85xx_edac_mod-y := fsl_ddr_edac.o mpc85xx_edac.o
 obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac_mod.o
 
+layerscape_edac_mod-y  := fsl_ddr_edac.o layerscape_edac.o
+obj-$(CONFIG_EDAC_LAYERSCAPE)  += layerscape_edac_mod.o
+
 obj-$(CONFIG_EDAC_MV64X60) += mv64x60_edac.o
 obj-$(CONFIG_EDAC_CELL)+= cell_edac.o
 obj-$(CONFIG_EDAC_PPC4XX)  += ppc4xx_edac.o
diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c
index d8ce1f6..afade14 100644
--- a/drivers/edac/fsl_ddr_edac.c
+++ b/drivers/edac/fsl_ddr_edac.c
@@ -26,6 +26,7 @@
 
 #include 
 #include 
+#include 
 #include "edac_module.h"
 #include "edac_core.h"
 #include "fsl_ddr_edac.h"
@@ -478,7 +479,6 @@ int fsl_mc_err_probe(struct platform_device *op)
 
pdata = mci->pvt_info;
pdata->name = "fsl_mc_err";
-   pdata->irq = NO_IRQ;
mci->pdev = >dev;
pdata->edac_idx = edac_mc_idx++;
dev_set_drvdata(mci->pdev, mci);
diff --git a/drivers/edac/layerscape_edac.c b/drivers/edac/layerscape_edac.c
new file mode 100644
index 000..6ba771d
--- /dev/null
+++ b/drivers/edac/layerscape_edac.c
@@ -0,0 +1,67 @@
+/*
+ * Freescale Memory Controller kernel module
+ *
+ * Derived from mpc85xx_edac.c
+ * Author: Dave Jiang 
+ *
+ * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include "edac_core.h"
+#include "fsl_ddr_edac.h"
+
+static const struct of_device_id fsl_ddr_mc_err_of_match[] = {
+   { .compatible = "fsl,qoriq-memory-controller", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, fsl_ddr_mc_err_of_match);
+
+static struct platform_driver fsl_ddr_mc_err_driver = {
+   .probe = fsl_mc_err_probe,
+   .remove = fsl_mc_err_remove,
+   .driver = {
+   .name = "fsl_ddr_mc_err",
+   .of_match_table = fsl_ddr_mc_err_of_match,
+   },
+};
+
+static int __init fsl_ddr_mc_init(void)
+{
+   int res = 0;
+
+   /* make sure error reporting method is sane */
+   switch (edac_op_state) {
+   case EDAC_OPSTATE_POLL:
+   case EDAC_OPSTATE_INT:
+   break;
+   default:
+   edac_op_state = EDAC_OPSTATE_INT;
+   break;
+   }
+
+   res = platform_driver_register(_ddr_mc_err_driver);
+   if (res) {
+   pr_err("Layerscape EDAC: MC fails to register\n");
+   return res;
+   }
+
+   return 0;
+}
+
+module_init(fsl_ddr_mc_init);
+
+static void __exit fsl_ddr_mc_exit(void)
+{
+   platform_driver_unregister(_ddr_mc_err_driver);
+}
+
+module_exit(fsl_ddr_mc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Montavista Software, Inc.");
+module_param(edac_op_state, int, 0444);
+MODULE_PARM_DESC(edac_op_state,
+"EDAC Error Reporting state: 0=Poll, 2=Interrupt");
-- 
2.7.4



Re: [PATCH v2] console: Don't prefer first registered if DT specifies stdout-path

2016-08-09 Thread Andrew Morton
On Tue, 9 Aug 2016 16:19:37 +0100 Paul Burton  wrote:

> If a device tree specifies a preferred device for kernel console output
> via the stdout-path or linux,stdout-path chosen node properties or the
> stdout alias then the kernel ought to honor it & output the kernel
> console to that device. As it stands, this isn't the case. Whilst we
> parse the stdout-path properties & set an of_stdout variable from
> of_alias_scan(), and use that from of_console_check() to determine
> whether to add a console device as a preferred console whilst
> registering it, we also prefer the first registered console if no other
> has been selected at the time of its registration.
> 
> This means that if a console other than the one the device tree selects
> via stdout-path is registered first, we will switch to using it & when
> the stdout-path console is later registered the call to
> add_preferred_console() via of_console_check() is too late to do
> anything useful. In practice this seems to mean that we switch to the
> dummy console device fairly early & see no further console output:
> 
> Console: colour dummy device 80x25
> console [tty0] enabled
> bootconsole [ns16550a0] disabled
> 
> Fix this by not automatically preferring the first registered console if
> one is specified by the device tree. This allows consoles to be
> registered but not enabled, and once the driver for the console selected
> by stdout-path calls of_console_check() the driver will be added to the
> list of preferred consoles before any other console has been enabled.
> When that console is then registered via register_console() it will be
> enabled as expected.

Looks reasonable.  Could you please do `grep -r stdout-path
Documentation' and check that everything therein is complete, accurate
and necessary?



[PATCH] pwm: Unexport children before chip removal

2016-08-09 Thread David Hsu
Exported pwm channels aren't removed before the pwmchip and are
leaked. This results in invalid sysfs files. This fix removes
all exported pwm channels before chip removal.

Signed-off-by: David Hsu 
---
 drivers/pwm/core.c  |  2 ++
 drivers/pwm/sysfs.c | 18 ++
 include/linux/pwm.h |  5 +
 3 files changed, 25 insertions(+)

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index ed337a8c..869af84 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -339,6 +339,8 @@ int pwmchip_remove(struct pwm_chip *chip)
unsigned int i;
int ret = 0;
 
+   pwmchip_sysfs_unexport_children(chip);
+
mutex_lock(_lock);
 
for (i = 0; i < chip->npwm; i++) {
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index cb2b376..b3ccb8f 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -400,6 +400,24 @@ void pwmchip_sysfs_unexport(struct pwm_chip *chip)
}
 }
 
+void pwmchip_sysfs_unexport_children(struct pwm_chip *chip)
+{
+   struct device *parent;
+   unsigned int i;
+
+   parent = class_find_device(_class, NULL, chip,
+  pwmchip_sysfs_match);
+   if (!parent)
+   return;
+
+   for (i = 0; i < chip->npwm; i++) {
+   struct pwm_device *pwm = >pwms[i];
+
+   if (test_bit(PWMF_EXPORTED, >flags))
+   pwm_unexport_child(parent, pwm);
+   }
+}
+
 static int __init pwm_sysfs_init(void)
 {
return class_register(_class);
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index c038ae3..16a0ae0 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -530,6 +530,7 @@ static inline void pwm_remove_table(struct pwm_lookup 
*table, size_t num)
 #ifdef CONFIG_PWM_SYSFS
 void pwmchip_sysfs_export(struct pwm_chip *chip);
 void pwmchip_sysfs_unexport(struct pwm_chip *chip);
+void pwmchip_sysfs_unexport_children(struct pwm_chip *chip);
 #else
 static inline void pwmchip_sysfs_export(struct pwm_chip *chip)
 {
@@ -538,6 +539,10 @@ static inline void pwmchip_sysfs_export(struct pwm_chip 
*chip)
 static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip)
 {
 }
+
+static inline void pwmchip_sysfs_unexport_children(struct pwm_chip *chip)
+{
+}
 #endif /* CONFIG_PWM_SYSFS */
 
 #endif /* __LINUX_PWM_H */
-- 
2.8.0.rc3.226.g39d4020



Re: [PATCH v2] console: Don't prefer first registered if DT specifies stdout-path

2016-08-09 Thread Andrew Morton
On Tue, 9 Aug 2016 16:19:37 +0100 Paul Burton  wrote:

> If a device tree specifies a preferred device for kernel console output
> via the stdout-path or linux,stdout-path chosen node properties or the
> stdout alias then the kernel ought to honor it & output the kernel
> console to that device. As it stands, this isn't the case. Whilst we
> parse the stdout-path properties & set an of_stdout variable from
> of_alias_scan(), and use that from of_console_check() to determine
> whether to add a console device as a preferred console whilst
> registering it, we also prefer the first registered console if no other
> has been selected at the time of its registration.
> 
> This means that if a console other than the one the device tree selects
> via stdout-path is registered first, we will switch to using it & when
> the stdout-path console is later registered the call to
> add_preferred_console() via of_console_check() is too late to do
> anything useful. In practice this seems to mean that we switch to the
> dummy console device fairly early & see no further console output:
> 
> Console: colour dummy device 80x25
> console [tty0] enabled
> bootconsole [ns16550a0] disabled
> 
> Fix this by not automatically preferring the first registered console if
> one is specified by the device tree. This allows consoles to be
> registered but not enabled, and once the driver for the console selected
> by stdout-path calls of_console_check() the driver will be added to the
> list of preferred consoles before any other console has been enabled.
> When that console is then registered via register_console() it will be
> enabled as expected.

Looks reasonable.  Could you please do `grep -r stdout-path
Documentation' and check that everything therein is complete, accurate
and necessary?



[PATCH] pwm: Unexport children before chip removal

2016-08-09 Thread David Hsu
Exported pwm channels aren't removed before the pwmchip and are
leaked. This results in invalid sysfs files. This fix removes
all exported pwm channels before chip removal.

Signed-off-by: David Hsu 
---
 drivers/pwm/core.c  |  2 ++
 drivers/pwm/sysfs.c | 18 ++
 include/linux/pwm.h |  5 +
 3 files changed, 25 insertions(+)

diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index ed337a8c..869af84 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -339,6 +339,8 @@ int pwmchip_remove(struct pwm_chip *chip)
unsigned int i;
int ret = 0;
 
+   pwmchip_sysfs_unexport_children(chip);
+
mutex_lock(_lock);
 
for (i = 0; i < chip->npwm; i++) {
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index cb2b376..b3ccb8f 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -400,6 +400,24 @@ void pwmchip_sysfs_unexport(struct pwm_chip *chip)
}
 }
 
+void pwmchip_sysfs_unexport_children(struct pwm_chip *chip)
+{
+   struct device *parent;
+   unsigned int i;
+
+   parent = class_find_device(_class, NULL, chip,
+  pwmchip_sysfs_match);
+   if (!parent)
+   return;
+
+   for (i = 0; i < chip->npwm; i++) {
+   struct pwm_device *pwm = >pwms[i];
+
+   if (test_bit(PWMF_EXPORTED, >flags))
+   pwm_unexport_child(parent, pwm);
+   }
+}
+
 static int __init pwm_sysfs_init(void)
 {
return class_register(_class);
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index c038ae3..16a0ae0 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -530,6 +530,7 @@ static inline void pwm_remove_table(struct pwm_lookup 
*table, size_t num)
 #ifdef CONFIG_PWM_SYSFS
 void pwmchip_sysfs_export(struct pwm_chip *chip);
 void pwmchip_sysfs_unexport(struct pwm_chip *chip);
+void pwmchip_sysfs_unexport_children(struct pwm_chip *chip);
 #else
 static inline void pwmchip_sysfs_export(struct pwm_chip *chip)
 {
@@ -538,6 +539,10 @@ static inline void pwmchip_sysfs_export(struct pwm_chip 
*chip)
 static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip)
 {
 }
+
+static inline void pwmchip_sysfs_unexport_children(struct pwm_chip *chip)
+{
+}
 #endif /* CONFIG_PWM_SYSFS */
 
 #endif /* __LINUX_PWM_H */
-- 
2.8.0.rc3.226.g39d4020



[Patch v4 3/9] driver/edac/fsl-ddr: Separate FSL DDR EDAC driver from MPC85xx

2016-08-09 Thread York Sun
The mpc85xx compatible DDR controllers are used on ARM-based SoCs.
Separate the DDR part from mpc85xx EDAC driver and prepare to support
both architecture.

Signed-off-by: York Sun 

---
Change log
  v4: Change comment in file header
  Use lower case "fsl_ddr_edac" for EDAC_MOD_STR
  Drop exporting probe and remove symbols
  v3: Fix compiling errors and warnings caused by patch ordering
  v2: Reordered patch
  Separate FSL DDR commont code as shared object, not another driver
  This patch is generated with "git format-patch -M40 -C40" to show
  copy-and-delete.

 drivers/edac/Makefile   |   5 +-
 drivers/edac/{mpc85xx_edac.c => fsl_ddr_edac.c} | 701 +---
 drivers/edac/{mpc85xx_edac.h => fsl_ddr_edac.h} | 110 +---
 drivers/edac/mpc85xx_edac.c | 559 +--
 drivers/edac/mpc85xx_edac.h |  66 ---
 5 files changed, 28 insertions(+), 1413 deletions(-)
 copy drivers/edac/{mpc85xx_edac.c => fsl_ddr_edac.c} (43%)
 copy drivers/edac/{mpc85xx_edac.h => fsl_ddr_edac.h} (43%)

diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index f9e4a3e..ee047a4 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -50,7 +50,10 @@ amd64_edac_mod-$(CONFIG_EDAC_AMD64_ERROR_INJECTION) += 
amd64_edac_inj.o
 obj-$(CONFIG_EDAC_AMD64)   += amd64_edac_mod.o
 
 obj-$(CONFIG_EDAC_PASEMI)  += pasemi_edac.o
-obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac.o
+
+mpc85xx_edac_mod-y := fsl_ddr_edac.o mpc85xx_edac.o
+obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac_mod.o
+
 obj-$(CONFIG_EDAC_MV64X60) += mv64x60_edac.o
 obj-$(CONFIG_EDAC_CELL)+= cell_edac.o
 obj-$(CONFIG_EDAC_PPC4XX)  += ppc4xx_edac.o
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/fsl_ddr_edac.c
similarity index 43%
copy from drivers/edac/mpc85xx_edac.c
copy to drivers/edac/fsl_ddr_edac.c
index c0b0951..ca7636f 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/fsl_ddr_edac.c
@@ -1,5 +1,9 @@
 /*
- * Freescale MPC85xx Memory Controller kernel module
+ * Freescale Memory Controller kernel module
+ *
+ * Support Power-based SoCs including MPC85xx, MPC86xx, MPC83xx and
+ * ARM-based Layerscape SoCs including LS2xxx. Originally split
+ * out from mpc85xx_edac EDAC driver.
  *
  * Parts Copyrighted (c) 2013 by Freescale Semiconductor, Inc.
  *
@@ -20,33 +24,20 @@
 #include 
 #include 
 #include 
-#include 
 
 #include 
 #include 
 #include "edac_module.h"
 #include "edac_core.h"
-#include "mpc85xx_edac.h"
+#include "fsl_ddr_edac.h"
+
+#define EDAC_MOD_STR   "fsl_ddr_edac"
 
-static int edac_dev_idx;
-#ifdef CONFIG_PCI
-static int edac_pci_idx;
-#endif
 static int edac_mc_idx;
 
 static u32 orig_ddr_err_disable;
 static u32 orig_ddr_err_sbe;
 
-/*
- * PCI Err defines
- */
-#ifdef CONFIG_PCI
-static u32 orig_pci_err_cap_dr;
-static u32 orig_pci_err_en;
-#endif
-
-static u32 orig_l2_err_disable;
-
 / MC SYSFS parts ***/
 
 #define to_mci(k) container_of(k, struct mem_ctl_info, dev)
@@ -141,589 +132,6 @@ static struct attribute *mpc85xx_dev_attrs[] = {
 
 ATTRIBUTE_GROUPS(mpc85xx_dev);
 
-/ PCI Err device ***/
-#ifdef CONFIG_PCI
-
-static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci)
-{
-   struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
-   u32 err_detect;
-
-   err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
-
-   /* master aborts can happen during PCI config cycles */
-   if (!(err_detect & ~(PCI_EDE_MULTI_ERR | PCI_EDE_MST_ABRT))) {
-   out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
-   return;
-   }
-
-   pr_err("PCI error(s) detected\n");
-   pr_err("PCI/X ERR_DR register: %#08x\n", err_detect);
-
-   pr_err("PCI/X ERR_ATTRIB register: %#08x\n",
-  in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ATTRIB));
-   pr_err("PCI/X ERR_ADDR register: %#08x\n",
-  in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR));
-   pr_err("PCI/X ERR_EXT_ADDR register: %#08x\n",
-  in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EXT_ADDR));
-   pr_err("PCI/X ERR_DL register: %#08x\n",
-  in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DL));
-   pr_err("PCI/X ERR_DH register: %#08x\n",
-  in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DH));
-
-   /* clear error bits */
-   out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
-
-   if (err_detect & PCI_EDE_PERR_MASK)
-   edac_pci_handle_pe(pci, pci->ctl_name);
-
-   if ((err_detect & ~PCI_EDE_MULTI_ERR) & ~PCI_EDE_PERR_MASK)
-   edac_pci_handle_npe(pci, pci->ctl_name);
-}
-
-static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci)
-{
-   struct mpc85xx_pci_pdata *pdata = 

[Patch v4 3/9] driver/edac/fsl-ddr: Separate FSL DDR EDAC driver from MPC85xx

2016-08-09 Thread York Sun
The mpc85xx compatible DDR controllers are used on ARM-based SoCs.
Separate the DDR part from mpc85xx EDAC driver and prepare to support
both architecture.

Signed-off-by: York Sun 

---
Change log
  v4: Change comment in file header
  Use lower case "fsl_ddr_edac" for EDAC_MOD_STR
  Drop exporting probe and remove symbols
  v3: Fix compiling errors and warnings caused by patch ordering
  v2: Reordered patch
  Separate FSL DDR commont code as shared object, not another driver
  This patch is generated with "git format-patch -M40 -C40" to show
  copy-and-delete.

 drivers/edac/Makefile   |   5 +-
 drivers/edac/{mpc85xx_edac.c => fsl_ddr_edac.c} | 701 +---
 drivers/edac/{mpc85xx_edac.h => fsl_ddr_edac.h} | 110 +---
 drivers/edac/mpc85xx_edac.c | 559 +--
 drivers/edac/mpc85xx_edac.h |  66 ---
 5 files changed, 28 insertions(+), 1413 deletions(-)
 copy drivers/edac/{mpc85xx_edac.c => fsl_ddr_edac.c} (43%)
 copy drivers/edac/{mpc85xx_edac.h => fsl_ddr_edac.h} (43%)

diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index f9e4a3e..ee047a4 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -50,7 +50,10 @@ amd64_edac_mod-$(CONFIG_EDAC_AMD64_ERROR_INJECTION) += 
amd64_edac_inj.o
 obj-$(CONFIG_EDAC_AMD64)   += amd64_edac_mod.o
 
 obj-$(CONFIG_EDAC_PASEMI)  += pasemi_edac.o
-obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac.o
+
+mpc85xx_edac_mod-y := fsl_ddr_edac.o mpc85xx_edac.o
+obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac_mod.o
+
 obj-$(CONFIG_EDAC_MV64X60) += mv64x60_edac.o
 obj-$(CONFIG_EDAC_CELL)+= cell_edac.o
 obj-$(CONFIG_EDAC_PPC4XX)  += ppc4xx_edac.o
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/fsl_ddr_edac.c
similarity index 43%
copy from drivers/edac/mpc85xx_edac.c
copy to drivers/edac/fsl_ddr_edac.c
index c0b0951..ca7636f 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/fsl_ddr_edac.c
@@ -1,5 +1,9 @@
 /*
- * Freescale MPC85xx Memory Controller kernel module
+ * Freescale Memory Controller kernel module
+ *
+ * Support Power-based SoCs including MPC85xx, MPC86xx, MPC83xx and
+ * ARM-based Layerscape SoCs including LS2xxx. Originally split
+ * out from mpc85xx_edac EDAC driver.
  *
  * Parts Copyrighted (c) 2013 by Freescale Semiconductor, Inc.
  *
@@ -20,33 +24,20 @@
 #include 
 #include 
 #include 
-#include 
 
 #include 
 #include 
 #include "edac_module.h"
 #include "edac_core.h"
-#include "mpc85xx_edac.h"
+#include "fsl_ddr_edac.h"
+
+#define EDAC_MOD_STR   "fsl_ddr_edac"
 
-static int edac_dev_idx;
-#ifdef CONFIG_PCI
-static int edac_pci_idx;
-#endif
 static int edac_mc_idx;
 
 static u32 orig_ddr_err_disable;
 static u32 orig_ddr_err_sbe;
 
-/*
- * PCI Err defines
- */
-#ifdef CONFIG_PCI
-static u32 orig_pci_err_cap_dr;
-static u32 orig_pci_err_en;
-#endif
-
-static u32 orig_l2_err_disable;
-
 / MC SYSFS parts ***/
 
 #define to_mci(k) container_of(k, struct mem_ctl_info, dev)
@@ -141,589 +132,6 @@ static struct attribute *mpc85xx_dev_attrs[] = {
 
 ATTRIBUTE_GROUPS(mpc85xx_dev);
 
-/ PCI Err device ***/
-#ifdef CONFIG_PCI
-
-static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci)
-{
-   struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
-   u32 err_detect;
-
-   err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR);
-
-   /* master aborts can happen during PCI config cycles */
-   if (!(err_detect & ~(PCI_EDE_MULTI_ERR | PCI_EDE_MST_ABRT))) {
-   out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
-   return;
-   }
-
-   pr_err("PCI error(s) detected\n");
-   pr_err("PCI/X ERR_DR register: %#08x\n", err_detect);
-
-   pr_err("PCI/X ERR_ATTRIB register: %#08x\n",
-  in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ATTRIB));
-   pr_err("PCI/X ERR_ADDR register: %#08x\n",
-  in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR));
-   pr_err("PCI/X ERR_EXT_ADDR register: %#08x\n",
-  in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EXT_ADDR));
-   pr_err("PCI/X ERR_DL register: %#08x\n",
-  in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DL));
-   pr_err("PCI/X ERR_DH register: %#08x\n",
-  in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DH));
-
-   /* clear error bits */
-   out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect);
-
-   if (err_detect & PCI_EDE_PERR_MASK)
-   edac_pci_handle_pe(pci, pci->ctl_name);
-
-   if ((err_detect & ~PCI_EDE_MULTI_ERR) & ~PCI_EDE_PERR_MASK)
-   edac_pci_handle_npe(pci, pci->ctl_name);
-}
-
-static void mpc85xx_pcie_check(struct edac_pci_ctl_info *pci)
-{
-   struct mpc85xx_pci_pdata *pdata = pci->pvt_info;
-   

[Patch v4 5/9] driver/edac/fsl_ddr: Add DDR types

2016-08-09 Thread York Sun
The compatible DDR controllers may support DDR, DDR2, DDR3, DDR4. An
individual controller doesn't support all of them. EDAC driver reads
the controller to determine which mode is running.

Signed-off-by: York Sun 

---
Change log
  v4: Drop DSC_SDTYPE_DDR* macros, use naked numbers as suggested
  Update commit message.
  v3: no change
  v2: no change

 drivers/edac/fsl_ddr_edac.c | 24 
 drivers/edac/fsl_ddr_edac.h |  4 
 2 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c
index 2675833..46b00e1 100644
--- a/drivers/edac/fsl_ddr_edac.c
+++ b/drivers/edac/fsl_ddr_edac.c
@@ -371,30 +371,36 @@ static void fsl_ddr_init_csrows(struct mem_ctl_info *mci)
sdtype = sdram_ctl & DSC_SDTYPE_MASK;
if (sdram_ctl & DSC_RD_EN) {
switch (sdtype) {
-   case DSC_SDTYPE_DDR:
+   case 0x0200:
mtype = MEM_RDDR;
break;
-   case DSC_SDTYPE_DDR2:
+   case 0x0300:
mtype = MEM_RDDR2;
break;
-   case DSC_SDTYPE_DDR3:
+   case 0x0700:
mtype = MEM_RDDR3;
break;
+   case 0x0500:
+   mtype = MEM_RDDR4;
+   break;
default:
mtype = MEM_UNKNOWN;
break;
}
} else {
switch (sdtype) {
-   case DSC_SDTYPE_DDR:
+   case 0x0200:
mtype = MEM_DDR;
break;
-   case DSC_SDTYPE_DDR2:
+   case 0x0300:
mtype = MEM_DDR2;
break;
-   case DSC_SDTYPE_DDR3:
+   case 0x0700:
mtype = MEM_DDR3;
break;
+   case 0x0500:
+   mtype = MEM_DDR4;
+   break;
default:
mtype = MEM_UNKNOWN;
break;
@@ -499,8 +505,10 @@ int fsl_mc_err_probe(struct platform_device *op)
}
 
edac_dbg(3, "init mci\n");
-   mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_RDDR2 |
-   MEM_FLAG_DDR | MEM_FLAG_DDR2;
+   mci->mtype_cap = MEM_FLAG_DDR | MEM_FLAG_RDDR |
+MEM_FLAG_DDR2 | MEM_FLAG_RDDR2 |
+MEM_FLAG_DDR3 | MEM_FLAG_RDDR3 |
+MEM_FLAG_DDR4 | MEM_FLAG_RDDR4;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
mci->edac_cap = EDAC_FLAG_SECDED;
mci->mod_name = EDAC_MOD_STR;
diff --git a/drivers/edac/fsl_ddr_edac.h b/drivers/edac/fsl_ddr_edac.h
index 1eccc62..4ccee29 100644
--- a/drivers/edac/fsl_ddr_edac.h
+++ b/drivers/edac/fsl_ddr_edac.h
@@ -50,10 +50,6 @@
 #define DSC_DBW_64 0x
 
 #define DSC_SDTYPE_MASK0x0700
-
-#define DSC_SDTYPE_DDR 0x0200
-#define DSC_SDTYPE_DDR20x0300
-#define DSC_SDTYPE_DDR30x0700
 #define DSC_X32_EN 0x0020
 
 /* Err_Int_En */
-- 
2.7.4



[Patch v4 1/9] driver/edac/mpc85xx_edac: Drop setting/clearing RFXE bit in HID1

2016-08-09 Thread York Sun
On e500v1, read fault exception enable (RFXE) controls whether
assertion of core_fault_in causes a machine check interrupt.
Assertion of core_fault_in can result from uncorrectable data
error, such as  an L2 multi-bit ECC error. It can also occur from
a system error if logic on the integrated device signals a fault
for nonfatal errors. RFXE bit is cleared out of reset, and should
be left clear for normal operation. Assertion of core_fault_in does
not cause a machine check.

RFXE is set specifically for RIO (Rapid IO) and PCI for book E to
catch the errors by machine check. With this bit set, EDAC driver
can't get the interrupt in case of uncorrectable error. So this
bit is cleared in favor of EDAC. However, the benefit of catching
such uncorrectable error doesn't outweigh the other errors which
may hang the system. Beside, e500v2 has different errors masked
by RFXE, and e500mc doesn't support this bit. It is more reasonable
to leave RFXE as is in EDAC driver, and leave the uncorrectable
errors triggering machine check for e500v1.

Signed-off-by: York Sun 
Suggested-by: Scott Wood 

---
Change log
  v4: Fix typo in commit message
  v3: Revise commit message
  v2: new patch in this set

 drivers/edac/mpc85xx_edac.c | 40 
 1 file changed, 40 deletions(-)

diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index ca63d0d..fdc3d9b 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -46,9 +46,6 @@ static u32 orig_pci_err_en;
 #endif
 
 static u32 orig_l2_err_disable;
-#ifdef CONFIG_FSL_SOC_BOOKE
-static u32 orig_hid1[2];
-#endif
 
 / MC SYSFS parts ***/
 
@@ -1225,14 +1222,6 @@ static struct platform_driver mpc85xx_mc_err_driver = {
},
 };
 
-#ifdef CONFIG_FSL_SOC_BOOKE
-static void __init mpc85xx_mc_clear_rfxe(void *data)
-{
-   orig_hid1[smp_processor_id()] = mfspr(SPRN_HID1);
-   mtspr(SPRN_HID1, (orig_hid1[smp_processor_id()] & ~HID1_RFXE));
-}
-#endif
-
 static struct platform_driver * const drivers[] = {
_mc_err_driver,
_l2_err_driver,
@@ -1263,42 +1252,13 @@ static int __init mpc85xx_mc_init(void)
if (res)
printk(KERN_WARNING EDAC_MOD_STR "drivers fail to register\n");
 
-#ifdef CONFIG_FSL_SOC_BOOKE
-   pvr = mfspr(SPRN_PVR);
-
-   if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
-   (PVR_VER(pvr) == PVR_VER_E500V2)) {
-   /*
-* need to clear HID1[RFXE] to disable machine check int
-* so we can catch it
-*/
-   if (edac_op_state == EDAC_OPSTATE_INT)
-   on_each_cpu(mpc85xx_mc_clear_rfxe, NULL, 0);
-   }
-#endif
-
return 0;
 }
 
 module_init(mpc85xx_mc_init);
 
-#ifdef CONFIG_FSL_SOC_BOOKE
-static void __exit mpc85xx_mc_restore_hid1(void *data)
-{
-   mtspr(SPRN_HID1, orig_hid1[smp_processor_id()]);
-}
-#endif
-
 static void __exit mpc85xx_mc_exit(void)
 {
-#ifdef CONFIG_FSL_SOC_BOOKE
-   u32 pvr = mfspr(SPRN_PVR);
-
-   if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
-   (PVR_VER(pvr) == PVR_VER_E500V2)) {
-   on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
-   }
-#endif
platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
 }
 
-- 
2.7.4



[Patch v4 4/9] driver/edac/fsl_ddr: Rename macros and names

2016-08-09 Thread York Sun
Use generic names for macros, variables and functions.

Signed-off-by: York Sun 

---
Change log
  v4: Replace MPC85XX_MC_* with FSL_MC_*
  v3: Absort changes from reording patches
  v2: Separated from "House cleaning" patch of v1

 drivers/edac/fsl_ddr_edac.c | 166 ++--
 drivers/edac/fsl_ddr_edac.h |  43 ++--
 drivers/edac/mpc85xx_edac.c |   4 +-
 3 files changed, 105 insertions(+), 108 deletions(-)

diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c
index ca7636f..2675833 100644
--- a/drivers/edac/fsl_ddr_edac.c
+++ b/drivers/edac/fsl_ddr_edac.c
@@ -42,74 +42,74 @@ static u32 orig_ddr_err_sbe;
 
 #define to_mci(k) container_of(k, struct mem_ctl_info, dev)
 
-static ssize_t mpc85xx_mc_inject_data_hi_show(struct device *dev,
- struct device_attribute *mattr,
- char *data)
+static ssize_t fsl_mc_inject_data_hi_show(struct device *dev,
+ struct device_attribute *mattr,
+ char *data)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
+   struct fsl_mc_pdata *pdata = mci->pvt_info;
return sprintf(data, "0x%08x",
   in_be32(pdata->mc_vbase +
-  MPC85XX_MC_DATA_ERR_INJECT_HI));
+  FSL_MC_DATA_ERR_INJECT_HI));
 }
 
-static ssize_t mpc85xx_mc_inject_data_lo_show(struct device *dev,
- struct device_attribute *mattr,
+static ssize_t fsl_mc_inject_data_lo_show(struct device *dev,
+ struct device_attribute *mattr,
  char *data)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
+   struct fsl_mc_pdata *pdata = mci->pvt_info;
return sprintf(data, "0x%08x",
   in_be32(pdata->mc_vbase +
-  MPC85XX_MC_DATA_ERR_INJECT_LO));
+  FSL_MC_DATA_ERR_INJECT_LO));
 }
 
-static ssize_t mpc85xx_mc_inject_ctrl_show(struct device *dev,
-  struct device_attribute *mattr,
+static ssize_t fsl_mc_inject_ctrl_show(struct device *dev,
+  struct device_attribute *mattr,
   char *data)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
+   struct fsl_mc_pdata *pdata = mci->pvt_info;
return sprintf(data, "0x%08x",
-  in_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT));
+  in_be32(pdata->mc_vbase + FSL_MC_ECC_ERR_INJECT));
 }
 
-static ssize_t mpc85xx_mc_inject_data_hi_store(struct device *dev,
-  struct device_attribute *mattr,
+static ssize_t fsl_mc_inject_data_hi_store(struct device *dev,
+  struct device_attribute *mattr,
   const char *data, size_t count)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
+   struct fsl_mc_pdata *pdata = mci->pvt_info;
if (isdigit(*data)) {
-   out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_HI,
+   out_be32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_HI,
 simple_strtoul(data, NULL, 0));
return count;
}
return 0;
 }
 
-static ssize_t mpc85xx_mc_inject_data_lo_store(struct device *dev,
-  struct device_attribute *mattr,
+static ssize_t fsl_mc_inject_data_lo_store(struct device *dev,
+  struct device_attribute *mattr,
   const char *data, size_t count)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
+   struct fsl_mc_pdata *pdata = mci->pvt_info;
if (isdigit(*data)) {
-   out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_LO,
+   out_be32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_LO,
 simple_strtoul(data, NULL, 0));
return count;
}
return 0;
 }
 
-static ssize_t mpc85xx_mc_inject_ctrl_store(struct device *dev,
-  struct device_attribute *mattr,
+static ssize_t fsl_mc_inject_ctrl_store(struct device *dev,
+   struct device_attribute *mattr,
   const char *data, size_t count)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata 

[Patch v4 2/9] driver/edac/mpc85xx_edac: Replace printk with proper pr_* format

2016-08-09 Thread York Sun
Replace printk with more preferred pr_err/pr_warn/pr_info format.

Signed-off-by: York Sun 

---
Change log
  v4: no change
  v3: no change
  v2: Reordered patch. Change more printk statement than v1 patch.

 drivers/edac/mpc85xx_edac.c | 72 ++---
 1 file changed, 35 insertions(+), 37 deletions(-)

diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index fdc3d9b..c0b0951 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -157,18 +157,18 @@ static void mpc85xx_pci_check(struct edac_pci_ctl_info 
*pci)
return;
}
 
-   printk(KERN_ERR "PCI error(s) detected\n");
-   printk(KERN_ERR "PCI/X ERR_DR register: %#08x\n", err_detect);
+   pr_err("PCI error(s) detected\n");
+   pr_err("PCI/X ERR_DR register: %#08x\n", err_detect);
 
-   printk(KERN_ERR "PCI/X ERR_ATTRIB register: %#08x\n",
+   pr_err("PCI/X ERR_ATTRIB register: %#08x\n",
   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ATTRIB));
-   printk(KERN_ERR "PCI/X ERR_ADDR register: %#08x\n",
+   pr_err("PCI/X ERR_ADDR register: %#08x\n",
   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR));
-   printk(KERN_ERR "PCI/X ERR_EXT_ADDR register: %#08x\n",
+   pr_err("PCI/X ERR_EXT_ADDR register: %#08x\n",
   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EXT_ADDR));
-   printk(KERN_ERR "PCI/X ERR_DL register: %#08x\n",
+   pr_err("PCI/X ERR_DL register: %#08x\n",
   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DL));
-   printk(KERN_ERR "PCI/X ERR_DH register: %#08x\n",
+   pr_err("PCI/X ERR_DH register: %#08x\n",
   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DH));
 
/* clear error bits */
@@ -294,7 +294,7 @@ static int mpc85xx_pci_err_probe(struct platform_device *op)
 
res = of_address_to_resource(of_node, 0, );
if (res) {
-   printk(KERN_ERR "%s: Unable to get resource for "
+   pr_err("%s: Unable to get resource for "
   "PCI err regs\n", __func__);
goto err;
}
@@ -304,7 +304,7 @@ static int mpc85xx_pci_err_probe(struct platform_device *op)
 
if (!devm_request_mem_region(>dev, r.start, resource_size(),
pdata->name)) {
-   printk(KERN_ERR "%s: Error while requesting mem region\n",
+   pr_err("%s: Error while requesting mem region\n",
   __func__);
res = -EBUSY;
goto err;
@@ -312,7 +312,7 @@ static int mpc85xx_pci_err_probe(struct platform_device *op)
 
pdata->pci_vbase = devm_ioremap(>dev, r.start, resource_size());
if (!pdata->pci_vbase) {
-   printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
+   pr_err("%s: Unable to setup PCI err regs\n", __func__);
res = -ENOMEM;
goto err;
}
@@ -353,15 +353,14 @@ static int mpc85xx_pci_err_probe(struct platform_device 
*op)
   IRQF_SHARED,
   "[EDAC] PCI err", pci);
if (res < 0) {
-   printk(KERN_ERR
-  "%s: Unable to request irq %d for "
+   pr_err("%s: Unable to request irq %d for "
   "MPC85xx PCI err\n", __func__, pdata->irq);
irq_dispose_mapping(pdata->irq);
res = -ENODEV;
goto err2;
}
 
-   printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for PCI Err\n",
+   pr_info(EDAC_MOD_STR " acquired irq %d for PCI Err\n",
   pdata->irq);
}
 
@@ -383,7 +382,7 @@ static int mpc85xx_pci_err_probe(struct platform_device *op)
 
devres_remove_group(>dev, mpc85xx_pci_err_probe);
edac_dbg(3, "success\n");
-   printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n");
+   pr_info(EDAC_MOD_STR " PCI err registered\n");
 
return 0;
 
@@ -526,17 +525,17 @@ static void mpc85xx_l2_check(struct edac_device_ctl_info 
*edac_dev)
if (!(err_detect & L2_EDE_MASK))
return;
 
-   printk(KERN_ERR "ECC Error in CPU L2 cache\n");
-   printk(KERN_ERR "L2 Error Detect Register: 0x%08x\n", err_detect);
-   printk(KERN_ERR "L2 Error Capture Data High Register: 0x%08x\n",
+   pr_err("ECC Error in CPU L2 cache\n");
+   pr_err("L2 Error Detect Register: 0x%08x\n", err_detect);
+   pr_err("L2 Error Capture Data High Register: 0x%08x\n",
   in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATAHI));
-   printk(KERN_ERR "L2 Error Capture Data Lo Register: 0x%08x\n",
+   pr_err("L2 Error Capture Data Lo Register: 0x%08x\n",
   in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATALO));
-   printk(KERN_ERR "L2 Error 

[Patch v4 5/9] driver/edac/fsl_ddr: Add DDR types

2016-08-09 Thread York Sun
The compatible DDR controllers may support DDR, DDR2, DDR3, DDR4. An
individual controller doesn't support all of them. EDAC driver reads
the controller to determine which mode is running.

Signed-off-by: York Sun 

---
Change log
  v4: Drop DSC_SDTYPE_DDR* macros, use naked numbers as suggested
  Update commit message.
  v3: no change
  v2: no change

 drivers/edac/fsl_ddr_edac.c | 24 
 drivers/edac/fsl_ddr_edac.h |  4 
 2 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c
index 2675833..46b00e1 100644
--- a/drivers/edac/fsl_ddr_edac.c
+++ b/drivers/edac/fsl_ddr_edac.c
@@ -371,30 +371,36 @@ static void fsl_ddr_init_csrows(struct mem_ctl_info *mci)
sdtype = sdram_ctl & DSC_SDTYPE_MASK;
if (sdram_ctl & DSC_RD_EN) {
switch (sdtype) {
-   case DSC_SDTYPE_DDR:
+   case 0x0200:
mtype = MEM_RDDR;
break;
-   case DSC_SDTYPE_DDR2:
+   case 0x0300:
mtype = MEM_RDDR2;
break;
-   case DSC_SDTYPE_DDR3:
+   case 0x0700:
mtype = MEM_RDDR3;
break;
+   case 0x0500:
+   mtype = MEM_RDDR4;
+   break;
default:
mtype = MEM_UNKNOWN;
break;
}
} else {
switch (sdtype) {
-   case DSC_SDTYPE_DDR:
+   case 0x0200:
mtype = MEM_DDR;
break;
-   case DSC_SDTYPE_DDR2:
+   case 0x0300:
mtype = MEM_DDR2;
break;
-   case DSC_SDTYPE_DDR3:
+   case 0x0700:
mtype = MEM_DDR3;
break;
+   case 0x0500:
+   mtype = MEM_DDR4;
+   break;
default:
mtype = MEM_UNKNOWN;
break;
@@ -499,8 +505,10 @@ int fsl_mc_err_probe(struct platform_device *op)
}
 
edac_dbg(3, "init mci\n");
-   mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_RDDR2 |
-   MEM_FLAG_DDR | MEM_FLAG_DDR2;
+   mci->mtype_cap = MEM_FLAG_DDR | MEM_FLAG_RDDR |
+MEM_FLAG_DDR2 | MEM_FLAG_RDDR2 |
+MEM_FLAG_DDR3 | MEM_FLAG_RDDR3 |
+MEM_FLAG_DDR4 | MEM_FLAG_RDDR4;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
mci->edac_cap = EDAC_FLAG_SECDED;
mci->mod_name = EDAC_MOD_STR;
diff --git a/drivers/edac/fsl_ddr_edac.h b/drivers/edac/fsl_ddr_edac.h
index 1eccc62..4ccee29 100644
--- a/drivers/edac/fsl_ddr_edac.h
+++ b/drivers/edac/fsl_ddr_edac.h
@@ -50,10 +50,6 @@
 #define DSC_DBW_64 0x
 
 #define DSC_SDTYPE_MASK0x0700
-
-#define DSC_SDTYPE_DDR 0x0200
-#define DSC_SDTYPE_DDR20x0300
-#define DSC_SDTYPE_DDR30x0700
 #define DSC_X32_EN 0x0020
 
 /* Err_Int_En */
-- 
2.7.4



[Patch v4 1/9] driver/edac/mpc85xx_edac: Drop setting/clearing RFXE bit in HID1

2016-08-09 Thread York Sun
On e500v1, read fault exception enable (RFXE) controls whether
assertion of core_fault_in causes a machine check interrupt.
Assertion of core_fault_in can result from uncorrectable data
error, such as  an L2 multi-bit ECC error. It can also occur from
a system error if logic on the integrated device signals a fault
for nonfatal errors. RFXE bit is cleared out of reset, and should
be left clear for normal operation. Assertion of core_fault_in does
not cause a machine check.

RFXE is set specifically for RIO (Rapid IO) and PCI for book E to
catch the errors by machine check. With this bit set, EDAC driver
can't get the interrupt in case of uncorrectable error. So this
bit is cleared in favor of EDAC. However, the benefit of catching
such uncorrectable error doesn't outweigh the other errors which
may hang the system. Beside, e500v2 has different errors masked
by RFXE, and e500mc doesn't support this bit. It is more reasonable
to leave RFXE as is in EDAC driver, and leave the uncorrectable
errors triggering machine check for e500v1.

Signed-off-by: York Sun 
Suggested-by: Scott Wood 

---
Change log
  v4: Fix typo in commit message
  v3: Revise commit message
  v2: new patch in this set

 drivers/edac/mpc85xx_edac.c | 40 
 1 file changed, 40 deletions(-)

diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index ca63d0d..fdc3d9b 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -46,9 +46,6 @@ static u32 orig_pci_err_en;
 #endif
 
 static u32 orig_l2_err_disable;
-#ifdef CONFIG_FSL_SOC_BOOKE
-static u32 orig_hid1[2];
-#endif
 
 / MC SYSFS parts ***/
 
@@ -1225,14 +1222,6 @@ static struct platform_driver mpc85xx_mc_err_driver = {
},
 };
 
-#ifdef CONFIG_FSL_SOC_BOOKE
-static void __init mpc85xx_mc_clear_rfxe(void *data)
-{
-   orig_hid1[smp_processor_id()] = mfspr(SPRN_HID1);
-   mtspr(SPRN_HID1, (orig_hid1[smp_processor_id()] & ~HID1_RFXE));
-}
-#endif
-
 static struct platform_driver * const drivers[] = {
_mc_err_driver,
_l2_err_driver,
@@ -1263,42 +1252,13 @@ static int __init mpc85xx_mc_init(void)
if (res)
printk(KERN_WARNING EDAC_MOD_STR "drivers fail to register\n");
 
-#ifdef CONFIG_FSL_SOC_BOOKE
-   pvr = mfspr(SPRN_PVR);
-
-   if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
-   (PVR_VER(pvr) == PVR_VER_E500V2)) {
-   /*
-* need to clear HID1[RFXE] to disable machine check int
-* so we can catch it
-*/
-   if (edac_op_state == EDAC_OPSTATE_INT)
-   on_each_cpu(mpc85xx_mc_clear_rfxe, NULL, 0);
-   }
-#endif
-
return 0;
 }
 
 module_init(mpc85xx_mc_init);
 
-#ifdef CONFIG_FSL_SOC_BOOKE
-static void __exit mpc85xx_mc_restore_hid1(void *data)
-{
-   mtspr(SPRN_HID1, orig_hid1[smp_processor_id()]);
-}
-#endif
-
 static void __exit mpc85xx_mc_exit(void)
 {
-#ifdef CONFIG_FSL_SOC_BOOKE
-   u32 pvr = mfspr(SPRN_PVR);
-
-   if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
-   (PVR_VER(pvr) == PVR_VER_E500V2)) {
-   on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
-   }
-#endif
platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
 }
 
-- 
2.7.4



[Patch v4 4/9] driver/edac/fsl_ddr: Rename macros and names

2016-08-09 Thread York Sun
Use generic names for macros, variables and functions.

Signed-off-by: York Sun 

---
Change log
  v4: Replace MPC85XX_MC_* with FSL_MC_*
  v3: Absort changes from reording patches
  v2: Separated from "House cleaning" patch of v1

 drivers/edac/fsl_ddr_edac.c | 166 ++--
 drivers/edac/fsl_ddr_edac.h |  43 ++--
 drivers/edac/mpc85xx_edac.c |   4 +-
 3 files changed, 105 insertions(+), 108 deletions(-)

diff --git a/drivers/edac/fsl_ddr_edac.c b/drivers/edac/fsl_ddr_edac.c
index ca7636f..2675833 100644
--- a/drivers/edac/fsl_ddr_edac.c
+++ b/drivers/edac/fsl_ddr_edac.c
@@ -42,74 +42,74 @@ static u32 orig_ddr_err_sbe;
 
 #define to_mci(k) container_of(k, struct mem_ctl_info, dev)
 
-static ssize_t mpc85xx_mc_inject_data_hi_show(struct device *dev,
- struct device_attribute *mattr,
- char *data)
+static ssize_t fsl_mc_inject_data_hi_show(struct device *dev,
+ struct device_attribute *mattr,
+ char *data)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
+   struct fsl_mc_pdata *pdata = mci->pvt_info;
return sprintf(data, "0x%08x",
   in_be32(pdata->mc_vbase +
-  MPC85XX_MC_DATA_ERR_INJECT_HI));
+  FSL_MC_DATA_ERR_INJECT_HI));
 }
 
-static ssize_t mpc85xx_mc_inject_data_lo_show(struct device *dev,
- struct device_attribute *mattr,
+static ssize_t fsl_mc_inject_data_lo_show(struct device *dev,
+ struct device_attribute *mattr,
  char *data)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
+   struct fsl_mc_pdata *pdata = mci->pvt_info;
return sprintf(data, "0x%08x",
   in_be32(pdata->mc_vbase +
-  MPC85XX_MC_DATA_ERR_INJECT_LO));
+  FSL_MC_DATA_ERR_INJECT_LO));
 }
 
-static ssize_t mpc85xx_mc_inject_ctrl_show(struct device *dev,
-  struct device_attribute *mattr,
+static ssize_t fsl_mc_inject_ctrl_show(struct device *dev,
+  struct device_attribute *mattr,
   char *data)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
+   struct fsl_mc_pdata *pdata = mci->pvt_info;
return sprintf(data, "0x%08x",
-  in_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT));
+  in_be32(pdata->mc_vbase + FSL_MC_ECC_ERR_INJECT));
 }
 
-static ssize_t mpc85xx_mc_inject_data_hi_store(struct device *dev,
-  struct device_attribute *mattr,
+static ssize_t fsl_mc_inject_data_hi_store(struct device *dev,
+  struct device_attribute *mattr,
   const char *data, size_t count)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
+   struct fsl_mc_pdata *pdata = mci->pvt_info;
if (isdigit(*data)) {
-   out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_HI,
+   out_be32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_HI,
 simple_strtoul(data, NULL, 0));
return count;
}
return 0;
 }
 
-static ssize_t mpc85xx_mc_inject_data_lo_store(struct device *dev,
-  struct device_attribute *mattr,
+static ssize_t fsl_mc_inject_data_lo_store(struct device *dev,
+  struct device_attribute *mattr,
   const char *data, size_t count)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata *pdata = mci->pvt_info;
+   struct fsl_mc_pdata *pdata = mci->pvt_info;
if (isdigit(*data)) {
-   out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_LO,
+   out_be32(pdata->mc_vbase + FSL_MC_DATA_ERR_INJECT_LO,
 simple_strtoul(data, NULL, 0));
return count;
}
return 0;
 }
 
-static ssize_t mpc85xx_mc_inject_ctrl_store(struct device *dev,
-  struct device_attribute *mattr,
+static ssize_t fsl_mc_inject_ctrl_store(struct device *dev,
+   struct device_attribute *mattr,
   const char *data, size_t count)
 {
struct mem_ctl_info *mci = to_mci(dev);
-   struct mpc85xx_mc_pdata *pdata = 

[Patch v4 2/9] driver/edac/mpc85xx_edac: Replace printk with proper pr_* format

2016-08-09 Thread York Sun
Replace printk with more preferred pr_err/pr_warn/pr_info format.

Signed-off-by: York Sun 

---
Change log
  v4: no change
  v3: no change
  v2: Reordered patch. Change more printk statement than v1 patch.

 drivers/edac/mpc85xx_edac.c | 72 ++---
 1 file changed, 35 insertions(+), 37 deletions(-)

diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index fdc3d9b..c0b0951 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -157,18 +157,18 @@ static void mpc85xx_pci_check(struct edac_pci_ctl_info 
*pci)
return;
}
 
-   printk(KERN_ERR "PCI error(s) detected\n");
-   printk(KERN_ERR "PCI/X ERR_DR register: %#08x\n", err_detect);
+   pr_err("PCI error(s) detected\n");
+   pr_err("PCI/X ERR_DR register: %#08x\n", err_detect);
 
-   printk(KERN_ERR "PCI/X ERR_ATTRIB register: %#08x\n",
+   pr_err("PCI/X ERR_ATTRIB register: %#08x\n",
   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ATTRIB));
-   printk(KERN_ERR "PCI/X ERR_ADDR register: %#08x\n",
+   pr_err("PCI/X ERR_ADDR register: %#08x\n",
   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR));
-   printk(KERN_ERR "PCI/X ERR_EXT_ADDR register: %#08x\n",
+   pr_err("PCI/X ERR_EXT_ADDR register: %#08x\n",
   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EXT_ADDR));
-   printk(KERN_ERR "PCI/X ERR_DL register: %#08x\n",
+   pr_err("PCI/X ERR_DL register: %#08x\n",
   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DL));
-   printk(KERN_ERR "PCI/X ERR_DH register: %#08x\n",
+   pr_err("PCI/X ERR_DH register: %#08x\n",
   in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DH));
 
/* clear error bits */
@@ -294,7 +294,7 @@ static int mpc85xx_pci_err_probe(struct platform_device *op)
 
res = of_address_to_resource(of_node, 0, );
if (res) {
-   printk(KERN_ERR "%s: Unable to get resource for "
+   pr_err("%s: Unable to get resource for "
   "PCI err regs\n", __func__);
goto err;
}
@@ -304,7 +304,7 @@ static int mpc85xx_pci_err_probe(struct platform_device *op)
 
if (!devm_request_mem_region(>dev, r.start, resource_size(),
pdata->name)) {
-   printk(KERN_ERR "%s: Error while requesting mem region\n",
+   pr_err("%s: Error while requesting mem region\n",
   __func__);
res = -EBUSY;
goto err;
@@ -312,7 +312,7 @@ static int mpc85xx_pci_err_probe(struct platform_device *op)
 
pdata->pci_vbase = devm_ioremap(>dev, r.start, resource_size());
if (!pdata->pci_vbase) {
-   printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__);
+   pr_err("%s: Unable to setup PCI err regs\n", __func__);
res = -ENOMEM;
goto err;
}
@@ -353,15 +353,14 @@ static int mpc85xx_pci_err_probe(struct platform_device 
*op)
   IRQF_SHARED,
   "[EDAC] PCI err", pci);
if (res < 0) {
-   printk(KERN_ERR
-  "%s: Unable to request irq %d for "
+   pr_err("%s: Unable to request irq %d for "
   "MPC85xx PCI err\n", __func__, pdata->irq);
irq_dispose_mapping(pdata->irq);
res = -ENODEV;
goto err2;
}
 
-   printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for PCI Err\n",
+   pr_info(EDAC_MOD_STR " acquired irq %d for PCI Err\n",
   pdata->irq);
}
 
@@ -383,7 +382,7 @@ static int mpc85xx_pci_err_probe(struct platform_device *op)
 
devres_remove_group(>dev, mpc85xx_pci_err_probe);
edac_dbg(3, "success\n");
-   printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n");
+   pr_info(EDAC_MOD_STR " PCI err registered\n");
 
return 0;
 
@@ -526,17 +525,17 @@ static void mpc85xx_l2_check(struct edac_device_ctl_info 
*edac_dev)
if (!(err_detect & L2_EDE_MASK))
return;
 
-   printk(KERN_ERR "ECC Error in CPU L2 cache\n");
-   printk(KERN_ERR "L2 Error Detect Register: 0x%08x\n", err_detect);
-   printk(KERN_ERR "L2 Error Capture Data High Register: 0x%08x\n",
+   pr_err("ECC Error in CPU L2 cache\n");
+   pr_err("L2 Error Detect Register: 0x%08x\n", err_detect);
+   pr_err("L2 Error Capture Data High Register: 0x%08x\n",
   in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATAHI));
-   printk(KERN_ERR "L2 Error Capture Data Lo Register: 0x%08x\n",
+   pr_err("L2 Error Capture Data Lo Register: 0x%08x\n",
   in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATALO));
-   printk(KERN_ERR "L2 Error Syndrome Register: 

Re: Kernel modules under new copyleft licence : (was Re: [PATCH v2] module.h: add copyleft-next >= 0.3.1 as GPL compatible)

2016-08-09 Thread Richard Fontana
On Tue, Aug 09, 2016 at 09:04:35PM +0100, Alan Cox wrote:
> Outside of the "derivative work" GPL clause they don't quite look
> compatible to me as a non-lawyer (eg the definition of "source code"
> looks to differ on scripts etc). 

The clause that permits derived works to be licensed under the GPL is
all that's needed for GPL compatibility (in the sense that combined
works of GPL-licensed and copyleft-next-licensed code can be licensed
under the GPL without imposition of any additional restrictions on
downstream recipients).

Richard


Re: Kernel modules under new copyleft licence : (was Re: [PATCH v2] module.h: add copyleft-next >= 0.3.1 as GPL compatible)

2016-08-09 Thread Richard Fontana
On Tue, Aug 09, 2016 at 09:04:35PM +0100, Alan Cox wrote:
> Outside of the "derivative work" GPL clause they don't quite look
> compatible to me as a non-lawyer (eg the definition of "source code"
> looks to differ on scripts etc). 

The clause that permits derived works to be licensed under the GPL is
all that's needed for GPL compatibility (in the sense that combined
works of GPL-licensed and copyleft-next-licensed code can be licensed
under the GPL without imposition of any additional restrictions on
downstream recipients).

Richard


Re: [RFCv2][PATCH 2/5] arm: Implement ARCH_HAS_FORCE_CACHE

2016-08-09 Thread Florian Fainelli
On 08/08/2016 10:49 AM, Laura Abbott wrote:
> arm may need the kernel_force_cache APIs to guarantee data consistency.
> Implement versions of these APIs based on the DMA APIs.
> 
> Signed-off-by: Laura Abbott 
> ---
>  arch/arm/include/asm/cacheflush.h |   4 ++
>  arch/arm/mm/dma-mapping.c | 119 
> --
>  arch/arm/mm/flush.c   | 115 

Why is the code moved between dma-mapping.c and flush.c? It was not
obvious while looking at these patches why this is needed.
-- 
Florian


Re: [RFCv2][PATCH 2/5] arm: Implement ARCH_HAS_FORCE_CACHE

2016-08-09 Thread Florian Fainelli
On 08/08/2016 10:49 AM, Laura Abbott wrote:
> arm may need the kernel_force_cache APIs to guarantee data consistency.
> Implement versions of these APIs based on the DMA APIs.
> 
> Signed-off-by: Laura Abbott 
> ---
>  arch/arm/include/asm/cacheflush.h |   4 ++
>  arch/arm/mm/dma-mapping.c | 119 
> --
>  arch/arm/mm/flush.c   | 115 

Why is the code moved between dma-mapping.c and flush.c? It was not
obvious while looking at these patches why this is needed.
-- 
Florian


Re: [RFC PATCH v5 2/3] Documentation: DT: net: Add Xilinx gmiitorgmii converter device tree binding documentation

2016-08-09 Thread Florian Fainelli
On 08/09/2016 02:34 AM, Kedareswara rao Appana wrote:
> Device-tree binding documentation for xilinx gmiitorgmii converter.
> 
> Signed-off-by: Kedareswara rao Appana 
> ---
> Changes for v5:
> ---> Fixed Indentation in the example as suggested by Michal.
> Changes for v4:
> --> Modified compatible as suggested by Rob.
> --> Removed underscores from the converter node name as suggested by Rob.
> Changes for v3:
> --> None.
> Changes for v2:
> --> New patch.
> 
>  .../devicetree/bindings/net/xilinx_gmii2rgmii.txt  | 38 
> ++
>  1 file changed, 38 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/net/xilinx_gmii2rgmii.txt
> 
> diff --git a/Documentation/devicetree/bindings/net/xilinx_gmii2rgmii.txt 
> b/Documentation/devicetree/bindings/net/xilinx_gmii2rgmii.txt
> new file mode 100644
> index 000..5f48793
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/xilinx_gmii2rgmii.txt
> @@ -0,0 +1,38 @@
> +XILINX GMIITORGMII Converter Driver Device Tree Bindings
> +
> +
> +The Gigabit Media Independent Interface (GMII) to Reduced Gigabit Media
> +Independent Interface (RGMII) core provides the RGMII between RGMII-compliant
> +Ethernet physical media devices (PHY) and the Gigabit Ethernet controller.
> +This core can be used in all three modes of operation(10/100/1000 Mb/s).
> +The Management Data Input/Output (MDIO) interface is used to configure the
> +Speed of operation. This core can switch dynamically between the three
> +Different speed modes by configuring the conveter register through mdio 
> write.
> +
> +The MDIO is a bus to which the PHY devices are connected.  For each
> +device that exists on this bus, a child node should be created.  See
> +the definition of the PHY node in booting-without-of.txt for an example
> +of how to define a PHY.

I would skip this paragraph which does not really help with
understanding, and just refer to
Documentation/devicetree/bindings/net/phy.txt for examples.


> +
> +This converter sits between the ethernet MAC and the external phy.
> +MAC <==> GMII2RGMII <==> RGMII_PHY
> +
> +Required properties:
> +- compatible : Should be "xlnx,gmii-to-rgmii-1.0"
> +- reg: The ID number for the phy, usually a small integer

You would want specify that "reg" property needs to match the one of the
PHY (specified via phy-handle) you are converting to/from for this
"proxy" piece of hardware to work.

If these two have the same "reg" value, is not that going to lead to
duplicate MDIO devices created on the bus, this may work, based on
probing ordering, but seems unusual, you don't really need the "reg"
property here it seems?

> +- phy-handle : Should point to the external phy device.
> +   See ethernet.txt file in the same directory.
> +
> +Example:
> + mdio {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + phy: ethernet-phy@0 {
> + ..
> + };
> + gmiitorgmii: gmiitorgmii@8 {
> + compatible = "xlnx,gmii-to-rgmii-1.0";
> + reg = <8>;
> + phy-handle = <>;
> + };
> + };
> 


-- 
Florian


Re: [RFC PATCH v5 2/3] Documentation: DT: net: Add Xilinx gmiitorgmii converter device tree binding documentation

2016-08-09 Thread Florian Fainelli
On 08/09/2016 02:34 AM, Kedareswara rao Appana wrote:
> Device-tree binding documentation for xilinx gmiitorgmii converter.
> 
> Signed-off-by: Kedareswara rao Appana 
> ---
> Changes for v5:
> ---> Fixed Indentation in the example as suggested by Michal.
> Changes for v4:
> --> Modified compatible as suggested by Rob.
> --> Removed underscores from the converter node name as suggested by Rob.
> Changes for v3:
> --> None.
> Changes for v2:
> --> New patch.
> 
>  .../devicetree/bindings/net/xilinx_gmii2rgmii.txt  | 38 
> ++
>  1 file changed, 38 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/net/xilinx_gmii2rgmii.txt
> 
> diff --git a/Documentation/devicetree/bindings/net/xilinx_gmii2rgmii.txt 
> b/Documentation/devicetree/bindings/net/xilinx_gmii2rgmii.txt
> new file mode 100644
> index 000..5f48793
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/xilinx_gmii2rgmii.txt
> @@ -0,0 +1,38 @@
> +XILINX GMIITORGMII Converter Driver Device Tree Bindings
> +
> +
> +The Gigabit Media Independent Interface (GMII) to Reduced Gigabit Media
> +Independent Interface (RGMII) core provides the RGMII between RGMII-compliant
> +Ethernet physical media devices (PHY) and the Gigabit Ethernet controller.
> +This core can be used in all three modes of operation(10/100/1000 Mb/s).
> +The Management Data Input/Output (MDIO) interface is used to configure the
> +Speed of operation. This core can switch dynamically between the three
> +Different speed modes by configuring the conveter register through mdio 
> write.
> +
> +The MDIO is a bus to which the PHY devices are connected.  For each
> +device that exists on this bus, a child node should be created.  See
> +the definition of the PHY node in booting-without-of.txt for an example
> +of how to define a PHY.

I would skip this paragraph which does not really help with
understanding, and just refer to
Documentation/devicetree/bindings/net/phy.txt for examples.


> +
> +This converter sits between the ethernet MAC and the external phy.
> +MAC <==> GMII2RGMII <==> RGMII_PHY
> +
> +Required properties:
> +- compatible : Should be "xlnx,gmii-to-rgmii-1.0"
> +- reg: The ID number for the phy, usually a small integer

You would want specify that "reg" property needs to match the one of the
PHY (specified via phy-handle) you are converting to/from for this
"proxy" piece of hardware to work.

If these two have the same "reg" value, is not that going to lead to
duplicate MDIO devices created on the bus, this may work, based on
probing ordering, but seems unusual, you don't really need the "reg"
property here it seems?

> +- phy-handle : Should point to the external phy device.
> +   See ethernet.txt file in the same directory.
> +
> +Example:
> + mdio {
> + #address-cells = <1>;
> + #size-cells = <0>;
> + phy: ethernet-phy@0 {
> + ..
> + };
> + gmiitorgmii: gmiitorgmii@8 {
> + compatible = "xlnx,gmii-to-rgmii-1.0";
> + reg = <8>;
> + phy-handle = <>;
> + };
> + };
> 


-- 
Florian


[PATCH 10/12] [media] dvb_frontend: move kref to struct dvb_frontend

2016-08-09 Thread Max Kellermann
This commit amends my old commit fe35637b0a9f ("[media] dvb_frontend:
eliminate blocking wait in dvb_unregister_frontend()"), which added
kref to struct dvb_frontend_private.  It turned out that there are
several use-after-free bugs left, which affect the struct
dvb_frontend.  Protecting it with kref also protects struct
dvb_frontend_private, so we can simply move it.

This is how the use-after-free looks like in KASAN:

BUG: KASAN: use-after-free in string+0x60/0xb1 at addr 880033bd9fc0
Read of size 1 by task kworker/0:2/617
CPU: 0 PID: 617 Comm: kworker/0:2 Not tainted 4.8.0-rc1-hosting+ #60
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
Workqueue: usb_hub_wq hub_event
  880033757218 81394e50 880033bd9fd0
 880035c03b00 880033757240 811f271d 880033bd9fc0
 11000677b3f8 ed000677b3f8 8800337572b8 811f2afe
Call Trace:
 [...]
 [] vsnprintf+0x39d/0x7e9
 [] add_uevent_var+0x10f/0x1dc
 [] rc_dev_uevent+0x55/0x6f
 [] dev_uevent+0x2e1/0x316
 [] kobject_uevent_env+0x27e/0x701
 [] kobject_uevent+0xb/0xd
 [] device_del+0x322/0x383
 [] rc_unregister_device+0x98/0xc3
 [] dvb_usb_remote_exit+0x7a/0x90
 [] dvb_usb_exit+0x1d/0xe5
 [] dvb_usb_device_exit+0x69/0x7d
 [] pctv452e_usb_disconnect+0x7b/0x80
 [...]
Object at 880033bd9fc0, in cache kmalloc-16 size: 16
Allocated:
 [...]
Freed:
PID = 617
 [...]
 [] kfree+0xd9/0x166
 [] ir_free_table+0x2f/0x51
 [] rc_unregister_device+0x4d/0xc3
 [] dvb_usb_remote_exit+0x7a/0x90
 [] dvb_usb_exit+0x1d/0xe5
 [] dvb_usb_device_exit+0x69/0x7d
 [] pctv452e_usb_disconnect+0x7b/0x80

Another one:

BUG: KASAN: use-after-free in do_sys_poll+0x336/0x6b8 at addr 
88003563fcc0
Read of size 8 by task tuner on fronte/1042
CPU: 1 PID: 1042 Comm: tuner on fronte Tainted: GB   
4.8.0-rc1-hosting+ #60
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
  88003353f910 81394e50 88003563fd80
 880035c03200 88003353f938 811f271d 88003563fc80
 110006ac7f98 ed0006ac7f98 88003353f9b0 811f2afe
Call Trace:
 [...]
 [] do_sys_poll+0x336/0x6b8
 [...]
 [] SyS_poll+0xa9/0x194
 [...]
Object at 88003563fc80, in cache kmalloc-256 size: 256
Allocated:
 [...]
Freed:
PID = 617
 [...]
 [] kfree+0xd9/0x166
 [] dvb_unregister_device+0xd6/0xe5
 [] dvb_unregister_frontend+0x4b/0x66
 [] dvb_usb_adapter_frontend_exit+0x69/0xac
 [] dvb_usb_exit+0x43/0xe5
 [] dvb_usb_device_exit+0x69/0x7d
 [] pctv452e_usb_disconnect+0x7b/0x80

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_frontend.c |   46 ++---
 drivers/media/dvb-core/dvb_frontend.h |1 +
 2 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c 
b/drivers/media/dvb-core/dvb_frontend.c
index 5bbe389..c38143b4 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -99,8 +99,6 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to 
 seconds on open(
 static DEFINE_MUTEX(frontend_mutex);
 
 struct dvb_frontend_private {
-   struct kref refcount;
-
/* thread/frontend values */
struct dvb_device *dvbdev;
struct dvb_frontend_parameters parameters_out;
@@ -138,21 +136,30 @@ struct dvb_frontend_private {
 #endif
 };
 
-static void dvb_frontend_private_free(struct kref *ref)
+static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
+   void (*release)(struct dvb_frontend 
*fe));
+
+static void dvb_frontend_free(struct kref *ref)
 {
-   struct dvb_frontend_private *fepriv =
-   container_of(ref, struct dvb_frontend_private, refcount);
+   struct dvb_frontend *fe =
+   container_of(ref, struct dvb_frontend, refcount);
+   struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+   dvb_free_device(fepriv->dvbdev);
+
+   dvb_frontend_invoke_release(fe, fe->ops.release);
+
kfree(fepriv);
 }
 
-static void dvb_frontend_private_put(struct dvb_frontend_private *fepriv)
+static void dvb_frontend_put(struct dvb_frontend *fe)
 {
-   kref_put(>refcount, dvb_frontend_private_free);
+   kref_put(>refcount, dvb_frontend_free);
 }
 
-static void dvb_frontend_private_get(struct dvb_frontend_private *fepriv)
+static void dvb_frontend_get(struct dvb_frontend *fe)
 {
-   kref_get(>refcount);
+   kref_get(>refcount);
 }
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
@@ -2569,7 +2576,7 @@ static int dvb_frontend_open(struct inode *inode, struct 
file *file)
fepriv->events.eventr = fepriv->events.eventw = 0;
}
 
-   dvb_frontend_private_get(fepriv);
+   

[PATCH 10/12] [media] dvb_frontend: move kref to struct dvb_frontend

2016-08-09 Thread Max Kellermann
This commit amends my old commit fe35637b0a9f ("[media] dvb_frontend:
eliminate blocking wait in dvb_unregister_frontend()"), which added
kref to struct dvb_frontend_private.  It turned out that there are
several use-after-free bugs left, which affect the struct
dvb_frontend.  Protecting it with kref also protects struct
dvb_frontend_private, so we can simply move it.

This is how the use-after-free looks like in KASAN:

BUG: KASAN: use-after-free in string+0x60/0xb1 at addr 880033bd9fc0
Read of size 1 by task kworker/0:2/617
CPU: 0 PID: 617 Comm: kworker/0:2 Not tainted 4.8.0-rc1-hosting+ #60
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
Workqueue: usb_hub_wq hub_event
  880033757218 81394e50 880033bd9fd0
 880035c03b00 880033757240 811f271d 880033bd9fc0
 11000677b3f8 ed000677b3f8 8800337572b8 811f2afe
Call Trace:
 [...]
 [] vsnprintf+0x39d/0x7e9
 [] add_uevent_var+0x10f/0x1dc
 [] rc_dev_uevent+0x55/0x6f
 [] dev_uevent+0x2e1/0x316
 [] kobject_uevent_env+0x27e/0x701
 [] kobject_uevent+0xb/0xd
 [] device_del+0x322/0x383
 [] rc_unregister_device+0x98/0xc3
 [] dvb_usb_remote_exit+0x7a/0x90
 [] dvb_usb_exit+0x1d/0xe5
 [] dvb_usb_device_exit+0x69/0x7d
 [] pctv452e_usb_disconnect+0x7b/0x80
 [...]
Object at 880033bd9fc0, in cache kmalloc-16 size: 16
Allocated:
 [...]
Freed:
PID = 617
 [...]
 [] kfree+0xd9/0x166
 [] ir_free_table+0x2f/0x51
 [] rc_unregister_device+0x4d/0xc3
 [] dvb_usb_remote_exit+0x7a/0x90
 [] dvb_usb_exit+0x1d/0xe5
 [] dvb_usb_device_exit+0x69/0x7d
 [] pctv452e_usb_disconnect+0x7b/0x80

Another one:

BUG: KASAN: use-after-free in do_sys_poll+0x336/0x6b8 at addr 
88003563fcc0
Read of size 8 by task tuner on fronte/1042
CPU: 1 PID: 1042 Comm: tuner on fronte Tainted: GB   
4.8.0-rc1-hosting+ #60
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
  88003353f910 81394e50 88003563fd80
 880035c03200 88003353f938 811f271d 88003563fc80
 110006ac7f98 ed0006ac7f98 88003353f9b0 811f2afe
Call Trace:
 [...]
 [] do_sys_poll+0x336/0x6b8
 [...]
 [] SyS_poll+0xa9/0x194
 [...]
Object at 88003563fc80, in cache kmalloc-256 size: 256
Allocated:
 [...]
Freed:
PID = 617
 [...]
 [] kfree+0xd9/0x166
 [] dvb_unregister_device+0xd6/0xe5
 [] dvb_unregister_frontend+0x4b/0x66
 [] dvb_usb_adapter_frontend_exit+0x69/0xac
 [] dvb_usb_exit+0x43/0xe5
 [] dvb_usb_device_exit+0x69/0x7d
 [] pctv452e_usb_disconnect+0x7b/0x80

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_frontend.c |   46 ++---
 drivers/media/dvb-core/dvb_frontend.h |1 +
 2 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c 
b/drivers/media/dvb-core/dvb_frontend.c
index 5bbe389..c38143b4 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -99,8 +99,6 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to 
 seconds on open(
 static DEFINE_MUTEX(frontend_mutex);
 
 struct dvb_frontend_private {
-   struct kref refcount;
-
/* thread/frontend values */
struct dvb_device *dvbdev;
struct dvb_frontend_parameters parameters_out;
@@ -138,21 +136,30 @@ struct dvb_frontend_private {
 #endif
 };
 
-static void dvb_frontend_private_free(struct kref *ref)
+static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
+   void (*release)(struct dvb_frontend 
*fe));
+
+static void dvb_frontend_free(struct kref *ref)
 {
-   struct dvb_frontend_private *fepriv =
-   container_of(ref, struct dvb_frontend_private, refcount);
+   struct dvb_frontend *fe =
+   container_of(ref, struct dvb_frontend, refcount);
+   struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+   dvb_free_device(fepriv->dvbdev);
+
+   dvb_frontend_invoke_release(fe, fe->ops.release);
+
kfree(fepriv);
 }
 
-static void dvb_frontend_private_put(struct dvb_frontend_private *fepriv)
+static void dvb_frontend_put(struct dvb_frontend *fe)
 {
-   kref_put(>refcount, dvb_frontend_private_free);
+   kref_put(>refcount, dvb_frontend_free);
 }
 
-static void dvb_frontend_private_get(struct dvb_frontend_private *fepriv)
+static void dvb_frontend_get(struct dvb_frontend *fe)
 {
-   kref_get(>refcount);
+   kref_get(>refcount);
 }
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
@@ -2569,7 +2576,7 @@ static int dvb_frontend_open(struct inode *inode, struct 
file *file)
fepriv->events.eventr = fepriv->events.eventw = 0;
}
 
-   dvb_frontend_private_get(fepriv);
+   dvb_frontend_get(fe);
 
   

[PATCH 09/12] [media] stb0899: move code to "detach" callback

2016-08-09 Thread Max Kellermann
Ensure that STB0899_POSTPROC_GPIO_POWER is set synchronously.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-frontends/stb0899_drv.c |   11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/media/dvb-frontends/stb0899_drv.c 
b/drivers/media/dvb-frontends/stb0899_drv.c
index 1d34e95..8dc4894 100644
--- a/drivers/media/dvb-frontends/stb0899_drv.c
+++ b/drivers/media/dvb-frontends/stb0899_drv.c
@@ -614,13 +614,19 @@ static int stb0899_postproc(struct stb0899_state *state, 
u8 ctl, int enable)
return 0;
 }
 
-static void stb0899_release(struct dvb_frontend *fe)
+static void stb0899_detach(struct dvb_frontend *fe)
 {
struct stb0899_state *state = fe->demodulator_priv;
 
-   dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend");
/* post process event */
stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
+}
+
+static void stb0899_release(struct dvb_frontend *fe)
+{
+   struct stb0899_state *state = fe->demodulator_priv;
+
+   dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend");
kfree(state);
 }
 
@@ -1603,6 +1609,7 @@ static const struct dvb_frontend_ops stb0899_ops = {
  FE_CAN_QPSK
},
 
+   .detach = stb0899_detach,
.release= stb0899_release,
.init   = stb0899_init,
.sleep  = stb0899_sleep,



[PATCH 09/12] [media] stb0899: move code to "detach" callback

2016-08-09 Thread Max Kellermann
Ensure that STB0899_POSTPROC_GPIO_POWER is set synchronously.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-frontends/stb0899_drv.c |   11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/media/dvb-frontends/stb0899_drv.c 
b/drivers/media/dvb-frontends/stb0899_drv.c
index 1d34e95..8dc4894 100644
--- a/drivers/media/dvb-frontends/stb0899_drv.c
+++ b/drivers/media/dvb-frontends/stb0899_drv.c
@@ -614,13 +614,19 @@ static int stb0899_postproc(struct stb0899_state *state, 
u8 ctl, int enable)
return 0;
 }
 
-static void stb0899_release(struct dvb_frontend *fe)
+static void stb0899_detach(struct dvb_frontend *fe)
 {
struct stb0899_state *state = fe->demodulator_priv;
 
-   dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend");
/* post process event */
stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0);
+}
+
+static void stb0899_release(struct dvb_frontend *fe)
+{
+   struct stb0899_state *state = fe->demodulator_priv;
+
+   dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend");
kfree(state);
 }
 
@@ -1603,6 +1609,7 @@ static const struct dvb_frontend_ops stb0899_ops = {
  FE_CAN_QPSK
},
 
+   .detach = stb0899_detach,
.release= stb0899_release,
.init   = stb0899_init,
.sleep  = stb0899_sleep,



[PATCH 11/12] [media] media-entity: clear media_gobj.mdev in _destroy()

2016-08-09 Thread Max Kellermann
media_gobj_destroy() may be called twice on one instance - once by
media_device_unregister() and again by dvb_media_device_free().  The
function media_remove_intf_links() establishes and documents the
convention that mdev==NULL means that the object is not registered,
but nobody ever NULLs this variable.  So this patch really implements
this behavior, and adds another mdev==NULL check to
media_gobj_destroy() to protect against double removal.

Signed-off-by: Max Kellermann 
---
 drivers/media/media-entity.c |6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index d8a2299..9526338 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -203,10 +203,16 @@ void media_gobj_destroy(struct media_gobj *gobj)
 {
dev_dbg_obj(__func__, gobj);
 
+   /* Do nothing if the object is not linked. */
+   if (gobj->mdev == NULL)
+   return;
+
gobj->mdev->topology_version++;
 
/* Remove the object from mdev list */
list_del(>list);
+
+   gobj->mdev = NULL;
 }
 
 int media_entity_pads_init(struct media_entity *entity, u16 num_pads,



[PATCH 05/12] [media] dvb_frontend: merge duplicate dvb_tuner_ops.release implementations

2016-08-09 Thread Max Kellermann
Most release callback functions are identical: free the "tuner_priv"
and clear it.  Let's eliminate some bloat by providing this simple
implementation in the dvb_frontend library.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_frontend.c  |9 +
 drivers/media/dvb-core/dvb_frontend.h  |7 +++
 drivers/media/dvb-frontends/dib0070.c  |9 +
 drivers/media/dvb-frontends/dib0090.c  |   11 ++-
 drivers/media/dvb-frontends/dvb-pll.c  |9 +
 drivers/media/dvb-frontends/itd1000.c  |9 +
 drivers/media/dvb-frontends/ix2505v.c  |   12 +---
 drivers/media/dvb-frontends/stb6000.c  |9 +
 drivers/media/dvb-frontends/stb6100.c  |   14 +-
 drivers/media/dvb-frontends/stv6110.c  |9 +
 drivers/media/dvb-frontends/stv6110x.c |   12 +---
 drivers/media/dvb-frontends/tda18271c2dd.c |   10 +-
 drivers/media/dvb-frontends/tda665x.c  |   11 +--
 drivers/media/dvb-frontends/tda8261.c  |   11 +--
 drivers/media/dvb-frontends/tda826x.c  |9 +
 drivers/media/dvb-frontends/tua6100.c  |9 +
 drivers/media/dvb-frontends/zl10036.c  |   12 +---
 drivers/media/tuners/fc0011.c  |   10 +-
 drivers/media/tuners/fc0012.c  |9 +
 drivers/media/tuners/fc0013.c  |9 +
 drivers/media/tuners/mc44s803.c|   12 +---
 drivers/media/tuners/mt2060.c  |9 +
 drivers/media/tuners/mt20xx.c  |   12 ++--
 drivers/media/tuners/mt2266.c  |9 +
 drivers/media/tuners/qt1010.c  |9 +
 drivers/media/tuners/tda18218.c|9 +
 drivers/media/tuners/tda827x.c |   11 ++-
 drivers/media/tuners/tea5761.c |   10 +-
 drivers/media/tuners/tea5767.c |   10 +-
 29 files changed, 46 insertions(+), 245 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c 
b/drivers/media/dvb-core/dvb_frontend.c
index be99c8d..ed9686b 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -169,6 +169,15 @@ static bool has_get_frontend(struct dvb_frontend *fe)
return fe->ops.get_frontend != NULL;
 }
 
+int
+dvb_tuner_simple_release(struct dvb_frontend *fe)
+{
+   kfree(fe->tuner_priv);
+   fe->tuner_priv = NULL;
+   return 0;
+}
+EXPORT_SYMBOL(dvb_tuner_simple_release);
+
 /*
  * Due to DVBv3 API calls, a delivery system should be mapped into one of
  * the 4 DVBv3 delivery systems (FE_QPSK, FE_QAM, FE_OFDM or FE_ATSC),
diff --git a/drivers/media/dvb-core/dvb_frontend.h 
b/drivers/media/dvb-core/dvb_frontend.h
index fb6e848..6b675a8 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -267,6 +267,13 @@ struct dvb_tuner_ops {
 };
 
 /**
+ * A common default implementation for dvb_tuner_ops.release.  All it
+ * does is kfree() the tuner_priv and assign NULL to it.
+ */
+int
+dvb_tuner_simple_release(struct dvb_frontend *fe);
+
+/**
  * struct analog_demod_info - Information struct for analog TV part of the 
demod
  *
  * @name:  Name of the analog TV demodulator
diff --git a/drivers/media/dvb-frontends/dib0070.c 
b/drivers/media/dvb-frontends/dib0070.c
index ee7d669..8e31f12 100644
--- a/drivers/media/dvb-frontends/dib0070.c
+++ b/drivers/media/dvb-frontends/dib0070.c
@@ -722,13 +722,6 @@ static int dib0070_get_frequency(struct dvb_frontend *fe, 
u32 *frequency)
return 0;
 }
 
-static int dib0070_release(struct dvb_frontend *fe)
-{
-   kfree(fe->tuner_priv);
-   fe->tuner_priv = NULL;
-   return 0;
-}
-
 static const struct dvb_tuner_ops dib0070_ops = {
.info = {
.name   = "DiBcom DiB0070",
@@ -736,7 +729,7 @@ static const struct dvb_tuner_ops dib0070_ops = {
.frequency_max  = 86000,
.frequency_step =  1000,
},
-   .release   = dib0070_release,
+   .release   = dvb_tuner_simple_release,
 
.init  = dib0070_wakeup,
.sleep = dib0070_sleep,
diff --git a/drivers/media/dvb-frontends/dib0090.c 
b/drivers/media/dvb-frontends/dib0090.c
index 14c4032..7780df2 100644
--- a/drivers/media/dvb-frontends/dib0090.c
+++ b/drivers/media/dvb-frontends/dib0090.c
@@ -2524,13 +2524,6 @@ static int dib0090_tune(struct dvb_frontend *fe)
return ret;
 }
 
-static int dib0090_release(struct dvb_frontend *fe)
-{
-   kfree(fe->tuner_priv);
-   fe->tuner_priv = NULL;
-   return 0;
-}
-
 enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
 {
struct dib0090_state *state = fe->tuner_priv;
@@ -2592,7 +2585,7 @@ static const struct dvb_tuner_ops dib0090_ops = {
 .frequency_max = 

[PATCH 04/12] [media] dvb: make DVB frontend *_ops instances "const"

2016-08-09 Thread Max Kellermann
These are immutable.  Making them "const" allows the compiler to move
them to the "rodata" section.

Note that cxd2841er_t_c_ops cannot be made "const", because
cxd2841er_attach() modifies it.  Ouch!

Signed-off-by: Max Kellermann 
---
 drivers/media/common/siano/smsdvb-main.c  |2 +-
 drivers/media/dvb-frontends/af9013.c  |4 ++--
 drivers/media/dvb-frontends/af9033.c  |2 +-
 drivers/media/dvb-frontends/as102_fe.c|2 +-
 drivers/media/dvb-frontends/ascot2e.c |2 +-
 drivers/media/dvb-frontends/atbm8830.c|2 +-
 drivers/media/dvb-frontends/au8522_dig.c  |4 ++--
 drivers/media/dvb-frontends/bcm3510.c |4 ++--
 drivers/media/dvb-frontends/cx22700.c |4 ++--
 drivers/media/dvb-frontends/cx24110.c |4 ++--
 drivers/media/dvb-frontends/cx24116.c |4 ++--
 drivers/media/dvb-frontends/cx24117.c |4 ++--
 drivers/media/dvb-frontends/cx24120.c |4 ++--
 drivers/media/dvb-frontends/cx24123.c |4 ++--
 drivers/media/dvb-frontends/cxd2841er.c   |4 ++--
 drivers/media/dvb-frontends/dib3000mb.c   |4 ++--
 drivers/media/dvb-frontends/dib3000mc.c   |4 ++--
 drivers/media/dvb-frontends/dib7000m.c|4 ++--
 drivers/media/dvb-frontends/dib7000p.c|4 ++--
 drivers/media/dvb-frontends/dib9000.c |4 ++--
 drivers/media/dvb-frontends/drx39xyj/drxj.c   |4 ++--
 drivers/media/dvb-frontends/drxd_hard.c   |2 +-
 drivers/media/dvb-frontends/drxk_hard.c   |2 +-
 drivers/media/dvb-frontends/ds3000.c  |4 ++--
 drivers/media/dvb-frontends/dvb-pll.c |2 +-
 drivers/media/dvb-frontends/dvb_dummy_fe.c|   12 ++--
 drivers/media/dvb-frontends/ec100.c   |4 ++--
 drivers/media/dvb-frontends/hd29l2.c  |4 ++--
 drivers/media/dvb-frontends/helene.c  |4 ++--
 drivers/media/dvb-frontends/horus3a.c |2 +-
 drivers/media/dvb-frontends/ix2505v.c |2 +-
 drivers/media/dvb-frontends/l64781.c  |4 ++--
 drivers/media/dvb-frontends/lg2160.c  |4 ++--
 drivers/media/dvb-frontends/lgdt3305.c|8 
 drivers/media/dvb-frontends/lgdt3306a.c   |4 ++--
 drivers/media/dvb-frontends/lgdt330x.c|8 
 drivers/media/dvb-frontends/lgs8gl5.c |4 ++--
 drivers/media/dvb-frontends/lgs8gxx.c |2 +-
 drivers/media/dvb-frontends/m88ds3103.c   |4 ++--
 drivers/media/dvb-frontends/m88rs2000.c   |2 +-
 drivers/media/dvb-frontends/mb86a16.c |2 +-
 drivers/media/dvb-frontends/mb86a20s.c|4 ++--
 drivers/media/dvb-frontends/mn88472.c |2 +-
 drivers/media/dvb-frontends/mt312.c   |2 +-
 drivers/media/dvb-frontends/mt352.c   |4 ++--
 drivers/media/dvb-frontends/nxt200x.c |4 ++--
 drivers/media/dvb-frontends/nxt6000.c |4 ++--
 drivers/media/dvb-frontends/or51132.c |4 ++--
 drivers/media/dvb-frontends/or51211.c |4 ++--
 drivers/media/dvb-frontends/rtl2830.c |2 +-
 drivers/media/dvb-frontends/rtl2832.c |2 +-
 drivers/media/dvb-frontends/s5h1409.c |4 ++--
 drivers/media/dvb-frontends/s5h1411.c |4 ++--
 drivers/media/dvb-frontends/s5h1420.c |4 ++--
 drivers/media/dvb-frontends/s5h1432.c |4 ++--
 drivers/media/dvb-frontends/s921.c|4 ++--
 drivers/media/dvb-frontends/si2165.c  |2 +-
 drivers/media/dvb-frontends/si21xx.c  |2 +-
 drivers/media/dvb-frontends/sp8870.c  |4 ++--
 drivers/media/dvb-frontends/sp887x.c  |4 ++--
 drivers/media/dvb-frontends/stb0899_drv.c |2 +-
 drivers/media/dvb-frontends/stb6000.c |2 +-
 drivers/media/dvb-frontends/stb6100.c |2 +-
 drivers/media/dvb-frontends/stv0288.c |2 +-
 drivers/media/dvb-frontends/stv0297.c |4 ++--
 drivers/media/dvb-frontends/stv0299.c |4 ++--
 drivers/media/dvb-frontends/stv0367.c |4 ++--
 drivers/media/dvb-frontends/stv0900_core.c|2 +-
 drivers/media/dvb-frontends/stv090x.c |2 +-
 drivers/media/dvb-frontends/stv6110.c |2 +-
 drivers/media/dvb-frontends/stv6110x.c|2 +-
 drivers/media/dvb-frontends/tda10021.c|4 ++--
 drivers/media/dvb-frontends/tda10023.c|4 ++--
 drivers/media/dvb-frontends/tda10048.c|4 ++--
 drivers/media/dvb-frontends/tda1004x.c|4 ++--
 drivers/media/dvb-frontends/tda10071.c|4 ++--
 drivers/media/dvb-frontends/tda10086.c|2 +-
 drivers/media/dvb-frontends/tda18271c2dd.c|2 +-
 drivers/media/dvb-frontends/tda665x.c |2 +-
 drivers/media/dvb-frontends/tda8083.c |4 ++--
 drivers/media/dvb-frontends/tda8261.c |2 +-
 

[PATCH 08/12] [media] dvb_frontend: add "detach" callback

2016-08-09 Thread Max Kellermann
Prepare for making "release" asynchronous (via kref).  Some operations
may need to be run synchronously in dvb_frontend_detach(), and that's
why we need a "detach" callback.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_frontend.c |1 +
 drivers/media/dvb-core/dvb_frontend.h |7 ++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c 
b/drivers/media/dvb-core/dvb_frontend.c
index 1177414..5bbe389 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -2770,6 +2770,7 @@ void dvb_frontend_detach(struct dvb_frontend* fe)
dvb_frontend_invoke_release(fe, fe->ops.release_sec);
dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release);
dvb_frontend_invoke_release(fe, fe->ops.analog_ops.release);
+   dvb_frontend_invoke_release(fe, fe->ops.detach);
dvb_frontend_invoke_release(fe, fe->ops.release);
 }
 EXPORT_SYMBOL(dvb_frontend_detach);
diff --git a/drivers/media/dvb-core/dvb_frontend.h 
b/drivers/media/dvb-core/dvb_frontend.h
index 5bfb16b..d535571 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -330,7 +330,11 @@ struct dtv_frontend_properties;
  *
  * @info:  embedded struct dvb_tuner_info with tuner properties
  * @delsys:Delivery systems supported by the frontend
- * @release:   callback function called when frontend is dettached.
+ * @detach:callback function called when frontend is detached.
+ * drivers should clean up, but not yet free the struct
+ * dvb_frontend allocation.
+ * @release:   callback function called when frontend is ready to be
+ * freed.
  * drivers should free any allocated memory.
  * @release_sec:   callback function requesting that the Satelite Equipment
  * Control (SEC) driver to release and free any memory
@@ -415,6 +419,7 @@ struct dvb_frontend_ops {
 
u8 delsys[MAX_DELSYS];
 
+   void (*detach)(struct dvb_frontend *fe);
void (*release)(struct dvb_frontend* fe);
void (*release_sec)(struct dvb_frontend* fe);
 



[PATCH 01/12] [media] rc-main: clear rc_map.name in ir_free_table()

2016-08-09 Thread Max Kellermann
rc_unregister_device() will first call ir_free_table(), and later
device_del(); however, the latter causes a call to rc_dev_uevent(),
which prints rc_map.name, which at this point has already bee freed.

This fixes a use-after-free bug found with KASAN.

Signed-off-by: Max Kellermann 
---
 drivers/media/rc/rc-main.c |1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 8e7f292..1e5a520 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -159,6 +159,7 @@ static void ir_free_table(struct rc_map *rc_map)
 {
rc_map->size = 0;
kfree(rc_map->name);
+   rc_map->name = NULL;
kfree(rc_map->scan);
rc_map->scan = NULL;
 }



[PATCH 11/12] [media] media-entity: clear media_gobj.mdev in _destroy()

2016-08-09 Thread Max Kellermann
media_gobj_destroy() may be called twice on one instance - once by
media_device_unregister() and again by dvb_media_device_free().  The
function media_remove_intf_links() establishes and documents the
convention that mdev==NULL means that the object is not registered,
but nobody ever NULLs this variable.  So this patch really implements
this behavior, and adds another mdev==NULL check to
media_gobj_destroy() to protect against double removal.

Signed-off-by: Max Kellermann 
---
 drivers/media/media-entity.c |6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index d8a2299..9526338 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -203,10 +203,16 @@ void media_gobj_destroy(struct media_gobj *gobj)
 {
dev_dbg_obj(__func__, gobj);
 
+   /* Do nothing if the object is not linked. */
+   if (gobj->mdev == NULL)
+   return;
+
gobj->mdev->topology_version++;
 
/* Remove the object from mdev list */
list_del(>list);
+
+   gobj->mdev = NULL;
 }
 
 int media_entity_pads_init(struct media_entity *entity, u16 num_pads,



[PATCH 05/12] [media] dvb_frontend: merge duplicate dvb_tuner_ops.release implementations

2016-08-09 Thread Max Kellermann
Most release callback functions are identical: free the "tuner_priv"
and clear it.  Let's eliminate some bloat by providing this simple
implementation in the dvb_frontend library.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_frontend.c  |9 +
 drivers/media/dvb-core/dvb_frontend.h  |7 +++
 drivers/media/dvb-frontends/dib0070.c  |9 +
 drivers/media/dvb-frontends/dib0090.c  |   11 ++-
 drivers/media/dvb-frontends/dvb-pll.c  |9 +
 drivers/media/dvb-frontends/itd1000.c  |9 +
 drivers/media/dvb-frontends/ix2505v.c  |   12 +---
 drivers/media/dvb-frontends/stb6000.c  |9 +
 drivers/media/dvb-frontends/stb6100.c  |   14 +-
 drivers/media/dvb-frontends/stv6110.c  |9 +
 drivers/media/dvb-frontends/stv6110x.c |   12 +---
 drivers/media/dvb-frontends/tda18271c2dd.c |   10 +-
 drivers/media/dvb-frontends/tda665x.c  |   11 +--
 drivers/media/dvb-frontends/tda8261.c  |   11 +--
 drivers/media/dvb-frontends/tda826x.c  |9 +
 drivers/media/dvb-frontends/tua6100.c  |9 +
 drivers/media/dvb-frontends/zl10036.c  |   12 +---
 drivers/media/tuners/fc0011.c  |   10 +-
 drivers/media/tuners/fc0012.c  |9 +
 drivers/media/tuners/fc0013.c  |9 +
 drivers/media/tuners/mc44s803.c|   12 +---
 drivers/media/tuners/mt2060.c  |9 +
 drivers/media/tuners/mt20xx.c  |   12 ++--
 drivers/media/tuners/mt2266.c  |9 +
 drivers/media/tuners/qt1010.c  |9 +
 drivers/media/tuners/tda18218.c|9 +
 drivers/media/tuners/tda827x.c |   11 ++-
 drivers/media/tuners/tea5761.c |   10 +-
 drivers/media/tuners/tea5767.c |   10 +-
 29 files changed, 46 insertions(+), 245 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c 
b/drivers/media/dvb-core/dvb_frontend.c
index be99c8d..ed9686b 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -169,6 +169,15 @@ static bool has_get_frontend(struct dvb_frontend *fe)
return fe->ops.get_frontend != NULL;
 }
 
+int
+dvb_tuner_simple_release(struct dvb_frontend *fe)
+{
+   kfree(fe->tuner_priv);
+   fe->tuner_priv = NULL;
+   return 0;
+}
+EXPORT_SYMBOL(dvb_tuner_simple_release);
+
 /*
  * Due to DVBv3 API calls, a delivery system should be mapped into one of
  * the 4 DVBv3 delivery systems (FE_QPSK, FE_QAM, FE_OFDM or FE_ATSC),
diff --git a/drivers/media/dvb-core/dvb_frontend.h 
b/drivers/media/dvb-core/dvb_frontend.h
index fb6e848..6b675a8 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -267,6 +267,13 @@ struct dvb_tuner_ops {
 };
 
 /**
+ * A common default implementation for dvb_tuner_ops.release.  All it
+ * does is kfree() the tuner_priv and assign NULL to it.
+ */
+int
+dvb_tuner_simple_release(struct dvb_frontend *fe);
+
+/**
  * struct analog_demod_info - Information struct for analog TV part of the 
demod
  *
  * @name:  Name of the analog TV demodulator
diff --git a/drivers/media/dvb-frontends/dib0070.c 
b/drivers/media/dvb-frontends/dib0070.c
index ee7d669..8e31f12 100644
--- a/drivers/media/dvb-frontends/dib0070.c
+++ b/drivers/media/dvb-frontends/dib0070.c
@@ -722,13 +722,6 @@ static int dib0070_get_frequency(struct dvb_frontend *fe, 
u32 *frequency)
return 0;
 }
 
-static int dib0070_release(struct dvb_frontend *fe)
-{
-   kfree(fe->tuner_priv);
-   fe->tuner_priv = NULL;
-   return 0;
-}
-
 static const struct dvb_tuner_ops dib0070_ops = {
.info = {
.name   = "DiBcom DiB0070",
@@ -736,7 +729,7 @@ static const struct dvb_tuner_ops dib0070_ops = {
.frequency_max  = 86000,
.frequency_step =  1000,
},
-   .release   = dib0070_release,
+   .release   = dvb_tuner_simple_release,
 
.init  = dib0070_wakeup,
.sleep = dib0070_sleep,
diff --git a/drivers/media/dvb-frontends/dib0090.c 
b/drivers/media/dvb-frontends/dib0090.c
index 14c4032..7780df2 100644
--- a/drivers/media/dvb-frontends/dib0090.c
+++ b/drivers/media/dvb-frontends/dib0090.c
@@ -2524,13 +2524,6 @@ static int dib0090_tune(struct dvb_frontend *fe)
return ret;
 }
 
-static int dib0090_release(struct dvb_frontend *fe)
-{
-   kfree(fe->tuner_priv);
-   fe->tuner_priv = NULL;
-   return 0;
-}
-
 enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
 {
struct dib0090_state *state = fe->tuner_priv;
@@ -2592,7 +2585,7 @@ static const struct dvb_tuner_ops dib0090_ops = {
 .frequency_max = 86000,
 

[PATCH 04/12] [media] dvb: make DVB frontend *_ops instances "const"

2016-08-09 Thread Max Kellermann
These are immutable.  Making them "const" allows the compiler to move
them to the "rodata" section.

Note that cxd2841er_t_c_ops cannot be made "const", because
cxd2841er_attach() modifies it.  Ouch!

Signed-off-by: Max Kellermann 
---
 drivers/media/common/siano/smsdvb-main.c  |2 +-
 drivers/media/dvb-frontends/af9013.c  |4 ++--
 drivers/media/dvb-frontends/af9033.c  |2 +-
 drivers/media/dvb-frontends/as102_fe.c|2 +-
 drivers/media/dvb-frontends/ascot2e.c |2 +-
 drivers/media/dvb-frontends/atbm8830.c|2 +-
 drivers/media/dvb-frontends/au8522_dig.c  |4 ++--
 drivers/media/dvb-frontends/bcm3510.c |4 ++--
 drivers/media/dvb-frontends/cx22700.c |4 ++--
 drivers/media/dvb-frontends/cx24110.c |4 ++--
 drivers/media/dvb-frontends/cx24116.c |4 ++--
 drivers/media/dvb-frontends/cx24117.c |4 ++--
 drivers/media/dvb-frontends/cx24120.c |4 ++--
 drivers/media/dvb-frontends/cx24123.c |4 ++--
 drivers/media/dvb-frontends/cxd2841er.c   |4 ++--
 drivers/media/dvb-frontends/dib3000mb.c   |4 ++--
 drivers/media/dvb-frontends/dib3000mc.c   |4 ++--
 drivers/media/dvb-frontends/dib7000m.c|4 ++--
 drivers/media/dvb-frontends/dib7000p.c|4 ++--
 drivers/media/dvb-frontends/dib9000.c |4 ++--
 drivers/media/dvb-frontends/drx39xyj/drxj.c   |4 ++--
 drivers/media/dvb-frontends/drxd_hard.c   |2 +-
 drivers/media/dvb-frontends/drxk_hard.c   |2 +-
 drivers/media/dvb-frontends/ds3000.c  |4 ++--
 drivers/media/dvb-frontends/dvb-pll.c |2 +-
 drivers/media/dvb-frontends/dvb_dummy_fe.c|   12 ++--
 drivers/media/dvb-frontends/ec100.c   |4 ++--
 drivers/media/dvb-frontends/hd29l2.c  |4 ++--
 drivers/media/dvb-frontends/helene.c  |4 ++--
 drivers/media/dvb-frontends/horus3a.c |2 +-
 drivers/media/dvb-frontends/ix2505v.c |2 +-
 drivers/media/dvb-frontends/l64781.c  |4 ++--
 drivers/media/dvb-frontends/lg2160.c  |4 ++--
 drivers/media/dvb-frontends/lgdt3305.c|8 
 drivers/media/dvb-frontends/lgdt3306a.c   |4 ++--
 drivers/media/dvb-frontends/lgdt330x.c|8 
 drivers/media/dvb-frontends/lgs8gl5.c |4 ++--
 drivers/media/dvb-frontends/lgs8gxx.c |2 +-
 drivers/media/dvb-frontends/m88ds3103.c   |4 ++--
 drivers/media/dvb-frontends/m88rs2000.c   |2 +-
 drivers/media/dvb-frontends/mb86a16.c |2 +-
 drivers/media/dvb-frontends/mb86a20s.c|4 ++--
 drivers/media/dvb-frontends/mn88472.c |2 +-
 drivers/media/dvb-frontends/mt312.c   |2 +-
 drivers/media/dvb-frontends/mt352.c   |4 ++--
 drivers/media/dvb-frontends/nxt200x.c |4 ++--
 drivers/media/dvb-frontends/nxt6000.c |4 ++--
 drivers/media/dvb-frontends/or51132.c |4 ++--
 drivers/media/dvb-frontends/or51211.c |4 ++--
 drivers/media/dvb-frontends/rtl2830.c |2 +-
 drivers/media/dvb-frontends/rtl2832.c |2 +-
 drivers/media/dvb-frontends/s5h1409.c |4 ++--
 drivers/media/dvb-frontends/s5h1411.c |4 ++--
 drivers/media/dvb-frontends/s5h1420.c |4 ++--
 drivers/media/dvb-frontends/s5h1432.c |4 ++--
 drivers/media/dvb-frontends/s921.c|4 ++--
 drivers/media/dvb-frontends/si2165.c  |2 +-
 drivers/media/dvb-frontends/si21xx.c  |2 +-
 drivers/media/dvb-frontends/sp8870.c  |4 ++--
 drivers/media/dvb-frontends/sp887x.c  |4 ++--
 drivers/media/dvb-frontends/stb0899_drv.c |2 +-
 drivers/media/dvb-frontends/stb6000.c |2 +-
 drivers/media/dvb-frontends/stb6100.c |2 +-
 drivers/media/dvb-frontends/stv0288.c |2 +-
 drivers/media/dvb-frontends/stv0297.c |4 ++--
 drivers/media/dvb-frontends/stv0299.c |4 ++--
 drivers/media/dvb-frontends/stv0367.c |4 ++--
 drivers/media/dvb-frontends/stv0900_core.c|2 +-
 drivers/media/dvb-frontends/stv090x.c |2 +-
 drivers/media/dvb-frontends/stv6110.c |2 +-
 drivers/media/dvb-frontends/stv6110x.c|2 +-
 drivers/media/dvb-frontends/tda10021.c|4 ++--
 drivers/media/dvb-frontends/tda10023.c|4 ++--
 drivers/media/dvb-frontends/tda10048.c|4 ++--
 drivers/media/dvb-frontends/tda1004x.c|4 ++--
 drivers/media/dvb-frontends/tda10071.c|4 ++--
 drivers/media/dvb-frontends/tda10086.c|2 +-
 drivers/media/dvb-frontends/tda18271c2dd.c|2 +-
 drivers/media/dvb-frontends/tda665x.c |2 +-
 drivers/media/dvb-frontends/tda8083.c |4 ++--
 drivers/media/dvb-frontends/tda8261.c |2 +-
 

[PATCH 08/12] [media] dvb_frontend: add "detach" callback

2016-08-09 Thread Max Kellermann
Prepare for making "release" asynchronous (via kref).  Some operations
may need to be run synchronously in dvb_frontend_detach(), and that's
why we need a "detach" callback.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_frontend.c |1 +
 drivers/media/dvb-core/dvb_frontend.h |7 ++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c 
b/drivers/media/dvb-core/dvb_frontend.c
index 1177414..5bbe389 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -2770,6 +2770,7 @@ void dvb_frontend_detach(struct dvb_frontend* fe)
dvb_frontend_invoke_release(fe, fe->ops.release_sec);
dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release);
dvb_frontend_invoke_release(fe, fe->ops.analog_ops.release);
+   dvb_frontend_invoke_release(fe, fe->ops.detach);
dvb_frontend_invoke_release(fe, fe->ops.release);
 }
 EXPORT_SYMBOL(dvb_frontend_detach);
diff --git a/drivers/media/dvb-core/dvb_frontend.h 
b/drivers/media/dvb-core/dvb_frontend.h
index 5bfb16b..d535571 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -330,7 +330,11 @@ struct dtv_frontend_properties;
  *
  * @info:  embedded struct dvb_tuner_info with tuner properties
  * @delsys:Delivery systems supported by the frontend
- * @release:   callback function called when frontend is dettached.
+ * @detach:callback function called when frontend is detached.
+ * drivers should clean up, but not yet free the struct
+ * dvb_frontend allocation.
+ * @release:   callback function called when frontend is ready to be
+ * freed.
  * drivers should free any allocated memory.
  * @release_sec:   callback function requesting that the Satelite Equipment
  * Control (SEC) driver to release and free any memory
@@ -415,6 +419,7 @@ struct dvb_frontend_ops {
 
u8 delsys[MAX_DELSYS];
 
+   void (*detach)(struct dvb_frontend *fe);
void (*release)(struct dvb_frontend* fe);
void (*release_sec)(struct dvb_frontend* fe);
 



[PATCH 01/12] [media] rc-main: clear rc_map.name in ir_free_table()

2016-08-09 Thread Max Kellermann
rc_unregister_device() will first call ir_free_table(), and later
device_del(); however, the latter causes a call to rc_dev_uevent(),
which prints rc_map.name, which at this point has already bee freed.

This fixes a use-after-free bug found with KASAN.

Signed-off-by: Max Kellermann 
---
 drivers/media/rc/rc-main.c |1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 8e7f292..1e5a520 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -159,6 +159,7 @@ static void ir_free_table(struct rc_map *rc_map)
 {
rc_map->size = 0;
kfree(rc_map->name);
+   rc_map->name = NULL;
kfree(rc_map->scan);
rc_map->scan = NULL;
 }



[PATCH 03/12] [media] dvb-core/en50221: use dvb_remove_device()

2016-08-09 Thread Max Kellermann
Commit da677fe14364 ("[media] dvb-core/en50221: use kref to manage
struct dvb_ca_private") moved the dvb_unregister_device() call to the
kref callback, but that left lots of stale device state visible to
userspace (e.g. in sysfs).  By using dvb_remove_device() and
dvb_free_device() instead of dvb_unregister_device(), we can avoid
that.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_ca_en50221.c |3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c 
b/drivers/media/dvb-core/dvb_ca_en50221.c
index b5b5b19..09e759c 100644
--- a/drivers/media/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb-core/dvb_ca_en50221.c
@@ -166,7 +166,7 @@ static void dvb_ca_private_free(struct dvb_ca_private *ca)
 {
unsigned int i;
 
-   dvb_unregister_device(ca->dvbdev);
+   dvb_free_device(ca->dvbdev);
for (i = 0; i < ca->slot_count; i++)
vfree(ca->slot_info[i].rx_buffer.data);
 
@@ -1794,6 +1794,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
for (i = 0; i < ca->slot_count; i++) {
dvb_ca_en50221_slot_shutdown(ca, i);
}
+   dvb_remove_device(ca->dvbdev);
dvb_ca_private_put(ca);
pubca->private = NULL;
 }



[PATCH 02/12] [media] dvbdev: split dvb_unregister_device()

2016-08-09 Thread Max Kellermann
dvb_unregister_device() has a major problem: it combines unregistering
with memory disposal.  Sometimes, it is necessary to unregister a
device, but no memory can be freed yet, because a process still has a
(stale) file handle.  Therefore, we need to split
dvb_unregister_device().  This will allow sanitizing a few callers.

With my new design, dvb_unregister_device() appears misnamed, but to
reduce patch noise, I'm not renaming it just yet.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvbdev.c |   19 ++-
 drivers/media/dvb-core/dvbdev.h |   23 +++
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index 75a3f4b..1bc2dba 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -523,7 +523,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct 
dvb_device **pdvbdev,
 EXPORT_SYMBOL(dvb_register_device);
 
 
-void dvb_unregister_device(struct dvb_device *dvbdev)
+void dvb_remove_device(struct dvb_device *dvbdev)
 {
if (!dvbdev)
return;
@@ -537,9 +537,26 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
 
list_del (>list_head);
+}
+EXPORT_SYMBOL(dvb_remove_device);
+
+
+void dvb_free_device(struct dvb_device *dvbdev)
+{
+   if (!dvbdev)
+   return;
+
kfree (dvbdev->fops);
kfree (dvbdev);
 }
+EXPORT_SYMBOL(dvb_free_device);
+
+
+void dvb_unregister_device(struct dvb_device *dvbdev)
+{
+   dvb_remove_device(dvbdev);
+   dvb_free_device(dvbdev);
+}
 EXPORT_SYMBOL(dvb_unregister_device);
 
 
diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h
index 4aff7bd..576bbd4 100644
--- a/drivers/media/dvb-core/dvbdev.h
+++ b/drivers/media/dvb-core/dvbdev.h
@@ -212,8 +212,31 @@ int dvb_register_device(struct dvb_adapter *adap,
int demux_sink_pads);
 
 /**
+ * dvb_remove_device - Remove a registered DVB device
+ *
+ * This does not free memory.  To do that, call dvb_free_device().
+ *
+ * @dvbdev:pointer to struct dvb_device
+ */
+void dvb_remove_device(struct dvb_device *dvbdev);
+
+/**
+ * dvb_free_device - Free memory occupied by a DVB device.
+ *
+ * Call dvb_unregister_device() before calling this function.
+ *
+ * @dvbdev:pointer to struct dvb_device
+ */
+void dvb_free_device(struct dvb_device *dvbdev);
+
+/**
  * dvb_unregister_device - Unregisters a DVB device
  *
+ * This is a combination of dvb_remove_device() and dvb_free_device().
+ * Using this function is usually a mistake, and is often an indicator
+ * for a use-after-free bug (when a userspace process keeps a file
+ * handle to a detached device).
+ *
  * @dvbdev:pointer to struct dvb_device
  */
 void dvb_unregister_device(struct dvb_device *dvbdev);



[PATCH 06/12] [media] dvb_frontend: tuner_ops.release returns void

2016-08-09 Thread Max Kellermann
It is not clear what this return value means.  All implemenations
return 0, and the one caller ignores the value.  Let's remove this
useless return value completely.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_frontend.c |3 +--
 drivers/media/dvb-core/dvb_frontend.h |4 ++--
 drivers/media/dvb-frontends/ascot2e.c |3 +--
 drivers/media/dvb-frontends/cx24113.c |3 +--
 drivers/media/dvb-frontends/helene.c  |3 +--
 drivers/media/dvb-frontends/horus3a.c |3 +--
 drivers/media/dvb-frontends/ts2020.c  |3 +--
 drivers/media/dvb-frontends/zl10039.c |3 +--
 drivers/media/tuners/max2165.c|4 +---
 drivers/media/tuners/mt2063.c |4 +---
 drivers/media/tuners/mt2131.c |3 +--
 drivers/media/tuners/mxl5005s.c   |3 +--
 drivers/media/tuners/mxl5007t.c   |4 +---
 drivers/media/tuners/r820t.c  |4 +---
 drivers/media/tuners/tda18271-fe.c|4 +---
 drivers/media/tuners/tuner-simple.c   |4 +---
 drivers/media/tuners/tuner-xc2028.c   |4 +---
 drivers/media/tuners/xc4000.c |4 +---
 drivers/media/tuners/xc5000.c |4 +---
 drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c |3 +--
 20 files changed, 21 insertions(+), 49 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c 
b/drivers/media/dvb-core/dvb_frontend.c
index ed9686b..fea635b 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -169,12 +169,11 @@ static bool has_get_frontend(struct dvb_frontend *fe)
return fe->ops.get_frontend != NULL;
 }
 
-int
+void
 dvb_tuner_simple_release(struct dvb_frontend *fe)
 {
kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
-   return 0;
 }
 EXPORT_SYMBOL(dvb_tuner_simple_release);
 
diff --git a/drivers/media/dvb-core/dvb_frontend.h 
b/drivers/media/dvb-core/dvb_frontend.h
index 6b675a8..5bfb16b 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -225,7 +225,7 @@ struct dvb_tuner_ops {
 
struct dvb_tuner_info info;
 
-   int (*release)(struct dvb_frontend *fe);
+   void (*release)(struct dvb_frontend *fe);
int (*init)(struct dvb_frontend *fe);
int (*sleep)(struct dvb_frontend *fe);
int (*suspend)(struct dvb_frontend *fe);
@@ -270,7 +270,7 @@ struct dvb_tuner_ops {
  * A common default implementation for dvb_tuner_ops.release.  All it
  * does is kfree() the tuner_priv and assign NULL to it.
  */
-int
+void
 dvb_tuner_simple_release(struct dvb_frontend *fe);
 
 /**
diff --git a/drivers/media/dvb-frontends/ascot2e.c 
b/drivers/media/dvb-frontends/ascot2e.c
index ad304ee..0ee0df5 100644
--- a/drivers/media/dvb-frontends/ascot2e.c
+++ b/drivers/media/dvb-frontends/ascot2e.c
@@ -254,14 +254,13 @@ static int ascot2e_init(struct dvb_frontend *fe)
return ascot2e_leave_power_save(priv);
 }
 
-static int ascot2e_release(struct dvb_frontend *fe)
+static void ascot2e_release(struct dvb_frontend *fe)
 {
struct ascot2e_priv *priv = fe->tuner_priv;
 
dev_dbg(>i2c->dev, "%s()\n", __func__);
kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
-   return 0;
 }
 
 static int ascot2e_sleep(struct dvb_frontend *fe)
diff --git a/drivers/media/dvb-frontends/cx24113.c 
b/drivers/media/dvb-frontends/cx24113.c
index 3883c3b..0c0b4f6 100644
--- a/drivers/media/dvb-frontends/cx24113.c
+++ b/drivers/media/dvb-frontends/cx24113.c
@@ -527,13 +527,12 @@ static int cx24113_get_frequency(struct dvb_frontend *fe, 
u32 *frequency)
return 0;
 }
 
-static int cx24113_release(struct dvb_frontend *fe)
+static void cx24113_release(struct dvb_frontend *fe)
 {
struct cx24113_state *state = fe->tuner_priv;
dprintk("\n");
fe->tuner_priv = NULL;
kfree(state);
-   return 0;
 }
 
 static const struct dvb_tuner_ops cx24113_tuner_ops = {
diff --git a/drivers/media/dvb-frontends/helene.c 
b/drivers/media/dvb-frontends/helene.c
index 4cb0505..fa56a20 100644
--- a/drivers/media/dvb-frontends/helene.c
+++ b/drivers/media/dvb-frontends/helene.c
@@ -434,14 +434,13 @@ static int helene_init(struct dvb_frontend *fe)
return helene_leave_power_save(priv);
 }
 
-static int helene_release(struct dvb_frontend *fe)
+static void helene_release(struct dvb_frontend *fe)
 {
struct helene_priv *priv = fe->tuner_priv;
 
dev_dbg(>i2c->dev, "%s()\n", __func__);
kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
-   return 0;
 }
 
 static int helene_sleep(struct dvb_frontend *fe)
diff --git a/drivers/media/dvb-frontends/horus3a.c 
b/drivers/media/dvb-frontends/horus3a.c
index 0c089b5..94bb4f7 100644
--- a/drivers/media/dvb-frontends/horus3a.c
+++ b/drivers/media/dvb-frontends/horus3a.c
@@ -151,14 +151,13 @@ 

[PATCH 03/12] [media] dvb-core/en50221: use dvb_remove_device()

2016-08-09 Thread Max Kellermann
Commit da677fe14364 ("[media] dvb-core/en50221: use kref to manage
struct dvb_ca_private") moved the dvb_unregister_device() call to the
kref callback, but that left lots of stale device state visible to
userspace (e.g. in sysfs).  By using dvb_remove_device() and
dvb_free_device() instead of dvb_unregister_device(), we can avoid
that.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_ca_en50221.c |3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c 
b/drivers/media/dvb-core/dvb_ca_en50221.c
index b5b5b19..09e759c 100644
--- a/drivers/media/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb-core/dvb_ca_en50221.c
@@ -166,7 +166,7 @@ static void dvb_ca_private_free(struct dvb_ca_private *ca)
 {
unsigned int i;
 
-   dvb_unregister_device(ca->dvbdev);
+   dvb_free_device(ca->dvbdev);
for (i = 0; i < ca->slot_count; i++)
vfree(ca->slot_info[i].rx_buffer.data);
 
@@ -1794,6 +1794,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
for (i = 0; i < ca->slot_count; i++) {
dvb_ca_en50221_slot_shutdown(ca, i);
}
+   dvb_remove_device(ca->dvbdev);
dvb_ca_private_put(ca);
pubca->private = NULL;
 }



[PATCH 02/12] [media] dvbdev: split dvb_unregister_device()

2016-08-09 Thread Max Kellermann
dvb_unregister_device() has a major problem: it combines unregistering
with memory disposal.  Sometimes, it is necessary to unregister a
device, but no memory can be freed yet, because a process still has a
(stale) file handle.  Therefore, we need to split
dvb_unregister_device().  This will allow sanitizing a few callers.

With my new design, dvb_unregister_device() appears misnamed, but to
reduce patch noise, I'm not renaming it just yet.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvbdev.c |   19 ++-
 drivers/media/dvb-core/dvbdev.h |   23 +++
 2 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
index 75a3f4b..1bc2dba 100644
--- a/drivers/media/dvb-core/dvbdev.c
+++ b/drivers/media/dvb-core/dvbdev.c
@@ -523,7 +523,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct 
dvb_device **pdvbdev,
 EXPORT_SYMBOL(dvb_register_device);
 
 
-void dvb_unregister_device(struct dvb_device *dvbdev)
+void dvb_remove_device(struct dvb_device *dvbdev)
 {
if (!dvbdev)
return;
@@ -537,9 +537,26 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
 
list_del (>list_head);
+}
+EXPORT_SYMBOL(dvb_remove_device);
+
+
+void dvb_free_device(struct dvb_device *dvbdev)
+{
+   if (!dvbdev)
+   return;
+
kfree (dvbdev->fops);
kfree (dvbdev);
 }
+EXPORT_SYMBOL(dvb_free_device);
+
+
+void dvb_unregister_device(struct dvb_device *dvbdev)
+{
+   dvb_remove_device(dvbdev);
+   dvb_free_device(dvbdev);
+}
 EXPORT_SYMBOL(dvb_unregister_device);
 
 
diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h
index 4aff7bd..576bbd4 100644
--- a/drivers/media/dvb-core/dvbdev.h
+++ b/drivers/media/dvb-core/dvbdev.h
@@ -212,8 +212,31 @@ int dvb_register_device(struct dvb_adapter *adap,
int demux_sink_pads);
 
 /**
+ * dvb_remove_device - Remove a registered DVB device
+ *
+ * This does not free memory.  To do that, call dvb_free_device().
+ *
+ * @dvbdev:pointer to struct dvb_device
+ */
+void dvb_remove_device(struct dvb_device *dvbdev);
+
+/**
+ * dvb_free_device - Free memory occupied by a DVB device.
+ *
+ * Call dvb_unregister_device() before calling this function.
+ *
+ * @dvbdev:pointer to struct dvb_device
+ */
+void dvb_free_device(struct dvb_device *dvbdev);
+
+/**
  * dvb_unregister_device - Unregisters a DVB device
  *
+ * This is a combination of dvb_remove_device() and dvb_free_device().
+ * Using this function is usually a mistake, and is often an indicator
+ * for a use-after-free bug (when a userspace process keeps a file
+ * handle to a detached device).
+ *
  * @dvbdev:pointer to struct dvb_device
  */
 void dvb_unregister_device(struct dvb_device *dvbdev);



[PATCH 06/12] [media] dvb_frontend: tuner_ops.release returns void

2016-08-09 Thread Max Kellermann
It is not clear what this return value means.  All implemenations
return 0, and the one caller ignores the value.  Let's remove this
useless return value completely.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_frontend.c |3 +--
 drivers/media/dvb-core/dvb_frontend.h |4 ++--
 drivers/media/dvb-frontends/ascot2e.c |3 +--
 drivers/media/dvb-frontends/cx24113.c |3 +--
 drivers/media/dvb-frontends/helene.c  |3 +--
 drivers/media/dvb-frontends/horus3a.c |3 +--
 drivers/media/dvb-frontends/ts2020.c  |3 +--
 drivers/media/dvb-frontends/zl10039.c |3 +--
 drivers/media/tuners/max2165.c|4 +---
 drivers/media/tuners/mt2063.c |4 +---
 drivers/media/tuners/mt2131.c |3 +--
 drivers/media/tuners/mxl5005s.c   |3 +--
 drivers/media/tuners/mxl5007t.c   |4 +---
 drivers/media/tuners/r820t.c  |4 +---
 drivers/media/tuners/tda18271-fe.c|4 +---
 drivers/media/tuners/tuner-simple.c   |4 +---
 drivers/media/tuners/tuner-xc2028.c   |4 +---
 drivers/media/tuners/xc4000.c |4 +---
 drivers/media/tuners/xc5000.c |4 +---
 drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c |3 +--
 20 files changed, 21 insertions(+), 49 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c 
b/drivers/media/dvb-core/dvb_frontend.c
index ed9686b..fea635b 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -169,12 +169,11 @@ static bool has_get_frontend(struct dvb_frontend *fe)
return fe->ops.get_frontend != NULL;
 }
 
-int
+void
 dvb_tuner_simple_release(struct dvb_frontend *fe)
 {
kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
-   return 0;
 }
 EXPORT_SYMBOL(dvb_tuner_simple_release);
 
diff --git a/drivers/media/dvb-core/dvb_frontend.h 
b/drivers/media/dvb-core/dvb_frontend.h
index 6b675a8..5bfb16b 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -225,7 +225,7 @@ struct dvb_tuner_ops {
 
struct dvb_tuner_info info;
 
-   int (*release)(struct dvb_frontend *fe);
+   void (*release)(struct dvb_frontend *fe);
int (*init)(struct dvb_frontend *fe);
int (*sleep)(struct dvb_frontend *fe);
int (*suspend)(struct dvb_frontend *fe);
@@ -270,7 +270,7 @@ struct dvb_tuner_ops {
  * A common default implementation for dvb_tuner_ops.release.  All it
  * does is kfree() the tuner_priv and assign NULL to it.
  */
-int
+void
 dvb_tuner_simple_release(struct dvb_frontend *fe);
 
 /**
diff --git a/drivers/media/dvb-frontends/ascot2e.c 
b/drivers/media/dvb-frontends/ascot2e.c
index ad304ee..0ee0df5 100644
--- a/drivers/media/dvb-frontends/ascot2e.c
+++ b/drivers/media/dvb-frontends/ascot2e.c
@@ -254,14 +254,13 @@ static int ascot2e_init(struct dvb_frontend *fe)
return ascot2e_leave_power_save(priv);
 }
 
-static int ascot2e_release(struct dvb_frontend *fe)
+static void ascot2e_release(struct dvb_frontend *fe)
 {
struct ascot2e_priv *priv = fe->tuner_priv;
 
dev_dbg(>i2c->dev, "%s()\n", __func__);
kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
-   return 0;
 }
 
 static int ascot2e_sleep(struct dvb_frontend *fe)
diff --git a/drivers/media/dvb-frontends/cx24113.c 
b/drivers/media/dvb-frontends/cx24113.c
index 3883c3b..0c0b4f6 100644
--- a/drivers/media/dvb-frontends/cx24113.c
+++ b/drivers/media/dvb-frontends/cx24113.c
@@ -527,13 +527,12 @@ static int cx24113_get_frequency(struct dvb_frontend *fe, 
u32 *frequency)
return 0;
 }
 
-static int cx24113_release(struct dvb_frontend *fe)
+static void cx24113_release(struct dvb_frontend *fe)
 {
struct cx24113_state *state = fe->tuner_priv;
dprintk("\n");
fe->tuner_priv = NULL;
kfree(state);
-   return 0;
 }
 
 static const struct dvb_tuner_ops cx24113_tuner_ops = {
diff --git a/drivers/media/dvb-frontends/helene.c 
b/drivers/media/dvb-frontends/helene.c
index 4cb0505..fa56a20 100644
--- a/drivers/media/dvb-frontends/helene.c
+++ b/drivers/media/dvb-frontends/helene.c
@@ -434,14 +434,13 @@ static int helene_init(struct dvb_frontend *fe)
return helene_leave_power_save(priv);
 }
 
-static int helene_release(struct dvb_frontend *fe)
+static void helene_release(struct dvb_frontend *fe)
 {
struct helene_priv *priv = fe->tuner_priv;
 
dev_dbg(>i2c->dev, "%s()\n", __func__);
kfree(fe->tuner_priv);
fe->tuner_priv = NULL;
-   return 0;
 }
 
 static int helene_sleep(struct dvb_frontend *fe)
diff --git a/drivers/media/dvb-frontends/horus3a.c 
b/drivers/media/dvb-frontends/horus3a.c
index 0c089b5..94bb4f7 100644
--- a/drivers/media/dvb-frontends/horus3a.c
+++ b/drivers/media/dvb-frontends/horus3a.c
@@ -151,14 +151,13 @@ static int 

[PATCH 12/12] drivers/media/media-device: fix double free bug in _unregister()

2016-08-09 Thread Max Kellermann
While removing all interfaces in media_device_unregister(), all
media_interface pointers are freed.  This is illegal and results in
double kfree() if any media_interface is still linked at this point;
maybe because a userspace process still has a file handle.  Once the
process closes the file handle, dvb_media_device_free() gets called,
which frees the dvb_device.intf_devnode again.

This patch removes the unnecessary kfree() call, and documents who's
responsible for really freeing it.

Signed-off-by: Max Kellermann 
---
 drivers/media/media-device.c |6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 1795abe..113a4d1 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -803,9 +803,13 @@ void media_device_unregister(struct media_device *mdev)
/* Remove all interfaces from the media device */
list_for_each_entry_safe(intf, tmp_intf, >interfaces,
 graph_obj.list) {
+   /*
+* Unlink the interface, but don't free it here; the
+* module which created it is responsible for freeing
+* it
+*/
__media_remove_intf_links(intf);
media_gobj_destroy(>graph_obj);
-   kfree(intf);
}
 
mutex_unlock(>graph_mutex);



[PATCH 07/12] [media] dvb_frontend: merge the two dvb_frontend_detach() versions

2016-08-09 Thread Max Kellermann
This code duplication is confusing and error prone.  Let's merge them
by moving the release/dvb_detach call into one function with one
#ifdef.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_frontend.c |   42 +
 1 file changed, 12 insertions(+), 30 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c 
b/drivers/media/dvb-core/dvb_frontend.c
index fea635b..1177414 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -2754,40 +2754,22 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
 }
 EXPORT_SYMBOL(dvb_unregister_frontend);
 
-#ifdef CONFIG_MEDIA_ATTACH
-void dvb_frontend_detach(struct dvb_frontend* fe)
+static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
+   void (*release)(struct dvb_frontend 
*fe))
 {
-   void *ptr;
-
-   if (fe->ops.release_sec) {
-   fe->ops.release_sec(fe);
-   dvb_detach(fe->ops.release_sec);
-   }
-   if (fe->ops.tuner_ops.release) {
-   fe->ops.tuner_ops.release(fe);
-   dvb_detach(fe->ops.tuner_ops.release);
-   }
-   if (fe->ops.analog_ops.release) {
-   fe->ops.analog_ops.release(fe);
-   dvb_detach(fe->ops.analog_ops.release);
-   }
-   ptr = (void*)fe->ops.release;
-   if (ptr) {
-   fe->ops.release(fe);
-   dvb_detach(ptr);
+   if (release) {
+   release(fe);
+#ifdef CONFIG_MEDIA_ATTACH
+   dvb_detach(release);
+#endif
}
 }
-#else
+
 void dvb_frontend_detach(struct dvb_frontend* fe)
 {
-   if (fe->ops.release_sec)
-   fe->ops.release_sec(fe);
-   if (fe->ops.tuner_ops.release)
-   fe->ops.tuner_ops.release(fe);
-   if (fe->ops.analog_ops.release)
-   fe->ops.analog_ops.release(fe);
-   if (fe->ops.release)
-   fe->ops.release(fe);
+   dvb_frontend_invoke_release(fe, fe->ops.release_sec);
+   dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release);
+   dvb_frontend_invoke_release(fe, fe->ops.analog_ops.release);
+   dvb_frontend_invoke_release(fe, fe->ops.release);
 }
-#endif
 EXPORT_SYMBOL(dvb_frontend_detach);



[PATCH 12/12] drivers/media/media-device: fix double free bug in _unregister()

2016-08-09 Thread Max Kellermann
While removing all interfaces in media_device_unregister(), all
media_interface pointers are freed.  This is illegal and results in
double kfree() if any media_interface is still linked at this point;
maybe because a userspace process still has a file handle.  Once the
process closes the file handle, dvb_media_device_free() gets called,
which frees the dvb_device.intf_devnode again.

This patch removes the unnecessary kfree() call, and documents who's
responsible for really freeing it.

Signed-off-by: Max Kellermann 
---
 drivers/media/media-device.c |6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 1795abe..113a4d1 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -803,9 +803,13 @@ void media_device_unregister(struct media_device *mdev)
/* Remove all interfaces from the media device */
list_for_each_entry_safe(intf, tmp_intf, >interfaces,
 graph_obj.list) {
+   /*
+* Unlink the interface, but don't free it here; the
+* module which created it is responsible for freeing
+* it
+*/
__media_remove_intf_links(intf);
media_gobj_destroy(>graph_obj);
-   kfree(intf);
}
 
mutex_unlock(>graph_mutex);



[PATCH 07/12] [media] dvb_frontend: merge the two dvb_frontend_detach() versions

2016-08-09 Thread Max Kellermann
This code duplication is confusing and error prone.  Let's merge them
by moving the release/dvb_detach call into one function with one
#ifdef.

Signed-off-by: Max Kellermann 
---
 drivers/media/dvb-core/dvb_frontend.c |   42 +
 1 file changed, 12 insertions(+), 30 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c 
b/drivers/media/dvb-core/dvb_frontend.c
index fea635b..1177414 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -2754,40 +2754,22 @@ int dvb_unregister_frontend(struct dvb_frontend* fe)
 }
 EXPORT_SYMBOL(dvb_unregister_frontend);
 
-#ifdef CONFIG_MEDIA_ATTACH
-void dvb_frontend_detach(struct dvb_frontend* fe)
+static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
+   void (*release)(struct dvb_frontend 
*fe))
 {
-   void *ptr;
-
-   if (fe->ops.release_sec) {
-   fe->ops.release_sec(fe);
-   dvb_detach(fe->ops.release_sec);
-   }
-   if (fe->ops.tuner_ops.release) {
-   fe->ops.tuner_ops.release(fe);
-   dvb_detach(fe->ops.tuner_ops.release);
-   }
-   if (fe->ops.analog_ops.release) {
-   fe->ops.analog_ops.release(fe);
-   dvb_detach(fe->ops.analog_ops.release);
-   }
-   ptr = (void*)fe->ops.release;
-   if (ptr) {
-   fe->ops.release(fe);
-   dvb_detach(ptr);
+   if (release) {
+   release(fe);
+#ifdef CONFIG_MEDIA_ATTACH
+   dvb_detach(release);
+#endif
}
 }
-#else
+
 void dvb_frontend_detach(struct dvb_frontend* fe)
 {
-   if (fe->ops.release_sec)
-   fe->ops.release_sec(fe);
-   if (fe->ops.tuner_ops.release)
-   fe->ops.tuner_ops.release(fe);
-   if (fe->ops.analog_ops.release)
-   fe->ops.analog_ops.release(fe);
-   if (fe->ops.release)
-   fe->ops.release(fe);
+   dvb_frontend_invoke_release(fe, fe->ops.release_sec);
+   dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release);
+   dvb_frontend_invoke_release(fe, fe->ops.analog_ops.release);
+   dvb_frontend_invoke_release(fe, fe->ops.release);
 }
-#endif
 EXPORT_SYMBOL(dvb_frontend_detach);



Re: [RFC PATCH v5 1/3] net: Add mask for Control register 10Mbps speed

2016-08-09 Thread Florian Fainelli
On 08/09/2016 02:34 AM, Kedareswara rao Appana wrote:
> This patch adds mask for the Control register
> 10Mbps speed.
> 
> Signed-off-by: Kedareswara rao Appana 

Reviewed-by: Florian Fainelli 
-- 
Florian


Re: [RFC PATCH v5 1/3] net: Add mask for Control register 10Mbps speed

2016-08-09 Thread Florian Fainelli
On 08/09/2016 02:34 AM, Kedareswara rao Appana wrote:
> This patch adds mask for the Control register
> 10Mbps speed.
> 
> Signed-off-by: Kedareswara rao Appana 

Reviewed-by: Florian Fainelli 
-- 
Florian


Re: [RFC PATCH v7 1/7] Restartable sequences system call

2016-08-09 Thread Peter Zijlstra
On Tue, Aug 09, 2016 at 08:06:40PM +, Mathieu Desnoyers wrote:
> >> +static int rseq_increment_event_counter(struct task_struct *t)
> >> +{
> >> +  if (__put_user(++t->rseq_event_counter,
> >> +  >rseq->u.e.event_counter))
> >> +  return -1;
> >> +  return 0;
> >> +}

> >> +void __rseq_handle_notify_resume(struct pt_regs *regs)
> >> +{
> >> +  struct task_struct *t = current;
> >> +
> >> +  if (unlikely(t->flags & PF_EXITING))
> >> +  return;
> >> +  if (!access_ok(VERIFY_WRITE, t->rseq, sizeof(*t->rseq)))
> >> +  goto error;
> >> +  if (__put_user(raw_smp_processor_id(), >rseq->u.e.cpu_id))
> >> +  goto error;
> >> +  if (rseq_increment_event_counter(t))
> > 
> > It seems a shame to not use a single __put_user() here. You did the
> > layout to explicitly allow for this, but then you don't.
> 
> The event counter increment needs to be performed at least once before
> returning to user-space whenever the thread is preempted or has a signal
> delivered. This counter increment needs to occur even if we are not nested
> over a restartable assembly block. (more detailed explanation about this
> follows at the end of this email)
> 
> The rseq_ip_fixup only ever needs to update the rseq_cs pointer
> field if it preempts/delivers a signal over a restartable
> assembly block, which happens very rarely.
> 
> Therefore, since the event counter increment is more frequent than
> setting rseq_cs ptr, I don't see much value in trying to combine
> those two into a single __put_user().
> 
> The reason why I combined both the cpu_id and event_counter
> fields into the same 64-bit integer is for user-space rseq_start()
> to be able to fetch them through a single load when the architecture
> allows it.

I wasn't talking about the rseq_up_fixup(), I was talking about both
unconditional __put_user()'s on cpu_id and event_counter.

These are 2 unconditinoal u32 stores that could very easily be done as a
single u64 store (on 64bit hardware).


Re: [RFC PATCH v7 1/7] Restartable sequences system call

2016-08-09 Thread Peter Zijlstra
On Tue, Aug 09, 2016 at 08:06:40PM +, Mathieu Desnoyers wrote:
> >> +static int rseq_increment_event_counter(struct task_struct *t)
> >> +{
> >> +  if (__put_user(++t->rseq_event_counter,
> >> +  >rseq->u.e.event_counter))
> >> +  return -1;
> >> +  return 0;
> >> +}

> >> +void __rseq_handle_notify_resume(struct pt_regs *regs)
> >> +{
> >> +  struct task_struct *t = current;
> >> +
> >> +  if (unlikely(t->flags & PF_EXITING))
> >> +  return;
> >> +  if (!access_ok(VERIFY_WRITE, t->rseq, sizeof(*t->rseq)))
> >> +  goto error;
> >> +  if (__put_user(raw_smp_processor_id(), >rseq->u.e.cpu_id))
> >> +  goto error;
> >> +  if (rseq_increment_event_counter(t))
> > 
> > It seems a shame to not use a single __put_user() here. You did the
> > layout to explicitly allow for this, but then you don't.
> 
> The event counter increment needs to be performed at least once before
> returning to user-space whenever the thread is preempted or has a signal
> delivered. This counter increment needs to occur even if we are not nested
> over a restartable assembly block. (more detailed explanation about this
> follows at the end of this email)
> 
> The rseq_ip_fixup only ever needs to update the rseq_cs pointer
> field if it preempts/delivers a signal over a restartable
> assembly block, which happens very rarely.
> 
> Therefore, since the event counter increment is more frequent than
> setting rseq_cs ptr, I don't see much value in trying to combine
> those two into a single __put_user().
> 
> The reason why I combined both the cpu_id and event_counter
> fields into the same 64-bit integer is for user-space rseq_start()
> to be able to fetch them through a single load when the architecture
> allows it.

I wasn't talking about the rseq_up_fixup(), I was talking about both
unconditional __put_user()'s on cpu_id and event_counter.

These are 2 unconditinoal u32 stores that could very easily be done as a
single u64 store (on 64bit hardware).


Re: [RFC PATCH v5 3/3] net: phy: Add gmiitorgmii converter support

2016-08-09 Thread Florian Fainelli
On 08/09/2016 02:34 AM, Kedareswara rao Appana wrote:
> This patch adds support for gmiitorgmii converter.
> 
> The GMII to RGMII IP core provides the Reduced Gigabit Media
> Independent Interface (RGMII) between Ethernet physical media
> Devices and the Gigabit Ethernet controller. This core can
> Switch dynamically between the three different speed modes of
> Operation by configuring the converter register through mdio write.
> 
> MDIO interface is used to set operating speed of Ethernet MAC.
> 
> This converter sits between the MAC and the external phy
> MAC <==> GMII2RGMII <==> RGMII_PHY

This looks good, just a few things, see below:

> 
> Signed-off-by: Kedareswara rao Appana 
> ---
> Thanks a lot Andrew for your inputs.
> Changes for v5:
> --> Fixed return values in the probe as suggested by punnaiah.
> --> Added a mask for the converter speed as suggested by punnaiah.
> Changes for v4:
> --> Updated phydev speed for all 3 speeds as suggested by zhuyj.
> Changes for v3:
> --> Updated the driver as suggested by Andrew.
> Changes for v2:
> --> Passed struct xphy pointer directly to the fix_mac_speed
> API as suggested by the Florian.
> --> Added checks for the phy-node fail case as suggested
> by the Florian
> 
>  drivers/net/phy/Kconfig |   8 +++
>  drivers/net/phy/Makefile|   1 +
>  drivers/net/phy/xilinx_gmii2rgmii.c | 121 
> 
>  3 files changed, 130 insertions(+)
>  create mode 100644 drivers/net/phy/xilinx_gmii2rgmii.c
> 
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index 1b534ea..c79f347 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -312,6 +312,14 @@ config MICROSEMI_PHY
>  ---help---
>Currently supports the VSC8531 and VSC8541 PHYs
>  
> +config XILINX_GMII2RGMII
> +   tristate "Xilinx GMII2RGMII converter driver"
> +   default y

Don't force that, or at least make the default based on the potential
users/drivers here.

> +   ---help---
> + This driver support xilinx GMII to RGMII IP core it provides
> + the Reduced Gigabit Media Independent Interface(RGMII) between
> + Ethernet physical media devices and the Gigabit Ethernet controller.
> +
>  endif # PHYLIB
>  
>  config MICREL_KS8995MA
> diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
> index a713bd4..73d65ce 100644
> --- a/drivers/net/phy/Makefile
> +++ b/drivers/net/phy/Makefile
> @@ -50,3 +50,4 @@ obj-$(CONFIG_MDIO_BCM_IPROC)+= mdio-bcm-iproc.o
>  obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o
>  obj-$(CONFIG_MDIO_HISI_FEMAC)+= mdio-hisi-femac.o
>  obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o
> +obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
> diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c 
> b/drivers/net/phy/xilinx_gmii2rgmii.c
> new file mode 100644
> index 000..1456e27
> --- /dev/null
> +++ b/drivers/net/phy/xilinx_gmii2rgmii.c
> @@ -0,0 +1,121 @@
> +/* Xilinx GMII2RGMII Converter driver
> + *
> + * Copyright (C) 2016 Xilinx, Inc.
> + *
> + * Author: Kedareswara rao Appana 
> + *
> + * Description:
> + * This driver is developed for Xilinx GMII2RGMII Converter
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define XILINX_GMII2RGMII_REG0x10
> +#define XILINX_GMII2RGMII_SPEED_MASK 0x2040

BMCR_SPEED1000 | BMCR_SPEED100 would be clearer here.

> +
> +struct gmii2rgmii {
> + struct phy_device *phy_dev;
> + struct phy_driver *phy_drv;
> + struct phy_driver conv_phy_drv;
> + int addr;
> +};
> +
> +static int xgmiitorgmii_read_status(struct phy_device *phydev)
> +{
> + struct gmii2rgmii *priv = (struct gmii2rgmii *)phydev->priv;

Casting is not required here, priv is void *.

> + u16 val = 0;
> +
> + priv->phy_drv->read_status(phydev);
> +
> + val = mdiobus_read(phydev->mdio.bus, priv->addr, XILINX_GMII2RGMII_REG);
> + val &= XILINX_GMII2RGMII_SPEED_MASK;
> +
> + switch (phydev->speed) {
> + case SPEED_1000:
> + val |= BMCR_SPEED1000;

Is the fall through really intentional here? See genphy_setup_forced()
for instance.

> + case SPEED_100:
> + val |= BMCR_SPEED100;
> + case SPEED_10:
> + val |= BMCR_SPEED10;
> + }
> +
> + mdiobus_write(phydev->mdio.bus, priv->addr, XILINX_GMII2RGMII_REG, val);
> +
> + return 0;
> +}

Re: [RFC PATCH v5 3/3] net: phy: Add gmiitorgmii converter support

2016-08-09 Thread Florian Fainelli
On 08/09/2016 02:34 AM, Kedareswara rao Appana wrote:
> This patch adds support for gmiitorgmii converter.
> 
> The GMII to RGMII IP core provides the Reduced Gigabit Media
> Independent Interface (RGMII) between Ethernet physical media
> Devices and the Gigabit Ethernet controller. This core can
> Switch dynamically between the three different speed modes of
> Operation by configuring the converter register through mdio write.
> 
> MDIO interface is used to set operating speed of Ethernet MAC.
> 
> This converter sits between the MAC and the external phy
> MAC <==> GMII2RGMII <==> RGMII_PHY

This looks good, just a few things, see below:

> 
> Signed-off-by: Kedareswara rao Appana 
> ---
> Thanks a lot Andrew for your inputs.
> Changes for v5:
> --> Fixed return values in the probe as suggested by punnaiah.
> --> Added a mask for the converter speed as suggested by punnaiah.
> Changes for v4:
> --> Updated phydev speed for all 3 speeds as suggested by zhuyj.
> Changes for v3:
> --> Updated the driver as suggested by Andrew.
> Changes for v2:
> --> Passed struct xphy pointer directly to the fix_mac_speed
> API as suggested by the Florian.
> --> Added checks for the phy-node fail case as suggested
> by the Florian
> 
>  drivers/net/phy/Kconfig |   8 +++
>  drivers/net/phy/Makefile|   1 +
>  drivers/net/phy/xilinx_gmii2rgmii.c | 121 
> 
>  3 files changed, 130 insertions(+)
>  create mode 100644 drivers/net/phy/xilinx_gmii2rgmii.c
> 
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index 1b534ea..c79f347 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -312,6 +312,14 @@ config MICROSEMI_PHY
>  ---help---
>Currently supports the VSC8531 and VSC8541 PHYs
>  
> +config XILINX_GMII2RGMII
> +   tristate "Xilinx GMII2RGMII converter driver"
> +   default y

Don't force that, or at least make the default based on the potential
users/drivers here.

> +   ---help---
> + This driver support xilinx GMII to RGMII IP core it provides
> + the Reduced Gigabit Media Independent Interface(RGMII) between
> + Ethernet physical media devices and the Gigabit Ethernet controller.
> +
>  endif # PHYLIB
>  
>  config MICREL_KS8995MA
> diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
> index a713bd4..73d65ce 100644
> --- a/drivers/net/phy/Makefile
> +++ b/drivers/net/phy/Makefile
> @@ -50,3 +50,4 @@ obj-$(CONFIG_MDIO_BCM_IPROC)+= mdio-bcm-iproc.o
>  obj-$(CONFIG_INTEL_XWAY_PHY) += intel-xway.o
>  obj-$(CONFIG_MDIO_HISI_FEMAC)+= mdio-hisi-femac.o
>  obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o
> +obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
> diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c 
> b/drivers/net/phy/xilinx_gmii2rgmii.c
> new file mode 100644
> index 000..1456e27
> --- /dev/null
> +++ b/drivers/net/phy/xilinx_gmii2rgmii.c
> @@ -0,0 +1,121 @@
> +/* Xilinx GMII2RGMII Converter driver
> + *
> + * Copyright (C) 2016 Xilinx, Inc.
> + *
> + * Author: Kedareswara rao Appana 
> + *
> + * Description:
> + * This driver is developed for Xilinx GMII2RGMII Converter
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define XILINX_GMII2RGMII_REG0x10
> +#define XILINX_GMII2RGMII_SPEED_MASK 0x2040

BMCR_SPEED1000 | BMCR_SPEED100 would be clearer here.

> +
> +struct gmii2rgmii {
> + struct phy_device *phy_dev;
> + struct phy_driver *phy_drv;
> + struct phy_driver conv_phy_drv;
> + int addr;
> +};
> +
> +static int xgmiitorgmii_read_status(struct phy_device *phydev)
> +{
> + struct gmii2rgmii *priv = (struct gmii2rgmii *)phydev->priv;

Casting is not required here, priv is void *.

> + u16 val = 0;
> +
> + priv->phy_drv->read_status(phydev);
> +
> + val = mdiobus_read(phydev->mdio.bus, priv->addr, XILINX_GMII2RGMII_REG);
> + val &= XILINX_GMII2RGMII_SPEED_MASK;
> +
> + switch (phydev->speed) {
> + case SPEED_1000:
> + val |= BMCR_SPEED1000;

Is the fall through really intentional here? See genphy_setup_forced()
for instance.

> + case SPEED_100:
> + val |= BMCR_SPEED100;
> + case SPEED_10:
> + val |= BMCR_SPEED10;
> + }
> +
> + mdiobus_write(phydev->mdio.bus, priv->addr, XILINX_GMII2RGMII_REG, val);
> +
> + return 0;
> +}
[snip]

> +static int __init 

Re: [PATCH] mm/vmalloc: fix align value calculation error

2016-08-09 Thread Andrew Morton
On Fri, 5 Aug 2016 23:48:21 +0800 zijun_hu  wrote:

> From: zijun_hu 
> Date: Fri, 5 Aug 2016 22:10:07 +0800
> Subject: [PATCH 1/1] mm/vmalloc: fix align value calculation error
> 
> it causes double align requirement for __get_vm_area_node() if parameter
> size is power of 2 and VM_IOREMAP is set in parameter flags
> 
> get_order_long() is implemented and used instead of fls_long() for
> fixing the bug

Makes sense.  I think.

> --- a/include/linux/bitops.h
> +++ b/include/linux/bitops.h
> @@ -192,6 +192,23 @@ static inline unsigned fls_long(unsigned long l)
>  }
>  
>  /**
> + * get_order_long - get order after rounding @l up to power of 2
> + * @l: parameter
> + *
> + * it is same as get_count_order() but long type parameter
> + * or 0 is returned if @l == 0UL
> + */
> +static inline int get_order_long(unsigned long l)
> +{
> + if (l == 0UL)
> + return 0;
> + else if (l & (l - 1UL))
> + return fls_long(l);
> + else
> + return fls_long(l) - 1;
> +}
> +
> +/**
>   * __ffs64 - find first set bit in a 64 bit word
>   * @word: The 64 bit word
>   *
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index 91f44e7..7d717f3 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -1360,7 +1360,7 @@ static struct vm_struct *__get_vm_area_node(unsigned 
> long size,
>  
>   BUG_ON(in_interrupt());
>   if (flags & VM_IOREMAP)
> - align = 1ul << clamp_t(int, fls_long(size),
> + align = 1ul << clamp_t(int, get_order_long(size),
>  PAGE_SHIFT, IOREMAP_MAX_ORDER);
>  
>   size = PAGE_ALIGN(size);

It would be better to call this get_count_order_long(), I think?  To
match get_count_order()?

get_count_order() is a weird name and perhaps both of these should be
renamed to things which actually make sense.  That's a separate issue.

--- a/include/linux/bitops.h~mm-vmalloc-fix-align-value-calculation-error-fix
+++ a/include/linux/bitops.h
@@ -75,6 +75,23 @@ static inline int get_count_order(unsign
return order;
 }
 
+/**
+ * get_count_order_long - get order after rounding @l up to power of 2
+ * @l: parameter
+ *
+ * The same as get_count_order() but accepts a long type parameter
+ * or 0 is returned if @l == 0UL
+ */
+static inline int get_count_order_long(unsigned long l)
+{
+   if (l == 0UL)
+   return 0;
+   else if (l & (l - 1UL))
+   return fls_long(l);
+   else
+   return fls_long(l) - 1;
+}
+
 static __always_inline unsigned long hweight_long(unsigned long w)
 {
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
@@ -192,23 +209,6 @@ static inline unsigned fls_long(unsigned
 }
 
 /**
- * get_order_long - get order after rounding @l up to power of 2
- * @l: parameter
- *
- * it is same as get_count_order() but long type parameter
- * or 0 is returned if @l == 0UL
- */
-static inline int get_order_long(unsigned long l)
-{
-   if (l == 0UL)
-   return 0;
-   else if (l & (l - 1UL))
-   return fls_long(l);
-   else
-   return fls_long(l) - 1;
-}
-
-/**
  * __ffs64 - find first set bit in a 64 bit word
  * @word: The 64 bit word
  *
--- a/mm/vmalloc.c~mm-vmalloc-fix-align-value-calculation-error-fix
+++ a/mm/vmalloc.c
@@ -1360,7 +1360,7 @@ static struct vm_struct *__get_vm_area_n
 
BUG_ON(in_interrupt());
if (flags & VM_IOREMAP)
-   align = 1ul << clamp_t(int, get_order_long(size),
+   align = 1ul << clamp_t(int, get_count_order_long(size),
   PAGE_SHIFT, IOREMAP_MAX_ORDER);
 
size = PAGE_ALIGN(size);
_



Re: [PATCH] mm/vmalloc: fix align value calculation error

2016-08-09 Thread Andrew Morton
On Fri, 5 Aug 2016 23:48:21 +0800 zijun_hu  wrote:

> From: zijun_hu 
> Date: Fri, 5 Aug 2016 22:10:07 +0800
> Subject: [PATCH 1/1] mm/vmalloc: fix align value calculation error
> 
> it causes double align requirement for __get_vm_area_node() if parameter
> size is power of 2 and VM_IOREMAP is set in parameter flags
> 
> get_order_long() is implemented and used instead of fls_long() for
> fixing the bug

Makes sense.  I think.

> --- a/include/linux/bitops.h
> +++ b/include/linux/bitops.h
> @@ -192,6 +192,23 @@ static inline unsigned fls_long(unsigned long l)
>  }
>  
>  /**
> + * get_order_long - get order after rounding @l up to power of 2
> + * @l: parameter
> + *
> + * it is same as get_count_order() but long type parameter
> + * or 0 is returned if @l == 0UL
> + */
> +static inline int get_order_long(unsigned long l)
> +{
> + if (l == 0UL)
> + return 0;
> + else if (l & (l - 1UL))
> + return fls_long(l);
> + else
> + return fls_long(l) - 1;
> +}
> +
> +/**
>   * __ffs64 - find first set bit in a 64 bit word
>   * @word: The 64 bit word
>   *
> diff --git a/mm/vmalloc.c b/mm/vmalloc.c
> index 91f44e7..7d717f3 100644
> --- a/mm/vmalloc.c
> +++ b/mm/vmalloc.c
> @@ -1360,7 +1360,7 @@ static struct vm_struct *__get_vm_area_node(unsigned 
> long size,
>  
>   BUG_ON(in_interrupt());
>   if (flags & VM_IOREMAP)
> - align = 1ul << clamp_t(int, fls_long(size),
> + align = 1ul << clamp_t(int, get_order_long(size),
>  PAGE_SHIFT, IOREMAP_MAX_ORDER);
>  
>   size = PAGE_ALIGN(size);

It would be better to call this get_count_order_long(), I think?  To
match get_count_order()?

get_count_order() is a weird name and perhaps both of these should be
renamed to things which actually make sense.  That's a separate issue.

--- a/include/linux/bitops.h~mm-vmalloc-fix-align-value-calculation-error-fix
+++ a/include/linux/bitops.h
@@ -75,6 +75,23 @@ static inline int get_count_order(unsign
return order;
 }
 
+/**
+ * get_count_order_long - get order after rounding @l up to power of 2
+ * @l: parameter
+ *
+ * The same as get_count_order() but accepts a long type parameter
+ * or 0 is returned if @l == 0UL
+ */
+static inline int get_count_order_long(unsigned long l)
+{
+   if (l == 0UL)
+   return 0;
+   else if (l & (l - 1UL))
+   return fls_long(l);
+   else
+   return fls_long(l) - 1;
+}
+
 static __always_inline unsigned long hweight_long(unsigned long w)
 {
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
@@ -192,23 +209,6 @@ static inline unsigned fls_long(unsigned
 }
 
 /**
- * get_order_long - get order after rounding @l up to power of 2
- * @l: parameter
- *
- * it is same as get_count_order() but long type parameter
- * or 0 is returned if @l == 0UL
- */
-static inline int get_order_long(unsigned long l)
-{
-   if (l == 0UL)
-   return 0;
-   else if (l & (l - 1UL))
-   return fls_long(l);
-   else
-   return fls_long(l) - 1;
-}
-
-/**
  * __ffs64 - find first set bit in a 64 bit word
  * @word: The 64 bit word
  *
--- a/mm/vmalloc.c~mm-vmalloc-fix-align-value-calculation-error-fix
+++ a/mm/vmalloc.c
@@ -1360,7 +1360,7 @@ static struct vm_struct *__get_vm_area_n
 
BUG_ON(in_interrupt());
if (flags & VM_IOREMAP)
-   align = 1ul << clamp_t(int, get_order_long(size),
+   align = 1ul << clamp_t(int, get_count_order_long(size),
   PAGE_SHIFT, IOREMAP_MAX_ORDER);
 
size = PAGE_ALIGN(size);
_



Re: [RFC][PATCH 5/3] tracing: Add smi counting to HWLAT

2016-08-09 Thread Peter Zijlstra
On Tue, Aug 09, 2016 at 02:05:43PM -0400, Steven Rostedt wrote:
> +int arch_smi_count(void)
> +{
> + unsigned long long count;
> + int err;
> +
> + err = rdmsrl_safe(MSR_SMI_COUNT, );
> + if (err)
> + return 0;

That's really yucky, relying on _safe() to detect availability.

Also, I just found AMD Fam15h has this counter through PMCs (event
0x2b).

> +
> + return count;
> +}


Re: [RFC][PATCH 5/3] tracing: Add smi counting to HWLAT

2016-08-09 Thread Peter Zijlstra
On Tue, Aug 09, 2016 at 02:05:43PM -0400, Steven Rostedt wrote:
> +int arch_smi_count(void)
> +{
> + unsigned long long count;
> + int err;
> +
> + err = rdmsrl_safe(MSR_SMI_COUNT, );
> + if (err)
> + return 0;

That's really yucky, relying on _safe() to detect availability.

Also, I just found AMD Fam15h has this counter through PMCs (event
0x2b).

> +
> + return count;
> +}


Re: [Resend][PATCH] x86/power/64: Always create temporary identity mapping correctly

2016-08-09 Thread Rafael J. Wysocki
On Tue, Aug 9, 2016 at 10:02 PM, Jiri Kosina  wrote:
> On Tue, 9 Aug 2016, Rafael J. Wysocki wrote:
>
>> I have a murky suspicion, but it is really weird.  Namely, what if
>> restore_jump_address in set_up_temporary_text_mapping() happens to be
>> covered by the restore kernel's identity mapping?  Then, the image
>> kernel's entry point may get overwritten by something else in
>> core_restore_code().
>
> So this made me to actually test a scenario where I'd suspend a kernel
> that's known-broken (i.e. contains 021182e52fe), and then have it resumed
> by a kernel that has 021182e52fe reverted. It resumed successfully.
>
> Just a datapoint.

That indicates the problem is somewhere in the restore kernel and no
surprises there.

I am able to reproduce the original problem (a triple fault on resume
with CONFIG_RANDOMIZE_MEMORY set) without the $subject patch, but the
patch fixes it for me.

Question is why it is not sufficient for you and Boris and the above
theory is about the only one I can come up with ATM.

I'm going to compare the configs etc, but I guess I just end up
writing a patch to test that theory unless someone has any other idea
in the meantime.

Thanks,
Rafael


Re: [Resend][PATCH] x86/power/64: Always create temporary identity mapping correctly

2016-08-09 Thread Rafael J. Wysocki
On Tue, Aug 9, 2016 at 10:02 PM, Jiri Kosina  wrote:
> On Tue, 9 Aug 2016, Rafael J. Wysocki wrote:
>
>> I have a murky suspicion, but it is really weird.  Namely, what if
>> restore_jump_address in set_up_temporary_text_mapping() happens to be
>> covered by the restore kernel's identity mapping?  Then, the image
>> kernel's entry point may get overwritten by something else in
>> core_restore_code().
>
> So this made me to actually test a scenario where I'd suspend a kernel
> that's known-broken (i.e. contains 021182e52fe), and then have it resumed
> by a kernel that has 021182e52fe reverted. It resumed successfully.
>
> Just a datapoint.

That indicates the problem is somewhere in the restore kernel and no
surprises there.

I am able to reproduce the original problem (a triple fault on resume
with CONFIG_RANDOMIZE_MEMORY set) without the $subject patch, but the
patch fixes it for me.

Question is why it is not sufficient for you and Boris and the above
theory is about the only one I can come up with ATM.

I'm going to compare the configs etc, but I guess I just end up
writing a patch to test that theory unless someone has any other idea
in the meantime.

Thanks,
Rafael


Re: [PACTH v1] mm, proc: Implement /proc//totmaps

2016-08-09 Thread Robert Foss



On 2016-08-09 03:24 PM, Jann Horn wrote:

On Tue, Aug 09, 2016 at 12:05:43PM -0400, robert.f...@collabora.com wrote:

From: Sonny Rao 

This is based on earlier work by Thiago Goncales. It implements a new
per process proc file which summarizes the contents of the smaps file
but doesn't display any addresses.  It gives more detailed information
than statm like the PSS (proprotional set size).  It differs from the
original implementation in that it doesn't use the full blown set of
seq operations, uses a different termination condition, and doesn't
displayed "Locked" as that was broken on the original implemenation.

This new proc file provides information faster than parsing the potentially
huge smaps file.

Signed-off-by: Sonny Rao 

Tested-by: Robert Foss 
Signed-off-by: Robert Foss 




+static int totmaps_proc_show(struct seq_file *m, void *data)
+{
+   struct proc_maps_private *priv = m->private;
+   struct mm_struct *mm;
+   struct vm_area_struct *vma;
+   struct mem_size_stats *mss_sum = priv->mss;
+
+   /* reference to priv->task already taken */
+   /* but need to get the mm here because */
+   /* task could be in the process of exiting */


Can you please elaborate on this? My understanding here is that you
intend for the caller to be able to repeatedly read the same totmaps
file with pread() and still see updated information after the target
process has called execve() and be able to detect process death
(instead of simply seeing stale values). Is that accurate?

I would prefer it if you could grab a reference to the mm_struct
directly at open time.


Sonny, do you know more about the above comment?





+   mm = get_task_mm(priv->task);
+   if (!mm || IS_ERR(mm))
+   return -EINVAL;


get_task_mm() doesn't return error codes, and all other callers just
check whether the return value is NULL.



I'll have that fixed in v2, thanks for spotting it!




+   down_read(>mmap_sem);
+   hold_task_mempolicy(priv);
+
+   for (vma = mm->mmap; vma != priv->tail_vma; vma = vma->vm_next) {
+   struct mem_size_stats mss;
+   struct mm_walk smaps_walk = {
+   .pmd_entry = smaps_pte_range,
+   .mm = vma->vm_mm,
+   .private = ,
+   };
+
+   if (vma->vm_mm && !is_vm_hugetlb_page(vma)) {
+   memset(, 0, sizeof(mss));
+   walk_page_vma(vma, _walk);
+   add_smaps_sum(, mss_sum);
+   }
+   }


E... what? You accumulate values from mem_size_stats items into a
struct mss_sum that is associated with the struct file? So when you
read the file the second time, you get the old values plus the new ones?
And when you read the file in parallel, you get inconsistent values?

For most files in procfs, the behavior is that you can just call
pread(fd, buf, sizeof(buf), 0) on the same fd again and again, giving
you the current values every time, without mutating state. I strongly
recommend that you get rid of priv->mss and just accumulate the state
in a local variable (maybe one on the stack).


So a simple "static struct mem_size_stats" in totmaps_proc_show() would 
be a better solution?






@@ -836,6 +911,50 @@ static int tid_smaps_open(struct inode *inode, struct file 
*file)
return do_maps_open(inode, file, _tid_smaps_op);
 }

+static int totmaps_open(struct inode *inode, struct file *file)
+{
+   struct proc_maps_private *priv;
+   int ret = -ENOMEM;
+   priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+   if (priv) {
+   priv->mss = kzalloc(sizeof(*priv->mss), GFP_KERNEL);
+   if (!priv->mss)
+   return -ENOMEM;


Memory leak: If the first allocation works and the second one doesn't, this
doesn't free the first allocation.

Please change this to use the typical goto pattern for error handling.


Fix will be implemented in v2.




+
+   /* we need to grab references to the task_struct */
+   /* at open time, because there's a potential information */
+   /* leak where the totmaps file is opened and held open */
+   /* while the underlying pid to task mapping changes */
+   /* underneath it */


Nit: That's not how comments are done in the kernel. Maybe change this to
a normal block comment instead of one block comment per line?


I'm not sure how that one slipped by, but I'll change it in v2.




+   priv->task = get_pid_task(proc_pid(inode), PIDTYPE_PID);


`get_pid_task(proc_pid(inode), PIDTYPE_PID)` is exactly the definition
of get_proc_task(inode), maybe use that instead?



Will do. v2 will fix this.


+   if (!priv->task) {
+   kfree(priv->mss);
+   kfree(priv);
+   

Re: [PACTH v1] mm, proc: Implement /proc//totmaps

2016-08-09 Thread Robert Foss



On 2016-08-09 03:24 PM, Jann Horn wrote:

On Tue, Aug 09, 2016 at 12:05:43PM -0400, robert.f...@collabora.com wrote:

From: Sonny Rao 

This is based on earlier work by Thiago Goncales. It implements a new
per process proc file which summarizes the contents of the smaps file
but doesn't display any addresses.  It gives more detailed information
than statm like the PSS (proprotional set size).  It differs from the
original implementation in that it doesn't use the full blown set of
seq operations, uses a different termination condition, and doesn't
displayed "Locked" as that was broken on the original implemenation.

This new proc file provides information faster than parsing the potentially
huge smaps file.

Signed-off-by: Sonny Rao 

Tested-by: Robert Foss 
Signed-off-by: Robert Foss 




+static int totmaps_proc_show(struct seq_file *m, void *data)
+{
+   struct proc_maps_private *priv = m->private;
+   struct mm_struct *mm;
+   struct vm_area_struct *vma;
+   struct mem_size_stats *mss_sum = priv->mss;
+
+   /* reference to priv->task already taken */
+   /* but need to get the mm here because */
+   /* task could be in the process of exiting */


Can you please elaborate on this? My understanding here is that you
intend for the caller to be able to repeatedly read the same totmaps
file with pread() and still see updated information after the target
process has called execve() and be able to detect process death
(instead of simply seeing stale values). Is that accurate?

I would prefer it if you could grab a reference to the mm_struct
directly at open time.


Sonny, do you know more about the above comment?





+   mm = get_task_mm(priv->task);
+   if (!mm || IS_ERR(mm))
+   return -EINVAL;


get_task_mm() doesn't return error codes, and all other callers just
check whether the return value is NULL.



I'll have that fixed in v2, thanks for spotting it!




+   down_read(>mmap_sem);
+   hold_task_mempolicy(priv);
+
+   for (vma = mm->mmap; vma != priv->tail_vma; vma = vma->vm_next) {
+   struct mem_size_stats mss;
+   struct mm_walk smaps_walk = {
+   .pmd_entry = smaps_pte_range,
+   .mm = vma->vm_mm,
+   .private = ,
+   };
+
+   if (vma->vm_mm && !is_vm_hugetlb_page(vma)) {
+   memset(, 0, sizeof(mss));
+   walk_page_vma(vma, _walk);
+   add_smaps_sum(, mss_sum);
+   }
+   }


E... what? You accumulate values from mem_size_stats items into a
struct mss_sum that is associated with the struct file? So when you
read the file the second time, you get the old values plus the new ones?
And when you read the file in parallel, you get inconsistent values?

For most files in procfs, the behavior is that you can just call
pread(fd, buf, sizeof(buf), 0) on the same fd again and again, giving
you the current values every time, without mutating state. I strongly
recommend that you get rid of priv->mss and just accumulate the state
in a local variable (maybe one on the stack).


So a simple "static struct mem_size_stats" in totmaps_proc_show() would 
be a better solution?






@@ -836,6 +911,50 @@ static int tid_smaps_open(struct inode *inode, struct file 
*file)
return do_maps_open(inode, file, _tid_smaps_op);
 }

+static int totmaps_open(struct inode *inode, struct file *file)
+{
+   struct proc_maps_private *priv;
+   int ret = -ENOMEM;
+   priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+   if (priv) {
+   priv->mss = kzalloc(sizeof(*priv->mss), GFP_KERNEL);
+   if (!priv->mss)
+   return -ENOMEM;


Memory leak: If the first allocation works and the second one doesn't, this
doesn't free the first allocation.

Please change this to use the typical goto pattern for error handling.


Fix will be implemented in v2.




+
+   /* we need to grab references to the task_struct */
+   /* at open time, because there's a potential information */
+   /* leak where the totmaps file is opened and held open */
+   /* while the underlying pid to task mapping changes */
+   /* underneath it */


Nit: That's not how comments are done in the kernel. Maybe change this to
a normal block comment instead of one block comment per line?


I'm not sure how that one slipped by, but I'll change it in v2.




+   priv->task = get_pid_task(proc_pid(inode), PIDTYPE_PID);


`get_pid_task(proc_pid(inode), PIDTYPE_PID)` is exactly the definition
of get_proc_task(inode), maybe use that instead?



Will do. v2 will fix this.


+   if (!priv->task) {
+   kfree(priv->mss);
+   kfree(priv);
+   return -ESRCH;
+   }
+
+   ret = single_open(file, totmaps_proc_show, priv);
+  

[PATCH 6/6] mtd: spi-nor: Enable QPP for winbond parts

2016-08-09 Thread Jagan Teki
Enable QPP support for winbond flash parts.

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/spi-nor/spi-nor.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 66d6e0b..838f6ea 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -981,28 +981,28 @@ static const struct flash_info spi_nor_ids[] = {
{ "w25x80", INFO(0xef3014, 0, 64 * 1024,  16, SECT_4K) },
{ "w25x16", INFO(0xef3015, 0, 64 * 1024,  32, SECT_4K) },
{ "w25x32", INFO(0xef3016, 0, 64 * 1024,  64, SECT_4K) },
-   { "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K) },
+   { "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
{
"w25q32dw", INFO(0xef6016, 0, 64 * 1024,  64,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+   SPI_NOR_QUAD_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
-   { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
+   { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
{
"w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+   SPI_NOR_QUAD_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
{
"w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+   SPI_NOR_QUAD_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
-   { "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
-   { "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K) },
-   { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
-   { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) },
+   { "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
+   { "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
+   { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
+   { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
 
/* Catalyst / On Semiconductor -- non-JEDEC */
{ "cat25c11", CAT25_INFO(  16, 8, 16, 1, SPI_NOR_NO_ERASE | 
SPI_NOR_NO_FR) },
-- 
2.7.4



[PATCH 6/6] mtd: spi-nor: Enable QPP for winbond parts

2016-08-09 Thread Jagan Teki
Enable QPP support for winbond flash parts.

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/spi-nor/spi-nor.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 66d6e0b..838f6ea 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -981,28 +981,28 @@ static const struct flash_info spi_nor_ids[] = {
{ "w25x80", INFO(0xef3014, 0, 64 * 1024,  16, SECT_4K) },
{ "w25x16", INFO(0xef3015, 0, 64 * 1024,  32, SECT_4K) },
{ "w25x32", INFO(0xef3016, 0, 64 * 1024,  64, SECT_4K) },
-   { "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K) },
+   { "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
{
"w25q32dw", INFO(0xef6016, 0, 64 * 1024,  64,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+   SPI_NOR_QUAD_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
-   { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
+   { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
{
"w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+   SPI_NOR_QUAD_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
{
"w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+   SPI_NOR_QUAD_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
-   { "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
-   { "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K) },
-   { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
-   { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) },
+   { "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
+   { "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
+   { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
+   { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | 
SPI_NOR_QUAD_WRITE) },
 
/* Catalyst / On Semiconductor -- non-JEDEC */
{ "cat25c11", CAT25_INFO(  16, 8, 16, 1, SPI_NOR_NO_ERASE | 
SPI_NOR_NO_FR) },
-- 
2.7.4



Re: [PATCH] device probe: add self triggered delayed work request

2016-08-09 Thread Qing Huang



On 08/09/2016 03:11 AM, Shamir Rabinovitch wrote:

On Mon, Aug 08, 2016 at 05:10:05PM -0700, Qing Huang wrote:

Not sure if I understood your scenario. Why there is a deadlock here?


  CPU0   | CPU1
-
  driver_deferred_probe_add  | 
driver_deferred_probe_trigger_wrapper
   mutex_lock(_probe_mutex) |  
driver_deferred_probe_trigger
cancel_delayed_work(_probe_trigger_work)|   
mutex_lock(_probe_mutex)
 wait for "driver_deferred_probe_trigger_wrapper"|wait for 
"deferred_probe_mutex"

is this possible scenario with this patch?

if yes then CPU0 will wait for CPU1 to finish the delayed work whith
mutex deferred_probe_mutex held while CPU1 will try to finish the
delayed work and will wait for the same mutex forever.


CPU0 will not wait for "driver_deferred_probe_trigger_wrapper" to 
finish, it simply puts the work request onto the queue and returns.


Qing



it seems like dead lock scenario to me.

please say if this scenario is possible.

BR, Shamir Rabinovitch




Re: [PATCH] device probe: add self triggered delayed work request

2016-08-09 Thread Qing Huang



On 08/09/2016 03:11 AM, Shamir Rabinovitch wrote:

On Mon, Aug 08, 2016 at 05:10:05PM -0700, Qing Huang wrote:

Not sure if I understood your scenario. Why there is a deadlock here?


  CPU0   | CPU1
-
  driver_deferred_probe_add  | 
driver_deferred_probe_trigger_wrapper
   mutex_lock(_probe_mutex) |  
driver_deferred_probe_trigger
cancel_delayed_work(_probe_trigger_work)|   
mutex_lock(_probe_mutex)
 wait for "driver_deferred_probe_trigger_wrapper"|wait for 
"deferred_probe_mutex"

is this possible scenario with this patch?

if yes then CPU0 will wait for CPU1 to finish the delayed work whith
mutex deferred_probe_mutex held while CPU1 will try to finish the
delayed work and will wait for the same mutex forever.


CPU0 will not wait for "driver_deferred_probe_trigger_wrapper" to 
finish, it simply puts the work request onto the queue and returns.


Qing



it seems like dead lock scenario to me.

please say if this scenario is possible.

BR, Shamir Rabinovitch




Re: [Resend][PATCH] x86/power/64: Always create temporary identity mapping correctly

2016-08-09 Thread Rafael J. Wysocki
On Tue, Aug 9, 2016 at 6:27 PM, Thomas Garnier  wrote:
> On Tue, Aug 9, 2016 at 9:18 AM, Rafael J. Wysocki  wrote:
>> On Tue, Aug 9, 2016 at 5:05 PM, Jiri Kosina  wrote:
>>> On Tue, 9 Aug 2016, Thomas Garnier wrote:
>>>
 >> Okay, I did one-by-one reverts, and the one above, i.e.
 >>
 >>   commit 021182e52fe01c1f7b126f97fd6ba048dc4234fd
 >>   Author: Thomas Garnier 
 >>   Date:   Tue Jun 21 17:47:03 2016 -0700
 >>
 >>   x86/mm: Enable KASLR for physical mapping memory regions
 >>
 >> is the one that is the culprit on my machine. With this one reverted,
 >> resume hibernation doesn't reboot (tripple fault?), but proceeds
 >> succesfully.

 My .config is attached. It is basically defconfig (x86_64) + kvmconfig
 plus the following:

 CONFIG_PHYSICAL_START=0x100
 CONFIG_RELOCATABLE=y
 CONFIG_RANDOMIZE_BASE=y
 CONFIG_X86_NEED_RELOCS=y
 CONFIG_PHYSICAL_ALIGN=0x100
 CONFIG_RANDOMIZE_MEMORY=y
 CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING=0xa
 CONFIG_X86_PTDUMP_CORE=y
 CONFIG_X86_PTDUMP=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
 CONFIG_KALLSYMS_BASE_RELATIVE=y
 CONFIG_PANIC_ON_OOPS=y
 CONFIG_KGDB=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_EARLY_PRINTK_DBGP=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_INFO_DWARF4=y
>>>
>>> The config I am reproducing the bug with (on thinkpad x200s) can be found
>>> at
>>>
>>> http://www.jikos.cz/jikos/junk/.config
>>>
>>> Either later today or tomorrow I could test with the same physical start
>>> and align values you're using to see whether that'd make any difference.
>>>
 > As discussed with Rafael privately, I also tried this very patch
 > (x86/power/64: Always create temporary identity mapping correctly) on top
 > of the reverted revert of 021182e52fe01c1f7b1 (see the full log below),
 > but such kernel triple faults on resume as well.
 >
 > 87c38d2 x86/power/64: Always create temporary identity mapping correctly
 > 3cb504a Revert "Revert "x86/mm: Enable KASLR for physical mapping memory 
 > regions""
 > 758850d Revert "x86/mm: Enable KASLR for physical mapping memory regions"
 > 4a02dfb Revert "x86/mm: Enable KASLR for vmalloc memory regions"
 > 037863f Revert "x86/mm: Add memory hotplug support for KASLR memory 
 > randomization"
 > 3416a21 Revert "x86/mm: Do not reference phys addr beyond kernel"
 > 69227be Revert "mm: reorganize SLAB freelist randomization"
 > a1d8d71 Revert "mm: SLUB freelist randomization"
 >
 > IOW, 021182e52f introduces a bug for which there is no existing fix yet.

 You mean it is something different from the previous KASLR bugs we saw?
>>>
>>> No, I just wanted to explicitly point out that "x86/power/64: Always
>>> create temporary identity mapping correctly" is not a fix for this issue.
>>
>> It is better to say that the $subject patch is not sufficient to fix
>> it, because I'm quite confident that it is necessary for that. :-)
>>
>> Without the $subject patch kernel_ident_mapping_init() makes
>> assumptions that simply are not met in the randomized identity mapping
>> base case.  Moreover, hibernation works for Thomas with $subject patch
>> applied, but it doesn't without it.
>>
>> So there is something else that we are missing.
>>
>> I have a murky suspicion, but it is really weird.  Namely, what if
>> restore_jump_address in set_up_temporary_text_mapping() happens to be
>> covered by the restore kernel's identity mapping?  Then, the image
>> kernel's entry point may get overwritten by something else in
>> core_restore_code().
>>
>> But is this possible even?  Thomas?
>
> I had a similar theory before when I was investigating the original
> crash. How is it avoided even without KASLR?

It doesn't have to be actively avoided then.  restore_jump_address is
a kernel text address and if __PAGE_OFFSET is the same for both the
restore and image kernels, it is guaranteed to be above the identity
mapping in both of them.

If the base of the identity mapping is randomized in both of them,
though, that may not be guaranteed any more.

> Given the space for the physical memory mapping, I doubt this issue
> would happen all the time though.

It should not, but it's not impossible for it to happen every time, at
least in a small number of attempts.

Thanks,
Rafael


Re: [Resend][PATCH] x86/power/64: Always create temporary identity mapping correctly

2016-08-09 Thread Rafael J. Wysocki
On Tue, Aug 9, 2016 at 6:27 PM, Thomas Garnier  wrote:
> On Tue, Aug 9, 2016 at 9:18 AM, Rafael J. Wysocki  wrote:
>> On Tue, Aug 9, 2016 at 5:05 PM, Jiri Kosina  wrote:
>>> On Tue, 9 Aug 2016, Thomas Garnier wrote:
>>>
 >> Okay, I did one-by-one reverts, and the one above, i.e.
 >>
 >>   commit 021182e52fe01c1f7b126f97fd6ba048dc4234fd
 >>   Author: Thomas Garnier 
 >>   Date:   Tue Jun 21 17:47:03 2016 -0700
 >>
 >>   x86/mm: Enable KASLR for physical mapping memory regions
 >>
 >> is the one that is the culprit on my machine. With this one reverted,
 >> resume hibernation doesn't reboot (tripple fault?), but proceeds
 >> succesfully.

 My .config is attached. It is basically defconfig (x86_64) + kvmconfig
 plus the following:

 CONFIG_PHYSICAL_START=0x100
 CONFIG_RELOCATABLE=y
 CONFIG_RANDOMIZE_BASE=y
 CONFIG_X86_NEED_RELOCS=y
 CONFIG_PHYSICAL_ALIGN=0x100
 CONFIG_RANDOMIZE_MEMORY=y
 CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING=0xa
 CONFIG_X86_PTDUMP_CORE=y
 CONFIG_X86_PTDUMP=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
 CONFIG_KALLSYMS_BASE_RELATIVE=y
 CONFIG_PANIC_ON_OOPS=y
 CONFIG_KGDB=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_EARLY_PRINTK_DBGP=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_INFO_DWARF4=y
>>>
>>> The config I am reproducing the bug with (on thinkpad x200s) can be found
>>> at
>>>
>>> http://www.jikos.cz/jikos/junk/.config
>>>
>>> Either later today or tomorrow I could test with the same physical start
>>> and align values you're using to see whether that'd make any difference.
>>>
 > As discussed with Rafael privately, I also tried this very patch
 > (x86/power/64: Always create temporary identity mapping correctly) on top
 > of the reverted revert of 021182e52fe01c1f7b1 (see the full log below),
 > but such kernel triple faults on resume as well.
 >
 > 87c38d2 x86/power/64: Always create temporary identity mapping correctly
 > 3cb504a Revert "Revert "x86/mm: Enable KASLR for physical mapping memory 
 > regions""
 > 758850d Revert "x86/mm: Enable KASLR for physical mapping memory regions"
 > 4a02dfb Revert "x86/mm: Enable KASLR for vmalloc memory regions"
 > 037863f Revert "x86/mm: Add memory hotplug support for KASLR memory 
 > randomization"
 > 3416a21 Revert "x86/mm: Do not reference phys addr beyond kernel"
 > 69227be Revert "mm: reorganize SLAB freelist randomization"
 > a1d8d71 Revert "mm: SLUB freelist randomization"
 >
 > IOW, 021182e52f introduces a bug for which there is no existing fix yet.

 You mean it is something different from the previous KASLR bugs we saw?
>>>
>>> No, I just wanted to explicitly point out that "x86/power/64: Always
>>> create temporary identity mapping correctly" is not a fix for this issue.
>>
>> It is better to say that the $subject patch is not sufficient to fix
>> it, because I'm quite confident that it is necessary for that. :-)
>>
>> Without the $subject patch kernel_ident_mapping_init() makes
>> assumptions that simply are not met in the randomized identity mapping
>> base case.  Moreover, hibernation works for Thomas with $subject patch
>> applied, but it doesn't without it.
>>
>> So there is something else that we are missing.
>>
>> I have a murky suspicion, but it is really weird.  Namely, what if
>> restore_jump_address in set_up_temporary_text_mapping() happens to be
>> covered by the restore kernel's identity mapping?  Then, the image
>> kernel's entry point may get overwritten by something else in
>> core_restore_code().
>>
>> But is this possible even?  Thomas?
>
> I had a similar theory before when I was investigating the original
> crash. How is it avoided even without KASLR?

It doesn't have to be actively avoided then.  restore_jump_address is
a kernel text address and if __PAGE_OFFSET is the same for both the
restore and image kernels, it is guaranteed to be above the identity
mapping in both of them.

If the base of the identity mapping is randomized in both of them,
though, that may not be guaranteed any more.

> Given the space for the physical memory mapping, I doubt this issue
> would happen all the time though.

It should not, but it's not impossible for it to happen every time, at
least in a small number of attempts.

Thanks,
Rafael


Re: [PATCH v4 2/4] mfd: Add Samsung Exynos Low Power Audio Subsystem driver

2016-08-09 Thread Lee Jones
On Tue, 09 Aug 2016, Sylwester Nawrocki wrote:

> On 08/09/2016 05:05 PM, Lee Jones wrote:
> >> +static SIMPLE_DEV_PM_OPS(lpass_pm_ops, exynos_lpass_suspend,
> >> > +exynos_lpass_resume);
> > Put this up by the PM functions.
> 
> Sorry, I don't understand this comment, which PM functions do you
> mean exactly?

*_suspend and *_resume.  PM == Power Management.

You also need to place the functions in side some CONFIG_PM_SLEEP
guards.  Grep around, you'll see what I mean.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


Re: [PATCH v4 2/4] mfd: Add Samsung Exynos Low Power Audio Subsystem driver

2016-08-09 Thread Lee Jones
On Tue, 09 Aug 2016, Sylwester Nawrocki wrote:

> On 08/09/2016 05:05 PM, Lee Jones wrote:
> >> +static SIMPLE_DEV_PM_OPS(lpass_pm_ops, exynos_lpass_suspend,
> >> > +exynos_lpass_resume);
> > Put this up by the PM functions.
> 
> Sorry, I don't understand this comment, which PM functions do you
> mean exactly?

*_suspend and *_resume.  PM == Power Management.

You also need to place the functions in side some CONFIG_PM_SLEEP
guards.  Grep around, you'll see what I mean.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog


[PATCH 0/6] mtd: spi-nor: Add QPP support

2016-08-09 Thread Jagan Teki
This series adding support for 4-wire quad page program(32h)
for supported flash chips.

Jagan Teki (6):
  mtd: spi-nor: Add quad page program support
  mtd: m25p80: Use spi-nor quad page program
  mtd: spi-nor: Enable QPP for macronix parts
  mtd: spi-nor: Enable QPP for micron parts
  mtd: spi-nor: Enable QPP for spansion parts
  mtd: spi-nor: Enable QPP for winbond parts

 drivers/mtd/devices/m25p80.c  |  2 +
 drivers/mtd/spi-nor/spi-nor.c | 87 +--
 include/linux/mtd/spi-nor.h   |  2 +
 3 files changed, 54 insertions(+), 37 deletions(-)

-- 
2.7.4



[PATCH 0/6] mtd: spi-nor: Add QPP support

2016-08-09 Thread Jagan Teki
This series adding support for 4-wire quad page program(32h)
for supported flash chips.

Jagan Teki (6):
  mtd: spi-nor: Add quad page program support
  mtd: m25p80: Use spi-nor quad page program
  mtd: spi-nor: Enable QPP for macronix parts
  mtd: spi-nor: Enable QPP for micron parts
  mtd: spi-nor: Enable QPP for spansion parts
  mtd: spi-nor: Enable QPP for winbond parts

 drivers/mtd/devices/m25p80.c  |  2 +
 drivers/mtd/spi-nor/spi-nor.c | 87 +--
 include/linux/mtd/spi-nor.h   |  2 +
 3 files changed, 54 insertions(+), 37 deletions(-)

-- 
2.7.4



[PATCH 4/6] mtd: spi-nor: Enable QPP for micron parts

2016-08-09 Thread Jagan Teki
Enable QPP support for micron flash parts.

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/spi-nor/spi-nor.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 24a077d..05596cf 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -878,17 +878,17 @@ static const struct flash_info spi_nor_ids[] = {
{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ | 
SPI_NOR_QUAD_WRITE) },
 
/* Micron */
-   { "n25q032", INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) 
},
-   { "n25q032a",INFO(0x20bb16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) 
},
-   { "n25q064", INFO(0x20ba17, 0, 64 * 1024,  128, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "n25q064a",INFO(0x20bb17, 0, 64 * 1024,  128, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "n25q256a",INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "n25q512a",INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ) },
-   { "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ) },
-   { "n25q00",  INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ) },
-   { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ) },
+   { "n25q032", INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ | 
SPI_NOR_QUAD_WRITE) },
+   { "n25q032a",INFO(0x20bb16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ | 
SPI_NOR_QUAD_WRITE) },
+   { "n25q064", INFO(0x20ba17, 0, 64 * 1024,  128, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q064a",INFO(0x20bb17, 0, 64 * 1024,  128, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q256a",INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q512a",INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q00",  INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
 
/* PMC */
{ "pm25lv512",   INFO(0,0, 32 * 1024,2, SECT_4K_PMC) },
-- 
2.7.4



[PATCH 4/6] mtd: spi-nor: Enable QPP for micron parts

2016-08-09 Thread Jagan Teki
Enable QPP support for micron flash parts.

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/spi-nor/spi-nor.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 24a077d..05596cf 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -878,17 +878,17 @@ static const struct flash_info spi_nor_ids[] = {
{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ | 
SPI_NOR_QUAD_WRITE) },
 
/* Micron */
-   { "n25q032", INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) 
},
-   { "n25q032a",INFO(0x20bb16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) 
},
-   { "n25q064", INFO(0x20ba17, 0, 64 * 1024,  128, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "n25q064a",INFO(0x20bb17, 0, 64 * 1024,  128, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "n25q256a",INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "n25q512a",INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ) },
-   { "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ) },
-   { "n25q00",  INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ) },
-   { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ) },
+   { "n25q032", INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ | 
SPI_NOR_QUAD_WRITE) },
+   { "n25q032a",INFO(0x20bb16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ | 
SPI_NOR_QUAD_WRITE) },
+   { "n25q064", INFO(0x20ba17, 0, 64 * 1024,  128, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q064a",INFO(0x20bb17, 0, 64 * 1024,  128, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q256a",INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q512a",INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q00",  INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "n25q00a", INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
 
/* PMC */
{ "pm25lv512",   INFO(0,0, 32 * 1024,2, SECT_4K_PMC) },
-- 
2.7.4



[PATCH 1/6] mtd: spi-nor: Add quad page program support

2016-08-09 Thread Jagan Teki
Add quad page program support with the use of nor->flags
and then controller will use 4 lines for data transmission
which is quite faster than page program(02h)

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/spi-nor/spi-nor.c | 13 +
 include/linux/mtd/spi-nor.h   |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index d0fc165..f88bd7e 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -75,6 +75,7 @@ struct flash_info {
 * bit. Must be used with
 * SPI_NOR_HAS_LOCK.
 */
+#define SPI_NOR_QUAD_WRITE BIT(10) /* Flash supports Quad Write */
 };
 
 #define JEDEC_MFR(info)((info)->id[0])
@@ -1306,6 +1307,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
struct device *dev = nor->dev;
struct mtd_info *mtd = >mtd;
struct device_node *np = spi_nor_get_flash_node(nor);
+   bool need_quad = false;
int ret;
int i;
 
@@ -1441,6 +1443,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
return ret;
}
nor->flash_read = SPI_NOR_QUAD;
+   need_quad = true;
} else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) {
nor->flash_read = SPI_NOR_DUAL;
}
@@ -1465,6 +1468,16 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
}
 
nor->program_opcode = SPINOR_OP_PP;
+   if (nor->flags == SNOR_F_USE_QPP && info->flags & SPI_NOR_QUAD_WRITE) {
+   if (!need_quad)
+   ret = set_quad_mode(nor, info);
+   if (ret) {
+   dev_err(dev, "quad mode not supported\n");
+   return ret;
+   }
+   }
+   nor->program_opcode = SPINOR_OP_QPP;
+   }
 
if (info->addr_width)
nor->addr_width = info->addr_width;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index c425c7b..aa0e6cd 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -46,6 +46,7 @@
 #define SPINOR_OP_READ_1_1_2   0x3b/* Read data bytes (Dual SPI) */
 #define SPINOR_OP_READ_1_1_4   0x6b/* Read data bytes (Quad SPI) */
 #define SPINOR_OP_PP   0x02/* Page program (up to 256 bytes) */
+#define SPINOR_OP_QPP  0x32/* Quad Page program */
 #define SPINOR_OP_BE_4K0x20/* Erase 4KiB block */
 #define SPINOR_OP_BE_4K_PMC0xd7/* Erase 4KiB block on PMC chips */
 #define SPINOR_OP_BE_32K   0x52/* Erase 32KiB block */
@@ -119,6 +120,7 @@ enum spi_nor_ops {
 enum spi_nor_option_flags {
SNOR_F_USE_FSR  = BIT(0),
SNOR_F_HAS_SR_TB= BIT(1),
+   SNOR_F_USE_QPP  = BIT(2),
 };
 
 /**
-- 
2.7.4



[PATCH 1/6] mtd: spi-nor: Add quad page program support

2016-08-09 Thread Jagan Teki
Add quad page program support with the use of nor->flags
and then controller will use 4 lines for data transmission
which is quite faster than page program(02h)

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/spi-nor/spi-nor.c | 13 +
 include/linux/mtd/spi-nor.h   |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index d0fc165..f88bd7e 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -75,6 +75,7 @@ struct flash_info {
 * bit. Must be used with
 * SPI_NOR_HAS_LOCK.
 */
+#define SPI_NOR_QUAD_WRITE BIT(10) /* Flash supports Quad Write */
 };
 
 #define JEDEC_MFR(info)((info)->id[0])
@@ -1306,6 +1307,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
struct device *dev = nor->dev;
struct mtd_info *mtd = >mtd;
struct device_node *np = spi_nor_get_flash_node(nor);
+   bool need_quad = false;
int ret;
int i;
 
@@ -1441,6 +1443,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
return ret;
}
nor->flash_read = SPI_NOR_QUAD;
+   need_quad = true;
} else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) {
nor->flash_read = SPI_NOR_DUAL;
}
@@ -1465,6 +1468,16 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, 
enum read_mode mode)
}
 
nor->program_opcode = SPINOR_OP_PP;
+   if (nor->flags == SNOR_F_USE_QPP && info->flags & SPI_NOR_QUAD_WRITE) {
+   if (!need_quad)
+   ret = set_quad_mode(nor, info);
+   if (ret) {
+   dev_err(dev, "quad mode not supported\n");
+   return ret;
+   }
+   }
+   nor->program_opcode = SPINOR_OP_QPP;
+   }
 
if (info->addr_width)
nor->addr_width = info->addr_width;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index c425c7b..aa0e6cd 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -46,6 +46,7 @@
 #define SPINOR_OP_READ_1_1_2   0x3b/* Read data bytes (Dual SPI) */
 #define SPINOR_OP_READ_1_1_4   0x6b/* Read data bytes (Quad SPI) */
 #define SPINOR_OP_PP   0x02/* Page program (up to 256 bytes) */
+#define SPINOR_OP_QPP  0x32/* Quad Page program */
 #define SPINOR_OP_BE_4K0x20/* Erase 4KiB block */
 #define SPINOR_OP_BE_4K_PMC0xd7/* Erase 4KiB block on PMC chips */
 #define SPINOR_OP_BE_32K   0x52/* Erase 32KiB block */
@@ -119,6 +120,7 @@ enum spi_nor_ops {
 enum spi_nor_option_flags {
SNOR_F_USE_FSR  = BIT(0),
SNOR_F_HAS_SR_TB= BIT(1),
+   SNOR_F_USE_QPP  = BIT(2),
 };
 
 /**
-- 
2.7.4



[PATCH 5/6] mtd: spi-nor: Enable QPP for spansion parts

2016-08-09 Thread Jagan Teki
Enable QPP support for spansion flash parts.

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/spi-nor/spi-nor.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 05596cf..66d6e0b 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -898,17 +898,17 @@ static const struct flash_info spi_nor_ids[] = {
/* Spansion -- single (large) sector size only, at least
 * for the chips listed here (without boot sectors).
 */
-   { "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-   { "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-   { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
-   { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-   { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-   { "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
-   { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
-   { "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
-   { "s25fl128s",  INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-   { "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+   { "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 
SPI_NOR_QUAD_WRITE) },
+   { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 
SPI_NOR_QUAD_WRITE) },
+   { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 
SPI_NOR_QUAD_WRITE) },
+   { "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 
SPI_NOR_QUAD_WRITE) },
+   { "s25fl128s",  INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
{ "s25sl004a",  INFO(0x010212,  0,  64 * 1024,   8, 0) },
{ "s25sl008a",  INFO(0x010213,  0,  64 * 1024,  16, 0) },
{ "s25sl016a",  INFO(0x010214,  0,  64 * 1024,  32, 0) },
-- 
2.7.4



[PATCH 5/6] mtd: spi-nor: Enable QPP for spansion parts

2016-08-09 Thread Jagan Teki
Enable QPP support for spansion flash parts.

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/spi-nor/spi-nor.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 05596cf..66d6e0b 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -898,17 +898,17 @@ static const struct flash_info spi_nor_ids[] = {
/* Spansion -- single (large) sector size only, at least
 * for the chips listed here (without boot sectors).
 */
-   { "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-   { "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-   { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
-   { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-   { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-   { "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
-   { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
-   { "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
-   { "s25fl128s",  INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | 
SPI_NOR_QUAD_READ) },
-   { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-   { "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+   { "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 
SPI_NOR_QUAD_WRITE) },
+   { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s25fl512s",  INFO(0x010220, 0x4d00, 256 * 1024, 256, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 
SPI_NOR_QUAD_WRITE) },
+   { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 
SPI_NOR_QUAD_WRITE) },
+   { "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 
SPI_NOR_QUAD_WRITE) },
+   { "s25fl128s",  INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | 
SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
+   { "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256, 
SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_QUAD_WRITE) },
{ "s25sl004a",  INFO(0x010212,  0,  64 * 1024,   8, 0) },
{ "s25sl008a",  INFO(0x010213,  0,  64 * 1024,  16, 0) },
{ "s25sl016a",  INFO(0x010214,  0,  64 * 1024,  32, 0) },
-- 
2.7.4



[PATCH 2/6] mtd: m25p80: Use spi-nor quad page program

2016-08-09 Thread Jagan Teki
Identify the 4-wire tx transfer from spi controller mode
value and then assign QPP support to nor->flags to make use
of that.

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/devices/m25p80.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 9cf7fcd..1033595 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -224,6 +224,8 @@ static int m25p_probe(struct spi_device *spi)
mode = SPI_NOR_QUAD;
else if (spi->mode & SPI_RX_DUAL)
mode = SPI_NOR_DUAL;
+   else if (spi->mode & SPI_TX_QUAD)
+   nor->flags = SNOR_F_USE_QPP;
 
if (data && data->name)
nor->mtd.name = data->name;
-- 
2.7.4



[PATCH 3/6] mtd: spi-nor: Enable QPP for macronix parts

2016-08-09 Thread Jagan Teki
Enable QPP support for micronix flash parts.

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/spi-nor/spi-nor.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index f88bd7e..24a077d 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -870,12 +870,12 @@ static const struct flash_info spi_nor_ids[] = {
{ "mx25l3255e",  INFO(0xc29e16, 0, 64 * 1024,  64, SECT_4K) },
{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
{ "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
-   { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
-   { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
-   { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
-   { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
-   { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) 
},
-   { "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) 
},
+   { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, SPI_NOR_QUAD_WRITE) 
},
+   { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, SPI_NOR_QUAD_WRITE) 
},
+   { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_QUAD_WRITE) 
},
+   { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, SPI_NOR_QUAD_WRITE) 
},
+   { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ | 
SPI_NOR_QUAD_WRITE) },
+   { "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ | 
SPI_NOR_QUAD_WRITE) },
 
/* Micron */
{ "n25q032", INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) 
},
-- 
2.7.4



[PATCH 2/6] mtd: m25p80: Use spi-nor quad page program

2016-08-09 Thread Jagan Teki
Identify the 4-wire tx transfer from spi controller mode
value and then assign QPP support to nor->flags to make use
of that.

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/devices/m25p80.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 9cf7fcd..1033595 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -224,6 +224,8 @@ static int m25p_probe(struct spi_device *spi)
mode = SPI_NOR_QUAD;
else if (spi->mode & SPI_RX_DUAL)
mode = SPI_NOR_DUAL;
+   else if (spi->mode & SPI_TX_QUAD)
+   nor->flags = SNOR_F_USE_QPP;
 
if (data && data->name)
nor->mtd.name = data->name;
-- 
2.7.4



[PATCH 3/6] mtd: spi-nor: Enable QPP for macronix parts

2016-08-09 Thread Jagan Teki
Enable QPP support for micronix flash parts.

Cc: Brian Norris 
Signed-off-by: Jagan Teki 
---
 drivers/mtd/spi-nor/spi-nor.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index f88bd7e..24a077d 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -870,12 +870,12 @@ static const struct flash_info spi_nor_ids[] = {
{ "mx25l3255e",  INFO(0xc29e16, 0, 64 * 1024,  64, SECT_4K) },
{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
{ "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
-   { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
-   { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
-   { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
-   { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
-   { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) 
},
-   { "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) 
},
+   { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, SPI_NOR_QUAD_WRITE) 
},
+   { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, SPI_NOR_QUAD_WRITE) 
},
+   { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, SPI_NOR_QUAD_WRITE) 
},
+   { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, SPI_NOR_QUAD_WRITE) 
},
+   { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ | 
SPI_NOR_QUAD_WRITE) },
+   { "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ | 
SPI_NOR_QUAD_WRITE) },
 
/* Micron */
{ "n25q032", INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) 
},
-- 
2.7.4



<    1   2   3   4   5   6   7   8   9   10   >