Re: [PATCH v2] net: dsa: b53: constify b53_io_ops structures
From: Julia LawallDate: 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
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
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
From: Robert JarzmikDate: 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
On Tue, 9 Aug 2016 16:19:37 +0100 Paul Burtonwrote: > 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
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
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
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
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
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
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
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 SunSuggested-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
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
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
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
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
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
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)
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)
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
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
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
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
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
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
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
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
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()
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
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"
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
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()
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()
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
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"
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
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()
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()
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()
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
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()
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()
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
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()
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
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()
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
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
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 AppanaReviewed-by: Florian Fainelli -- Florian
Re: [RFC PATCH v5 1/3] net: Add mask for Control register 10Mbps speed
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
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
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
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
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
On Fri, 5 Aug 2016 23:48:21 +0800 zijun_huwrote: > 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
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
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
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
On Tue, Aug 9, 2016 at 10:02 PM, Jiri Kosinawrote: > 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
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
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 RaoThis 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
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
Enable QPP support for winbond flash parts. Cc: Brian NorrisSigned-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
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
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
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
On Tue, Aug 9, 2016 at 6:27 PM, Thomas Garnierwrote: > 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
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
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
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
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
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
Enable QPP support for micron flash parts. Cc: Brian NorrisSigned-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
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
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 NorrisSigned-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
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
Enable QPP support for spansion flash parts. Cc: Brian NorrisSigned-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
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
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 NorrisSigned-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
Enable QPP support for micronix flash parts. Cc: Brian NorrisSigned-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
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
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