* Re: [PATCH v5 2/5] net: ethernet: cpsw: add optional third memory region for CONTROL module
From: Sergei Shtylyov @ 2013-08-23 19:10 UTC (permalink / raw)
To: Daniel Mack
Cc: netdev, bcousson, nsekhar, davem, ujhelyi.m, mugunthanvnm,
vaibhav.bedia, d-gerlach, linux-arm-kernel, linux-omap,
devicetree
In-Reply-To: <1377283987-20040-3-git-send-email-zonque@gmail.com>
Hello.
On 08/23/2013 10:53 PM, Daniel Mack wrote:
> At least the AM33xx SoC has a control module register to configure
> details such as the hardware ethernet interface mode.
> I'm not sure whether all SoCs which feature the cpsw block have such a
> register, so that third memory region is considered optional for now.
> Signed-off-by: Daniel Mack <zonque@gmail.com>
> ---
> Documentation/devicetree/bindings/net/cpsw.txt | 5 ++++-
> drivers/net/ethernet/ti/cpsw.c | 5 +++++
> 2 files changed, 9 insertions(+), 1 deletion(-)
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index fc3263f..4feba2f 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
[...]
> @@ -1989,6 +1990,10 @@ static int cpsw_probe(struct platform_device *pdev)
> goto clean_runtime_disable_ret;
> }
>
> + /* Don't fail hard if the optional control memory region is missing */
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
> + priv->gmii_sel_reg = devm_ioremap_resource(&pdev->dev, res);
Hm, but why now you don't fail if devm_ioremap_resource() fails?
WBR, Sergei
^ permalink raw reply
* Re: [PATCH v5 0/5] cpsw: support for control module register
From: Mugunthan V N @ 2013-08-23 19:13 UTC (permalink / raw)
To: Daniel Mack
Cc: netdev, bcousson, nsekhar, sergei.shtylyov, davem, ujhelyi.m,
vaibhav.bedia, d-gerlach, linux-arm-kernel, linux-omap,
devicetree
In-Reply-To: <1377283987-20040-1-git-send-email-zonque@gmail.com>
On Saturday 24 August 2013 12:23 AM, Daniel Mack wrote:
> Note that for personal reasons, I won't be able to work on that patch
> set for two weeks, starting from a few hours from now. If there are any
> more objections or comments, I'll catch up after that period. Or if
> anyone wants to make minor changes to my patches and resubmit them,
> I'd also be fine with that :)
>
> The compatible discussion is still ongoing, but I'd rather submit what
> I got until now, and I'm also still convinced that having
> ti,am3352-cpsw is still the best we can do.
Apart from the DT compatibility discussion this patch series looks good
to me.
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
Regards
Mugunthan V N
^ permalink raw reply
* Re: [PATCH v5 2/5] net: ethernet: cpsw: add optional third memory region for CONTROL module
From: Daniel Mack @ 2013-08-23 19:14 UTC (permalink / raw)
To: Sergei Shtylyov
Cc: netdev, bcousson, nsekhar, davem, ujhelyi.m, mugunthanvnm,
vaibhav.bedia, d-gerlach, linux-arm-kernel, linux-omap,
devicetree
In-Reply-To: <5217B3BE.8020003@cogentembedded.com>
On 23.08.2013 21:10, Sergei Shtylyov wrote:
> Hello.
>
> On 08/23/2013 10:53 PM, Daniel Mack wrote:
>
>> At least the AM33xx SoC has a control module register to configure
>> details such as the hardware ethernet interface mode.
>
>> I'm not sure whether all SoCs which feature the cpsw block have such a
>> register, so that third memory region is considered optional for now.
>
>> Signed-off-by: Daniel Mack <zonque@gmail.com>
>> ---
>> Documentation/devicetree/bindings/net/cpsw.txt | 5 ++++-
>> drivers/net/ethernet/ti/cpsw.c | 5 +++++
>> 2 files changed, 9 insertions(+), 1 deletion(-)
>
>> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
>> index fc3263f..4feba2f 100644
>> --- a/drivers/net/ethernet/ti/cpsw.c
>> +++ b/drivers/net/ethernet/ti/cpsw.c
> [...]
>> @@ -1989,6 +1990,10 @@ static int cpsw_probe(struct platform_device *pdev)
>> goto clean_runtime_disable_ret;
>> }
>>
>> + /* Don't fail hard if the optional control memory region is missing */
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
>> + priv->gmii_sel_reg = devm_ioremap_resource(&pdev->dev, res);
>
> Hm, but why now you don't fail if devm_ioremap_resource() fails?
Well, because I thought maybe we should just ignore failures of that
kind altogether for this optional resource. There will still be a
warning in that case. Did you like the old approach better?
Daniel
^ permalink raw reply
* Re: [PATCH v5 4/5] net: ethernet: cpsw: add support for hardware interface mode config
From: Sergei Shtylyov @ 2013-08-23 19:18 UTC (permalink / raw)
To: Daniel Mack
Cc: netdev, bcousson, nsekhar, davem, ujhelyi.m, mugunthanvnm,
vaibhav.bedia, d-gerlach, linux-arm-kernel, linux-omap,
devicetree
In-Reply-To: <1377283987-20040-5-git-send-email-zonque@gmail.com>
On 08/23/2013 10:53 PM, Daniel Mack wrote:
> The cpsw currently lacks code to properly set up the hardware interface
> mode on AM33xx. Other platforms might be equally affected.
> Usually, the bootloader will configure the control module register, so
> probably that's why such support wasn't needed in the past. In suspend
> mode though, this register is modified, and so it needs reprogramming
> after resume.
> This patch adds code that makes use of the previously added and optional
> support for passing the control mode register, and configures the
> correct register bits when the slave is opened.
> The AM33xx also has a bit for each slave to configure the RMII reference
> clock direction. Setting it is now supported by a per-slave DT property.
> This code path introducted by this patch is currently exclusive for
> am33xx.
> Signed-off-by: Daniel Mack <zonque@gmail.com>
[...]
> @@ -40,4 +41,11 @@ struct cpsw_platform_data {
> u32 hw_type; /* hardware type as specified in 'compatible' */
> };
>
> +/* SoC specific definitions for the CONTROL port */
> +#define AM33XX_GMII_SEL_MODE_MII (0)
> +#define AM33XX_GMII_SEL_MODE_RMII (1)
> +#define AM33XX_GMII_SEL_MODE_RGMII (2)
Parens around decimal literals are hardly needed even in macros.
WBR, Sergei
^ permalink raw reply
* Re: [PATCH net-next 01/10] net: etherdevice: add address inherit helper
From: Stephen Hemminger @ 2013-08-23 19:24 UTC (permalink / raw)
To: Bjørn Mork; +Cc: netdev
In-Reply-To: <1377250513-3662-2-git-send-email-bjorn@mork.no>
On Fri, 23 Aug 2013 11:35:04 +0200
Bjørn Mork <bjorn@mork.no> wrote:
> /**
> + * eth_hw_addr_inherit - Copy dev_addr from another net_device
> + * @dst: pointer to net_device to copy dev_addr to
> + * @src: pointer to net_device to copy dev_addr from
> + *
> + * Copy the Ethernet address from one net_device to another along with
> + * the addr_assign_type.
> + */
> +static inline int eth_hw_addr_inherit(struct net_device *dst,
> + struct net_device *src)
> +{
> + if (dst->addr_len != src->addr_len)
> + return -EINVAL;
> +
> + dst->addr_assign_type = src->addr_assign_type;
> + memcpy(dst->dev_addr, src->dev_addr, dst->addr_len);
> + return 0;
> +}
> +
Since all the other code in this file assumes addr_len == ETH_ALEN
why does this code need to handle variable addresses. Trivial but
then the memcpy is fixed size and can be optimized.
^ permalink raw reply
* [PATCH v6 1/5] net: ethernet: cpsw: switch to devres allocations
From: Daniel Mack @ 2013-08-23 19:32 UTC (permalink / raw)
To: netdev
Cc: bcousson, nsekhar, sergei.shtylyov, davem, ujhelyi.m,
mugunthanvnm, vaibhav.bedia, d-gerlach, linux-arm-kernel,
linux-omap, devicetree, Daniel Mack
In-Reply-To: <1377286330-29663-1-git-send-email-zonque@gmail.com>
This patch cleans up the allocation and error unwind paths, which
allows us to carry less information in struct cpsw_priv and reduce the
amount of jump labels in the probe functions.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/net/ethernet/ti/cpsw.c | 153 ++++++++++++-----------------------------
1 file changed, 43 insertions(+), 110 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 79974e3..fc3263f 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -367,8 +367,6 @@ struct cpsw_priv {
spinlock_t lock;
struct platform_device *pdev;
struct net_device *ndev;
- struct resource *cpsw_res;
- struct resource *cpsw_wr_res;
struct napi_struct napi;
struct device *dev;
struct cpsw_platform_data data;
@@ -1712,62 +1710,55 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
if (of_property_read_u32(node, "active_slave", &prop)) {
pr_err("Missing active_slave property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->active_slave = prop;
if (of_property_read_u32(node, "cpts_clock_mult", &prop)) {
pr_err("Missing cpts_clock_mult property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->cpts_clock_mult = prop;
if (of_property_read_u32(node, "cpts_clock_shift", &prop)) {
pr_err("Missing cpts_clock_shift property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->cpts_clock_shift = prop;
- data->slave_data = kcalloc(data->slaves, sizeof(struct cpsw_slave_data),
- GFP_KERNEL);
+ data->slave_data = devm_kzalloc(&pdev->dev, data->slaves
+ * sizeof(struct cpsw_slave_data),
+ GFP_KERNEL);
if (!data->slave_data)
- return -EINVAL;
+ return -ENOMEM;
if (of_property_read_u32(node, "cpdma_channels", &prop)) {
pr_err("Missing cpdma_channels property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->channels = prop;
if (of_property_read_u32(node, "ale_entries", &prop)) {
pr_err("Missing ale_entries property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->ale_entries = prop;
if (of_property_read_u32(node, "bd_ram_size", &prop)) {
pr_err("Missing bd_ram_size property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->bd_ram_size = prop;
if (of_property_read_u32(node, "rx_descs", &prop)) {
pr_err("Missing rx_descs property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->rx_descs = prop;
if (of_property_read_u32(node, "mac_control", &prop)) {
pr_err("Missing mac_control property in the DT.\n");
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
data->mac_control = prop;
@@ -1794,8 +1785,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
parp = of_get_property(slave_node, "phy_id", &lenp);
if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
pr_err("Missing slave[%d] phy_id property\n", i);
- ret = -EINVAL;
- goto error_ret;
+ return -EINVAL;
}
mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
phyid = be32_to_cpup(parp+1);
@@ -1825,10 +1815,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
return 0;
-
-error_ret:
- kfree(data->slave_data);
- return ret;
}
static int cpsw_probe_dual_emac(struct platform_device *pdev,
@@ -1870,7 +1856,6 @@ static int cpsw_probe_dual_emac(struct platform_device *pdev,
priv_sl2->coal_intvl = 0;
priv_sl2->bus_freq_mhz = priv->bus_freq_mhz;
- priv_sl2->cpsw_res = priv->cpsw_res;
priv_sl2->regs = priv->regs;
priv_sl2->host_port = priv->host_port;
priv_sl2->host_port_regs = priv->host_port_regs;
@@ -1914,8 +1899,8 @@ static int cpsw_probe(struct platform_device *pdev)
struct cpsw_priv *priv;
struct cpdma_params dma_params;
struct cpsw_ale_params ale_params;
- void __iomem *ss_regs, *wr_regs;
- struct resource *res;
+ void __iomem *ss_regs;
+ struct resource *res, *ss_res;
u32 slave_offset, sliver_offset, slave_size;
int ret = 0, i, k = 0;
@@ -1951,7 +1936,7 @@ static int cpsw_probe(struct platform_device *pdev)
if (cpsw_probe_dt(&priv->data, pdev)) {
pr_err("cpsw: platform data missing\n");
ret = -ENODEV;
- goto clean_ndev_ret;
+ goto clean_runtime_disable_ret;
}
data = &priv->data;
@@ -1965,11 +1950,12 @@ static int cpsw_probe(struct platform_device *pdev)
memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN);
- priv->slaves = kzalloc(sizeof(struct cpsw_slave) * data->slaves,
- GFP_KERNEL);
+ priv->slaves =
+ devm_kzalloc(&pdev->dev, sizeof(struct cpsw_slave) * data->slaves,
+ GFP_KERNEL);
if (!priv->slaves) {
- ret = -EBUSY;
- goto clean_ndev_ret;
+ ret = -ENOMEM;
+ goto clean_runtime_disable_ret;
}
for (i = 0; i < data->slaves; i++)
priv->slaves[i].slave_num = i;
@@ -1977,55 +1963,31 @@ static int cpsw_probe(struct platform_device *pdev)
priv->slaves[0].ndev = ndev;
priv->emac_port = 0;
- priv->clk = clk_get(&pdev->dev, "fck");
+ priv->clk = devm_clk_get(&pdev->dev, "fck");
if (IS_ERR(priv->clk)) {
- dev_err(&pdev->dev, "fck is not found\n");
+ dev_err(priv->dev, "fck is not found\n");
ret = -ENODEV;
- goto clean_slave_ret;
+ goto clean_runtime_disable_ret;
}
priv->coal_intvl = 0;
priv->bus_freq_mhz = clk_get_rate(priv->clk) / 1000000;
- priv->cpsw_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!priv->cpsw_res) {
- dev_err(priv->dev, "error getting i/o resource\n");
- ret = -ENOENT;
- goto clean_clk_ret;
- }
- if (!request_mem_region(priv->cpsw_res->start,
- resource_size(priv->cpsw_res), ndev->name)) {
- dev_err(priv->dev, "failed request i/o region\n");
- ret = -ENXIO;
- goto clean_clk_ret;
- }
- ss_regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res));
- if (!ss_regs) {
- dev_err(priv->dev, "unable to map i/o region\n");
- goto clean_cpsw_iores_ret;
+ ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ss_regs = devm_ioremap_resource(&pdev->dev, ss_res);
+ if (IS_ERR(ss_regs)) {
+ ret = PTR_ERR(ss_regs);
+ goto clean_runtime_disable_ret;
}
priv->regs = ss_regs;
priv->version = __raw_readl(&priv->regs->id_ver);
priv->host_port = HOST_PORT_NUM;
- priv->cpsw_wr_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!priv->cpsw_wr_res) {
- dev_err(priv->dev, "error getting i/o resource\n");
- ret = -ENOENT;
- goto clean_iomap_ret;
- }
- if (!request_mem_region(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res), ndev->name)) {
- dev_err(priv->dev, "failed request i/o region\n");
- ret = -ENXIO;
- goto clean_iomap_ret;
- }
- wr_regs = ioremap(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res));
- if (!wr_regs) {
- dev_err(priv->dev, "unable to map i/o region\n");
- goto clean_cpsw_wr_iores_ret;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ priv->wr_regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->wr_regs)) {
+ ret = PTR_ERR(priv->wr_regs);
+ goto clean_runtime_disable_ret;
}
- priv->wr_regs = wr_regs;
memset(&dma_params, 0, sizeof(dma_params));
memset(&ale_params, 0, sizeof(ale_params));
@@ -2056,12 +2018,12 @@ static int cpsw_probe(struct platform_device *pdev)
slave_size = CPSW2_SLAVE_SIZE;
sliver_offset = CPSW2_SLIVER_OFFSET;
dma_params.desc_mem_phys =
- (u32 __force) priv->cpsw_res->start + CPSW2_BD_OFFSET;
+ (u32 __force) ss_res->start + CPSW2_BD_OFFSET;
break;
default:
dev_err(priv->dev, "unknown version 0x%08x\n", priv->version);
ret = -ENODEV;
- goto clean_cpsw_wr_iores_ret;
+ goto clean_runtime_disable_ret;
}
for (i = 0; i < priv->data.slaves; i++) {
struct cpsw_slave *slave = &priv->slaves[i];
@@ -2089,7 +2051,7 @@ static int cpsw_probe(struct platform_device *pdev)
if (!priv->dma) {
dev_err(priv->dev, "error initializing dma\n");
ret = -ENOMEM;
- goto clean_wr_iomap_ret;
+ goto clean_runtime_disable_ret;
}
priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0),
@@ -2124,8 +2086,8 @@ static int cpsw_probe(struct platform_device *pdev)
while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) {
for (i = res->start; i <= res->end; i++) {
- if (request_irq(i, cpsw_interrupt, 0,
- dev_name(&pdev->dev), priv)) {
+ if (devm_request_irq(&pdev->dev, i, cpsw_interrupt, 0,
+ dev_name(priv->dev), priv)) {
dev_err(priv->dev, "error attaching irq\n");
goto clean_ale_ret;
}
@@ -2147,7 +2109,7 @@ static int cpsw_probe(struct platform_device *pdev)
if (ret) {
dev_err(priv->dev, "error registering net device\n");
ret = -ENODEV;
- goto clean_irq_ret;
+ goto clean_ale_ret;
}
if (cpts_register(&pdev->dev, priv->cpts,
@@ -2155,44 +2117,27 @@ static int cpsw_probe(struct platform_device *pdev)
dev_err(priv->dev, "error registering cpts device\n");
cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
- priv->cpsw_res->start, ndev->irq);
+ ss_res->start, ndev->irq);
if (priv->data.dual_emac) {
ret = cpsw_probe_dual_emac(pdev, priv);
if (ret) {
cpsw_err(priv, probe, "error probe slave 2 emac interface\n");
- goto clean_irq_ret;
+ goto clean_ale_ret;
}
}
return 0;
-clean_irq_ret:
- for (i = 0; i < priv->num_irqs; i++)
- free_irq(priv->irqs_table[i], priv);
clean_ale_ret:
cpsw_ale_destroy(priv->ale);
clean_dma_ret:
cpdma_chan_destroy(priv->txch);
cpdma_chan_destroy(priv->rxch);
cpdma_ctlr_destroy(priv->dma);
-clean_wr_iomap_ret:
- iounmap(priv->wr_regs);
-clean_cpsw_wr_iores_ret:
- release_mem_region(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res));
-clean_iomap_ret:
- iounmap(priv->regs);
-clean_cpsw_iores_ret:
- release_mem_region(priv->cpsw_res->start,
- resource_size(priv->cpsw_res));
-clean_clk_ret:
- clk_put(priv->clk);
-clean_slave_ret:
+clean_runtime_disable_ret:
pm_runtime_disable(&pdev->dev);
- kfree(priv->slaves);
clean_ndev_ret:
- kfree(priv->data.slave_data);
free_netdev(priv->ndev);
return ret;
}
@@ -2201,30 +2146,18 @@ static int cpsw_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct cpsw_priv *priv = netdev_priv(ndev);
- int i;
if (priv->data.dual_emac)
unregister_netdev(cpsw_get_slave_ndev(priv, 1));
unregister_netdev(ndev);
cpts_unregister(priv->cpts);
- for (i = 0; i < priv->num_irqs; i++)
- free_irq(priv->irqs_table[i], priv);
cpsw_ale_destroy(priv->ale);
cpdma_chan_destroy(priv->txch);
cpdma_chan_destroy(priv->rxch);
cpdma_ctlr_destroy(priv->dma);
- iounmap(priv->regs);
- release_mem_region(priv->cpsw_res->start,
- resource_size(priv->cpsw_res));
- iounmap(priv->wr_regs);
- release_mem_region(priv->cpsw_wr_res->start,
- resource_size(priv->cpsw_wr_res));
pm_runtime_disable(&pdev->dev);
- clk_put(priv->clk);
- kfree(priv->slaves);
- kfree(priv->data.slave_data);
if (priv->data.dual_emac)
free_netdev(cpsw_get_slave_ndev(priv, 1));
free_netdev(ndev);
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 5/5] ARM: dts: am33xx: adopt to cpsw changes
From: Daniel Mack @ 2013-08-23 19:32 UTC (permalink / raw)
To: netdev
Cc: bcousson, nsekhar, sergei.shtylyov, davem, ujhelyi.m,
mugunthanvnm, vaibhav.bedia, d-gerlach, linux-arm-kernel,
linux-omap, devicetree, Daniel Mack
In-Reply-To: <1377286330-29663-1-git-send-email-zonque@gmail.com>
This third memory region just denotes one single register in the CONTROL
module block. The driver uses that in order to set the correct physical
ethernet interface modes.
Also update the compatible string to make use of the am335x specific
features of the cpsw driver.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
arch/arm/boot/dts/am33xx.dtsi | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index a785b95..c7b41ae 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -446,7 +446,7 @@
};
mac: ethernet@4a100000 {
- compatible = "ti,cpsw";
+ compatible = "ti,am3352-cpsw", "ti,cpsw";
ti,hwmods = "cpgmac0";
cpdma_channels = <8>;
ale_entries = <1024>;
@@ -459,7 +459,8 @@
cpts_clock_mult = <0x80000000>;
cpts_clock_shift = <29>;
reg = <0x4a100000 0x800
- 0x4a101200 0x100>;
+ 0x4a101200 0x100
+ 0x44e10650 0x4>;
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 3/5] net: ethernet: cpsw: introduce ti,am3352-cpsw compatible string
From: Daniel Mack @ 2013-08-23 19:32 UTC (permalink / raw)
To: netdev
Cc: bcousson, nsekhar, sergei.shtylyov, davem, ujhelyi.m,
mugunthanvnm, vaibhav.bedia, d-gerlach, linux-arm-kernel,
linux-omap, devicetree, Daniel Mack
In-Reply-To: <1377286330-29663-1-git-send-email-zonque@gmail.com>
In order to support features that are specific to the AM335x IP, we have
to add hardware types and another compatible string.
Signed-off-by: Daniel Mack <zonque@gmail.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 3 ++-
drivers/net/ethernet/ti/cpsw.c | 32 ++++++++++++++++++++------
drivers/net/ethernet/ti/cpsw.h | 1 +
3 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 4e5ca54..b717458 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -2,7 +2,8 @@ TI SoC Ethernet Switch Controller Device Tree Bindings
------------------------------------------------------
Required properties:
-- compatible : Should be "ti,cpsw"
+- compatible : Should be "ti,cpsw" for generic cpsw support, or
+ "ti,am3352-cpsw" for AM3352 SoCs
- reg : physical base address and size of the cpsw
registers map.
An optional third memory region can be supplied if
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 485df80..8d023ab 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -155,6 +155,11 @@ do { \
((priv->data.dual_emac) ? priv->emac_port : \
priv->data.active_slave)
+enum {
+ CPSW_TYPE_GENERIC,
+ CPSW_TYPE_AM33XX
+};
+
static int debug_level;
module_param(debug_level, int, 0);
MODULE_PARM_DESC(debug_level, "cpsw debug level (NETIF_MSG bits)");
@@ -1692,17 +1697,36 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
slave->port_vlan = data->dual_emac_res_vlan;
}
+static const struct of_device_id cpsw_of_mtable[] = {
+ {
+ .compatible = "ti,am3352-cpsw",
+ .data = (void *) CPSW_TYPE_AM33XX
+ }, {
+ .compatible = "ti,cpsw",
+ .data = (void *) CPSW_TYPE_GENERIC
+ },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, cpsw_of_mtable);
+
static int cpsw_probe_dt(struct cpsw_platform_data *data,
struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
+ const struct of_device_id *match;
struct device_node *slave_node;
+ unsigned long match_data;
int i = 0, ret;
u32 prop;
- if (!node)
+ match = of_match_device(cpsw_of_mtable, &pdev->dev);
+
+ if (!node || !match)
return -EINVAL;
+ match_data = (unsigned long) match->data;
+ data->hw_type = match_data;
+
if (of_property_read_u32(node, "slaves", &prop)) {
pr_err("Missing slaves property in the DT.\n");
return -EINVAL;
@@ -2213,12 +2237,6 @@ static const struct dev_pm_ops cpsw_pm_ops = {
.resume = cpsw_resume,
};
-static const struct of_device_id cpsw_of_mtable[] = {
- { .compatible = "ti,cpsw", },
- { /* sentinel */ },
-};
-MODULE_DEVICE_TABLE(of, cpsw_of_mtable);
-
static struct platform_driver cpsw_driver = {
.driver = {
.name = "cpsw",
diff --git a/drivers/net/ethernet/ti/cpsw.h b/drivers/net/ethernet/ti/cpsw.h
index eb3e101..96c374a 100644
--- a/drivers/net/ethernet/ti/cpsw.h
+++ b/drivers/net/ethernet/ti/cpsw.h
@@ -37,6 +37,7 @@ struct cpsw_platform_data {
u32 mac_control; /* Mac control register */
u16 default_vlan; /* Def VLAN for ALE lookup in VLAN aware mode*/
bool dual_emac; /* Enable Dual EMAC mode */
+ u32 hw_type; /* hardware type as specified in 'compatible' */
};
#endif /* __CPSW_H__ */
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 2/5] net: ethernet: cpsw: add optional third memory region for CONTROL module
From: Daniel Mack @ 2013-08-23 19:32 UTC (permalink / raw)
To: netdev
Cc: bcousson, nsekhar, sergei.shtylyov, davem, ujhelyi.m,
mugunthanvnm, vaibhav.bedia, d-gerlach, linux-arm-kernel,
linux-omap, devicetree, Daniel Mack
In-Reply-To: <1377286330-29663-1-git-send-email-zonque@gmail.com>
At least the AM33xx SoC has a control module register to configure
details such as the hardware ethernet interface mode.
I'm not sure whether all SoCs which feature the cpsw block have such a
register, so that third memory region is considered optional for now.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 5 ++++-
drivers/net/ethernet/ti/cpsw.c | 11 +++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 05d660e..4e5ca54 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -4,7 +4,10 @@ TI SoC Ethernet Switch Controller Device Tree Bindings
Required properties:
- compatible : Should be "ti,cpsw"
- reg : physical base address and size of the cpsw
- registers map
+ registers map.
+ An optional third memory region can be supplied if
+ the platform has a control module register to
+ configure phy interface details
- interrupts : property with a value describing the interrupt
number
- interrupt-parent : The parent interrupt controller
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index fc3263f..485df80 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -372,6 +372,7 @@ struct cpsw_priv {
struct cpsw_platform_data data;
struct cpsw_ss_regs __iomem *regs;
struct cpsw_wr_regs __iomem *wr_regs;
+ u32 __iomem *gmii_sel_reg;
u8 __iomem *hw_stats;
struct cpsw_host_regs __iomem *host_port_regs;
u32 msg_enable;
@@ -1989,6 +1990,16 @@ static int cpsw_probe(struct platform_device *pdev)
goto clean_runtime_disable_ret;
}
+ /* Don't fail hard if the optional control memory region is missing */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ if (res) {
+ priv->gmii_sel_reg = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(priv->gmii_sel_reg)) {
+ ret = PTR_ERR(priv->gmii_sel_reg);
+ goto clean_runtime_disable_ret;
+ }
+ }
+
memset(&dma_params, 0, sizeof(dma_params));
memset(&ale_params, 0, sizeof(ale_params));
--
1.8.3.1
^ permalink raw reply related
* [PATCH v6 0/5] cpsw: support for control module register
From: Daniel Mack @ 2013-08-23 19:32 UTC (permalink / raw)
To: netdev
Cc: bcousson, nsekhar, sergei.shtylyov, davem, ujhelyi.m,
mugunthanvnm, vaibhav.bedia, d-gerlach, linux-arm-kernel,
linux-omap, devicetree, Daniel Mack
Hi,
this is the 6th version of my patch set, the version history is below.
Note that for personal reasons, I won't be able to work on that patch
set for two weeks, starting from a few hours from now. If there are any
more objections or comments, I'll catch up after that period. Or if
anyone wants to make minor changes to my patches and resubmit them,
I'd also be fine with that :)
The compatibility discussion is still ongoing, but I'd rather submit
what I got until now, and I'm also still convinced that having
ti,am3352-cpsw is the best we can do.
Thanks,
Daniel
v5 -> v6:
* re-add code to fail if 3rd memory region is given but invalid
* added Mugunthan's ack on all patches except the one that adds
ti,am3352-cpsw
* remove parens around integer constants
v4 -> v5:
* fix return value assignment in devm_ioremap_resource() error
paths (reported by Sergei Shtylyov)
* add more RGMII modes (reported by Mugunthan V N)
* check for IS_ERR(priv->gmii_sel_reg) in
cpsw_set_phy_interface_mode() (reported by Mugunthan V N)
* move SoC specific definitions to cpsw.h
* further simplify the probe logic, as devm_ioremap_resource()
will check for NULL resources (Sergei Shtylyov)
v3 -> v4:
* use IS_ERR() to check for failed devm_ioremap_resource()
calls (reported by Sergei Shtylyov)
v2 -> v3:
* swap "ti,am3352-cpsw" and "ti,cpsw" to work around a matching
bug (reported by Sekhar)
v1 -> v2:
* combine devm_request_mem_region() and devm_ioremap() and use
devm_ioremap_resource() (reported by Sergei Shtylyov)
* fix multi-line comment style (reported by Sergei Shtylyov)
* fix ti,rmii-clock-ext property name (reported by Sekhar)
* rebased to net-next (reported by Mugunthan V N, David Miller)
* add a new compatible type, and handle AM33xx specific
registers that way (reported by Sekhar)
* move gmii_sel_reg modifications to the open routine
(reported by Mugunthan V N)
Daniel Mack (5):
net: ethernet: cpsw: switch to devres allocations
net: ethernet: cpsw: add optional third memory region for CONTROL
module
net: ethernet: cpsw: introduce ti,am3352-cpsw compatible string
net: ethernet: cpsw: add support for hardware interface mode config
ARM: dts: am33xx: adopt to cpsw changes
Documentation/devicetree/bindings/net/cpsw.txt | 10 +-
arch/arm/boot/dts/am33xx.dtsi | 5 +-
drivers/net/ethernet/ti/cpsw.c | 252 +++++++++++++------------
drivers/net/ethernet/ti/cpsw.h | 9 +
4 files changed, 156 insertions(+), 120 deletions(-)
--
1.8.3.1
^ permalink raw reply
* [PATCH v6 4/5] net: ethernet: cpsw: add support for hardware interface mode config
From: Daniel Mack @ 2013-08-23 19:32 UTC (permalink / raw)
To: netdev
Cc: bcousson, nsekhar, sergei.shtylyov, davem, ujhelyi.m,
mugunthanvnm, vaibhav.bedia, d-gerlach, linux-arm-kernel,
linux-omap, devicetree, Daniel Mack
In-Reply-To: <1377286330-29663-1-git-send-email-zonque@gmail.com>
The cpsw currently lacks code to properly set up the hardware interface
mode on AM33xx. Other platforms might be equally affected.
Usually, the bootloader will configure the control module register, so
probably that's why such support wasn't needed in the past. In suspend
mode though, this register is modified, and so it needs reprogramming
after resume.
This patch adds code that makes use of the previously added and optional
support for passing the control mode register, and configures the
correct register bits when the slave is opened.
The AM33xx also has a bit for each slave to configure the RMII reference
clock direction. Setting it is now supported by a per-slave DT property.
This code path introducted by this patch is currently exclusive for
am33xx.
Signed-off-by: Daniel Mack <zonque@gmail.com>
Acked-by: Mugunthan V N <mugunthanvnm@ti.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 2 +
drivers/net/ethernet/ti/cpsw.c | 58 ++++++++++++++++++++++++++
drivers/net/ethernet/ti/cpsw.h | 8 ++++
3 files changed, 68 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index b717458..0895a51 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -34,6 +34,8 @@ Required properties:
- phy_id : Specifies slave phy id
- phy-mode : The interface between the SoC and the PHY (a string
that of_get_phy_mode() can understand)
+- ti,rmii-clock-ext : If present, the driver will configure the RMII
+ interface to external clock usage
- mac-address : Specifies slave MAC address
Optional properties:
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 8d023ab..6b47e78 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -980,6 +980,60 @@ static inline void cpsw_add_dual_emac_def_ale_entries(
priv->host_port, ALE_VLAN, slave->port_vlan);
}
+static void cpsw_set_phy_interface_mode(struct cpsw_slave *slave,
+ struct cpsw_priv *priv)
+{
+ u32 reg;
+ u32 mask;
+ u32 mode = 0;
+
+ switch (priv->data.hw_type) {
+ case CPSW_TYPE_AM33XX:
+ if (IS_ERR_OR_NULL(priv->gmii_sel_reg))
+ break;
+
+ reg = readl(priv->gmii_sel_reg);
+
+ if (slave->phy) {
+ switch (slave->phy->interface) {
+ case PHY_INTERFACE_MODE_MII:
+ default:
+ mode = AM33XX_GMII_SEL_MODE_MII;
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ mode = AM33XX_GMII_SEL_MODE_RMII;
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ mode = AM33XX_GMII_SEL_MODE_RGMII;
+ break;
+ };
+ }
+
+ mask = 0x3 << (slave->slave_num * 2) |
+ BIT(slave->slave_num + 6);
+ mode <<= slave->slave_num * 2;
+
+ if (slave->data->rmii_clock_external) {
+ if (slave->slave_num == 0)
+ mode |= AM33XX_GMII_SEL_RMII1_IO_CLK_EN;
+ else
+ mode |= AM33XX_GMII_SEL_RMII2_IO_CLK_EN;
+ }
+
+ reg &= ~mask;
+ reg |= mode;
+
+ writel(reg, priv->gmii_sel_reg);
+ break;
+
+ default:
+ break;
+ }
+}
+
static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
{
char name[32];
@@ -1028,6 +1082,8 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
slave->phy->phy_id);
phy_start(slave->phy);
}
+
+ cpsw_set_phy_interface_mode(slave, priv);
}
static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
@@ -1823,6 +1879,8 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
slave_data->phy_if = of_get_phy_mode(slave_node);
+ if (of_find_property(slave_node, "ti,rmii-clock-ext", NULL))
+ slave_data->rmii_clock_external = true;
if (data->dual_emac) {
if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
diff --git a/drivers/net/ethernet/ti/cpsw.h b/drivers/net/ethernet/ti/cpsw.h
index 96c374a..3a6cb16 100644
--- a/drivers/net/ethernet/ti/cpsw.h
+++ b/drivers/net/ethernet/ti/cpsw.h
@@ -19,6 +19,7 @@
struct cpsw_slave_data {
char phy_id[MII_BUS_ID_SIZE];
int phy_if;
+ bool rmii_clock_external;
u8 mac_addr[ETH_ALEN];
u16 dual_emac_res_vlan; /* Reserved VLAN for DualEMAC */
};
@@ -40,4 +41,11 @@ struct cpsw_platform_data {
u32 hw_type; /* hardware type as specified in 'compatible' */
};
+/* SoC specific definitions for the CONTROL port */
+#define AM33XX_GMII_SEL_MODE_MII 0
+#define AM33XX_GMII_SEL_MODE_RMII 1
+#define AM33XX_GMII_SEL_MODE_RGMII 2
+
+#define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7)
+#define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6)
#endif /* __CPSW_H__ */
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH v6 0/5] cpsw: support for control module register
From: Mugunthan V N @ 2013-08-23 19:38 UTC (permalink / raw)
To: Daniel Mack
Cc: devicetree, sergei.shtylyov, d-gerlach, netdev, nsekhar,
vaibhav.bedia, bcousson, ujhelyi.m, linux-omap, davem,
linux-arm-kernel
In-Reply-To: <1377286330-29663-1-git-send-email-zonque@gmail.com>
On Saturday 24 August 2013 01:02 AM, Daniel Mack wrote:
> Hi,
>
> this is the 6th version of my patch set, the version history is below.
>
> Note that for personal reasons, I won't be able to work on that patch
> set for two weeks, starting from a few hours from now. If there are any
> more objections or comments, I'll catch up after that period. Or if
> anyone wants to make minor changes to my patches and resubmit them,
> I'd also be fine with that :)
>
> The compatibility discussion is still ongoing, but I'd rather submit
> what I got until now, and I'm also still convinced that having
> ti,am3352-cpsw is the best we can do.
>
>
> Thanks,
> Daniel
>
> v5 -> v6:
> * re-add code to fail if 3rd memory region is given but invalid
> * added Mugunthan's ack on all patches except the one that adds
> ti,am3352-cpsw
> * remove parens around integer constants
I am also in your favour of adding ti,am3352-cpsw, but lets get other
comment. You can add my ack to that patch also if you are submitting
another version.
Regards
Mugunthan V N
^ permalink raw reply
* Re: [PATCH v6 0/5] cpsw: support for control module register
From: Daniel Mack @ 2013-08-23 19:41 UTC (permalink / raw)
To: Mugunthan V N
Cc: netdev, bcousson, nsekhar, sergei.shtylyov, davem, ujhelyi.m,
vaibhav.bedia, d-gerlach, linux-arm-kernel, linux-omap,
devicetree
In-Reply-To: <5217BA50.6050609@ti.com>
On 23.08.2013 21:38, Mugunthan V N wrote:
> On Saturday 24 August 2013 01:02 AM, Daniel Mack wrote:
>> v5 -> v6:
>> * re-add code to fail if 3rd memory region is given but invalid
>> * added Mugunthan's ack on all patches except the one that adds
>> ti,am3352-cpsw
>> * remove parens around integer constants
> I am also in your favour of adding ti,am3352-cpsw, but lets get other
> comment. You can add my ack to that patch also if you are submitting
> another version.
I don't think I'll have a chance to do that before I'm AFK for a while :)
That's also the only reason why I sent a v6 already. I would have
normally waited for that discussion to settle of course.
But as I said: I'd be fine if anyone adds another patch on top or amends
mine.
Thanks for the reviews again, everyone!
Daniel
^ permalink raw reply
* [PATCH v3 1/2] genl: Fix genl dumpit() locking.
From: Pravin B Shelar @ 2013-08-23 19:44 UTC (permalink / raw)
To: netdev; +Cc: Pravin B Shelar, Jesse Gross, Johannes Berg
In case of genl-family with parallel ops off, dumpif() callback
is expected to run under genl_lock, But commit def3117493eafd9df
(genl: Allow concurrent genl callbacks.) changed this behaviour
where only first dumpit() op was called under genl-lock.
For subsequent dump, only nlk->cb_lock was taken.
Following patch fixes it by defining locked dumpit() and done()
callback which takes care of genl-locking.
CC: Jesse Gross <jesse@nicira.com>
CC: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
---
v2-v3:
coding style fix.
v1-v2:
No change.
---
net/netlink/genetlink.c | 51 ++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index f85f8a2..f09d387 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -544,6 +544,30 @@ void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
}
EXPORT_SYMBOL(genlmsg_put);
+static int genl_lock_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct genl_ops *ops = cb->data;
+ int rc;
+
+ genl_lock();
+ rc = ops->dumpit(skb, cb);
+ genl_unlock();
+ return rc;
+}
+
+static int genl_lock_done(struct netlink_callback *cb)
+{
+ struct genl_ops *ops = cb->data;
+ int rc = 0;
+
+ if (ops->done) {
+ genl_lock();
+ rc = ops->done(cb);
+ genl_unlock();
+ }
+ return rc;
+}
+
static int genl_family_rcv_msg(struct genl_family *family,
struct sk_buff *skb,
struct nlmsghdr *nlh)
@@ -572,15 +596,32 @@ static int genl_family_rcv_msg(struct genl_family *family,
return -EPERM;
if ((nlh->nlmsg_flags & NLM_F_DUMP) == NLM_F_DUMP) {
- struct netlink_dump_control c = {
- .dump = ops->dumpit,
- .done = ops->done,
- };
+ int rc;
if (ops->dumpit == NULL)
return -EOPNOTSUPP;
- return netlink_dump_start(net->genl_sock, skb, nlh, &c);
+ if (!family->parallel_ops) {
+ struct netlink_dump_control c = {
+ .data = ops,
+ .dump = genl_lock_dumpit,
+ .done = genl_lock_done,
+ };
+
+ genl_unlock();
+ rc = netlink_dump_start(net->genl_sock, skb, nlh, &c);
+ genl_lock();
+
+ } else {
+ struct netlink_dump_control c = {
+ .dump = ops->dumpit,
+ .done = ops->done,
+ };
+
+ rc = netlink_dump_start(net->genl_sock, skb, nlh, &c);
+ }
+
+ return rc;
}
if (ops->doit == NULL)
--
1.7.1
^ permalink raw reply related
* [PATCH v3 2/2] genl: Hold reference on correct module while netlink-dump.
From: Pravin B Shelar @ 2013-08-23 19:45 UTC (permalink / raw)
To: netdev; +Cc: Pravin B Shelar, Jesse Gross, Johannes Berg
netlink dump operations take module as parameter to hold
reference for entire netlink dump duration.
Currently it holds ref only on genl module which is not correct
when we use ops registered to genl from another module.
Following patch adds module pointer to genl_ops so that netlink
can hold ref count on it.
CC: Jesse Gross <jesse@nicira.com>
CC: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
---
v2-v3:
get rid of extra argument (struct module *).
v1-v2:
No need to ref count genl module.
---
include/net/genetlink.h | 20 ++++++++++++++++++--
net/netlink/genetlink.c | 20 +++++++++++---------
2 files changed, 29 insertions(+), 11 deletions(-)
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 93024a4..8e0b6c8 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -61,6 +61,7 @@ struct genl_family {
struct list_head ops_list; /* private */
struct list_head family_list; /* private */
struct list_head mcast_groups; /* private */
+ struct module *module;
};
/**
@@ -121,9 +122,24 @@ struct genl_ops {
struct list_head ops_list;
};
-extern int genl_register_family(struct genl_family *family);
-extern int genl_register_family_with_ops(struct genl_family *family,
+extern int __genl_register_family(struct genl_family *family);
+
+static inline int genl_register_family(struct genl_family *family)
+{
+ family->module = THIS_MODULE;
+ return __genl_register_family(family);
+}
+
+extern int __genl_register_family_with_ops(struct genl_family *family,
struct genl_ops *ops, size_t n_ops);
+
+static inline int genl_register_family_with_ops(struct genl_family *family,
+ struct genl_ops *ops, size_t n_ops)
+{
+ family->module = THIS_MODULE;
+ return __genl_register_family_with_ops(family, ops, n_ops);
+}
+
extern int genl_unregister_family(struct genl_family *family);
extern int genl_register_ops(struct genl_family *, struct genl_ops *ops);
extern int genl_unregister_ops(struct genl_family *, struct genl_ops *ops);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index f09d387..f1c81d5 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -364,7 +364,7 @@ int genl_unregister_ops(struct genl_family *family, struct genl_ops *ops)
EXPORT_SYMBOL(genl_unregister_ops);
/**
- * genl_register_family - register a generic netlink family
+ * __genl_register_family - register a generic netlink family
* @family: generic netlink family
*
* Registers the specified family after validating it first. Only one
@@ -374,7 +374,7 @@ EXPORT_SYMBOL(genl_unregister_ops);
*
* Return 0 on success or a negative error code.
*/
-int genl_register_family(struct genl_family *family)
+int __genl_register_family(struct genl_family *family)
{
int err = -EINVAL;
@@ -430,10 +430,10 @@ errout_locked:
errout:
return err;
}
-EXPORT_SYMBOL(genl_register_family);
+EXPORT_SYMBOL(__genl_register_family);
/**
- * genl_register_family_with_ops - register a generic netlink family
+ * __genl_register_family_with_ops - register a generic netlink family
* @family: generic netlink family
* @ops: operations to be registered
* @n_ops: number of elements to register
@@ -457,12 +457,12 @@ EXPORT_SYMBOL(genl_register_family);
*
* Return 0 on success or a negative error code.
*/
-int genl_register_family_with_ops(struct genl_family *family,
+int __genl_register_family_with_ops(struct genl_family *family,
struct genl_ops *ops, size_t n_ops)
{
int err, i;
- err = genl_register_family(family);
+ err = __genl_register_family(family);
if (err)
return err;
@@ -476,7 +476,7 @@ err_out:
genl_unregister_family(family);
return err;
}
-EXPORT_SYMBOL(genl_register_family_with_ops);
+EXPORT_SYMBOL(__genl_register_family_with_ops);
/**
* genl_unregister_family - unregister generic netlink family
@@ -603,22 +603,24 @@ static int genl_family_rcv_msg(struct genl_family *family,
if (!family->parallel_ops) {
struct netlink_dump_control c = {
+ .module = family->module,
.data = ops,
.dump = genl_lock_dumpit,
.done = genl_lock_done,
};
genl_unlock();
- rc = netlink_dump_start(net->genl_sock, skb, nlh, &c);
+ rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
genl_lock();
} else {
struct netlink_dump_control c = {
+ .module = family->module,
.dump = ops->dumpit,
.done = ops->done,
};
- rc = netlink_dump_start(net->genl_sock, skb, nlh, &c);
+ rc = __netlink_dump_start(net->genl_sock, skb, nlh, &c);
}
return rc;
--
1.7.1
^ permalink raw reply related
* sendto() bug?
From: Chris Clark @ 2013-08-23 19:19 UTC (permalink / raw)
To: davem; +Cc: netdev
Hi Dave,
I've run across a problem with the sendto() system call that first
appeared with commit f8126f1d:
=================================================================
commit f8126f1d5136be1ca1a3536d43ad7a710b5620f8
Author: David S. Miller <davem@davemloft.net>
Date: Fri Jul 13 05:03:45 2012 -0700
ipv4: Adjust semantics of rt->rt_gateway.
=================================================================
The issue arises when sendto() is used on a SOCK_RAW IP socket opened
with the IP_HDRINCL option. Instead of sending the packet to the
address given explicitly in the sendto() call, the kernel ignores the
given dest_addr and ARPs locally for the destination address given in
the constructed packet's IP header. Because the IP header's
destination address is not on a local subnet, the bogus ARP never
resolves and the packet is never sent.
A subsequent commit addressed a similar problem in netfilter:
=================================================================
commit 2ad5b9e4bd314fc685086b99e90e5de3bc59e26b
Author: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue Oct 16 22:33:29 2012 +0000
netfilter: xt_TEE: don't use destination address found in header
Torsten Luettgert bisected TEE regression starting with commit
f8126f1d5136be1 (ipv4: Adjust semantics of rt->rt_gateway.)
The problem is that it tries to ARP-lookup the original destination
address of the forwarded packet, not the address of the gateway.
Fix this using FLOWI_FLAG_KNOWN_NH Julian added in commit
c92b96553a80c1 (ipv4: Add FLOWI_FLAG_KNOWN_NH), so that known
nexthop (info->gw.ip) has preference on resolving.
=================================================================
In the same vein as 2ad5b9e4, I'm soliciting feedback on something
similar for raw_sendmsg():
=================================================================
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index dd44e0a..454d9c1 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -571,7 +571,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
RT_SCOPE_UNIVERSE,
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
- inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP,
+ inet_sk_flowi_flags(sk) | FLOWI_FLAG_CAN_SLEEP
+ | ((msg->msg_namelen
+ && (tos & RTO_ONLINK)) ? FLOWI_FLAG_KNOWN_NH : 0),
daddr, saddr, 0, 0);
if (!inet->hdrincl) {
=================================================================
The thought here is to apply the FLOWI_FLAG_KNOWN_NH flag when:
(a) The dest_addr is given explicitly (msg->msg_namelen), and
(b) The socket is in MSG_DONTROUTE mode (tos & RTO_ONLINK).
This change fixes the problem because the FLOWI_FLAG_KNOWN_NH flag
ends up (very indirectly) triggering the following code in
rt_set_nexthop() which sets rt->rt_gateway to the address specified in
the sendto() call, which ultimately causes the packet to be forwarded
to that address rather than wrongly ARPing locally for the (different,
remote) address in the IP header:
=================================================================
if (unlikely(!cached)) {
/* Routes we intend to cache in nexthop exception or
* FIB nexthop have the DST_NOCACHE bit clear.
* However, if we are unsuccessful at storing this
* route into the cache we really need to set it.
*/
rt->dst.flags |= DST_NOCACHE;
if (!rt->rt_gateway)
-> rt->rt_gateway = daddr;
=================================================================
While the diff resolves the particular problem that I encountered, I'm
soliciting feedback because I'm not sure it is necessary and
sufficient beyond my particular test case.
Thanks,
Chris
^ permalink raw reply related
* Re: [PATCH v4 3/5] net: ethernet: cpsw: introduce ti,am3352-cpsw compatible string
From: Santosh Shilimkar @ 2013-08-23 19:54 UTC (permalink / raw)
To: Mugunthan V N
Cc: Sekhar Nori, Daniel Mack, netdev, bcousson, sergei.shtylyov,
davem, ujhelyi.m, vaibhav.bedia, d-gerlach, linux-arm-kernel,
linux-omap, devicetree
In-Reply-To: <5217AA15.7010907@ti.com>
On Friday 23 August 2013 02:29 PM, Mugunthan V N wrote:
> On Friday 23 August 2013 11:40 PM, Santosh Shilimkar wrote:
>> On Friday 23 August 2013 01:39 PM, Sekhar Nori wrote:
>>> On 8/23/2013 10:58 PM, Santosh Shilimkar wrote:
>>>> On Friday 23 August 2013 01:24 PM, Daniel Mack wrote:
>>>>> On 23.08.2013 19:19, Santosh Shilimkar wrote:
>>>>>> On Friday 23 August 2013 01:09 PM, Sekhar Nori wrote:
>>>>>>> On 8/23/2013 10:26 PM, Santosh Shilimkar wrote:
>>>>>>>> So just stick the IP version or call it cpsw-v1... cpsw-v2 etc.
>>>>>>> If this could be handled using IP version then the right way would be to
>>>>>>> just read the IP version from hardware and use it. No need of DT property.
>>>>>>>
>>>>>> Thats fine as well but I thought the patch needed additional properties like
>>>>>> CM reg-address come from DT and hence the separate compatible. If you can
>>>>>> manage without that, thats even better.
>>>>> We can't, that's the whole point :)
>>>>>
>>>> I saw that from the patch :)
>>>>
>>>>> Well, theoretically, we could for now, but that's not a clean solution.
>>>>> Again: the problem here is that the control port is separated from the
>>>>> cpsw core, and so we have to implement something specific for the AM3352
>>>>> SoC. I know that's a violation of clean and generic driver ideas, but
>>>>> there's no way we can assume that every cpsw v2 ip block has a control
>>>>> port that is compatible to the one found on am335x chips.
>>>>>
>>>> But there is a possibility that other SOC will just use the same
>>>> control module approach. So using a revision IP is just fine. BTW,
>>> But this is misleading because it makes appear like the same compatible
>>> can be used on on another SoC like DRA7 which probably has the same
>>> version of IP but a different control module implementation, when in
>>> practice it cannot.
>>>
>>> The fact is we are doing something SoC specific in the driver and we
>>> cannot hide that behind IP versions. If really in practice there comes
>>> another SoC with the same control module definition then it can always
>>> use ti,am3352-cpsw compatible as well. The compatible name does not
>>> preclude its usage.
>>>
>> My point was the CPSW needs a feature which is implemented using
>> control module rather than within the IP itself. Its an implementation
>> detail. As such the additional feature makes sense for that IP. O.w
>> there was no need to do any monkeying with control module.
>>
>> E.g
>> MMC card detect is a basic functionality, implemented by various types
>> like control module, PMIC or MMC IP itself. As such the driver need
>> that support and all the implementation details needs to still handled
>> to make that part work.
>>
>>
>
> CPSW core as such understands only GMII/MII signals, there is an
> additional module which converts GMII/MII signals to RGMII/RMII signals
> respectively which is called as CPRGMII/CPRMII as specified in the
> AM335x TRM in Figure 14-1. Ethernet Switch Integration.
>
> So to control this sub-module, the control register is used and this has
> to be configured according to the EVM design like what mode of phy is
> connected. CPRGMII and CPRMII is no way related to CPSW core.
>
Ok then why are you polluting cpsw driver with that code which
not realted to CPSW as you said above. You are contradicting what
you said by supporting the SOC usage in the core CPSW driver.
Regards,
Santosh
^ permalink raw reply
* Re: travelling...
From: Antonio Quartulli @ 2013-08-23 20:16 UTC (permalink / raw)
To: David Miller, netdev, linux-wireless, netfilter-devel
In-Reply-To: <20130823182943.GE808@order.stressinduktion.org>
[-- Attachment #1: Type: text/plain, Size: 814 bytes --]
On Fri, Aug 23, 2013 at 08:29:43PM +0200, Hannes Frederic Sowa wrote:
> On Fri, Aug 23, 2013 at 11:13:08AM -0700, David Miller wrote:
> >
> > I'm travelling over the weekend so I won't be as responsive as
> > usual.
> >
> > I just pushed 'net' to Linus and he pulled it in. I plan to work
> > on my next set of -stable submissions this coming Monday.
> >
> > If a merge of 'net' into 'net-next' would be useful for someone,
> > now would be a really good time to tell me.
>
> If it would not take you too much time, it would be nice. I depend on
> a change in net to make another small patch. :)
If possible I'd need that too in order to send a couple of changes to net-next.
Have a nice weekend!
--
Antonio Quartulli
..each of us alone is worth nothing..
Ernesto "Che" Guevara
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH RFC net-next] net: epoll support for busy poll
From: Eric Wong @ 2013-08-23 20:36 UTC (permalink / raw)
To: Eliezer Tamir
Cc: David Miller, linux-kernel, netdev, e1000-devel, Eilon Greenstein,
Amir Vadai, Eric Dumazet, Willem de Bruijn, Eliezer Tamir
In-Reply-To: <52170E78.1010704@linux.intel.com>
Eliezer Tamir <eliezer.tamir@linux.intel.com> wrote:
> I'm not sure I understand your claim that epoll has a higher latency
> than poll.
Nevermind, I usually live in an EPOLLONESHOT bubble so I use more
epoll_ctl than "normal" epoll apps :x
Anyways, good to know epoll wins over poll. Thanks.
^ permalink raw reply
* Re: [PATCH 1/2] genl: Fix genl dumpit() locking.
From: Pravin Shelar @ 2013-08-23 20:52 UTC (permalink / raw)
To: Johannes Berg; +Cc: netdev, Jesse Gross
In-Reply-To: <1377251485.14021.17.camel@jlt4.sipsolutions.net>
On Fri, Aug 23, 2013 at 2:51 AM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> On Fri, 2013-08-23 at 09:29 +0200, Johannes Berg wrote:
>
>> > You are thinking abt genl-sock -> nlk -> cb_lock which is not used in
>> > genl-dump locking if cb_lock is NULL while creating nl socket.
>>
>> You're right, this is also done for each userland socket, so each socket
>> now gets its own cb_mutex. This would help genl families with
>> parallel_ops.
>
> I'm still missing something. Kernel 3.4 had cb_mutex assign to the
> genl_mutex, but we saw the original crash there, apparently dumpit
> *wasn't* (always) locked with it?
>
Can you point me to original crash on 3.4?
Thanks.
^ permalink raw reply
* [net-next 1/1] bna: firmware update to 3.2.1.1
From: Rasesh Mody @ 2013-08-23 21:31 UTC (permalink / raw)
To: davem, netdev; +Cc: adapter_linux_open_src_team, Rasesh Mody
This patch updates the firmware to address the thermal notification issue
Signed-off-by: Rasesh Mody <rmody@brocade.com>
---
drivers/net/ethernet/brocade/bna/cna.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/brocade/bna/cna.h b/drivers/net/ethernet/brocade/bna/cna.h
index c37f706..43405f6 100644
--- a/drivers/net/ethernet/brocade/bna/cna.h
+++ b/drivers/net/ethernet/brocade/bna/cna.h
@@ -37,8 +37,8 @@
extern char bfa_version[];
-#define CNA_FW_FILE_CT "ctfw-3.2.1.0.bin"
-#define CNA_FW_FILE_CT2 "ct2fw-3.2.1.0.bin"
+#define CNA_FW_FILE_CT "ctfw-3.2.1.1.bin"
+#define CNA_FW_FILE_CT2 "ct2fw-3.2.1.1.bin"
#define FC_SYMNAME_MAX 256 /*!< max name server symbolic name size */
#pragma pack(1)
--
1.8.3.rc2
^ permalink raw reply related
* Re: [PATCH net-next 01/10] net: etherdevice: add address inherit helper
From: Bjørn Mork @ 2013-08-23 22:28 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20130823122404.7aebb2c8@nehalam.linuxnetplumber.net>
Stephen Hemminger <stephen@networkplumber.org> writes:
> On Fri, 23 Aug 2013 11:35:04 +0200
> Bjørn Mork <bjorn@mork.no> wrote:
>
>> /**
>> + * eth_hw_addr_inherit - Copy dev_addr from another net_device
>> + * @dst: pointer to net_device to copy dev_addr to
>> + * @src: pointer to net_device to copy dev_addr from
>> + *
>> + * Copy the Ethernet address from one net_device to another along with
>> + * the addr_assign_type.
>> + */
>> +static inline int eth_hw_addr_inherit(struct net_device *dst,
>> + struct net_device *src)
>> +{
>> + if (dst->addr_len != src->addr_len)
>> + return -EINVAL;
>> +
>> + dst->addr_assign_type = src->addr_assign_type;
>> + memcpy(dst->dev_addr, src->dev_addr, dst->addr_len);
>> + return 0;
>> +}
>> +
>
> Since all the other code in this file assumes addr_len == ETH_ALEN
> why does this code need to handle variable addresses. Trivial but
> then the memcpy is fixed size and can be optimized.
Didn't know that. I'll make that change in the next version. Not that
optimization matters much here, but consistency is always good.
Bjørn
^ permalink raw reply
* [RFC] b44: use phylib
From: Hauke Mehrtens @ 2013-08-23 22:56 UTC (permalink / raw)
To: zambrano; +Cc: netdev, Hauke Mehrtens, Florian Fainelli
This splits the driver into the mac and a phy driver. On routers where
this driver is used we have a switch which implements a phy and can be
controlled by a phy driver.
I have just tested this on my router with a switch as phy and not on normal desktop PC.
This is based on a patch by Florian Fainelli <florian@openwrt.org>
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Cc: Florian Fainelli <florian@openwrt.org>
---
drivers/net/ethernet/broadcom/Kconfig | 1 +
drivers/net/ethernet/broadcom/b44.c | 217 ++++++++++++++++++---------------
drivers/net/ethernet/broadcom/b44.h | 5 +-
3 files changed, 126 insertions(+), 97 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 2fa5b86..3f97d9f 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -23,6 +23,7 @@ config B44
depends on SSB_POSSIBLE && HAS_DMA
select SSB
select MII
+ select PHYLIB
---help---
If you have a network (Ethernet) controller of this type, say Y
or M and read the Ethernet-HOWTO, available from
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 9b017d9..4c741d7 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -29,6 +29,7 @@
#include <linux/dma-mapping.h>
#include <linux/ssb/ssb.h>
#include <linux/slab.h>
+#include <linux/phy.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -299,21 +300,23 @@ static inline int b44_writephy(struct b44 *bp, int reg, u32 val)
}
/* miilib interface */
-static int b44_mii_read(struct net_device *dev, int phy_id, int location)
+static int b44_mii_read(struct mii_bus *bus, int phy_id, int location)
{
u32 val;
- struct b44 *bp = netdev_priv(dev);
+ struct b44 *bp = bus->priv;
int rc = __b44_readphy(bp, phy_id, location, &val);
if (rc)
return 0xffffffff;
return val;
}
-static void b44_mii_write(struct net_device *dev, int phy_id, int location,
- int val)
+static int b44_mii_write(struct mii_bus *bus, int phy_id, int location,
+ u16 val)
{
- struct b44 *bp = netdev_priv(dev);
+ struct b44 *bp = bus->priv;
__b44_writephy(bp, phy_id, location, val);
+
+ return 0;
}
static int b44_phy_reset(struct b44 *bp)
@@ -1795,102 +1798,24 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct b44 *bp = netdev_priv(dev);
- cmd->supported = (SUPPORTED_Autoneg);
- cmd->supported |= (SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_MII);
-
- cmd->advertising = 0;
- if (bp->flags & B44_FLAG_ADV_10HALF)
- cmd->advertising |= ADVERTISED_10baseT_Half;
- if (bp->flags & B44_FLAG_ADV_10FULL)
- cmd->advertising |= ADVERTISED_10baseT_Full;
- if (bp->flags & B44_FLAG_ADV_100HALF)
- cmd->advertising |= ADVERTISED_100baseT_Half;
- if (bp->flags & B44_FLAG_ADV_100FULL)
- cmd->advertising |= ADVERTISED_100baseT_Full;
- cmd->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
- ethtool_cmd_speed_set(cmd, ((bp->flags & B44_FLAG_100_BASE_T) ?
- SPEED_100 : SPEED_10));
- cmd->duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ?
- DUPLEX_FULL : DUPLEX_HALF;
- cmd->port = 0;
- cmd->phy_address = bp->phy_addr;
- cmd->transceiver = (bp->flags & B44_FLAG_INTERNAL_PHY) ?
- XCVR_INTERNAL : XCVR_EXTERNAL;
- cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ?
- AUTONEG_DISABLE : AUTONEG_ENABLE;
- if (cmd->autoneg == AUTONEG_ENABLE)
- cmd->advertising |= ADVERTISED_Autoneg;
- if (!netif_running(dev)){
- ethtool_cmd_speed_set(cmd, 0);
- cmd->duplex = 0xff;
- }
- cmd->maxtxpkt = 0;
- cmd->maxrxpkt = 0;
- return 0;
+ return phy_ethtool_gset(bp->phydev, cmd);
}
static int b44_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct b44 *bp = netdev_priv(dev);
- u32 speed = ethtool_cmd_speed(cmd);
-
- /* We do not support gigabit. */
- if (cmd->autoneg == AUTONEG_ENABLE) {
- if (cmd->advertising &
- (ADVERTISED_1000baseT_Half |
- ADVERTISED_1000baseT_Full))
- return -EINVAL;
- } else if ((speed != SPEED_100 &&
- speed != SPEED_10) ||
- (cmd->duplex != DUPLEX_HALF &&
- cmd->duplex != DUPLEX_FULL)) {
- return -EINVAL;
- }
+ int ret;
spin_lock_irq(&bp->lock);
- if (cmd->autoneg == AUTONEG_ENABLE) {
- bp->flags &= ~(B44_FLAG_FORCE_LINK |
- B44_FLAG_100_BASE_T |
- B44_FLAG_FULL_DUPLEX |
- B44_FLAG_ADV_10HALF |
- B44_FLAG_ADV_10FULL |
- B44_FLAG_ADV_100HALF |
- B44_FLAG_ADV_100FULL);
- if (cmd->advertising == 0) {
- bp->flags |= (B44_FLAG_ADV_10HALF |
- B44_FLAG_ADV_10FULL |
- B44_FLAG_ADV_100HALF |
- B44_FLAG_ADV_100FULL);
- } else {
- if (cmd->advertising & ADVERTISED_10baseT_Half)
- bp->flags |= B44_FLAG_ADV_10HALF;
- if (cmd->advertising & ADVERTISED_10baseT_Full)
- bp->flags |= B44_FLAG_ADV_10FULL;
- if (cmd->advertising & ADVERTISED_100baseT_Half)
- bp->flags |= B44_FLAG_ADV_100HALF;
- if (cmd->advertising & ADVERTISED_100baseT_Full)
- bp->flags |= B44_FLAG_ADV_100FULL;
- }
- } else {
- bp->flags |= B44_FLAG_FORCE_LINK;
- bp->flags &= ~(B44_FLAG_100_BASE_T | B44_FLAG_FULL_DUPLEX);
- if (speed == SPEED_100)
- bp->flags |= B44_FLAG_100_BASE_T;
- if (cmd->duplex == DUPLEX_FULL)
- bp->flags |= B44_FLAG_FULL_DUPLEX;
- }
-
if (netif_running(dev))
b44_setup_phy(bp);
+ ret = phy_ethtool_sset(bp->phydev, cmd);
+
spin_unlock_irq(&bp->lock);
- return 0;
+ return ret;
}
static void b44_get_ringparam(struct net_device *dev,
@@ -2066,20 +1991,80 @@ static const struct ethtool_ops b44_ethtool_ops = {
static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct mii_ioctl_data *data = if_mii(ifr);
struct b44 *bp = netdev_priv(dev);
int err = -EINVAL;
if (!netif_running(dev))
goto out;
+ if (!bp->phydev)
+ return -EINVAL;
+
spin_lock_irq(&bp->lock);
- err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
+ err = phy_mii_ioctl(bp->phydev, ifr, cmd);
spin_unlock_irq(&bp->lock);
out:
return err;
}
+static void b44_adjust_link(struct net_device *dev)
+{
+ struct b44 *bp = netdev_priv(dev);
+ struct phy_device *phydev = bp->phydev;
+ int status_changed = 0;
+
+ BUG_ON(!phydev);
+
+ if (bp->old_link != phydev->link) {
+ status_changed = 1;
+ bp->old_link = phydev->link;
+ }
+
+ /* reflect duplex change */
+ if (phydev->link && (bp->old_duplex != phydev->duplex)) {
+ status_changed = 1;
+ bp->old_duplex = phydev->duplex;
+ }
+
+ if (status_changed) {
+ pr_info("%s: link %s", dev->name, phydev->link ?
+ "UP" : "DOWN");
+ if (phydev->link)
+ pr_cont(" - %d/%s", phydev->speed,
+ phydev->duplex == DUPLEX_FULL ? "full" : "half");
+ pr_cont("\n");
+ }
+}
+
+static int b44_mii_probe(struct net_device *dev)
+{
+ struct b44 *bp = netdev_priv(dev);
+ struct phy_device *phydev = NULL;
+ char phy_id[MII_BUS_ID_SIZE + 3];
+
+ /* connect to PHY */
+ snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
+ bp->mii_bus->id, bp->phy_addr);
+
+ phydev = phy_connect(dev, phy_id, &b44_adjust_link,
+ PHY_INTERFACE_MODE_MII);
+ if (IS_ERR(phydev)) {
+ netdev_err(dev, "could not attach PHY: %s", phy_id);
+ bp->phy_addr = B44_PHY_ADDR_NO_PHY;
+ return PTR_ERR(phydev);
+ }
+
+ bp->phydev = phydev;
+ bp->old_link = 0;
+ bp->old_duplex = -1;
+ bp->phy_addr = phydev->addr;
+
+ netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
+ phydev->drv->name, dev_name(&phydev->dev));
+
+ return 0;
+}
+
static int b44_get_invariants(struct b44 *bp)
{
struct ssb_device *sdev = bp->sdev;
@@ -2197,12 +2182,38 @@ static int b44_init_one(struct ssb_device *sdev,
goto err_out_powerdown;
}
- bp->mii_if.dev = dev;
- bp->mii_if.mdio_read = b44_mii_read;
- bp->mii_if.mdio_write = b44_mii_write;
- bp->mii_if.phy_id = bp->phy_addr;
- bp->mii_if.phy_id_mask = 0x1f;
- bp->mii_if.reg_num_mask = 0x1f;
+ bp->mii_bus = mdiobus_alloc();
+ if (!bp->mii_bus) {
+ dev_err(sdev->dev, "mdiobus_alloc() failed\n");
+ err = -ENOMEM;
+ goto err_out_powerdown;
+ }
+
+ bp->mii_bus->priv = bp;
+ bp->mii_bus->read = b44_mii_read;
+ bp->mii_bus->write = b44_mii_write;
+ bp->mii_bus->name = "b44_eth_mii";
+ snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", instance);
+ bp->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+ if (!bp->mii_bus->irq) {
+ dev_err(sdev->dev, "mii_bus irq allocation failed\n");
+ err = -ENOMEM;
+ goto err_out_mdiobus;
+ }
+
+ memset(bp->mii_bus->irq, PHY_POLL, sizeof(int) * PHY_MAX_ADDR);
+
+ err = mdiobus_register(bp->mii_bus);
+ if (err) {
+ dev_err(sdev->dev, "failed to register MII bus\n");
+ goto err_out_mdiobus_irq;
+ }
+
+ err = b44_mii_probe(dev);
+ if (err) {
+ dev_err(sdev->dev, "failed to probe MII bus\n");
+ goto err_out_mdiobus_unregister;
+ }
/* By default, advertise all speed/duplex settings. */
bp->flags |= (B44_FLAG_ADV_10HALF | B44_FLAG_ADV_10FULL |
@@ -2234,6 +2245,16 @@ static int b44_init_one(struct ssb_device *sdev,
return 0;
+
+err_out_mdiobus_unregister:
+ mdiobus_unregister(bp->mii_bus);
+
+err_out_mdiobus_irq:
+ kfree(bp->mii_bus->irq);
+
+err_out_mdiobus:
+ mdiobus_free(bp->mii_bus);
+
err_out_powerdown:
ssb_bus_may_powerdown(sdev->bus);
@@ -2247,8 +2268,12 @@ out:
static void b44_remove_one(struct ssb_device *sdev)
{
struct net_device *dev = ssb_get_drvdata(sdev);
+ struct b44 *bp = netdev_priv(dev);
unregister_netdev(dev);
+ mdiobus_unregister(bp->mii_bus);
+ kfree(bp->mii_bus->irq);
+ mdiobus_free(bp->mii_bus);
ssb_device_disable(sdev, 0);
ssb_bus_may_powerdown(sdev->bus);
free_netdev(dev);
diff --git a/drivers/net/ethernet/broadcom/b44.h b/drivers/net/ethernet/broadcom/b44.h
index 8993d72..0b8db8b 100644
--- a/drivers/net/ethernet/broadcom/b44.h
+++ b/drivers/net/ethernet/broadcom/b44.h
@@ -396,7 +396,10 @@ struct b44 {
u32 tx_pending;
u8 phy_addr;
u8 force_copybreak;
- struct mii_if_info mii_if;
+ struct phy_device *phydev;
+ struct mii_bus *mii_bus;
+ int old_link;
+ int old_duplex;
};
#endif /* _B44_H */
--
1.7.10.4
^ permalink raw reply related
* Re: [RFC] b44: use phylib
From: Joe Perches @ 2013-08-23 23:10 UTC (permalink / raw)
To: Hauke Mehrtens; +Cc: zambrano, netdev, Florian Fainelli
In-Reply-To: <1377298608-18016-1-git-send-email-hauke@hauke-m.de>
On Sat, 2013-08-24 at 00:56 +0200, Hauke Mehrtens wrote:
> This splits the driver into the mac and a phy driver. On routers where
> this driver is used we have a switch which implements a phy and can be
> controlled by a phy driver.
trivial comments only...
> diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
[]
> +static void b44_adjust_link(struct net_device *dev)
> +{
> + struct b44 *bp = netdev_priv(dev);
> + struct phy_device *phydev = bp->phydev;
> + int status_changed = 0;
bool?
> +static int b44_mii_probe(struct net_device *dev)
> +{
[]
> + if (IS_ERR(phydev)) {
> + netdev_err(dev, "could not attach PHY: %s", phy_id);
missing newline?
^ permalink raw reply
* Re: [net-next 1/2] Documentation/networking/: Update Intel wired LAN driver documentation
From: Jeff Kirsher @ 2013-08-24 0:09 UTC (permalink / raw)
To: Ben Hutchings; +Cc: davem, netdev, gospo, sassmann
In-Reply-To: <1377262419.3364.11.camel@bwh-desktop.uk.level5networks.com>
[-- Attachment #1: Type: text/plain, Size: 2238 bytes --]
On Fri, 2013-08-23 at 13:53 +0100, Ben Hutchings wrote:
> On Fri, 2013-08-23 at 05:29 -0700, Jeff Kirsher wrote:
> > Updates the documentation to the Intel wired LAN drivers.
>
> Except e100.txt which seems to be moving backward in time:
>
> [...]
> > --- a/Documentation/networking/e100.txt
> > +++ b/Documentation/networking/e100.txt
> > @@ -1,7 +1,7 @@
> > Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters
> > ==============================================================
> >
> > -November 15, 2005
> > +March 15, 2011
> >
> > Contents
> > ========
> > @@ -94,8 +94,8 @@ Additional Configurations
> >
> > Configuring a network driver to load properly when the system is started is
> > distribution dependent. Typically, the configuration process involves adding
> > - an alias line to /etc/modprobe.d/*.conf as well as editing other system
> > - startup scripts and/or configuration files. Many popular Linux
> > + an alias line to /etc/modules.conf or /etc/modprobe.conf as well as editing
>
> Reverting this fix:
>
> commit 970e2486492aa1eb47a436a5a4c81e92558986a9
> Author: Lucas De Marchi <lucas.demarchi@profusion.mobi>
> Date: Fri Mar 30 13:37:16 2012 -0700
>
> Documentation: remove references to /etc/modprobe.conf
>
> [...]
> > Enabling Wake on LAN* (WoL)
> > ---------------------------
> > - WoL is provided through the ethtool* utility. For instructions on enabling
> > - WoL with ethtool, refer to the ethtool man page.
> > + WoL is provided through the ethtool* utility. The ethtool utility is included
> > + with Red Hat* 8.0. For other Linux distributions, download and install
> [...]
>
> And part of this one:
>
> commit 68f20d948c86bd6bbc075052f6b6c45b8f56957e
> Author: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
> Date: Fri Dec 17 12:14:34 2010 +0000
>
> Documentation/networking: Update Intel Wired LAN docs
>
> Mentioning a 2002 distribution is completely pointless.
>
> Ben.
>
Thanks Ben, I will drop all the e100.txt changes at this point. The
driver has little to no changes in the last couple of years, so the
documentation should not be changing.
I will re-spin with a v2.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox