* [PATCH v2 0/2] Add CPSW VLAN Support
@ 2013-01-30 19:07 ` Mugunthan V N
0 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-30 19:07 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N
CPSW is capable of filtering VLAN packets in hardware. This patch series
implements VLAN support to CPSW driver.
This patch series is tested on net-next with AM335x EVM with ping test.
Changes from initial version
* added vlan support to existing add/delete unicast/multicast apis
* Made driver as default VLAN enabled so that drivers need to be recompiled
when stack is compiled with VLAN
Mugunthan V N (2):
drivers: net: cpsw: Add helper functions for VLAN ALE implementation
drivers: net:ethernet: cpsw: add support for VLAN
Documentation/devicetree/bindings/net/cpsw.txt | 2 +
drivers/net/ethernet/ti/cpsw.c | 100 ++++++++++++++++++++--
drivers/net/ethernet/ti/cpsw_ale.c | 106 +++++++++++++++++++++---
drivers/net/ethernet/ti/cpsw_ale.h | 20 +++--
include/linux/platform_data/cpsw.h | 1 +
5 files changed, 205 insertions(+), 24 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 0/2] Add CPSW VLAN Support
@ 2013-01-30 19:07 ` Mugunthan V N
0 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-30 19:07 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N
CPSW is capable of filtering VLAN packets in hardware. This patch series
implements VLAN support to CPSW driver.
This patch series is tested on net-next with AM335x EVM with ping test.
Changes from initial version
* added vlan support to existing add/delete unicast/multicast apis
* Made driver as default VLAN enabled so that drivers need to be recompiled
when stack is compiled with VLAN
Mugunthan V N (2):
drivers: net: cpsw: Add helper functions for VLAN ALE implementation
drivers: net:ethernet: cpsw: add support for VLAN
Documentation/devicetree/bindings/net/cpsw.txt | 2 +
drivers/net/ethernet/ti/cpsw.c | 100 ++++++++++++++++++++--
drivers/net/ethernet/ti/cpsw_ale.c | 106 +++++++++++++++++++++---
drivers/net/ethernet/ti/cpsw_ale.h | 20 +++--
include/linux/platform_data/cpsw.h | 1 +
5 files changed, 205 insertions(+), 24 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 0/2] Add CPSW VLAN Support
@ 2013-01-30 19:07 ` Mugunthan V N
0 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-30 19:07 UTC (permalink / raw)
To: linux-arm-kernel
CPSW is capable of filtering VLAN packets in hardware. This patch series
implements VLAN support to CPSW driver.
This patch series is tested on net-next with AM335x EVM with ping test.
Changes from initial version
* added vlan support to existing add/delete unicast/multicast apis
* Made driver as default VLAN enabled so that drivers need to be recompiled
when stack is compiled with VLAN
Mugunthan V N (2):
drivers: net: cpsw: Add helper functions for VLAN ALE implementation
drivers: net:ethernet: cpsw: add support for VLAN
Documentation/devicetree/bindings/net/cpsw.txt | 2 +
drivers/net/ethernet/ti/cpsw.c | 100 ++++++++++++++++++++--
drivers/net/ethernet/ti/cpsw_ale.c | 106 +++++++++++++++++++++---
drivers/net/ethernet/ti/cpsw_ale.h | 20 +++--
include/linux/platform_data/cpsw.h | 1 +
5 files changed, 205 insertions(+), 24 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation
2013-01-30 19:07 ` Mugunthan V N
(?)
@ 2013-01-30 19:07 ` Mugunthan V N
-1 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-30 19:07 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N
Add helper functions for VLAN ALE implementations for Add, Delete
Dump VLAN related ALE entries
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/net/ethernet/ti/cpsw.c | 8 +--
drivers/net/ethernet/ti/cpsw_ale.c | 106 ++++++++++++++++++++++++++++++++----
drivers/net/ethernet/ti/cpsw_ale.h | 20 +++++--
3 files changed, 112 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index b35e6a7..a40750e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -345,7 +345,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);
+ ALE_ALL_PORTS << priv->host_port, 0, 0, 0);
}
}
}
@@ -592,7 +592,7 @@ 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, ALE_MCAST_FWD_2);
+ 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);
@@ -624,9 +624,9 @@ 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);
+ 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, ALE_MCAST_FWD_2);
+ 1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
}
static int cpsw_ndo_open(struct net_device *ndev)
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 0e9ccc2..18b88ce 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -148,7 +148,7 @@ static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
return idx;
}
-static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
+int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS];
int type, idx;
@@ -160,6 +160,8 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
type = cpsw_ale_get_entry_type(ale_entry);
if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
continue;
+ if (cpsw_ale_get_vlan_id(ale_entry) != vid)
+ continue;
cpsw_ale_get_addr(ale_entry, entry_addr);
if (memcmp(entry_addr, addr, 6) == 0)
return idx;
@@ -167,6 +169,22 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
return -ENOENT;
}
+int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS];
+ int type, idx;
+
+ for (idx = 0; idx < ale->params.ale_entries; idx++) {
+ cpsw_ale_read(ale, idx, ale_entry);
+ type = cpsw_ale_get_entry_type(ale_entry);
+ if (type != ALE_TYPE_VLAN)
+ continue;
+ if (cpsw_ale_get_vlan_id(ale_entry) == vid)
+ return idx;
+ }
+ return -ENOENT;
+}
+
static int cpsw_ale_match_free(struct cpsw_ale *ale)
{
u32 ale_entry[ALE_ENTRY_WORDS];
@@ -274,19 +292,26 @@ int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
return 0;
}
-int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
+int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ if (flags & ALE_VLAN) {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
+ cpsw_ale_set_vlan_id(ale_entry, vid);
+ } else {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ }
+
cpsw_ale_set_addr(ale_entry, addr);
cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
cpsw_ale_set_port_num(ale_entry, port);
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
idx = cpsw_ale_match_free(ale);
if (idx < 0)
@@ -298,12 +323,13 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
return 0;
}
-int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
+int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
return -ENOENT;
@@ -313,18 +339,24 @@ int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
}
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
- int super, int mcast_state)
+ int flags, u16 vid, int mcast_state)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx, mask;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx >= 0)
cpsw_ale_read(ale, idx, ale_entry);
- cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ if (flags & ALE_VLAN) {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
+ cpsw_ale_set_vlan_id(ale_entry, vid);
+ } else {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ }
+
cpsw_ale_set_addr(ale_entry, addr);
- cpsw_ale_set_super(ale_entry, super);
+ cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
cpsw_ale_set_mcast_state(ale_entry, mcast_state);
mask = cpsw_ale_get_port_mask(ale_entry);
@@ -342,12 +374,13 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
return 0;
}
-int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
+int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
return -EINVAL;
@@ -362,6 +395,55 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
return 0;
}
+int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
+ int reg_mcast, int unreg_mcast)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx >= 0)
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
+ cpsw_ale_set_vlan_id(ale_entry, vid);
+
+ cpsw_ale_set_vlan_untag_force(ale_entry, untag);
+ cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast);
+ cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
+ cpsw_ale_set_vlan_member_list(ale_entry, port);
+
+ if (idx < 0)
+ idx = cpsw_ale_match_free(ale);
+ if (idx < 0)
+ idx = cpsw_ale_find_ageable(ale);
+ if (idx < 0)
+ return -ENOMEM;
+
+ cpsw_ale_write(ale, idx, ale_entry);
+ return 0;
+}
+
+int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx < 0)
+ return -ENOENT;
+
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ if (port_mask)
+ cpsw_ale_set_vlan_member_list(ale_entry, port_mask);
+ else
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
+
+ cpsw_ale_write(ale, idx, ale_entry);
+ return 0;
+}
+
struct ale_control_info {
const char *name;
int offset, port_offset;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index 2bd09cb..a002417 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -64,8 +64,10 @@ enum cpsw_ale_port_state {
};
/* ALE unicast entry flags - passed into cpsw_ale_add_ucast() */
-#define ALE_SECURE 1
-#define ALE_BLOCKED 2
+#define ALE_SECURE BIT(0)
+#define ALE_BLOCKED BIT(1)
+#define ALE_SUPER BIT(2)
+#define ALE_VLAN BIT(3)
#define ALE_MCAST_FWD 0
#define ALE_MCAST_BLOCK_LEARN_FWD 1
@@ -81,11 +83,17 @@ void cpsw_ale_stop(struct cpsw_ale *ale);
int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout);
int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask);
int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask);
-int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags);
-int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port);
+int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid);
+int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid);
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
- int super, int mcast_state);
-int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask);
+ int flags, u16 vid, int mcast_state);
+int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
+ int flags, u16 vid);
+int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
+ int reg_mcast, int unreg_mcast);
+int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port);
int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation
@ 2013-01-30 19:07 ` Mugunthan V N
0 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-30 19:07 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N
Add helper functions for VLAN ALE implementations for Add, Delete
Dump VLAN related ALE entries
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/net/ethernet/ti/cpsw.c | 8 +--
drivers/net/ethernet/ti/cpsw_ale.c | 106 ++++++++++++++++++++++++++++++++----
drivers/net/ethernet/ti/cpsw_ale.h | 20 +++++--
3 files changed, 112 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index b35e6a7..a40750e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -345,7 +345,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);
+ ALE_ALL_PORTS << priv->host_port, 0, 0, 0);
}
}
}
@@ -592,7 +592,7 @@ 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, ALE_MCAST_FWD_2);
+ 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);
@@ -624,9 +624,9 @@ 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);
+ 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, ALE_MCAST_FWD_2);
+ 1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
}
static int cpsw_ndo_open(struct net_device *ndev)
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 0e9ccc2..18b88ce 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -148,7 +148,7 @@ static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
return idx;
}
-static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
+int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS];
int type, idx;
@@ -160,6 +160,8 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
type = cpsw_ale_get_entry_type(ale_entry);
if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
continue;
+ if (cpsw_ale_get_vlan_id(ale_entry) != vid)
+ continue;
cpsw_ale_get_addr(ale_entry, entry_addr);
if (memcmp(entry_addr, addr, 6) == 0)
return idx;
@@ -167,6 +169,22 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
return -ENOENT;
}
+int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS];
+ int type, idx;
+
+ for (idx = 0; idx < ale->params.ale_entries; idx++) {
+ cpsw_ale_read(ale, idx, ale_entry);
+ type = cpsw_ale_get_entry_type(ale_entry);
+ if (type != ALE_TYPE_VLAN)
+ continue;
+ if (cpsw_ale_get_vlan_id(ale_entry) == vid)
+ return idx;
+ }
+ return -ENOENT;
+}
+
static int cpsw_ale_match_free(struct cpsw_ale *ale)
{
u32 ale_entry[ALE_ENTRY_WORDS];
@@ -274,19 +292,26 @@ int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
return 0;
}
-int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
+int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ if (flags & ALE_VLAN) {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
+ cpsw_ale_set_vlan_id(ale_entry, vid);
+ } else {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ }
+
cpsw_ale_set_addr(ale_entry, addr);
cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
cpsw_ale_set_port_num(ale_entry, port);
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
idx = cpsw_ale_match_free(ale);
if (idx < 0)
@@ -298,12 +323,13 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
return 0;
}
-int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
+int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
return -ENOENT;
@@ -313,18 +339,24 @@ int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
}
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
- int super, int mcast_state)
+ int flags, u16 vid, int mcast_state)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx, mask;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx >= 0)
cpsw_ale_read(ale, idx, ale_entry);
- cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ if (flags & ALE_VLAN) {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
+ cpsw_ale_set_vlan_id(ale_entry, vid);
+ } else {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ }
+
cpsw_ale_set_addr(ale_entry, addr);
- cpsw_ale_set_super(ale_entry, super);
+ cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
cpsw_ale_set_mcast_state(ale_entry, mcast_state);
mask = cpsw_ale_get_port_mask(ale_entry);
@@ -342,12 +374,13 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
return 0;
}
-int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
+int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
return -EINVAL;
@@ -362,6 +395,55 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
return 0;
}
+int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
+ int reg_mcast, int unreg_mcast)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx >= 0)
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
+ cpsw_ale_set_vlan_id(ale_entry, vid);
+
+ cpsw_ale_set_vlan_untag_force(ale_entry, untag);
+ cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast);
+ cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
+ cpsw_ale_set_vlan_member_list(ale_entry, port);
+
+ if (idx < 0)
+ idx = cpsw_ale_match_free(ale);
+ if (idx < 0)
+ idx = cpsw_ale_find_ageable(ale);
+ if (idx < 0)
+ return -ENOMEM;
+
+ cpsw_ale_write(ale, idx, ale_entry);
+ return 0;
+}
+
+int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx < 0)
+ return -ENOENT;
+
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ if (port_mask)
+ cpsw_ale_set_vlan_member_list(ale_entry, port_mask);
+ else
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
+
+ cpsw_ale_write(ale, idx, ale_entry);
+ return 0;
+}
+
struct ale_control_info {
const char *name;
int offset, port_offset;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index 2bd09cb..a002417 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -64,8 +64,10 @@ enum cpsw_ale_port_state {
};
/* ALE unicast entry flags - passed into cpsw_ale_add_ucast() */
-#define ALE_SECURE 1
-#define ALE_BLOCKED 2
+#define ALE_SECURE BIT(0)
+#define ALE_BLOCKED BIT(1)
+#define ALE_SUPER BIT(2)
+#define ALE_VLAN BIT(3)
#define ALE_MCAST_FWD 0
#define ALE_MCAST_BLOCK_LEARN_FWD 1
@@ -81,11 +83,17 @@ void cpsw_ale_stop(struct cpsw_ale *ale);
int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout);
int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask);
int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask);
-int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags);
-int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port);
+int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid);
+int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid);
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
- int super, int mcast_state);
-int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask);
+ int flags, u16 vid, int mcast_state);
+int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
+ int flags, u16 vid);
+int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
+ int reg_mcast, int unreg_mcast);
+int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port);
int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation
@ 2013-01-30 19:07 ` Mugunthan V N
0 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-30 19:07 UTC (permalink / raw)
To: linux-arm-kernel
Add helper functions for VLAN ALE implementations for Add, Delete
Dump VLAN related ALE entries
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
drivers/net/ethernet/ti/cpsw.c | 8 +--
drivers/net/ethernet/ti/cpsw_ale.c | 106 ++++++++++++++++++++++++++++++++----
drivers/net/ethernet/ti/cpsw_ale.h | 20 +++++--
3 files changed, 112 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index b35e6a7..a40750e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -345,7 +345,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);
+ ALE_ALL_PORTS << priv->host_port, 0, 0, 0);
}
}
}
@@ -592,7 +592,7 @@ 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, ALE_MCAST_FWD_2);
+ 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);
@@ -624,9 +624,9 @@ 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);
+ 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, ALE_MCAST_FWD_2);
+ 1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
}
static int cpsw_ndo_open(struct net_device *ndev)
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 0e9ccc2..18b88ce 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -148,7 +148,7 @@ static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
return idx;
}
-static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
+int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS];
int type, idx;
@@ -160,6 +160,8 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
type = cpsw_ale_get_entry_type(ale_entry);
if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
continue;
+ if (cpsw_ale_get_vlan_id(ale_entry) != vid)
+ continue;
cpsw_ale_get_addr(ale_entry, entry_addr);
if (memcmp(entry_addr, addr, 6) == 0)
return idx;
@@ -167,6 +169,22 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
return -ENOENT;
}
+int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS];
+ int type, idx;
+
+ for (idx = 0; idx < ale->params.ale_entries; idx++) {
+ cpsw_ale_read(ale, idx, ale_entry);
+ type = cpsw_ale_get_entry_type(ale_entry);
+ if (type != ALE_TYPE_VLAN)
+ continue;
+ if (cpsw_ale_get_vlan_id(ale_entry) == vid)
+ return idx;
+ }
+ return -ENOENT;
+}
+
static int cpsw_ale_match_free(struct cpsw_ale *ale)
{
u32 ale_entry[ALE_ENTRY_WORDS];
@@ -274,19 +292,26 @@ int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
return 0;
}
-int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
+int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ if (flags & ALE_VLAN) {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
+ cpsw_ale_set_vlan_id(ale_entry, vid);
+ } else {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ }
+
cpsw_ale_set_addr(ale_entry, addr);
cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
cpsw_ale_set_port_num(ale_entry, port);
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
idx = cpsw_ale_match_free(ale);
if (idx < 0)
@@ -298,12 +323,13 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
return 0;
}
-int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
+int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
return -ENOENT;
@@ -313,18 +339,24 @@ int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
}
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
- int super, int mcast_state)
+ int flags, u16 vid, int mcast_state)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx, mask;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx >= 0)
cpsw_ale_read(ale, idx, ale_entry);
- cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ if (flags & ALE_VLAN) {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
+ cpsw_ale_set_vlan_id(ale_entry, vid);
+ } else {
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
+ }
+
cpsw_ale_set_addr(ale_entry, addr);
- cpsw_ale_set_super(ale_entry, super);
+ cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
cpsw_ale_set_mcast_state(ale_entry, mcast_state);
mask = cpsw_ale_get_port_mask(ale_entry);
@@ -342,12 +374,13 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
return 0;
}
-int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
+int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
+ int flags, u16 vid)
{
u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
int idx;
- idx = cpsw_ale_match_addr(ale, addr);
+ idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
if (idx < 0)
return -EINVAL;
@@ -362,6 +395,55 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
return 0;
}
+int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
+ int reg_mcast, int unreg_mcast)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx >= 0)
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
+ cpsw_ale_set_vlan_id(ale_entry, vid);
+
+ cpsw_ale_set_vlan_untag_force(ale_entry, untag);
+ cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast);
+ cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
+ cpsw_ale_set_vlan_member_list(ale_entry, port);
+
+ if (idx < 0)
+ idx = cpsw_ale_match_free(ale);
+ if (idx < 0)
+ idx = cpsw_ale_find_ageable(ale);
+ if (idx < 0)
+ return -ENOMEM;
+
+ cpsw_ale_write(ale, idx, ale_entry);
+ return 0;
+}
+
+int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
+{
+ u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
+ int idx;
+
+ idx = cpsw_ale_match_vlan(ale, vid);
+ if (idx < 0)
+ return -ENOENT;
+
+ cpsw_ale_read(ale, idx, ale_entry);
+
+ if (port_mask)
+ cpsw_ale_set_vlan_member_list(ale_entry, port_mask);
+ else
+ cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
+
+ cpsw_ale_write(ale, idx, ale_entry);
+ return 0;
+}
+
struct ale_control_info {
const char *name;
int offset, port_offset;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index 2bd09cb..a002417 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -64,8 +64,10 @@ enum cpsw_ale_port_state {
};
/* ALE unicast entry flags - passed into cpsw_ale_add_ucast() */
-#define ALE_SECURE 1
-#define ALE_BLOCKED 2
+#define ALE_SECURE BIT(0)
+#define ALE_BLOCKED BIT(1)
+#define ALE_SUPER BIT(2)
+#define ALE_VLAN BIT(3)
#define ALE_MCAST_FWD 0
#define ALE_MCAST_BLOCK_LEARN_FWD 1
@@ -81,11 +83,17 @@ void cpsw_ale_stop(struct cpsw_ale *ale);
int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout);
int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask);
int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask);
-int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags);
-int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port);
+int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid);
+int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
+ int flags, u16 vid);
int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
- int super, int mcast_state);
-int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask);
+ int flags, u16 vid, int mcast_state);
+int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
+ int flags, u16 vid);
+int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
+ int reg_mcast, int unreg_mcast);
+int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port);
int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 2/2] drivers: net:ethernet: cpsw: add support for VLAN
2013-01-30 19:07 ` Mugunthan V N
(?)
@ 2013-01-30 19:07 ` Mugunthan V N
-1 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-30 19:07 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N
adding support for VLAN interface for cpsw.
CPSW VLAN Capability
* Can filter VLAN packets in Hardware
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 2 +
drivers/net/ethernet/ti/cpsw.c | 92 +++++++++++++++++++++++-
include/linux/platform_data/cpsw.h | 1 +
3 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 6ddd028..99696bf 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
+- default_vlan : Specifies Default VLAN for non tagged packets
+ ALE processing
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 a40750e..6c66f01 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -32,6 +32,7 @@
#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/of_device.h>
+#include <linux/if_vlan.h>
#include <linux/platform_data/cpsw.h>
@@ -118,6 +119,9 @@ do { \
#define TX_PRIORITY_MAPPING 0x33221100
#define CPDMA_TX_PRIORITY_MAP 0x76543210
+#define CPSW_VLAN_AWARE BIT(1)
+#define CPSW_ALE_VLAN_AWARE 1
+
#define cpsw_enable_irq(priv) \
do { \
u32 i; \
@@ -607,14 +611,41 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
}
}
+static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
+{
+ writel(priv->data.default_vlan, &priv->host_port_regs->port_vlan);
+ if (priv->version == CPSW_VERSION_1) {
+ slave_write(&priv->slaves[0], priv->data.default_vlan,
+ CPSW1_PORT_VLAN);
+ slave_write(&priv->slaves[1], priv->data.default_vlan,
+ CPSW1_PORT_VLAN);
+ } else {
+ slave_write(&priv->slaves[0], priv->data.default_vlan,
+ CPSW2_PORT_VLAN);
+ slave_write(&priv->slaves[1], priv->data.default_vlan,
+ CPSW2_PORT_VLAN);
+ }
+ cpsw_ale_add_vlan(priv->ale, priv->data.default_vlan,
+ ALE_ALL_PORTS << priv->host_port,
+ ALE_ALL_PORTS << priv->host_port,
+ ALE_ALL_PORTS << priv->host_port,
+ (BIT(1) | BIT(2)) << priv->host_port);
+}
+
static void cpsw_init_host_port(struct cpsw_priv *priv)
{
+ u32 control_reg;
+
/* soft reset the controller and initialize ale */
soft_reset("cpsw", &priv->regs->soft_reset);
cpsw_ale_start(priv->ale);
/* switch to vlan unaware mode */
- cpsw_ale_control_set(priv->ale, 0, ALE_VLAN_AWARE, 0);
+ cpsw_ale_control_set(priv->ale, priv->host_port, ALE_VLAN_AWARE,
+ CPSW_ALE_VLAN_AWARE);
+ control_reg = readl(&priv->regs->control);
+ control_reg |= CPSW_VLAN_AWARE;
+ writel(control_reg, &priv->regs->control);
/* setup host port priority mapping */
__raw_writel(CPDMA_TX_PRIORITY_MAP,
@@ -650,6 +681,9 @@ static int cpsw_ndo_open(struct net_device *ndev)
cpsw_init_host_port(priv);
for_each_slave(priv, cpsw_slave_open, priv);
+ /* Add default VLAN */
+ 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);
@@ -933,6 +967,55 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
}
#endif
+static inline void cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
+ unsigned short vid)
+{
+ cpsw_ale_add_vlan(priv->ale, vid, ALE_ALL_PORTS << priv->host_port,
+ 0, ALE_ALL_PORTS << priv->host_port,
+ (BIT(1) | BIT(2)) << priv->host_port);
+ cpsw_ale_add_ucast(priv->ale, priv->mac_addr,
+ priv->host_port, ALE_VLAN, vid);
+ cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+ ALE_ALL_PORTS << priv->host_port, ALE_VLAN, vid, 0);
+}
+
+static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev,
+ unsigned short vid)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ if (vid == priv->data.default_vlan)
+ return 0;
+
+ spin_lock(&priv->lock);
+
+ dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid);
+ cpsw_add_vlan_ale_entry(priv, vid);
+
+ spin_unlock(&priv->lock);
+ return 0;
+}
+
+static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
+ unsigned short vid)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ if (vid == priv->data.default_vlan)
+ return 0;
+
+ spin_lock(&priv->lock);
+
+ dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid);
+ cpsw_ale_del_vlan(priv->ale, vid, 0);
+ cpsw_ale_del_ucast(priv->ale, priv->mac_addr,
+ priv->host_port, ALE_VLAN, vid);
+ cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast, 0, ALE_VLAN, vid);
+
+ spin_unlock(&priv->lock);
+ return 0;
+}
+
static const struct net_device_ops cpsw_netdev_ops = {
.ndo_open = cpsw_ndo_open,
.ndo_stop = cpsw_ndo_stop,
@@ -947,6 +1030,8 @@ static const struct net_device_ops cpsw_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cpsw_ndo_poll_controller,
#endif
+ .ndo_vlan_rx_add_vid = cpsw_ndo_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = cpsw_ndo_vlan_rx_kill_vid,
};
static void cpsw_get_drvinfo(struct net_device *ndev,
@@ -1103,6 +1188,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->mac_control = prop;
+ if (!of_property_read_u32(node, "default_vlan", &prop))
+ data->default_vlan = prop;
+
/*
* Populate all the child nodes here...
*/
@@ -1356,7 +1444,7 @@ static int cpsw_probe(struct platform_device *pdev)
k++;
}
- ndev->flags |= IFF_ALLMULTI; /* see cpsw_ndo_change_rx_flags() */
+ ndev->features |= NETIF_F_HW_VLAN_FILTER;
ndev->netdev_ops = &cpsw_netdev_ops;
SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index 24368a2..e962cfd 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -35,6 +35,7 @@ struct cpsw_platform_data {
u32 bd_ram_size; /*buffer descriptor ram size */
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*/
};
#endif /* __CPSW_H__ */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 2/2] drivers: net:ethernet: cpsw: add support for VLAN
@ 2013-01-30 19:07 ` Mugunthan V N
0 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-30 19:07 UTC (permalink / raw)
To: netdev; +Cc: davem, linux-arm-kernel, linux-omap, Mugunthan V N
adding support for VLAN interface for cpsw.
CPSW VLAN Capability
* Can filter VLAN packets in Hardware
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 2 +
drivers/net/ethernet/ti/cpsw.c | 92 +++++++++++++++++++++++-
include/linux/platform_data/cpsw.h | 1 +
3 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 6ddd028..99696bf 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
+- default_vlan : Specifies Default VLAN for non tagged packets
+ ALE processing
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 a40750e..6c66f01 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -32,6 +32,7 @@
#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/of_device.h>
+#include <linux/if_vlan.h>
#include <linux/platform_data/cpsw.h>
@@ -118,6 +119,9 @@ do { \
#define TX_PRIORITY_MAPPING 0x33221100
#define CPDMA_TX_PRIORITY_MAP 0x76543210
+#define CPSW_VLAN_AWARE BIT(1)
+#define CPSW_ALE_VLAN_AWARE 1
+
#define cpsw_enable_irq(priv) \
do { \
u32 i; \
@@ -607,14 +611,41 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
}
}
+static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
+{
+ writel(priv->data.default_vlan, &priv->host_port_regs->port_vlan);
+ if (priv->version == CPSW_VERSION_1) {
+ slave_write(&priv->slaves[0], priv->data.default_vlan,
+ CPSW1_PORT_VLAN);
+ slave_write(&priv->slaves[1], priv->data.default_vlan,
+ CPSW1_PORT_VLAN);
+ } else {
+ slave_write(&priv->slaves[0], priv->data.default_vlan,
+ CPSW2_PORT_VLAN);
+ slave_write(&priv->slaves[1], priv->data.default_vlan,
+ CPSW2_PORT_VLAN);
+ }
+ cpsw_ale_add_vlan(priv->ale, priv->data.default_vlan,
+ ALE_ALL_PORTS << priv->host_port,
+ ALE_ALL_PORTS << priv->host_port,
+ ALE_ALL_PORTS << priv->host_port,
+ (BIT(1) | BIT(2)) << priv->host_port);
+}
+
static void cpsw_init_host_port(struct cpsw_priv *priv)
{
+ u32 control_reg;
+
/* soft reset the controller and initialize ale */
soft_reset("cpsw", &priv->regs->soft_reset);
cpsw_ale_start(priv->ale);
/* switch to vlan unaware mode */
- cpsw_ale_control_set(priv->ale, 0, ALE_VLAN_AWARE, 0);
+ cpsw_ale_control_set(priv->ale, priv->host_port, ALE_VLAN_AWARE,
+ CPSW_ALE_VLAN_AWARE);
+ control_reg = readl(&priv->regs->control);
+ control_reg |= CPSW_VLAN_AWARE;
+ writel(control_reg, &priv->regs->control);
/* setup host port priority mapping */
__raw_writel(CPDMA_TX_PRIORITY_MAP,
@@ -650,6 +681,9 @@ static int cpsw_ndo_open(struct net_device *ndev)
cpsw_init_host_port(priv);
for_each_slave(priv, cpsw_slave_open, priv);
+ /* Add default VLAN */
+ 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);
@@ -933,6 +967,55 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
}
#endif
+static inline void cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
+ unsigned short vid)
+{
+ cpsw_ale_add_vlan(priv->ale, vid, ALE_ALL_PORTS << priv->host_port,
+ 0, ALE_ALL_PORTS << priv->host_port,
+ (BIT(1) | BIT(2)) << priv->host_port);
+ cpsw_ale_add_ucast(priv->ale, priv->mac_addr,
+ priv->host_port, ALE_VLAN, vid);
+ cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+ ALE_ALL_PORTS << priv->host_port, ALE_VLAN, vid, 0);
+}
+
+static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev,
+ unsigned short vid)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ if (vid == priv->data.default_vlan)
+ return 0;
+
+ spin_lock(&priv->lock);
+
+ dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid);
+ cpsw_add_vlan_ale_entry(priv, vid);
+
+ spin_unlock(&priv->lock);
+ return 0;
+}
+
+static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
+ unsigned short vid)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ if (vid == priv->data.default_vlan)
+ return 0;
+
+ spin_lock(&priv->lock);
+
+ dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid);
+ cpsw_ale_del_vlan(priv->ale, vid, 0);
+ cpsw_ale_del_ucast(priv->ale, priv->mac_addr,
+ priv->host_port, ALE_VLAN, vid);
+ cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast, 0, ALE_VLAN, vid);
+
+ spin_unlock(&priv->lock);
+ return 0;
+}
+
static const struct net_device_ops cpsw_netdev_ops = {
.ndo_open = cpsw_ndo_open,
.ndo_stop = cpsw_ndo_stop,
@@ -947,6 +1030,8 @@ static const struct net_device_ops cpsw_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cpsw_ndo_poll_controller,
#endif
+ .ndo_vlan_rx_add_vid = cpsw_ndo_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = cpsw_ndo_vlan_rx_kill_vid,
};
static void cpsw_get_drvinfo(struct net_device *ndev,
@@ -1103,6 +1188,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->mac_control = prop;
+ if (!of_property_read_u32(node, "default_vlan", &prop))
+ data->default_vlan = prop;
+
/*
* Populate all the child nodes here...
*/
@@ -1356,7 +1444,7 @@ static int cpsw_probe(struct platform_device *pdev)
k++;
}
- ndev->flags |= IFF_ALLMULTI; /* see cpsw_ndo_change_rx_flags() */
+ ndev->features |= NETIF_F_HW_VLAN_FILTER;
ndev->netdev_ops = &cpsw_netdev_ops;
SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index 24368a2..e962cfd 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -35,6 +35,7 @@ struct cpsw_platform_data {
u32 bd_ram_size; /*buffer descriptor ram size */
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*/
};
#endif /* __CPSW_H__ */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 2/2] drivers: net:ethernet: cpsw: add support for VLAN
@ 2013-01-30 19:07 ` Mugunthan V N
0 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-30 19:07 UTC (permalink / raw)
To: linux-arm-kernel
adding support for VLAN interface for cpsw.
CPSW VLAN Capability
* Can filter VLAN packets in Hardware
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
---
Documentation/devicetree/bindings/net/cpsw.txt | 2 +
drivers/net/ethernet/ti/cpsw.c | 92 +++++++++++++++++++++++-
include/linux/platform_data/cpsw.h | 1 +
3 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
index 6ddd028..99696bf 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
+- default_vlan : Specifies Default VLAN for non tagged packets
+ ALE processing
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 a40750e..6c66f01 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -32,6 +32,7 @@
#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/of_device.h>
+#include <linux/if_vlan.h>
#include <linux/platform_data/cpsw.h>
@@ -118,6 +119,9 @@ do { \
#define TX_PRIORITY_MAPPING 0x33221100
#define CPDMA_TX_PRIORITY_MAP 0x76543210
+#define CPSW_VLAN_AWARE BIT(1)
+#define CPSW_ALE_VLAN_AWARE 1
+
#define cpsw_enable_irq(priv) \
do { \
u32 i; \
@@ -607,14 +611,41 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
}
}
+static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
+{
+ writel(priv->data.default_vlan, &priv->host_port_regs->port_vlan);
+ if (priv->version == CPSW_VERSION_1) {
+ slave_write(&priv->slaves[0], priv->data.default_vlan,
+ CPSW1_PORT_VLAN);
+ slave_write(&priv->slaves[1], priv->data.default_vlan,
+ CPSW1_PORT_VLAN);
+ } else {
+ slave_write(&priv->slaves[0], priv->data.default_vlan,
+ CPSW2_PORT_VLAN);
+ slave_write(&priv->slaves[1], priv->data.default_vlan,
+ CPSW2_PORT_VLAN);
+ }
+ cpsw_ale_add_vlan(priv->ale, priv->data.default_vlan,
+ ALE_ALL_PORTS << priv->host_port,
+ ALE_ALL_PORTS << priv->host_port,
+ ALE_ALL_PORTS << priv->host_port,
+ (BIT(1) | BIT(2)) << priv->host_port);
+}
+
static void cpsw_init_host_port(struct cpsw_priv *priv)
{
+ u32 control_reg;
+
/* soft reset the controller and initialize ale */
soft_reset("cpsw", &priv->regs->soft_reset);
cpsw_ale_start(priv->ale);
/* switch to vlan unaware mode */
- cpsw_ale_control_set(priv->ale, 0, ALE_VLAN_AWARE, 0);
+ cpsw_ale_control_set(priv->ale, priv->host_port, ALE_VLAN_AWARE,
+ CPSW_ALE_VLAN_AWARE);
+ control_reg = readl(&priv->regs->control);
+ control_reg |= CPSW_VLAN_AWARE;
+ writel(control_reg, &priv->regs->control);
/* setup host port priority mapping */
__raw_writel(CPDMA_TX_PRIORITY_MAP,
@@ -650,6 +681,9 @@ static int cpsw_ndo_open(struct net_device *ndev)
cpsw_init_host_port(priv);
for_each_slave(priv, cpsw_slave_open, priv);
+ /* Add default VLAN */
+ 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);
@@ -933,6 +967,55 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
}
#endif
+static inline void cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
+ unsigned short vid)
+{
+ cpsw_ale_add_vlan(priv->ale, vid, ALE_ALL_PORTS << priv->host_port,
+ 0, ALE_ALL_PORTS << priv->host_port,
+ (BIT(1) | BIT(2)) << priv->host_port);
+ cpsw_ale_add_ucast(priv->ale, priv->mac_addr,
+ priv->host_port, ALE_VLAN, vid);
+ cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
+ ALE_ALL_PORTS << priv->host_port, ALE_VLAN, vid, 0);
+}
+
+static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev,
+ unsigned short vid)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ if (vid == priv->data.default_vlan)
+ return 0;
+
+ spin_lock(&priv->lock);
+
+ dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid);
+ cpsw_add_vlan_ale_entry(priv, vid);
+
+ spin_unlock(&priv->lock);
+ return 0;
+}
+
+static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
+ unsigned short vid)
+{
+ struct cpsw_priv *priv = netdev_priv(ndev);
+
+ if (vid == priv->data.default_vlan)
+ return 0;
+
+ spin_lock(&priv->lock);
+
+ dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid);
+ cpsw_ale_del_vlan(priv->ale, vid, 0);
+ cpsw_ale_del_ucast(priv->ale, priv->mac_addr,
+ priv->host_port, ALE_VLAN, vid);
+ cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast, 0, ALE_VLAN, vid);
+
+ spin_unlock(&priv->lock);
+ return 0;
+}
+
static const struct net_device_ops cpsw_netdev_ops = {
.ndo_open = cpsw_ndo_open,
.ndo_stop = cpsw_ndo_stop,
@@ -947,6 +1030,8 @@ static const struct net_device_ops cpsw_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = cpsw_ndo_poll_controller,
#endif
+ .ndo_vlan_rx_add_vid = cpsw_ndo_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = cpsw_ndo_vlan_rx_kill_vid,
};
static void cpsw_get_drvinfo(struct net_device *ndev,
@@ -1103,6 +1188,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->mac_control = prop;
+ if (!of_property_read_u32(node, "default_vlan", &prop))
+ data->default_vlan = prop;
+
/*
* Populate all the child nodes here...
*/
@@ -1356,7 +1444,7 @@ static int cpsw_probe(struct platform_device *pdev)
k++;
}
- ndev->flags |= IFF_ALLMULTI; /* see cpsw_ndo_change_rx_flags() */
+ ndev->features |= NETIF_F_HW_VLAN_FILTER;
ndev->netdev_ops = &cpsw_netdev_ops;
SET_ETHTOOL_OPS(ndev, &cpsw_ethtool_ops);
diff --git a/include/linux/platform_data/cpsw.h b/include/linux/platform_data/cpsw.h
index 24368a2..e962cfd 100644
--- a/include/linux/platform_data/cpsw.h
+++ b/include/linux/platform_data/cpsw.h
@@ -35,6 +35,7 @@ struct cpsw_platform_data {
u32 bd_ram_size; /*buffer descriptor ram size */
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*/
};
#endif /* __CPSW_H__ */
--
1.7.9.5
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v2 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation
2013-01-30 19:07 ` Mugunthan V N
@ 2013-01-30 22:02 ` Francois Romieu
-1 siblings, 0 replies; 21+ messages in thread
From: Francois Romieu @ 2013-01-30 22:02 UTC (permalink / raw)
To: Mugunthan V N; +Cc: netdev, davem, linux-arm-kernel, linux-omap
Mugunthan V N <mugunthanvnm@ti.com> :
[...]
> diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
> index 0e9ccc2..18b88ce 100644
> --- a/drivers/net/ethernet/ti/cpsw_ale.c
> +++ b/drivers/net/ethernet/ti/cpsw_ale.c
[...]
> @@ -274,19 +292,26 @@ int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
> return 0;
> }
>
> -int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
> +int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
> + int flags, u16 vid)
> {
> u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
> int idx;
>
> - cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
> + if (flags & ALE_VLAN) {
> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
> + cpsw_ale_set_vlan_id(ale_entry, vid);
> + } else {
> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
> + }
> +
[...]
> + if (flags & ALE_VLAN) {
> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
> + cpsw_ale_set_vlan_id(ale_entry, vid);
> + } else {
> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
> + }
> +
It could be fctored out.
[...]
> @@ -362,6 +395,55 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
> return 0;
> }
>
> +int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
> + int reg_mcast, int unreg_mcast)
> +{
[...]
> +int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
[...]
Patch #2 doesn't use the returned status code.
--
Ueimor
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation
@ 2013-01-30 22:02 ` Francois Romieu
0 siblings, 0 replies; 21+ messages in thread
From: Francois Romieu @ 2013-01-30 22:02 UTC (permalink / raw)
To: linux-arm-kernel
Mugunthan V N <mugunthanvnm@ti.com> :
[...]
> diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
> index 0e9ccc2..18b88ce 100644
> --- a/drivers/net/ethernet/ti/cpsw_ale.c
> +++ b/drivers/net/ethernet/ti/cpsw_ale.c
[...]
> @@ -274,19 +292,26 @@ int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
> return 0;
> }
>
> -int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
> +int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
> + int flags, u16 vid)
> {
> u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
> int idx;
>
> - cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
> + if (flags & ALE_VLAN) {
> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
> + cpsw_ale_set_vlan_id(ale_entry, vid);
> + } else {
> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
> + }
> +
[...]
> + if (flags & ALE_VLAN) {
> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
> + cpsw_ale_set_vlan_id(ale_entry, vid);
> + } else {
> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
> + }
> +
It could be fctored out.
[...]
> @@ -362,6 +395,55 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
> return 0;
> }
>
> +int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
> + int reg_mcast, int unreg_mcast)
> +{
[...]
> +int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
[...]
Patch #2 doesn't use the returned status code.
--
Ueimor
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 2/2] drivers: net:ethernet: cpsw: add support for VLAN
2013-01-30 19:07 ` Mugunthan V N
@ 2013-01-30 22:02 ` Francois Romieu
-1 siblings, 0 replies; 21+ messages in thread
From: Francois Romieu @ 2013-01-30 22:02 UTC (permalink / raw)
To: Mugunthan V N; +Cc: netdev, davem, linux-arm-kernel, linux-omap
Mugunthan V N <mugunthanvnm@ti.com> :
[...]
> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
> index 6ddd028..99696bf 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
> +- default_vlan : Specifies Default VLAN for non tagged packets
> + ALE processing
Isn't it a device-tree hack for what should belong to a common API ?
[...]
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index a40750e..6c66f01 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
[...]
> @@ -607,14 +611,41 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
> }
> }
>
> +static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
> +{
> + writel(priv->data.default_vlan, &priv->host_port_regs->port_vlan);
> + if (priv->version == CPSW_VERSION_1) {
> + slave_write(&priv->slaves[0], priv->data.default_vlan,
> + CPSW1_PORT_VLAN);
> + slave_write(&priv->slaves[1], priv->data.default_vlan,
> + CPSW1_PORT_VLAN);
> + } else {
> + slave_write(&priv->slaves[0], priv->data.default_vlan,
> + CPSW2_PORT_VLAN);
> + slave_write(&priv->slaves[1], priv->data.default_vlan,
> + CPSW2_PORT_VLAN);
> + }
> + cpsw_ale_add_vlan(priv->ale, priv->data.default_vlan,
> + ALE_ALL_PORTS << priv->host_port,
> + ALE_ALL_PORTS << priv->host_port,
> + ALE_ALL_PORTS << priv->host_port,
> + (BIT(1) | BIT(2)) << priv->host_port);
> +}
static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
{
const int vlan = priv->data.default_vlan;
const int port = priv->host_port;
u32 reg;
int i;
reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN :
CPSW2_PORT_VLAN;
writel(vlan, &priv->host_port_regs->port_vlan);
for (int i = 0; i < 2; i++)
slave_write(priv->slaves + i, vlan, reg);
cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port,
ALE_ALL_PORTS << port, ALE_ALL_PORTS << port,
(BIT(1) | BIT(2)) << port);
}
... or somewhere between both. Your call.
[...]
> @@ -933,6 +967,55 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
> }
> #endif
>
> +static inline void cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
> + unsigned short vid)
> +{
> + cpsw_ale_add_vlan(priv->ale, vid, ALE_ALL_PORTS << priv->host_port,
> + 0, ALE_ALL_PORTS << priv->host_port,
> + (BIT(1) | BIT(2)) << priv->host_port);
"(BIT(1) | BIT(2))" is repeated a couple of times.
[...]
> +static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev,
> + unsigned short vid)
> +{
> + struct cpsw_priv *priv = netdev_priv(ndev);
> +
> + if (vid == priv->data.default_vlan)
> + return 0;
> +
> + spin_lock(&priv->lock);
> +
> + dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid);
> + cpsw_add_vlan_ale_entry(priv, vid);
> +
> + spin_unlock(&priv->lock);
> + return 0;
> +}
> +
> +static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
> + unsigned short vid)
> +{
> + struct cpsw_priv *priv = netdev_priv(ndev);
> +
> + if (vid == priv->data.default_vlan)
> + return 0;
> +
> + spin_lock(&priv->lock);
> +
> + dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid);
> + cpsw_ale_del_vlan(priv->ale, vid, 0);
> + cpsw_ale_del_ucast(priv->ale, priv->mac_addr,
> + priv->host_port, ALE_VLAN, vid);
> + cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast, 0, ALE_VLAN, vid);
> +
> + spin_unlock(&priv->lock);
What are you trying to achieve with the lock ?
It is not used anywhere else and both cpsw_ndo_vlan_rx_{add, kill}_vid are
called under RTNL.
--
Ueimor
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 2/2] drivers: net:ethernet: cpsw: add support for VLAN
@ 2013-01-30 22:02 ` Francois Romieu
0 siblings, 0 replies; 21+ messages in thread
From: Francois Romieu @ 2013-01-30 22:02 UTC (permalink / raw)
To: linux-arm-kernel
Mugunthan V N <mugunthanvnm@ti.com> :
[...]
> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
> index 6ddd028..99696bf 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
> +- default_vlan : Specifies Default VLAN for non tagged packets
> + ALE processing
Isn't it a device-tree hack for what should belong to a common API ?
[...]
> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
> index a40750e..6c66f01 100644
> --- a/drivers/net/ethernet/ti/cpsw.c
> +++ b/drivers/net/ethernet/ti/cpsw.c
[...]
> @@ -607,14 +611,41 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
> }
> }
>
> +static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
> +{
> + writel(priv->data.default_vlan, &priv->host_port_regs->port_vlan);
> + if (priv->version == CPSW_VERSION_1) {
> + slave_write(&priv->slaves[0], priv->data.default_vlan,
> + CPSW1_PORT_VLAN);
> + slave_write(&priv->slaves[1], priv->data.default_vlan,
> + CPSW1_PORT_VLAN);
> + } else {
> + slave_write(&priv->slaves[0], priv->data.default_vlan,
> + CPSW2_PORT_VLAN);
> + slave_write(&priv->slaves[1], priv->data.default_vlan,
> + CPSW2_PORT_VLAN);
> + }
> + cpsw_ale_add_vlan(priv->ale, priv->data.default_vlan,
> + ALE_ALL_PORTS << priv->host_port,
> + ALE_ALL_PORTS << priv->host_port,
> + ALE_ALL_PORTS << priv->host_port,
> + (BIT(1) | BIT(2)) << priv->host_port);
> +}
static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
{
const int vlan = priv->data.default_vlan;
const int port = priv->host_port;
u32 reg;
int i;
reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN :
CPSW2_PORT_VLAN;
writel(vlan, &priv->host_port_regs->port_vlan);
for (int i = 0; i < 2; i++)
slave_write(priv->slaves + i, vlan, reg);
cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port,
ALE_ALL_PORTS << port, ALE_ALL_PORTS << port,
(BIT(1) | BIT(2)) << port);
}
... or somewhere between both. Your call.
[...]
> @@ -933,6 +967,55 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
> }
> #endif
>
> +static inline void cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
> + unsigned short vid)
> +{
> + cpsw_ale_add_vlan(priv->ale, vid, ALE_ALL_PORTS << priv->host_port,
> + 0, ALE_ALL_PORTS << priv->host_port,
> + (BIT(1) | BIT(2)) << priv->host_port);
"(BIT(1) | BIT(2))" is repeated a couple of times.
[...]
> +static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev,
> + unsigned short vid)
> +{
> + struct cpsw_priv *priv = netdev_priv(ndev);
> +
> + if (vid == priv->data.default_vlan)
> + return 0;
> +
> + spin_lock(&priv->lock);
> +
> + dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid);
> + cpsw_add_vlan_ale_entry(priv, vid);
> +
> + spin_unlock(&priv->lock);
> + return 0;
> +}
> +
> +static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
> + unsigned short vid)
> +{
> + struct cpsw_priv *priv = netdev_priv(ndev);
> +
> + if (vid == priv->data.default_vlan)
> + return 0;
> +
> + spin_lock(&priv->lock);
> +
> + dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid);
> + cpsw_ale_del_vlan(priv->ale, vid, 0);
> + cpsw_ale_del_ucast(priv->ale, priv->mac_addr,
> + priv->host_port, ALE_VLAN, vid);
> + cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast, 0, ALE_VLAN, vid);
> +
> + spin_unlock(&priv->lock);
What are you trying to achieve with the lock ?
It is not used anywhere else and both cpsw_ndo_vlan_rx_{add, kill}_vid are
called under RTNL.
--
Ueimor
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation
2013-01-30 22:02 ` Francois Romieu
(?)
@ 2013-01-31 11:09 ` Mugunthan V N
-1 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-31 11:09 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, davem, linux-arm-kernel, linux-omap
On 1/31/2013 3:32 AM, Francois Romieu wrote:
> Mugunthan V N <mugunthanvnm@ti.com> :
> [...]
>> diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
>> index 0e9ccc2..18b88ce 100644
>> --- a/drivers/net/ethernet/ti/cpsw_ale.c
>> +++ b/drivers/net/ethernet/ti/cpsw_ale.c
> [...]
>> @@ -274,19 +292,26 @@ int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
>> return 0;
>> }
>>
>> -int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
>> +int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
>> + int flags, u16 vid)
>> {
>> u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
>> int idx;
>>
>> - cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
>> + if (flags & ALE_VLAN) {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
>> + cpsw_ale_set_vlan_id(ale_entry, vid);
>> + } else {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
>> + }
>> +
> [...]
>> + if (flags & ALE_VLAN) {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
>> + cpsw_ale_set_vlan_id(ale_entry, vid);
>> + } else {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
>> + }
>> +
> It could be fctored out.
Are you mentioning to have static inline function for the above two
statements above?
>
> [...]
>> @@ -362,6 +395,55 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
>> return 0;
>> }
>>
>> +int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
>> + int reg_mcast, int unreg_mcast)
>> +{
> [...]
>> +int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
> [...]
>
> Patch #2 doesn't use the returned status code.
Will modify the prototype to return void
Regards
Mugunthan V N
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation
@ 2013-01-31 11:09 ` Mugunthan V N
0 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-31 11:09 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, davem, linux-arm-kernel, linux-omap
On 1/31/2013 3:32 AM, Francois Romieu wrote:
> Mugunthan V N <mugunthanvnm@ti.com> :
> [...]
>> diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
>> index 0e9ccc2..18b88ce 100644
>> --- a/drivers/net/ethernet/ti/cpsw_ale.c
>> +++ b/drivers/net/ethernet/ti/cpsw_ale.c
> [...]
>> @@ -274,19 +292,26 @@ int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
>> return 0;
>> }
>>
>> -int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
>> +int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
>> + int flags, u16 vid)
>> {
>> u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
>> int idx;
>>
>> - cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
>> + if (flags & ALE_VLAN) {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
>> + cpsw_ale_set_vlan_id(ale_entry, vid);
>> + } else {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
>> + }
>> +
> [...]
>> + if (flags & ALE_VLAN) {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
>> + cpsw_ale_set_vlan_id(ale_entry, vid);
>> + } else {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
>> + }
>> +
> It could be fctored out.
Are you mentioning to have static inline function for the above two
statements above?
>
> [...]
>> @@ -362,6 +395,55 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
>> return 0;
>> }
>>
>> +int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
>> + int reg_mcast, int unreg_mcast)
>> +{
> [...]
>> +int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
> [...]
>
> Patch #2 doesn't use the returned status code.
Will modify the prototype to return void
Regards
Mugunthan V N
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation
@ 2013-01-31 11:09 ` Mugunthan V N
0 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-31 11:09 UTC (permalink / raw)
To: linux-arm-kernel
On 1/31/2013 3:32 AM, Francois Romieu wrote:
> Mugunthan V N <mugunthanvnm@ti.com> :
> [...]
>> diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
>> index 0e9ccc2..18b88ce 100644
>> --- a/drivers/net/ethernet/ti/cpsw_ale.c
>> +++ b/drivers/net/ethernet/ti/cpsw_ale.c
> [...]
>> @@ -274,19 +292,26 @@ int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
>> return 0;
>> }
>>
>> -int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
>> +int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
>> + int flags, u16 vid)
>> {
>> u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
>> int idx;
>>
>> - cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
>> + if (flags & ALE_VLAN) {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
>> + cpsw_ale_set_vlan_id(ale_entry, vid);
>> + } else {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
>> + }
>> +
> [...]
>> + if (flags & ALE_VLAN) {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
>> + cpsw_ale_set_vlan_id(ale_entry, vid);
>> + } else {
>> + cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
>> + }
>> +
> It could be fctored out.
Are you mentioning to have static inline function for the above two
statements above?
>
> [...]
>> @@ -362,6 +395,55 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
>> return 0;
>> }
>>
>> +int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
>> + int reg_mcast, int unreg_mcast)
>> +{
> [...]
>> +int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
> [...]
>
> Patch #2 doesn't use the returned status code.
Will modify the prototype to return void
Regards
Mugunthan V N
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 2/2] drivers: net:ethernet: cpsw: add support for VLAN
2013-01-30 22:02 ` Francois Romieu
(?)
@ 2013-01-31 11:09 ` Mugunthan V N
-1 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-31 11:09 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, davem, linux-arm-kernel, linux-omap
On 1/31/2013 3:32 AM, Francois Romieu wrote:
> Mugunthan V N <mugunthanvnm@ti.com> :
> [...]
>> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
>> index 6ddd028..99696bf 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
>> +- default_vlan : Specifies Default VLAN for non tagged packets
>> + ALE processing
> Isn't it a device-tree hack for what should belong to a common API ?
Its a hardware feature which stack will not be aware of. It is used in
the ALE filtering
process with a non-tagged packet arrives.
>
> [...]
>> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
>> index a40750e..6c66f01 100644
>> --- a/drivers/net/ethernet/ti/cpsw.c
>> +++ b/drivers/net/ethernet/ti/cpsw.c
> [...]
>> @@ -607,14 +611,41 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
>> }
>> }
>>
>> +static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
>> +{
>> + writel(priv->data.default_vlan, &priv->host_port_regs->port_vlan);
>> + if (priv->version == CPSW_VERSION_1) {
>> + slave_write(&priv->slaves[0], priv->data.default_vlan,
>> + CPSW1_PORT_VLAN);
>> + slave_write(&priv->slaves[1], priv->data.default_vlan,
>> + CPSW1_PORT_VLAN);
>> + } else {
>> + slave_write(&priv->slaves[0], priv->data.default_vlan,
>> + CPSW2_PORT_VLAN);
>> + slave_write(&priv->slaves[1], priv->data.default_vlan,
>> + CPSW2_PORT_VLAN);
>> + }
>> + cpsw_ale_add_vlan(priv->ale, priv->data.default_vlan,
>> + ALE_ALL_PORTS << priv->host_port,
>> + ALE_ALL_PORTS << priv->host_port,
>> + ALE_ALL_PORTS << priv->host_port,
>> + (BIT(1) | BIT(2)) << priv->host_port);
>> +}
> static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
> {
> const int vlan = priv->data.default_vlan;
> const int port = priv->host_port;
> u32 reg;
> int i;
>
> reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN :
> CPSW2_PORT_VLAN;
>
> writel(vlan, &priv->host_port_regs->port_vlan);
>
> for (int i = 0; i < 2; i++)
> slave_write(priv->slaves + i, vlan, reg);
>
> cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port,
> ALE_ALL_PORTS << port, ALE_ALL_PORTS << port,
> (BIT(1) | BIT(2)) << port);
> }
>
> ... or somewhere between both. Your call.
Will modify the code as this looks simpler
>
> [...]
>> @@ -933,6 +967,55 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
>> }
>> #endif
>>
>> +static inline void cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
>> + unsigned short vid)
>> +{
>> + cpsw_ale_add_vlan(priv->ale, vid, ALE_ALL_PORTS << priv->host_port,
>> + 0, ALE_ALL_PORTS << priv->host_port,
>> + (BIT(1) | BIT(2)) << priv->host_port);
> "(BIT(1) | BIT(2))" is repeated a couple of times.
Will replace with port number defines.
>
> [...]
>> +static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev,
>> + unsigned short vid)
>> +{
>> + struct cpsw_priv *priv = netdev_priv(ndev);
>> +
>> + if (vid == priv->data.default_vlan)
>> + return 0;
>> +
>> + spin_lock(&priv->lock);
>> +
>> + dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid);
>> + cpsw_add_vlan_ale_entry(priv, vid);
>> +
>> + spin_unlock(&priv->lock);
>> + return 0;
>> +}
>> +
>> +static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
>> + unsigned short vid)
>> +{
>> + struct cpsw_priv *priv = netdev_priv(ndev);
>> +
>> + if (vid == priv->data.default_vlan)
>> + return 0;
>> +
>> + spin_lock(&priv->lock);
>> +
>> + dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid);
>> + cpsw_ale_del_vlan(priv->ale, vid, 0);
>> + cpsw_ale_del_ucast(priv->ale, priv->mac_addr,
>> + priv->host_port, ALE_VLAN, vid);
>> + cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast, 0, ALE_VLAN, vid);
>> +
>> + spin_unlock(&priv->lock);
> What are you trying to achieve with the lock ?
>
> It is not used anywhere else and both cpsw_ndo_vlan_rx_{add, kill}_vid are
> called under RTNL.
Will remove the lock from both apis
Regards
Mugunthan V N
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 2/2] drivers: net:ethernet: cpsw: add support for VLAN
@ 2013-01-31 11:09 ` Mugunthan V N
0 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-31 11:09 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev, davem, linux-arm-kernel, linux-omap
On 1/31/2013 3:32 AM, Francois Romieu wrote:
> Mugunthan V N <mugunthanvnm@ti.com> :
> [...]
>> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
>> index 6ddd028..99696bf 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
>> +- default_vlan : Specifies Default VLAN for non tagged packets
>> + ALE processing
> Isn't it a device-tree hack for what should belong to a common API ?
Its a hardware feature which stack will not be aware of. It is used in
the ALE filtering
process with a non-tagged packet arrives.
>
> [...]
>> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
>> index a40750e..6c66f01 100644
>> --- a/drivers/net/ethernet/ti/cpsw.c
>> +++ b/drivers/net/ethernet/ti/cpsw.c
> [...]
>> @@ -607,14 +611,41 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
>> }
>> }
>>
>> +static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
>> +{
>> + writel(priv->data.default_vlan, &priv->host_port_regs->port_vlan);
>> + if (priv->version == CPSW_VERSION_1) {
>> + slave_write(&priv->slaves[0], priv->data.default_vlan,
>> + CPSW1_PORT_VLAN);
>> + slave_write(&priv->slaves[1], priv->data.default_vlan,
>> + CPSW1_PORT_VLAN);
>> + } else {
>> + slave_write(&priv->slaves[0], priv->data.default_vlan,
>> + CPSW2_PORT_VLAN);
>> + slave_write(&priv->slaves[1], priv->data.default_vlan,
>> + CPSW2_PORT_VLAN);
>> + }
>> + cpsw_ale_add_vlan(priv->ale, priv->data.default_vlan,
>> + ALE_ALL_PORTS << priv->host_port,
>> + ALE_ALL_PORTS << priv->host_port,
>> + ALE_ALL_PORTS << priv->host_port,
>> + (BIT(1) | BIT(2)) << priv->host_port);
>> +}
> static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
> {
> const int vlan = priv->data.default_vlan;
> const int port = priv->host_port;
> u32 reg;
> int i;
>
> reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN :
> CPSW2_PORT_VLAN;
>
> writel(vlan, &priv->host_port_regs->port_vlan);
>
> for (int i = 0; i < 2; i++)
> slave_write(priv->slaves + i, vlan, reg);
>
> cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port,
> ALE_ALL_PORTS << port, ALE_ALL_PORTS << port,
> (BIT(1) | BIT(2)) << port);
> }
>
> ... or somewhere between both. Your call.
Will modify the code as this looks simpler
>
> [...]
>> @@ -933,6 +967,55 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
>> }
>> #endif
>>
>> +static inline void cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
>> + unsigned short vid)
>> +{
>> + cpsw_ale_add_vlan(priv->ale, vid, ALE_ALL_PORTS << priv->host_port,
>> + 0, ALE_ALL_PORTS << priv->host_port,
>> + (BIT(1) | BIT(2)) << priv->host_port);
> "(BIT(1) | BIT(2))" is repeated a couple of times.
Will replace with port number defines.
>
> [...]
>> +static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev,
>> + unsigned short vid)
>> +{
>> + struct cpsw_priv *priv = netdev_priv(ndev);
>> +
>> + if (vid == priv->data.default_vlan)
>> + return 0;
>> +
>> + spin_lock(&priv->lock);
>> +
>> + dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid);
>> + cpsw_add_vlan_ale_entry(priv, vid);
>> +
>> + spin_unlock(&priv->lock);
>> + return 0;
>> +}
>> +
>> +static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
>> + unsigned short vid)
>> +{
>> + struct cpsw_priv *priv = netdev_priv(ndev);
>> +
>> + if (vid == priv->data.default_vlan)
>> + return 0;
>> +
>> + spin_lock(&priv->lock);
>> +
>> + dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid);
>> + cpsw_ale_del_vlan(priv->ale, vid, 0);
>> + cpsw_ale_del_ucast(priv->ale, priv->mac_addr,
>> + priv->host_port, ALE_VLAN, vid);
>> + cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast, 0, ALE_VLAN, vid);
>> +
>> + spin_unlock(&priv->lock);
> What are you trying to achieve with the lock ?
>
> It is not used anywhere else and both cpsw_ndo_vlan_rx_{add, kill}_vid are
> called under RTNL.
Will remove the lock from both apis
Regards
Mugunthan V N
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 2/2] drivers: net:ethernet: cpsw: add support for VLAN
@ 2013-01-31 11:09 ` Mugunthan V N
0 siblings, 0 replies; 21+ messages in thread
From: Mugunthan V N @ 2013-01-31 11:09 UTC (permalink / raw)
To: linux-arm-kernel
On 1/31/2013 3:32 AM, Francois Romieu wrote:
> Mugunthan V N <mugunthanvnm@ti.com> :
> [...]
>> diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt
>> index 6ddd028..99696bf 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
>> +- default_vlan : Specifies Default VLAN for non tagged packets
>> + ALE processing
> Isn't it a device-tree hack for what should belong to a common API ?
Its a hardware feature which stack will not be aware of. It is used in
the ALE filtering
process with a non-tagged packet arrives.
>
> [...]
>> diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
>> index a40750e..6c66f01 100644
>> --- a/drivers/net/ethernet/ti/cpsw.c
>> +++ b/drivers/net/ethernet/ti/cpsw.c
> [...]
>> @@ -607,14 +611,41 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
>> }
>> }
>>
>> +static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
>> +{
>> + writel(priv->data.default_vlan, &priv->host_port_regs->port_vlan);
>> + if (priv->version == CPSW_VERSION_1) {
>> + slave_write(&priv->slaves[0], priv->data.default_vlan,
>> + CPSW1_PORT_VLAN);
>> + slave_write(&priv->slaves[1], priv->data.default_vlan,
>> + CPSW1_PORT_VLAN);
>> + } else {
>> + slave_write(&priv->slaves[0], priv->data.default_vlan,
>> + CPSW2_PORT_VLAN);
>> + slave_write(&priv->slaves[1], priv->data.default_vlan,
>> + CPSW2_PORT_VLAN);
>> + }
>> + cpsw_ale_add_vlan(priv->ale, priv->data.default_vlan,
>> + ALE_ALL_PORTS << priv->host_port,
>> + ALE_ALL_PORTS << priv->host_port,
>> + ALE_ALL_PORTS << priv->host_port,
>> + (BIT(1) | BIT(2)) << priv->host_port);
>> +}
> static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
> {
> const int vlan = priv->data.default_vlan;
> const int port = priv->host_port;
> u32 reg;
> int i;
>
> reg = (priv->version == CPSW_VERSION_1) ? CPSW1_PORT_VLAN :
> CPSW2_PORT_VLAN;
>
> writel(vlan, &priv->host_port_regs->port_vlan);
>
> for (int i = 0; i < 2; i++)
> slave_write(priv->slaves + i, vlan, reg);
>
> cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port,
> ALE_ALL_PORTS << port, ALE_ALL_PORTS << port,
> (BIT(1) | BIT(2)) << port);
> }
>
> ... or somewhere between both. Your call.
Will modify the code as this looks simpler
>
> [...]
>> @@ -933,6 +967,55 @@ static void cpsw_ndo_poll_controller(struct net_device *ndev)
>> }
>> #endif
>>
>> +static inline void cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
>> + unsigned short vid)
>> +{
>> + cpsw_ale_add_vlan(priv->ale, vid, ALE_ALL_PORTS << priv->host_port,
>> + 0, ALE_ALL_PORTS << priv->host_port,
>> + (BIT(1) | BIT(2)) << priv->host_port);
> "(BIT(1) | BIT(2))" is repeated a couple of times.
Will replace with port number defines.
>
> [...]
>> +static int cpsw_ndo_vlan_rx_add_vid(struct net_device *ndev,
>> + unsigned short vid)
>> +{
>> + struct cpsw_priv *priv = netdev_priv(ndev);
>> +
>> + if (vid == priv->data.default_vlan)
>> + return 0;
>> +
>> + spin_lock(&priv->lock);
>> +
>> + dev_info(priv->dev, "Adding vlanid %d to vlan filter\n", vid);
>> + cpsw_add_vlan_ale_entry(priv, vid);
>> +
>> + spin_unlock(&priv->lock);
>> + return 0;
>> +}
>> +
>> +static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev,
>> + unsigned short vid)
>> +{
>> + struct cpsw_priv *priv = netdev_priv(ndev);
>> +
>> + if (vid == priv->data.default_vlan)
>> + return 0;
>> +
>> + spin_lock(&priv->lock);
>> +
>> + dev_info(priv->dev, "removing vlanid %d from vlan filter\n", vid);
>> + cpsw_ale_del_vlan(priv->ale, vid, 0);
>> + cpsw_ale_del_ucast(priv->ale, priv->mac_addr,
>> + priv->host_port, ALE_VLAN, vid);
>> + cpsw_ale_del_mcast(priv->ale, priv->ndev->broadcast, 0, ALE_VLAN, vid);
>> +
>> + spin_unlock(&priv->lock);
> What are you trying to achieve with the lock ?
>
> It is not used anywhere else and both cpsw_ndo_vlan_rx_{add, kill}_vid are
> called under RTNL.
Will remove the lock from both apis
Regards
Mugunthan V N
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation
2013-01-31 11:09 ` Mugunthan V N
@ 2013-01-31 21:43 ` Francois Romieu
-1 siblings, 0 replies; 21+ messages in thread
From: Francois Romieu @ 2013-01-31 21:43 UTC (permalink / raw)
To: Mugunthan V N; +Cc: netdev, davem, linux-arm-kernel, linux-omap
Mugunthan V N <mugunthanvnm@ti.com> :
> On 1/31/2013 3:32 AM, Francois Romieu wrote:
[...]
> > It could be factored out.
> Are you mentioning to have static inline function for the above two
> statements above?
Yes. The helper function does not need to be inlined if it does not
save space: this path is not performance critical.
[...]
> >Patch #2 doesn't use the returned status code.
> Will modify the prototype to return void
:o(
The driver should notify the upper layers that the request failed instead
of hiding the stuff under the carpet.
--
Ueimor
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation
@ 2013-01-31 21:43 ` Francois Romieu
0 siblings, 0 replies; 21+ messages in thread
From: Francois Romieu @ 2013-01-31 21:43 UTC (permalink / raw)
To: linux-arm-kernel
Mugunthan V N <mugunthanvnm@ti.com> :
> On 1/31/2013 3:32 AM, Francois Romieu wrote:
[...]
> > It could be factored out.
> Are you mentioning to have static inline function for the above two
> statements above?
Yes. The helper function does not need to be inlined if it does not
save space: this path is not performance critical.
[...]
> >Patch #2 doesn't use the returned status code.
> Will modify the prototype to return void
:o(
The driver should notify the upper layers that the request failed instead
of hiding the stuff under the carpet.
--
Ueimor
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2013-01-31 21:43 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-30 19:07 [PATCH v2 0/2] Add CPSW VLAN Support Mugunthan V N
2013-01-30 19:07 ` Mugunthan V N
2013-01-30 19:07 ` Mugunthan V N
2013-01-30 19:07 ` [PATCH v2 1/2] drivers: net: cpsw: Add helper functions for VLAN ALE implementation Mugunthan V N
2013-01-30 19:07 ` Mugunthan V N
2013-01-30 19:07 ` Mugunthan V N
2013-01-30 22:02 ` Francois Romieu
2013-01-30 22:02 ` Francois Romieu
2013-01-31 11:09 ` Mugunthan V N
2013-01-31 11:09 ` Mugunthan V N
2013-01-31 11:09 ` Mugunthan V N
2013-01-31 21:43 ` Francois Romieu
2013-01-31 21:43 ` Francois Romieu
2013-01-30 19:07 ` [PATCH v2 2/2] drivers: net:ethernet: cpsw: add support for VLAN Mugunthan V N
2013-01-30 19:07 ` Mugunthan V N
2013-01-30 19:07 ` Mugunthan V N
2013-01-30 22:02 ` Francois Romieu
2013-01-30 22:02 ` Francois Romieu
2013-01-31 11:09 ` Mugunthan V N
2013-01-31 11:09 ` Mugunthan V N
2013-01-31 11:09 ` Mugunthan V N
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.