* bridge interface initial carrier state
From: Dan Williams @ 2013-02-11 20:01 UTC (permalink / raw)
To: netdev
Hi,
I'm wondering if the initial carrier state of 'on' is intentional for a
bridge without ports; immediately after adding ports, the carrier is
recalculated and depends on the combined state of each port's carrier
and STP forwarding state. So a userspace program attempting to decide
whether the bridge was usable or not has to look at both (a) how many
ports are available and (b) bridge carrier state, instead of just
looking at the bridge carrier state.
Dan
^ permalink raw reply
* Re: [PATCH] ipv6: don't accept multicast traffic with scop 0
From: David Miller @ 2013-02-11 19:52 UTC (permalink / raw)
To: hannes; +Cc: netdev, yoshfuji, erik.hugne
In-Reply-To: <20130211194835.GD23991@order.stressinduktion.org>
From: Hannes Frederic Sowa <hannes@stressinduktion.org>
Date: Mon, 11 Feb 2013 20:48:35 +0100
> On Sun, Feb 10, 2013 at 01:48:51PM +0100, Hannes Frederic Sowa wrote:
>> + /*
>> + * RFC4291 2.7
>> + * Nodes must not originate a packet to a multicast address whose scop
>> + * field contains the reserved value 0; if such a packet is received, it
>> + * must be silently dropped.
>
> Just nit-picking: The field is actually called scop without e, as pointed out
> by three erratas to RFC4291. :)
That's funny because I added the 'e' to your patches while applying
them, it just looks completely stupid to refer to this things as
'scop'.
^ permalink raw reply
* [PATCH 3/3] driver: net: ethernet: cpsw: dual emac interface implementation
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N
In-Reply-To: <1360612340-9266-1-git-send-email-mugunthanvnm@ti.com>
The CPSW switch can act as Dual EMAC by segregating the switch ports
using VLAN and port VLAN as per the TRM description in
14.3.2.10.2 Dual Mac Mode
Following CPSW components will be common for both the interfaces.
* Interrupt source is common for both eth interfaces
* Interrupt pacing is common for both interfaces
* Hardware statistics is common for all the ports
* CPDMA is common for both eth interface
* CPTS is common for both the interface and it should not be enabled on
both the interface as timestamping information doesn't contain port
information.
Constrains
* Reserved VID of One port should not be used in other interface which will
enable switching functionality
* Same VID must not be used in both the interface which will enable switching
functionality
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 2 +
drivers/net/ethernet/ti/cpsw.c | 335 ++++++++++++++++++++----
include/linux/platform_data/cpsw.h | 3 +
3 files changed, 288 insertions(+), 52 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 6ddd028..ecfdf75 100644
--- a/Documentation/devicetree/bindings/net/cpsw.txt
+++ b/Documentation/devicetree/bindings/net/cpsw.txt
@@ -24,6 +24,8 @@ Required properties:
Optional properties:
- ti,hwmods : Must be "cpgmac0"
- no_bd_ram : Must be 0 or 1
+- dual_emac : Specifies Switch to act as Dual EMAC
+- dual_emac_res_vlan : Specifies VID to be used to segregate the ports
Note: "ti,hwmods" field is used to fetch the base address and irq
resources from TI, omap hwmod data base during device registration.
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 4b964bb..4ceed6e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -122,6 +122,10 @@ do { \
#define CPSW_VLAN_AWARE BIT(1)
#define CPSW_ALE_VLAN_AWARE 1
+#define CPSW_FIFO_NORMAL_MODE (0 << 15)
+#define CPSW_FIFO_DUAL_MAC_MODE (1 << 15)
+#define CPSW_FIFO_RATE_LIMIT_MODE (2 << 15)
+
#define cpsw_enable_irq(priv) \
do { \
u32 i; \
@@ -254,7 +258,7 @@ struct cpsw_ss_regs {
struct cpsw_host_regs {
u32 max_blks;
u32 blk_cnt;
- u32 flow_thresh;
+ u32 tx_in_ctl;
u32 port_vlan;
u32 tx_pri_map;
u32 cpdma_tx_pri_map;
@@ -281,6 +285,9 @@ struct cpsw_slave {
u32 mac_control;
struct cpsw_slave_data *data;
struct phy_device *phy;
+ struct net_device *ndev;
+ u32 port_vlan;
+ u32 open_stat;
};
static inline u32 slave_read(struct cpsw_slave *slave, u32 offset)
@@ -320,15 +327,63 @@ struct cpsw_priv {
u32 irqs_table[4];
u32 num_irqs;
struct cpts *cpts;
+ u32 emac_port;
};
#define napi_to_priv(napi) container_of(napi, struct cpsw_priv, napi)
-#define for_each_slave(priv, func, arg...) \
- do { \
- int idx; \
- for (idx = 0; idx < (priv)->data.slaves; idx++) \
- (func)((priv)->slaves + idx, ##arg); \
+#define for_each_slave(priv, func, arg...) \
+ do { \
+ int idx; \
+ if (priv->data.dual_emac) \
+ (func)((priv)->slaves + priv->emac_port, ##arg);\
+ else \
+ for (idx = 0; idx < (priv)->data.slaves; idx++) \
+ (func)((priv)->slaves + idx, ##arg); \
+ } while (0)
+#define cpsw_get_slave_ndev(priv, __slave_no__) \
+ (priv->slaves[__slave_no__].ndev)
+#define cpsw_get_slave_priv(priv, __slave_no__) \
+ ((priv->slaves[__slave_no__].ndev) ? \
+ netdev_priv(priv->slaves[__slave_no__].ndev) : NULL) \
+
+#define cpsw_dual_emac_src_port_detect(status, priv, ndev, skb) \
+ do { \
+ if (!priv->data.dual_emac) \
+ break; \
+ if (CPDMA_RX_SOURCE_PORT(status) == 1) { \
+ ndev = cpsw_get_slave_ndev(priv, 0); \
+ priv = netdev_priv(ndev); \
+ skb->dev = ndev; \
+ } else if (CPDMA_RX_SOURCE_PORT(status) == 2) { \
+ ndev = cpsw_get_slave_ndev(priv, 1); \
+ priv = netdev_priv(ndev); \
+ skb->dev = ndev; \
+ } \
} while (0)
+#define cpsw_add_mcast(priv, addr) \
+ do { \
+ if (priv->data.dual_emac) { \
+ struct cpsw_slave *slave = priv->slaves + \
+ priv->emac_port; \
+ int slave_port = cpsw_get_slave_port(priv, \
+ slave->slave_num); \
+ cpsw_ale_add_mcast(priv->ale, addr, \
+ 1 << slave_port | 1 << priv->host_port, \
+ ALE_VLAN, slave->port_vlan, 0); \
+ } else { \
+ cpsw_ale_add_mcast(priv->ale, addr, \
+ ALE_ALL_PORTS << priv->host_port, \
+ 0, 0, 0); \
+ } \
+ } while (0)
+
+static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
+{
+ if (priv->host_port == 0)
+ return slave_num + 1;
+ else
+ return slave_num;
+}
static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
{
@@ -348,8 +403,7 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
/* program multicast address list into ALE register */
netdev_for_each_mc_addr(ha, ndev) {
- cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr,
- ALE_ALL_PORTS << priv->host_port, 0, 0, 0);
+ cpsw_add_mcast(priv, (u8 *)ha->addr);
}
}
}
@@ -396,6 +450,8 @@ void cpsw_rx_handler(void *token, int len, int status)
struct cpsw_priv *priv = netdev_priv(ndev);
int ret = 0;
+ cpsw_dual_emac_src_port_detect(status, priv, ndev, skb);
+
/* free and bail if we are shutting down */
if (unlikely(!netif_running(ndev)) ||
unlikely(!netif_carrier_ok(ndev))) {
@@ -437,18 +493,17 @@ static irqreturn_t cpsw_interrupt(int irq, void *dev_id)
cpsw_intr_disable(priv);
cpsw_disable_irq(priv);
napi_schedule(&priv->napi);
+ } else {
+ priv = cpsw_get_slave_priv(priv, 1);
+ if (likely(priv) && likely(netif_running(priv->ndev))) {
+ cpsw_intr_disable(priv);
+ cpsw_disable_irq(priv);
+ napi_schedule(&priv->napi);
+ }
}
return IRQ_HANDLED;
}
-static inline int cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
-{
- if (priv->host_port == 0)
- return slave_num + 1;
- else
- return slave_num;
-}
-
static int cpsw_poll(struct napi_struct *napi, int budget)
{
struct cpsw_priv *priv = napi_to_priv(napi);
@@ -566,6 +621,54 @@ static inline int __show_stat(char *buf, int maxlen, const char *name, u32 val)
leader + strlen(name), val);
}
+static int cpsw_common_res_usage_state(struct cpsw_priv *priv)
+{
+ u32 i;
+ u32 usage_count = 0;
+
+ if (!priv->data.dual_emac)
+ return 0;
+
+ for (i = 0; i < priv->data.slaves; i++)
+ if (priv->slaves[i].open_stat)
+ usage_count++;
+
+ return usage_count;
+}
+
+static inline int cpsw_tx_packet_submit(struct net_device *ndev,
+ struct cpsw_priv *priv, struct sk_buff *skb)
+{
+ if (!priv->data.dual_emac)
+ return cpdma_chan_submit(priv->txch, skb, skb->data,
+ skb->len, 0, GFP_KERNEL);
+
+ if (ndev == cpsw_get_slave_ndev(priv, 0))
+ return cpdma_chan_submit(priv->txch, skb, skb->data,
+ skb->len, 1, GFP_KERNEL);
+ else
+ return cpdma_chan_submit(priv->txch, skb, skb->data,
+ skb->len, 2, GFP_KERNEL);
+}
+
+static inline void cpsw_add_dual_emac_def_ale_entries(
+ struct cpsw_priv *priv, struct cpsw_slave *slave,
+ u32 slave_port)
+{
+ u32 port_mask = 1 << slave_port | 1 << priv->host_port;
+
+ if (priv->version == CPSW_VERSION_1)
+ slave_write(slave, slave->port_vlan, CPSW1_PORT_VLAN);
+ else
+ slave_write(slave, slave->port_vlan, CPSW2_PORT_VLAN);
+ cpsw_ale_add_vlan(priv->ale, slave->port_vlan, port_mask,
+ port_mask, port_mask, 0);
+ cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+ port_mask, ALE_VLAN, slave->port_vlan, 0);
+ cpsw_ale_add_ucast(priv->ale, priv->mac_addr,
+ priv->host_port, ALE_VLAN, slave->port_vlan);
+}
+
static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
{
char name[32];
@@ -595,8 +698,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
slave_port = cpsw_get_slave_port(priv, slave->slave_num);
- cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
- 1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
+ if (priv->data.dual_emac)
+ cpsw_add_dual_emac_def_ale_entries(priv, slave, slave_port);
+ else
+ cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+ 1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
&cpsw_adjust_link, slave->data->phy_if);
@@ -634,6 +740,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
static void cpsw_init_host_port(struct cpsw_priv *priv)
{
u32 control_reg;
+ u32 fifo_mode;
/* soft reset the controller and initialize ale */
soft_reset("cpsw", &priv->regs->soft_reset);
@@ -645,6 +752,9 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
control_reg = readl(&priv->regs->control);
control_reg |= CPSW_VLAN_AWARE;
writel(control_reg, &priv->regs->control);
+ fifo_mode = (priv->data.dual_emac) ? CPSW_FIFO_DUAL_MAC_MODE :
+ CPSW_FIFO_NORMAL_MODE;
+ writel(fifo_mode, &priv->host_port_regs->tx_in_ctl);
/* setup host port priority mapping */
__raw_writel(CPDMA_TX_PRIORITY_MAP,
@@ -654,9 +764,12 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
cpsw_ale_control_set(priv->ale, priv->host_port,
ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
- cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 0, 0);
- cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
- 1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
+ if (!priv->data.dual_emac) {
+ cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port,
+ 0, 0);
+ cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+ 1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
+ }
}
static int cpsw_ndo_open(struct net_device *ndev)
@@ -665,7 +778,8 @@ static int cpsw_ndo_open(struct net_device *ndev)
int i, ret;
u32 reg;
- cpsw_intr_disable(priv);
+ if (!cpsw_common_res_usage_state(priv))
+ cpsw_intr_disable(priv);
netif_carrier_off(ndev);
pm_runtime_get_sync(&priv->pdev->dev);
@@ -677,46 +791,54 @@ static int cpsw_ndo_open(struct net_device *ndev)
CPSW_RTL_VERSION(reg));
/* initialize host and slave ports */
- cpsw_init_host_port(priv);
+ if (!cpsw_common_res_usage_state(priv))
+ cpsw_init_host_port(priv);
for_each_slave(priv, cpsw_slave_open, priv);
/* Add default VLAN */
- cpsw_add_default_vlan(priv);
+ if (!priv->data.dual_emac)
+ cpsw_add_default_vlan(priv);
- /* setup tx dma to fixed prio and zero offset */
- cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
- cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
+ if (!cpsw_common_res_usage_state(priv)) {
+ /* setup tx dma to fixed prio and zero offset */
+ cpdma_control_set(priv->dma, CPDMA_TX_PRIO_FIXED, 1);
+ cpdma_control_set(priv->dma, CPDMA_RX_BUFFER_OFFSET, 0);
- /* disable priority elevation and enable statistics on all ports */
- __raw_writel(0, &priv->regs->ptype);
+ /* disable priority elevation */
+ __raw_writel(0, &priv->regs->ptype);
- /* enable statistics collection only on the host port */
- __raw_writel(0x7, &priv->regs->stat_port_en);
+ /* enable statistics collection only on all ports */
+ __raw_writel(0x7, &priv->regs->stat_port_en);
- if (WARN_ON(!priv->data.rx_descs))
- priv->data.rx_descs = 128;
+ if (WARN_ON(!priv->data.rx_descs))
+ priv->data.rx_descs = 128;
- for (i = 0; i < priv->data.rx_descs; i++) {
- struct sk_buff *skb;
+ for (i = 0; i < priv->data.rx_descs; i++) {
+ struct sk_buff *skb;
- ret = -ENOMEM;
- skb = netdev_alloc_skb_ip_align(priv->ndev,
- priv->rx_packet_max);
- if (!skb)
- break;
- ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
+ ret = -ENOMEM;
+ skb = netdev_alloc_skb_ip_align(priv->ndev,
+ priv->rx_packet_max);
+ if (!skb)
+ break;
+ ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
skb_tailroom(skb), 0, GFP_KERNEL);
- if (WARN_ON(ret < 0))
- break;
+ if (WARN_ON(ret < 0))
+ break;
+ }
+ /* continue even if we didn't manage to submit all
+ * receive descs
+ */
+ cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
}
- /* continue even if we didn't manage to submit all receive descs */
- cpsw_info(priv, ifup, "submitted %d rx descriptors\n", i);
cpdma_ctlr_start(priv->dma);
cpsw_intr_enable(priv);
napi_enable(&priv->napi);
cpdma_ctlr_eoi(priv->dma);
+ if (priv->data.dual_emac)
+ priv->slaves[priv->emac_port].open_stat = true;
return 0;
}
@@ -737,12 +859,17 @@ static int cpsw_ndo_stop(struct net_device *ndev)
netif_stop_queue(priv->ndev);
napi_disable(&priv->napi);
netif_carrier_off(priv->ndev);
- cpsw_intr_disable(priv);
- cpdma_ctlr_int_ctrl(priv->dma, false);
- cpdma_ctlr_stop(priv->dma);
- cpsw_ale_stop(priv->ale);
+
+ if (cpsw_common_res_usage_state(priv) <= 1) {
+ cpsw_intr_disable(priv);
+ cpdma_ctlr_int_ctrl(priv->dma, false);
+ cpdma_ctlr_stop(priv->dma);
+ cpsw_ale_stop(priv->ale);
+ }
for_each_slave(priv, cpsw_slave_stop, priv);
pm_runtime_put_sync(&priv->pdev->dev);
+ if (priv->data.dual_emac)
+ priv->slaves[priv->emac_port].open_stat = false;
return 0;
}
@@ -766,8 +893,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
skb_tx_timestamp(skb);
- ret = cpdma_chan_submit(priv->txch, skb, skb->data,
- skb->len, 0, GFP_KERNEL);
+ ret = cpsw_tx_packet_submit(ndev, priv, skb);
if (unlikely(ret != 0)) {
cpsw_err(priv, tx_err, "desc submit failed\n");
goto fail;
@@ -836,9 +962,14 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
{
- struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
+ struct cpsw_slave *slave;
u32 ctrl, mtype;
+ if (priv->data.dual_emac)
+ slave = &priv->slaves[priv->emac_port];
+ else
+ slave = &priv->slaves[priv->data.cpts_active_slave];
+
ctrl = slave_read(slave, CPSW2_CONTROL);
ctrl &= ~CTRL_ALL_TS_MASK;
@@ -1124,6 +1255,7 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
slave->data = data;
slave->regs = regs + slave_reg_ofs;
slave->sliver = regs + sliver_reg_ofs;
+ slave->port_vlan = data->dual_emac_res_vlan;
}
static int cpsw_probe_dt(struct cpsw_platform_data *data,
@@ -1204,6 +1336,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->mac_control = prop;
+ if (!of_property_read_u32(node, "dual_emac", &prop))
+ data->dual_emac = prop;
+
/*
* Populate all the child nodes here...
*/
@@ -1237,6 +1372,18 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
if (mac_addr)
memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
+ if (data->dual_emac) {
+ if (of_property_read_u32(node, "dual_emac_res_vlan",
+ &prop)) {
+ pr_err("Missing dual_emac_res_vlan in DT.\n");
+ slave_data->dual_emac_res_vlan = i+1;
+ pr_err("Using %d as Reserved VLAN for %d slave\n",
+ slave_data->dual_emac_res_vlan, i);
+ } else {
+ slave_data->dual_emac_res_vlan = prop;
+ }
+ }
+
i++;
}
@@ -1247,6 +1394,79 @@ error_ret:
return ret;
}
+static int cpsw_probe_dual_emac(struct platform_device *pdev,
+ struct cpsw_priv *priv)
+{
+ struct cpsw_platform_data *data = &priv->data;
+ struct net_device *ndev;
+ struct cpsw_priv *priv_sl2;
+ int ret = 0, i;
+
+ ndev = alloc_etherdev(sizeof(struct cpsw_priv));
+ if (!ndev) {
+ pr_err("cpsw: error allocating net_device\n");
+ return -ENOMEM;
+ }
+
+ priv_sl2 = netdev_priv(ndev);
+ spin_lock_init(&priv_sl2->lock);
+ priv_sl2->data = *data;
+ priv_sl2->pdev = pdev;
+ priv_sl2->ndev = ndev;
+ priv_sl2->dev = &ndev->dev;
+ priv_sl2->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
+ priv_sl2->rx_packet_max = max(rx_packet_max, 128);
+
+ if (is_valid_ether_addr(data->slave_data[1].mac_addr)) {
+ memcpy(priv_sl2->mac_addr, data->slave_data[1].mac_addr,
+ ETH_ALEN);
+ pr_info("cpsw: Detected MACID = %pM\n", priv_sl2->mac_addr);
+ } else {
+ random_ether_addr(priv_sl2->mac_addr);
+ pr_info("cpsw: Random MACID = %pM\n", priv_sl2->mac_addr);
+ }
+ memcpy(ndev->dev_addr, priv_sl2->mac_addr, ETH_ALEN);
+
+ priv_sl2->slaves = priv->slaves;
+ priv_sl2->clk = priv->clk;
+
+ 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;
+ priv_sl2->wr_regs = priv->wr_regs;
+ priv_sl2->dma = priv->dma;
+ priv_sl2->txch = priv->txch;
+ priv_sl2->rxch = priv->rxch;
+ priv_sl2->ale = priv->ale;
+ priv_sl2->emac_port = 1;
+ priv->slaves[1].ndev = ndev;
+ priv_sl2->cpts = priv->cpts;
+ priv_sl2->version = priv->version;
+
+ for (i = 0; i < priv->num_irqs; i++) {
+ priv_sl2->irqs_table[i] = priv->irqs_table[i];
+ priv_sl2->num_irqs = priv->num_irqs;
+ }
+
+ ndev->features |= NETIF_F_HW_VLAN_FILTER;
+
+ ndev->netdev_ops = &cpsw_netdev_ops;
+ SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
+ netif_napi_add(ndev, &priv_sl2->napi, cpsw_poll, CPSW_POLL_WEIGHT);
+
+ /* register the network device */
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+ ret = register_netdev(ndev);
+ if (ret) {
+ pr_err("cpsw: error registering net device\n");
+ free_netdev(ndev);
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+
static int cpsw_probe(struct platform_device *pdev)
{
struct cpsw_platform_data *data = pdev->dev.platform_data;
@@ -1310,6 +1530,9 @@ static int cpsw_probe(struct platform_device *pdev)
for (i = 0; i < data->slaves; i++)
priv->slaves[i].slave_num = i;
+ priv->slaves[0].ndev = ndev;
+ priv->emac_port = 0;
+
priv->clk = clk_get(&pdev->dev, "fck");
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "fck is not found\n");
@@ -1484,6 +1707,14 @@ static int cpsw_probe(struct platform_device *pdev)
cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
priv->cpsw_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;
+ }
+ }
+
return 0;
clean_irq_ret:
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index e962cfd..798fb80 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -21,6 +21,8 @@ struct cpsw_slave_data {
char phy_id[MII_BUS_ID_SIZE];
int phy_if;
u8 mac_addr[ETH_ALEN];
+ u16 dual_emac_res_vlan; /* Reserved VLAN for DualEMAC */
+
};
struct cpsw_platform_data {
@@ -36,6 +38,7 @@ struct cpsw_platform_data {
u32 rx_descs; /* Number of Rx Descriptios */
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 */
};
#endif /* __CPSW_H__ */
--
1.7.9.5
^ permalink raw reply related
* [PATCH 0/3] Dual EMAC mode implementation of CPSW
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N
This patch series implements Dual EMAC mode implementation of CPSW
which acts as two standalone EMAC by segregating the switch using VIDs
and port VLAN
Mugunthan V N (3):
driver: net: ethernet: davinci_cpdma: add support for directed packet
and source port detection
driver: net: ethernet: cpsw: make cpts as pointer
driver: net: ethernet: cpsw: dual emac interface implementation
Documentation/devicetree/bindings/net/cpsw.txt | 2 +
drivers/net/ethernet/ti/cpsw.c | 387 +++++++++++++++++++-----
drivers/net/ethernet/ti/davinci_cpdma.c | 17 +-
drivers/net/ethernet/ti/davinci_cpdma.h | 4 +-
drivers/net/ethernet/ti/davinci_emac.c | 6 +-
include/linux/platform_data/cpsw.h | 3 +
6 files changed, 338 insertions(+), 81 deletions(-)
--
1.7.9.5
^ permalink raw reply
* [PATCH 2/3] driver: net: ethernet: cpsw: make cpts as pointer
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N
In-Reply-To: <1360612340-9266-1-git-send-email-mugunthanvnm@ti.com>
As CPTS is common module for both EMAC in Dual EMAC mode so making cpts as
pointer.
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/net/ethernet/ti/cpsw.c | 36 +++++++++++++++++++++---------------
1 file changed, 21 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 8ac60c7..4b964bb 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -319,7 +319,7 @@ struct cpsw_priv {
/* snapshot of IRQ numbers */
u32 irqs_table[4];
u32 num_irqs;
- struct cpts cpts;
+ struct cpts *cpts;
};
#define napi_to_priv(napi) container_of(napi, struct cpsw_priv, napi)
@@ -383,7 +383,7 @@ void cpsw_tx_handler(void *token, int len, int status)
*/
if (unlikely(netif_queue_stopped(ndev)))
netif_start_queue(ndev);
- cpts_tx_timestamp(&priv->cpts, skb);
+ cpts_tx_timestamp(priv->cpts, skb);
priv->stats.tx_packets++;
priv->stats.tx_bytes += len;
dev_kfree_skb_any(skb);
@@ -404,7 +404,7 @@ void cpsw_rx_handler(void *token, int len, int status)
}
if (likely(status >= 0)) {
skb_put(skb, len);
- cpts_rx_timestamp(&priv->cpts, skb);
+ cpts_rx_timestamp(priv->cpts, skb);
skb->protocol = eth_type_trans(skb, ndev);
netif_receive_skb(skb);
priv->stats.rx_bytes += len;
@@ -760,7 +760,8 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
}
- if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && priv->cpts.tx_enable)
+ if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+ priv->cpts->tx_enable)
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
skb_tx_timestamp(skb);
@@ -815,7 +816,7 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
u32 ts_en, seq_id;
- if (!priv->cpts.tx_enable && !priv->cpts.rx_enable) {
+ if (!priv->cpts->tx_enable && !priv->cpts->rx_enable) {
slave_write(slave, 0, CPSW1_TS_CTL);
return;
}
@@ -823,10 +824,10 @@ static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588;
ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS;
- if (priv->cpts.tx_enable)
+ if (priv->cpts->tx_enable)
ts_en |= CPSW_V1_TS_TX_EN;
- if (priv->cpts.rx_enable)
+ if (priv->cpts->rx_enable)
ts_en |= CPSW_V1_TS_RX_EN;
slave_write(slave, ts_en, CPSW1_TS_CTL);
@@ -841,10 +842,10 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
ctrl = slave_read(slave, CPSW2_CONTROL);
ctrl &= ~CTRL_ALL_TS_MASK;
- if (priv->cpts.tx_enable)
+ if (priv->cpts->tx_enable)
ctrl |= CTRL_TX_TS_BITS;
- if (priv->cpts.rx_enable)
+ if (priv->cpts->rx_enable)
ctrl |= CTRL_RX_TS_BITS;
mtype = (30 << TS_SEQ_ID_OFFSET_SHIFT) | EVENT_MSG_BITS;
@@ -857,7 +858,7 @@ static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
{
struct cpsw_priv *priv = netdev_priv(dev);
- struct cpts *cpts = &priv->cpts;
+ struct cpts *cpts = priv->cpts;
struct hwtstamp_config cfg;
if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
@@ -1086,7 +1087,7 @@ static int cpsw_get_ts_info(struct net_device *ndev,
SOF_TIMESTAMPING_RX_SOFTWARE |
SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
- info->phc_index = priv->cpts.phc_index;
+ info->phc_index = priv->cpts->phc_index;
info->tx_types =
(1 << HWTSTAMP_TX_OFF) |
(1 << HWTSTAMP_TX_ON);
@@ -1272,6 +1273,11 @@ static int cpsw_probe(struct platform_device *pdev)
priv->dev = &ndev->dev;
priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
priv->rx_packet_max = max(rx_packet_max, 128);
+ priv->cpts = devm_kzalloc(&pdev->dev, sizeof(struct cpts), GFP_KERNEL);
+ if (!ndev) {
+ pr_err("error allocating cpts\n");
+ goto clean_ndev_ret;
+ }
/*
* This may be required here for child devices.
@@ -1358,7 +1364,7 @@ static int cpsw_probe(struct platform_device *pdev)
switch (priv->version) {
case CPSW_VERSION_1:
priv->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET;
- priv->cpts.reg = ss_regs + CPSW1_CPTS_OFFSET;
+ priv->cpts->reg = ss_regs + CPSW1_CPTS_OFFSET;
dma_params.dmaregs = ss_regs + CPSW1_CPDMA_OFFSET;
dma_params.txhdp = ss_regs + CPSW1_STATERAM_OFFSET;
ale_params.ale_regs = ss_regs + CPSW1_ALE_OFFSET;
@@ -1369,7 +1375,7 @@ static int cpsw_probe(struct platform_device *pdev)
break;
case CPSW_VERSION_2:
priv->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET;
- priv->cpts.reg = ss_regs + CPSW2_CPTS_OFFSET;
+ priv->cpts->reg = ss_regs + CPSW2_CPTS_OFFSET;
dma_params.dmaregs = ss_regs + CPSW2_CPDMA_OFFSET;
dma_params.txhdp = ss_regs + CPSW2_STATERAM_OFFSET;
ale_params.ale_regs = ss_regs + CPSW2_ALE_OFFSET;
@@ -1471,7 +1477,7 @@ static int cpsw_probe(struct platform_device *pdev)
goto clean_irq_ret;
}
- if (cpts_register(&pdev->dev, &priv->cpts,
+ if (cpts_register(&pdev->dev, priv->cpts,
data->cpts_clock_mult, data->cpts_clock_shift))
dev_err(priv->dev, "error registering cpts device\n");
@@ -1516,7 +1522,7 @@ static int cpsw_remove(struct platform_device *pdev)
pr_info("removing device");
platform_set_drvdata(pdev, NULL);
- cpts_unregister(&priv->cpts);
+ cpts_unregister(priv->cpts);
free_irq(ndev->irq, priv);
cpsw_ale_destroy(priv->ale);
cpdma_chan_destroy(priv->txch);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/3] driver: net: ethernet: davinci_cpdma: add support for directed packet and source port detection
From: Mugunthan V N @ 2013-02-11 19:52 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N
In-Reply-To: <1360612340-9266-1-git-send-email-mugunthanvnm@ti.com>
* Introduced parameter to add port number for directed packet in cpdma_chan_submit
* Source port detection macro with DMA descriptor status
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/net/ethernet/ti/cpsw.c | 6 +++---
drivers/net/ethernet/ti/davinci_cpdma.c | 17 +++++++++++++++--
drivers/net/ethernet/ti/davinci_cpdma.h | 4 +++-
drivers/net/ethernet/ti/davinci_emac.c | 6 +++---
4 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 888708c..8ac60c7 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -424,7 +424,7 @@ void cpsw_rx_handler(void *token, int len, int status)
return;
ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
- skb_tailroom(skb), GFP_KERNEL);
+ skb_tailroom(skb), 0, GFP_KERNEL);
}
WARN_ON(ret < 0);
}
@@ -705,7 +705,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
if (!skb)
break;
ret = cpdma_chan_submit(priv->rxch, skb, skb->data,
- skb_tailroom(skb), GFP_KERNEL);
+ skb_tailroom(skb), 0, GFP_KERNEL);
if (WARN_ON(ret < 0))
break;
}
@@ -766,7 +766,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
skb_tx_timestamp(skb);
ret = cpdma_chan_submit(priv->txch, skb, skb->data,
- skb->len, GFP_KERNEL);
+ skb->len, 0, GFP_KERNEL);
if (unlikely(ret != 0)) {
cpsw_err(priv, tx_err, "desc submit failed\n");
goto fail;
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c
index afe14a6..ca25cc8 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.c
+++ b/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -60,6 +60,9 @@
#define CPDMA_DESC_EOQ BIT(28)
#define CPDMA_DESC_TD_COMPLETE BIT(27)
#define CPDMA_DESC_PASS_CRC BIT(26)
+#define CPDMA_DESC_TO_PORT_EN BIT(20)
+#define CPDMA_TO_PORT_SHIFT 16
+#define CPDMA_DESC_PORT_MASK (BIT(18) | BIT(17) | BIT(16))
#define CPDMA_TEARDOWN_VALUE 0xfffffffc
@@ -132,6 +135,14 @@ struct cpdma_chan {
#define chan_write(chan, fld, v) __raw_writel(v, (chan)->fld)
#define desc_write(desc, fld, v) __raw_writel((u32)(v), &(desc)->fld)
+#define cpdma_desc_to_port(chan, mode, directed) \
+ do { \
+ if (!is_rx_chan(chan) && ((directed == 1) || \
+ (directed == 2))) \
+ mode |= (CPDMA_DESC_TO_PORT_EN | \
+ (directed << CPDMA_TO_PORT_SHIFT)); \
+ } while (0)
+
/*
* Utility constructs for a cpdma descriptor pool. Some devices (e.g. davinci
* emac) have dedicated on-chip memory for these descriptors. Some other
@@ -664,7 +675,7 @@ static void __cpdma_chan_submit(struct cpdma_chan *chan,
}
int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
- int len, gfp_t gfp_mask)
+ int len, int directed, gfp_t gfp_mask)
{
struct cpdma_ctlr *ctlr = chan->ctlr;
struct cpdma_desc __iomem *desc;
@@ -694,6 +705,7 @@ int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
+ cpdma_desc_to_port(chan, mode, directed);
desc_write(desc, hw_next, 0);
desc_write(desc, hw_buffer, buffer);
@@ -784,7 +796,8 @@ static int __cpdma_chan_process(struct cpdma_chan *chan)
status = -EBUSY;
goto unlock_ret;
}
- status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE);
+ status = status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE |
+ CPDMA_DESC_PORT_MASK);
chan->head = desc_from_phys(pool, desc_read(desc, hw_next));
chan_write(chan, cp, desc_dma);
diff --git a/drivers/net/ethernet/ti/davinci_cpdma.h b/drivers/net/ethernet/ti/davinci_cpdma.h
index 8d2aeb2..a97d6ab 100644
--- a/drivers/net/ethernet/ti/davinci_cpdma.h
+++ b/drivers/net/ethernet/ti/davinci_cpdma.h
@@ -24,6 +24,8 @@
#define __chan_linear(chan_num) ((chan_num) & (CPDMA_MAX_CHANNELS - 1))
#define chan_linear(chan) __chan_linear((chan)->chan_num)
+#define CPDMA_RX_SOURCE_PORT(__status__) ((__status__ >> 16) & 0x7)
+
struct cpdma_params {
struct device *dev;
void __iomem *dmaregs;
@@ -82,7 +84,7 @@ int cpdma_chan_dump(struct cpdma_chan *chan);
int cpdma_chan_get_stats(struct cpdma_chan *chan,
struct cpdma_chan_stats *stats);
int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
- int len, gfp_t gfp_mask);
+ int len, int directed, gfp_t gfp_mask);
int cpdma_chan_process(struct cpdma_chan *chan, int quota);
int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 242ec55..52c0536 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1037,7 +1037,7 @@ static void emac_rx_handler(void *token, int len, int status)
recycle:
ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
- skb_tailroom(skb), GFP_KERNEL);
+ skb_tailroom(skb), 0, GFP_KERNEL);
WARN_ON(ret == -ENOMEM);
if (unlikely(ret < 0))
@@ -1092,7 +1092,7 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
skb_tx_timestamp(skb);
ret_code = cpdma_chan_submit(priv->txchan, skb, skb->data, skb->len,
- GFP_KERNEL);
+ 0, GFP_KERNEL);
if (unlikely(ret_code != 0)) {
if (netif_msg_tx_err(priv) && net_ratelimit())
dev_err(emac_dev, "DaVinci EMAC: desc submit failed");
@@ -1558,7 +1558,7 @@ static int emac_dev_open(struct net_device *ndev)
break;
ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
- skb_tailroom(skb), GFP_KERNEL);
+ skb_tailroom(skb), 0, GFP_KERNEL);
if (WARN_ON(ret < 0))
break;
}
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH] ipv6: don't accept multicast traffic with scop 0
From: Hannes Frederic Sowa @ 2013-02-11 19:48 UTC (permalink / raw)
To: netdev, yoshfuji, erik.hugne
In-Reply-To: <20130210124851.GB18219@order.stressinduktion.org>
On Sun, Feb 10, 2013 at 01:48:51PM +0100, Hannes Frederic Sowa wrote:
> + /*
> + * RFC4291 2.7
> + * Nodes must not originate a packet to a multicast address whose scop
> + * field contains the reserved value 0; if such a packet is received, it
> + * must be silently dropped.
Just nit-picking: The field is actually called scop without e, as pointed out
by three erratas to RFC4291. :)
^ permalink raw reply
* Re: atl1c DMA-API mapping errors in 3.8-rc6+
From: Josh Boyer @ 2013-02-11 19:48 UTC (permalink / raw)
To: Huang, Xiong
Cc: Jay Cliburn, Chris Snook, David S. Miller, netdev@vger.kernel.org,
sgruszka@redhat.com, nic-devel
In-Reply-To: <157393863283F442885425D2C4542856489C6811@nasanexd02f.na.qualcomm.com>
On Mon, Feb 11, 2013 at 06:03:53PM +0000, Huang, Xiong wrote:
> Josh
>
> Would you pls confirm if my patch fix this issue ? I have no platform on hand now and the office is closed due to CNY .
I'd be happy to build a kernel with a patch for the users to test with.
However, I don't see a patch here or on netdev. Did you forget to
include it or send it out, or did I miss it somewhere?
josh
^ permalink raw reply
* [PATCH] net: Fix possible wrong checksum generation.
From: Pravin B Shelar @ 2013-02-11 19:27 UTC (permalink / raw)
To: edumazet; +Cc: netdev, jesse, bhutchings, Pravin B Shelar
Patch cef401de7be8c4e (net: fix possible wrong checksum
generation) fixed wrong checksum calculation but it broke TSO by
defining new GSO type but not a netdev feature for that type.
net_gso_ok() would not allow hardware checksum/segmentation
offload of such packets without the feature.
Following patch fixes TSO and wrong checksum. This patch uses
same logic that Eric Dumazet used. Patch introduces new flag
SKBTX_SHARED_FRAG if at least one frag can be modified by
the user. but SKBTX_SHARED_FRAG flag is kept in skb shared
info tx_flags rather than gso_type.
tx_flags is better compared to gso_type since we can have skb with
shared frag without gso packet. It does not link SHARED_FRAG to
GSO, So there is no need to define netdev feature for this.
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
---
drivers/net/macvtap.c | 4 ++--
drivers/net/tun.c | 13 +++++--------
drivers/net/virtio_net.c | 13 +++++--------
include/linux/skbuff.h | 17 +++++++++--------
net/core/skbuff.c | 5 ++---
net/ipv4/af_inet.c | 1 -
net/ipv4/ip_output.c | 1 +
net/ipv4/tcp.c | 4 +---
net/ipv4/tcp_input.c | 4 ++--
net/ipv4/tcp_output.c | 4 ++--
net/ipv6/ip6_offload.c | 1 -
11 files changed, 29 insertions(+), 38 deletions(-)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index b181dfb..9724301 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -543,7 +543,6 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
skb->data_len += len;
skb->len += len;
skb->truesize += truesize;
- skb_shinfo(skb)->gso_type |= SKB_GSO_SHARED_FRAG;
atomic_add(truesize, &skb->sk->sk_wmem_alloc);
while (len) {
int off = base & ~PAGE_MASK;
@@ -599,7 +598,7 @@ static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb,
if (vnet_hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
skb_shinfo(skb)->gso_size = vnet_hdr->gso_size;
- skb_shinfo(skb)->gso_type |= gso_type;
+ skb_shinfo(skb)->gso_type = gso_type;
/* Header must be checked, and gso_segs computed. */
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
@@ -743,6 +742,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
if (zerocopy) {
skb_shinfo(skb)->destructor_arg = m->msg_control;
skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+ skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
}
if (vlan)
macvlan_start_xmit(skb, vlan->dev);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index b1038c0..b6f45c5 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1019,7 +1019,6 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
skb->data_len += len;
skb->len += len;
skb->truesize += truesize;
- skb_shinfo(skb)->gso_type |= SKB_GSO_SHARED_FRAG;
atomic_add(truesize, &skb->sk->sk_wmem_alloc);
while (len) {
int off = base & ~PAGE_MASK;
@@ -1165,18 +1164,16 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
}
if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
- unsigned short gso_type = 0;
-
pr_debug("GSO!\n");
switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
case VIRTIO_NET_HDR_GSO_TCPV4:
- gso_type = SKB_GSO_TCPV4;
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
break;
case VIRTIO_NET_HDR_GSO_TCPV6:
- gso_type = SKB_GSO_TCPV6;
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
break;
case VIRTIO_NET_HDR_GSO_UDP:
- gso_type = SKB_GSO_UDP;
+ skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
break;
default:
tun->dev->stats.rx_frame_errors++;
@@ -1185,10 +1182,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
}
if (gso.gso_type & VIRTIO_NET_HDR_GSO_ECN)
- gso_type |= SKB_GSO_TCP_ECN;
+ skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
skb_shinfo(skb)->gso_size = gso.gso_size;
- skb_shinfo(skb)->gso_type |= gso_type;
if (skb_shinfo(skb)->gso_size == 0) {
tun->dev->stats.rx_frame_errors++;
kfree_skb(skb);
@@ -1204,6 +1200,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
if (zerocopy) {
skb_shinfo(skb)->destructor_arg = msg_control;
skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
+ skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
}
skb_reset_network_header(skb);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 381a2d8..192c91c 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -227,7 +227,7 @@ static void set_skb_frag(struct sk_buff *skb, struct page *page,
skb->len += size;
skb->truesize += PAGE_SIZE;
skb_shinfo(skb)->nr_frags++;
- skb_shinfo(skb)->gso_type |= SKB_GSO_SHARED_FRAG;
+ skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
*len -= size;
}
@@ -387,18 +387,16 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
ntohs(skb->protocol), skb->len, skb->pkt_type);
if (hdr->hdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
- unsigned short gso_type = 0;
-
pr_debug("GSO!\n");
switch (hdr->hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
case VIRTIO_NET_HDR_GSO_TCPV4:
- gso_type = SKB_GSO_TCPV4;
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
break;
case VIRTIO_NET_HDR_GSO_UDP:
- gso_type = SKB_GSO_UDP;
+ skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
break;
case VIRTIO_NET_HDR_GSO_TCPV6:
- gso_type = SKB_GSO_TCPV6;
+ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
break;
default:
net_warn_ratelimited("%s: bad gso type %u.\n",
@@ -407,7 +405,7 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
}
if (hdr->hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN)
- gso_type |= SKB_GSO_TCP_ECN;
+ skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
skb_shinfo(skb)->gso_size = hdr->hdr.gso_size;
if (skb_shinfo(skb)->gso_size == 0) {
@@ -415,7 +413,6 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
goto frame_err;
}
- skb_shinfo(skb)->gso_type |= gso_type;
/* Header must be checked, and gso_segs computed. */
skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
skb_shinfo(skb)->gso_segs = 0;
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index d7573c3..9da9952 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -230,6 +230,13 @@ enum {
/* generate wifi status information (where possible) */
SKBTX_WIFI_STATUS = 1 << 4,
+
+ /* This indicates at least one fragment might be overwritten
+ * (as in vmsplice(), sendfile() ...)
+ * If we need to compute a TX checksum, we'll need to copy
+ * all frags to avoid possible bad checksum
+ */
+ SKBTX_SHARED_FRAG = 1 << 5,
};
/*
@@ -307,13 +314,6 @@ enum {
SKB_GSO_TCPV6 = 1 << 4,
SKB_GSO_FCOE = 1 << 5,
-
- /* This indicates at least one fragment might be overwritten
- * (as in vmsplice(), sendfile() ...)
- * If we need to compute a TX checksum, we'll need to copy
- * all frags to avoid possible bad checksum
- */
- SKB_GSO_SHARED_FRAG = 1 << 6,
};
#if BITS_PER_LONG > 32
@@ -2220,7 +2220,8 @@ static inline int skb_linearize(struct sk_buff *skb)
*/
static inline bool skb_has_shared_frag(const struct sk_buff *skb)
{
- return skb_shinfo(skb)->gso_type & SKB_GSO_SHARED_FRAG;
+ return skb_is_nonlinear(skb) &&
+ skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG;
}
/**
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 6114c11..46d3c82 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2336,8 +2336,7 @@ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len)
{
int pos = skb_headlen(skb);
- skb_shinfo(skb1)->gso_type = skb_shinfo(skb)->gso_type;
-
+ skb_shinfo(skb)->tx_flags = skb_shinfo(skb1)->tx_flags & SKBTX_SHARED_FRAG;
if (len < pos) /* Split line is inside header. */
skb_split_inside_header(skb, skb1, len, pos);
else /* Second chunk has no header, nothing to copy. */
@@ -2843,7 +2842,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
skb_copy_from_linear_data_offset(skb, offset,
skb_put(nskb, hsize), hsize);
- skb_shinfo(nskb)->gso_type = skb_shinfo(skb)->gso_type;
+ skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG;
while (pos < offset + len && i < nfrags) {
*frag = skb_shinfo(skb)->frags[i];
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 1aec92b..e6e5d85 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1287,7 +1287,6 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
SKB_GSO_UDP |
SKB_GSO_DODGY |
SKB_GSO_TCP_ECN |
- SKB_GSO_SHARED_FRAG |
0)))
goto out;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 3e98ed2..5e12dca 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -598,6 +598,7 @@ slow_path:
/* for offloaded checksums cleanup checksum before fragmentation */
if ((skb->ip_summed == CHECKSUM_PARTIAL) && skb_checksum_help(skb))
goto fail;
+ iph = ip_hdr(skb);
left = skb->len - hlen; /* Space per frame */
ptr = hlen; /* Where to start from */
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 2c7e596..8317f82 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -895,8 +895,7 @@ new_segment:
get_page(page);
skb_fill_page_desc(skb, i, page, offset, copy);
}
-
- skb_shinfo(skb)->gso_type |= SKB_GSO_SHARED_FRAG;
+ skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
skb->len += copy;
skb->data_len += copy;
@@ -3033,7 +3032,6 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
SKB_GSO_DODGY |
SKB_GSO_TCP_ECN |
SKB_GSO_TCPV6 |
- SKB_GSO_SHARED_FRAG |
0) ||
!(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
goto out;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ea678b6..76f2af0 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1239,13 +1239,13 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
*/
if (!skb_shinfo(prev)->gso_size) {
skb_shinfo(prev)->gso_size = mss;
- skb_shinfo(prev)->gso_type |= sk->sk_gso_type;
+ skb_shinfo(prev)->gso_type = sk->sk_gso_type;
}
/* CHECKME: To clear or not to clear? Mimics normal skb currently */
if (skb_shinfo(skb)->gso_segs <= 1) {
skb_shinfo(skb)->gso_size = 0;
- skb_shinfo(skb)->gso_type &= SKB_GSO_SHARED_FRAG;
+ skb_shinfo(skb)->gso_type = 0;
}
/* Difference in this won't matter, both ACKed by the same cumul. ACK */
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 367e2ec..667a6ad 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1133,7 +1133,6 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb)
static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb,
unsigned int mss_now)
{
- skb_shinfo(skb)->gso_type &= SKB_GSO_SHARED_FRAG;
if (skb->len <= mss_now || !sk_can_gso(sk) ||
skb->ip_summed == CHECKSUM_NONE) {
/* Avoid the costly divide in the normal
@@ -1141,10 +1140,11 @@ static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb,
*/
skb_shinfo(skb)->gso_segs = 1;
skb_shinfo(skb)->gso_size = 0;
+ skb_shinfo(skb)->gso_type = 0;
} else {
skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss_now);
skb_shinfo(skb)->gso_size = mss_now;
- skb_shinfo(skb)->gso_type |= sk->sk_gso_type;
+ skb_shinfo(skb)->gso_type = sk->sk_gso_type;
}
}
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index d141fc3..f26f0da 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -100,7 +100,6 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
SKB_GSO_DODGY |
SKB_GSO_TCP_ECN |
SKB_GSO_TCPV6 |
- SKB_GSO_SHARED_FRAG |
0)))
goto out;
--
1.7.1
^ permalink raw reply related
* soft lockup at __skb_recv_datagram() when fuzzing with trinity as root in VM
From: Tommi Rantala @ 2013-02-11 19:25 UTC (permalink / raw)
To: netdev; +Cc: Dave Jones
Hello,
I am quite easily reproducing this lockup when fuzzing with Trinity as
the root user in a virtual machine. It seems to be busy-looping in the
do-while loop in __skb_recv_datagram().
[ 83.541011] INFO: rcu_sched detected stalls on CPUs/tasks: {}
(detected by 0, t=26002 jiffies, g=27673, c=27672, q=75)
[ 83.541011] INFO: Stall ended before state dump start
[ 108.067010] BUG: soft lockup - CPU#0 stuck for 22s! [trinity-child31:2847]
[ 108.067010] irq event stamp: 244034822
[ 108.067010] hardirqs last enabled at (244034821):
[<ffffffff81ca2da5>] _raw_spin_unlock_irqrestore+0x55/0x70
[ 108.067010] hardirqs last disabled at (244034822):
[<ffffffff81ca4fad>] apic_timer_interrupt+0x6d/0x80
[ 108.067010] softirqs last enabled at (244030010):
[<ffffffff810a086a>] __do_softirq+0x1ca/0x240
[ 108.067010] softirqs last disabled at (244030005):
[<ffffffff81ca56fc>] call_softirq+0x1c/0x30
[ 108.067010] CPU 0
[ 108.067010] Pid: 2847, comm: trinity-child31 Tainted: G W
3.8.0-rc7+ #73 Bochs Bochs
[ 108.067010] RIP: 0010:[<ffffffff81ca2daa>] [<ffffffff81ca2daa>]
_raw_spin_unlock_irqrestore+0x5a/0x70
[ 108.067010] RSP: 0018:ffff88002fb5db38 EFLAGS: 00000286
[ 108.067010] RAX: ffff8800201ec520 RBX: ffffffff810d54fa RCX: 0000000000005220
[ 108.067010] RDX: ffff8800201ec520 RSI: 0000000000000001 RDI: 0000000000000286
[ 108.067010] RBP: ffff88002fb5db48 R08: 0000000000000068 R09: 0000000000000001
[ 108.067010] R10: 0000000000000001 R11: 0000000000000000 R12: ffffffff810f5b9d
[ 108.067010] R13: ffff88002fb5daa8 R14: 00000019294ba499 R15: 0000000000000086
[ 108.067010] FS: 00007f6aabc57700(0000) GS:ffff88003e000000(0000)
knlGS:0000000000000000
[ 108.067010] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 108.067010] CR2: 0000000000000009 CR3: 000000002fb08000 CR4: 00000000000006f0
[ 108.067010] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 108.067010] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[ 108.067010] Process trinity-child31 (pid: 2847, threadinfo
ffff88002fb5c000, task ffff8800201ec520)
[ 108.067010] Stack:
[ 108.067010] ffff88002fb5dc10 ffff88002fb5dc14 ffff88002fb5dbf8
ffffffff818cc103
[ 108.067010] ffff8800391a7d80 ffff8800201ec520 ffff88002fb5dbb8
7fffffffffffffff
[ 108.067010] ffff88002fb5dc54 40001202810d54fa ffff8800201ec520
ffff8800277f87e8
[ 108.067010] Call Trace:
[ 108.067010] [<ffffffff818cc103>] __skb_recv_datagram+0x1a3/0x3b0
[ 108.067010] [<ffffffff818cbbe0>] ?
csum_partial_copy_fromiovecend+0x220/0x220
[ 108.067010] [<ffffffff818cc33d>] skb_recv_datagram+0x2d/0x30
[ 108.067010] [<ffffffff813029a0>] ? selinux_syslog+0x70/0x70
[ 108.067010] [<ffffffff819ed43d>] rawv6_recvmsg+0xad/0x240
[ 108.067010] [<ffffffff818c4b04>] sock_common_recvmsg+0x34/0x50
[ 108.067010] [<ffffffff818bc8ec>] sock_recvmsg+0xbc/0xf0
[ 108.067010] [<ffffffff81084adf>] ? kvm_clock_read+0x1f/0x30
[ 108.067010] [<ffffffff810612d9>] ? sched_clock+0x9/0x10
[ 108.067010] [<ffffffff818bf31e>] sys_recvfrom+0xde/0x150
[ 108.067010] [<ffffffff810f5abd>] ? trace_hardirqs_on+0xd/0x10
[ 108.067010] [<ffffffff81ca2deb>] ? _raw_spin_unlock_irq+0x2b/0x40
[ 108.067010] [<ffffffff81ca4355>] ? sysret_check+0x22/0x5d
[ 108.067010] [<ffffffff810f5a15>] ? trace_hardirqs_on_caller+0x155/0x1f0
[ 108.067010] [<ffffffff8135718e>] ? trace_hardirqs_on_thunk+0x3a/0x3f
[ 108.067010] [<ffffffff81ca4329>] system_call_fastpath+0x16/0x1b
[ 108.067010] Code: ff f6 c7 02 75 1b 48 89 df 57 9d 0f 1f 44 00 00
e8 fc 2d 45 ff eb 19 66 2e 0f 1f 84 00 00 00 00 00 e8 0b 2d 45 ff 48
89 df 57 9d <0f> 1f 44 00 00 48 8b 5d f0 4c 8b 65 f8 c9 c3 0f 1f 80 00
00 00
Tommi
^ permalink raw reply
* Re: [PATCH] bridge: set priority of STP packets
From: David Miller @ 2013-02-11 19:18 UTC (permalink / raw)
To: stephen; +Cc: netdev
In-Reply-To: <20130211102222.37743b22@nehalam.linuxnetplumber.net>
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Mon, 11 Feb 2013 10:22:22 -0800
> Spanning Tree Protocol packets should have always been marked as
> control packets, this causes them to get queued in the high prirority
> FIFO. As Radia Perlman mentioned in her LCA talk, STP dies if bridge
> gets overloaded and can't communicate. This is a long-standing bug back
> to the first versions of Linux bridge.
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* Re: [PATCH net-next] mrp: make mrp_rcv static
From: David Miller @ 2013-02-11 19:18 UTC (permalink / raw)
To: stephen; +Cc: david.ward, netdev
In-Reply-To: <20130211082524.5fb3a976@nehalam.linuxnetplumber.net>
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Mon, 11 Feb 2013 08:25:24 -0800
> Sparse spotted local function that could be static.
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Applied.
^ permalink raw reply
* Re: [PATCH net-next] ethtool: fix sparse warning
From: David Miller @ 2013-02-11 19:18 UTC (permalink / raw)
To: stephen; +Cc: bhutchings, netdev
In-Reply-To: <20130211082228.1f1d7f88@nehalam.linuxnetplumber.net>
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Mon, 11 Feb 2013 08:22:28 -0800
> Fixes sparse complaints about dropping __user in casts.
> warning: cast removes address space of expression
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Applied.
^ permalink raw reply
* Re: [patch net-next] bridge: use dev->addr_assign_type to see if user change mac
From: David Miller @ 2013-02-11 19:18 UTC (permalink / raw)
To: jiri; +Cc: netdev, stephen
In-Reply-To: <1360532461-21003-1-git-send-email-jiri@resnulli.us>
From: Jiri Pirko <jiri@resnulli.us>
Date: Sun, 10 Feb 2013 22:41:01 +0100
> And remove no longer used br->flags.
>
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Applied.
^ permalink raw reply
* Re: [PATCH net-next v2] ipv6: by default join ff01::1 and in case of forwarding ff01::2 and ff05:2
From: David Miller @ 2013-02-11 19:17 UTC (permalink / raw)
To: hannes; +Cc: netdev, yoshfuji, erik.hugne
In-Reply-To: <20130210135018.GF18219@order.stressinduktion.org>
From: Hannes Frederic Sowa <hannes@stressinduktion.org>
Date: Sun, 10 Feb 2013 14:50:18 +0100
> Cc: Erik Hugne <erik.hugne@ericsson.com>
> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Applied.
^ permalink raw reply
* Re: [PATCH v5 00/45] CPU hotplug: stop_machine()-free CPU hotplug
From: Paul E. McKenney @ 2013-02-11 19:08 UTC (permalink / raw)
To: Srivatsa S. Bhat
Cc: Vincent Guittot, Russell King - ARM Linux, linux-doc, peterz,
fweisbec, linux-kernel, walken, mingo, linux-arch, xiaoguangrong,
wangyun, nikunj, linux-pm, Rusty Russell, rostedt, rjw, namhyung,
tglx, linux-arm-kernel, netdev, oleg, sbw, tj, akpm, linuxppc-dev
In-Reply-To: <5118E2CD.90401@linux.vnet.ibm.com>
On Mon, Feb 11, 2013 at 05:53:41PM +0530, Srivatsa S. Bhat wrote:
> On 02/11/2013 05:28 PM, Vincent Guittot wrote:
> > On 8 February 2013 19:09, Srivatsa S. Bhat
> > <srivatsa.bhat@linux.vnet.ibm.com> wrote:
[ . . . ]
> >> Adding Vincent to CC, who had previously evaluated the performance and
> >> latency implications of CPU hotplug on ARM platforms, IIRC.
> >>
> >
> > Hi Srivatsa,
> >
> > I can try to run some of our stress tests on your patches.
>
> Great!
>
> > Have you
> > got a git tree that i can pull ?
> >
>
> Unfortunately, no, none at the moment.. :-(
You do need to create an externally visible git tree. In the meantime,
I have added your series at rcu/bhat.2013.01.21a on -rcu:
git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
This should appear soon on a kernel.org mirror near you. ;-)
Thanx, Paul
^ permalink raw reply
* Re: [PATCH v2] ipv6: don't accept multicast traffic with scop 0
From: David Miller @ 2013-02-11 19:01 UTC (permalink / raw)
To: hannes; +Cc: netdev
In-Reply-To: <20130210153522.GA20897@order.stressinduktion.org>
From: Hannes Frederic Sowa <hannes@stressinduktion.org>
Date: Sun, 10 Feb 2013 16:35:22 +0100
> v2:
> a) moved before multicast source address check
> b) changed comment to netdev style
>
> Cc: Erik Hugne <erik.hugne@ericsson.com>
> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Applied.
^ permalink raw reply
* Re: [PATCH] ipv6: don't let node/interface scoped multicast traffic escape on the wire
From: David Miller @ 2013-02-11 19:01 UTC (permalink / raw)
To: hannes; +Cc: netdev, yoshfuji, erik.hugne
In-Reply-To: <20130210123335.GA18219@order.stressinduktion.org>
From: Hannes Frederic Sowa <hannes@stressinduktion.org>
Date: Sun, 10 Feb 2013 13:33:35 +0100
> Reported-by: Erik Hugne <erik.hugne@ericsson.com>
> Cc: Erik Hugne <erik.hugne@ericsson.com>
> Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Applied.
^ permalink raw reply
* Re: [PATCH] phy: fix phy_device_free memory leak
From: David Miller @ 2013-02-11 18:57 UTC (permalink / raw)
To: oss; +Cc: netdev
In-Reply-To: <20130211112827.GA24817@bordel.klfree.net>
From: Petr Malat <oss@malat.biz>
Date: Mon, 11 Feb 2013 12:28:27 +0100
> From: Petr Malat <oss@malat.biz>
>
> Fix memory leak in phy_device_free() for the case when phy_device*
> returned by phy_device_create() is not registered in the system.
> Signed-off-by: Petr Malat <oss@malat.biz>
> ---
> Bug description:
> phy_device_create() sets name of kobject using dev_set_name(), which
> allocates memory using kvasprintf(), but this memory isn't freed if
> the underlying device isn't registered properly, because kobject_cleanup()
> is not called in that case. This can happen (and actually is happening on
> our machines) if phy_device_register(), called by mdiobus_scan(), fails.
>
> Patch description:
> Name is freed by phy_device_free(). In the case a device is released
> trough kobject_cleanup()->device_release()->phy_device_release(), the name
> is set to NULL and it is not freed by phy_device_free(), because it will
> be freed later by kobject_cleanup().
All of this descriptive information belongs in the commit message
proper.
^ permalink raw reply
* Re: [patch net-next] bridge: use dev->addr_assign_type to see if user change mac
From: Stephen Hemminger @ 2013-02-11 18:54 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, davem
In-Reply-To: <1360532461-21003-1-git-send-email-jiri@resnulli.us>
On Sun, 10 Feb 2013 22:41:01 +0100
Jiri Pirko <jiri@resnulli.us> wrote:
> And remove no longer used br->flags.
>
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Acked-by: Stephen Hemminger <stephen@networkplumber.org>
^ permalink raw reply
* Re: [PATCH v2 net-next] skbuff: create skb_panic() to let caller specify panic
From: David Miller @ 2013-02-11 18:52 UTC (permalink / raw)
To: sakiwit; +Cc: jiri, netdev
In-Reply-To: <20130210234651.GD2496@mail.gmail.com>
From: Jean Sacren <sakiwit@gmail.com>
Date: Sun, 10 Feb 2013 16:46:52 -0700
> From: Jiri Pirko <jiri@resnulli.us>
> Date: Sun, 10 Feb 2013 19:24:51 +0100
>>
>> How about to leave skb_under_panic() and skb_over_panic() wrapping
>> functions there just to wrap "skb_panic(skb, sz, addr, __func__);" call?
>>
>> Seems nice that to state the name in str...
>
> That's really a good idea. If David drops again, I'll implement it.
I like Jiri's idea, please implement it.
^ permalink raw reply
* Re: [PATCH RESEND] net: fec_mpc52xx: Read MAC address from device-tree
From: David Miller @ 2013-02-11 18:50 UTC (permalink / raw)
To: sr; +Cc: netdev, linuxppc-dev, agust
In-Reply-To: <1360403352-24237-1-git-send-email-sr@denx.de>
From: Stefan Roese <sr@denx.de>
Date: Sat, 9 Feb 2013 10:49:12 +0100
> Until now, the MPC5200 FEC ethernet driver relied upon the bootloader
> (U-Boot) to write the MAC address into the ethernet controller
> registers. The Linux driver should not rely on such a thing. So
> lets read the MAC address from the DT as it should be done here.
>
> This fixes a problem with a MPC5200 board that uses the SPL U-Boot
> version without FEC initialization before Linux booting for
> boot speedup.
>
> Additionally a status line will now be printed upon successful
> driver probing, also displaying this MAC address.
>
> Signed-off-by: Stefan Roese <sr@denx.de>
I don't think this is a conservative enough change.
You have to keep the MAC register reading code around, as a backup
code path in case the OF device node lacks a MAC address, also:
> + if (!is_zero_ether_addr(mpc52xx_fec_mac_addr)) {
I really wish I would have caught this terrible module parameter
when the driver was initially submitted.
I would just get rid of this, and have a priority list of cases:
1) First, try OF node MAC address, if not present or invalid, then:
2) Read from MAC address registers, if invalid, then:
3) Log a warning message, and choose a random MAC address.
That way no matter what happens, the user will at least have a
functioning networking device.
^ permalink raw reply
* Re: [PATCH] cfg80211: configuration for WoWLAN over TCP
From: David Miller @ 2013-02-11 18:45 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, netdev, johannes.berg
In-Reply-To: <1360596853-13610-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes@sipsolutions.net>
Date: Mon, 11 Feb 2013 16:34:13 +0100
> From: Johannes Berg <johannes.berg@intel.com>
>
> Intel Wireless devices are able to make a TCP connection
> after suspending, sending some data and waking up when
> the connection receives wakeup data (or breaks). Add the
> WoWLAN configuration and feature advertising API for it.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
No objections from me:
Acked-by: David S. Miller <davem@davemloft.net>
^ permalink raw reply
* Re: [PATCH] sun.com documentation fixes
From: David Miller @ 2013-02-11 18:42 UTC (permalink / raw)
To: lists; +Cc: grant.likely, akpm, linux-doc, netdev, linux-kernel
In-Reply-To: <alpine.DEB.2.01.1302110332340.13050@trent.utfs.org>
From: Christian Kujau <lists@nerdbynature.de>
Date: Mon, 11 Feb 2013 03:52:49 -0800 (PST)
>
> After I came across a help text for SUNGEM mentioning a broken sun.com
> URL, I felt like fixing those up, as they are now pointing to oracle.com
> URLs.
>
> Signed-off-by: Christian Kujau <lists@nerdbynature.de>
Acked-by: David S. Miller <davem@davemloft.net>
^ permalink raw reply
* Re: [PATCH 2/2] net: calexdaxgmac: fixup endian issues after __raw IO function change
From: Ben Dooks @ 2013-02-11 18:27 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev, David S. Miller, Rob Herring, linux-arm-kernel
In-Reply-To: <1360606656.2701.18.camel@bwh-desktop.uk.solarflarecom.com>
On 11/02/13 18:17, Ben Hutchings wrote:
> On Sun, 2013-02-10 at 15:38 +0000, Ben Dooks wrote:
>> When changing to __raw acccessors in 0ec6d343f7bcf9e0944aa9ff65287b987ec00c0f
>> ("net: calxedaxgmac: use raw i/o accessors in rx and tx paths"), the driver
>> is now broken on big endian systems as the readl/writel have an implict
>> endian swap in them.
>>
>> Change all the places where the __raw calls are used to correctly convert
>> the constants in big endian format to the little endian data that the
>> peripheral expects to see.
>
> You are using le32_to_cpu() and cpu_to_le32() the wrong way round, and
> then putting casts on the wrong side, i.e. it should be:
>
> value = le32_to_cpu((__force __le32)__raw_readl(addr));
> __raw_writel((__force u32)cpu_to_le32(value), addr);
>
> (I do wonder why __raw I/O functions aren't declared to take/return __le
> types... it would avoid the need to cast altogether.)
Because they do things with the order the cpu is working in, the
read{x} and write{x} transfer cpu to bus-endian so returning an __le
type would not be correct.
I think you are right about the conversions, it is a headache trying
to think through.
It may be easier to provide _relaxed IO variants for all systems so
that we can avoid this in future.
>> Signed-off-by: Ben Dooks<ben.dooks@codethink.co.uk>
>> ---
>> drivers/net/ethernet/calxeda/xgmac.c | 10 +++++++---
>> 1 file changed, 7 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
>> index f91d9b2..96fd538 100644
>> --- a/drivers/net/ethernet/calxeda/xgmac.c
>> +++ b/drivers/net/ethernet/calxeda/xgmac.c
>> @@ -1202,7 +1202,8 @@ static int xgmac_poll(struct napi_struct *napi, int budget)
>>
>> if (work_done< budget) {
>> napi_complete(napi);
>> - __raw_writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA);
>> + __raw_writel(le32_to_cpu((__force __le32)DMA_INTR_DEFAULT_MASK),
>> + priv->base + XGMAC_DMA_INTR_ENA);
>> }
>> return work_done;
>> }
>> @@ -1348,7 +1349,7 @@ static irqreturn_t xgmac_pmt_interrupt(int irq, void *dev_id)
>> void __iomem *ioaddr = priv->base;
>>
>> intr_status = __raw_readl(ioaddr + XGMAC_INT_STAT);
>> - if (intr_status& XGMAC_INT_STAT_PMT) {
>> + if (intr_status& le32_to_cpu((__force __le32)XGMAC_INT_STAT_PMT)) {
>> netdev_dbg(priv->dev, "received Magic frame\n");
>> /* clear the PMT bits 5 and 6 by reading the PMT */
>> readl(ioaddr + XGMAC_PMT);
>> @@ -1369,6 +1370,8 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
>> intr_status&= __raw_readl(priv->base + XGMAC_DMA_INTR_ENA);
>> __raw_writel(intr_status, priv->base + XGMAC_DMA_STATUS);
>>
>> + intr_status = (__force u32)cpu_to_le32(intr_status);
>
> Perhaps intr_status should be split into two variables, for native and
> little-endian order.
>
> Ben.
That would be a possibility, although it would end up changing more code.
>> /* It displays the DMA process states (CSR5 register) */
>> /* ABNORMAL interrupts */
>> if (unlikely(intr_status& DMA_STATUS_AIS)) {
>> @@ -1403,7 +1406,8 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
>>
>> /* TX/RX NORMAL interrupts */
>> if (intr_status& (DMA_STATUS_RI | DMA_STATUS_TU | DMA_STATUS_TI)) {
>> - __raw_writel(DMA_INTR_ABNORMAL, priv->base + XGMAC_DMA_INTR_ENA);
>> + __raw_writel(le32_to_cpu((__force __le32)DMA_INTR_ABNORMAL),
>> + priv->base + XGMAC_DMA_INTR_ENA);
>> napi_schedule(&priv->napi);
>> }
>>
>
--
Ben Dooks http://www.codethink.co.uk/
Senior Engineer Codethink - Providing Genius
^ 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