aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMugunthan V N <mugunthanvnm@ti.com>2013-02-05 03:26:47 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-06 15:46:40 -0500
commite11b220f336c654db876027d40953acef90b0cae (patch)
tree1621d2e2acd1cd6432e36c34ef5bffb5476727c2
parentca99ca14c95ae49fb4c9cd3abf5f84d11a7e8a61 (diff)
drivers: net: cpsw: Add helper functions for VLAN ALE implementation
Add helper functions for VLAN ALE implementations for Add, Delete Dump VLAN related ALE entries Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/ti/cpsw.c8
-rw-r--r--drivers/net/ethernet/ti/cpsw_ale.c107
-rw-r--r--drivers/net/ethernet/ti/cpsw_ale.h20
3 files changed, 113 insertions, 22 deletions
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 9e63bff124fe..534bf7bc34db 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)
345 /* program multicast address list into ALE register */ 345 /* program multicast address list into ALE register */
346 netdev_for_each_mc_addr(ha, ndev) { 346 netdev_for_each_mc_addr(ha, ndev) {
347 cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr, 347 cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr,
348 ALE_ALL_PORTS << priv->host_port, 0, 0); 348 ALE_ALL_PORTS << priv->host_port, 0, 0, 0);
349 } 349 }
350 } 350 }
351} 351}
@@ -592,7 +592,7 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
592 slave_port = cpsw_get_slave_port(priv, slave->slave_num); 592 slave_port = cpsw_get_slave_port(priv, slave->slave_num);
593 593
594 cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, 594 cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
595 1 << slave_port, 0, ALE_MCAST_FWD_2); 595 1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
596 596
597 slave->phy = phy_connect(priv->ndev, slave->data->phy_id, 597 slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
598 &cpsw_adjust_link, slave->data->phy_if); 598 &cpsw_adjust_link, slave->data->phy_if);
@@ -624,9 +624,9 @@ static void cpsw_init_host_port(struct cpsw_priv *priv)
624 cpsw_ale_control_set(priv->ale, priv->host_port, 624 cpsw_ale_control_set(priv->ale, priv->host_port,
625 ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); 625 ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
626 626
627 cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 0); 627 cpsw_ale_add_ucast(priv->ale, priv->mac_addr, priv->host_port, 0, 0);
628 cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast, 628 cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
629 1 << priv->host_port, 0, ALE_MCAST_FWD_2); 629 1 << priv->host_port, 0, 0, ALE_MCAST_FWD_2);
630} 630}
631 631
632static int cpsw_ndo_open(struct net_device *ndev) 632static 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 0e9ccc2cf91f..7fa60d6092ed 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)
148 return idx; 148 return idx;
149} 149}
150 150
151static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr) 151int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr, u16 vid)
152{ 152{
153 u32 ale_entry[ALE_ENTRY_WORDS]; 153 u32 ale_entry[ALE_ENTRY_WORDS];
154 int type, idx; 154 int type, idx;
@@ -160,6 +160,8 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
160 type = cpsw_ale_get_entry_type(ale_entry); 160 type = cpsw_ale_get_entry_type(ale_entry);
161 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR) 161 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
162 continue; 162 continue;
163 if (cpsw_ale_get_vlan_id(ale_entry) != vid)
164 continue;
163 cpsw_ale_get_addr(ale_entry, entry_addr); 165 cpsw_ale_get_addr(ale_entry, entry_addr);
164 if (memcmp(entry_addr, addr, 6) == 0) 166 if (memcmp(entry_addr, addr, 6) == 0)
165 return idx; 167 return idx;
@@ -167,6 +169,22 @@ static int cpsw_ale_match_addr(struct cpsw_ale *ale, u8 *addr)
167 return -ENOENT; 169 return -ENOENT;
168} 170}
169 171
172int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
173{
174 u32 ale_entry[ALE_ENTRY_WORDS];
175 int type, idx;
176
177 for (idx = 0; idx < ale->params.ale_entries; idx++) {
178 cpsw_ale_read(ale, idx, ale_entry);
179 type = cpsw_ale_get_entry_type(ale_entry);
180 if (type != ALE_TYPE_VLAN)
181 continue;
182 if (cpsw_ale_get_vlan_id(ale_entry) == vid)
183 return idx;
184 }
185 return -ENOENT;
186}
187
170static int cpsw_ale_match_free(struct cpsw_ale *ale) 188static int cpsw_ale_match_free(struct cpsw_ale *ale)
171{ 189{
172 u32 ale_entry[ALE_ENTRY_WORDS]; 190 u32 ale_entry[ALE_ENTRY_WORDS];
@@ -274,19 +292,32 @@ int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask)
274 return 0; 292 return 0;
275} 293}
276 294
277int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags) 295static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
296 int flags, u16 vid)
297{
298 if (flags & ALE_VLAN) {
299 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
300 cpsw_ale_set_vlan_id(ale_entry, vid);
301 } else {
302 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
303 }
304}
305
306int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
307 int flags, u16 vid)
278{ 308{
279 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 309 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
280 int idx; 310 int idx;
281 311
282 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR); 312 cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
313
283 cpsw_ale_set_addr(ale_entry, addr); 314 cpsw_ale_set_addr(ale_entry, addr);
284 cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT); 315 cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
285 cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0); 316 cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
286 cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0); 317 cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
287 cpsw_ale_set_port_num(ale_entry, port); 318 cpsw_ale_set_port_num(ale_entry, port);
288 319
289 idx = cpsw_ale_match_addr(ale, addr); 320 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
290 if (idx < 0) 321 if (idx < 0)
291 idx = cpsw_ale_match_free(ale); 322 idx = cpsw_ale_match_free(ale);
292 if (idx < 0) 323 if (idx < 0)
@@ -298,12 +329,13 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags)
298 return 0; 329 return 0;
299} 330}
300 331
301int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port) 332int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
333 int flags, u16 vid)
302{ 334{
303 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 335 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
304 int idx; 336 int idx;
305 337
306 idx = cpsw_ale_match_addr(ale, addr); 338 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
307 if (idx < 0) 339 if (idx < 0)
308 return -ENOENT; 340 return -ENOENT;
309 341
@@ -313,18 +345,19 @@ int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port)
313} 345}
314 346
315int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask, 347int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
316 int super, int mcast_state) 348 int flags, u16 vid, int mcast_state)
317{ 349{
318 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 350 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
319 int idx, mask; 351 int idx, mask;
320 352
321 idx = cpsw_ale_match_addr(ale, addr); 353 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
322 if (idx >= 0) 354 if (idx >= 0)
323 cpsw_ale_read(ale, idx, ale_entry); 355 cpsw_ale_read(ale, idx, ale_entry);
324 356
325 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR); 357 cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
358
326 cpsw_ale_set_addr(ale_entry, addr); 359 cpsw_ale_set_addr(ale_entry, addr);
327 cpsw_ale_set_super(ale_entry, super); 360 cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
328 cpsw_ale_set_mcast_state(ale_entry, mcast_state); 361 cpsw_ale_set_mcast_state(ale_entry, mcast_state);
329 362
330 mask = cpsw_ale_get_port_mask(ale_entry); 363 mask = cpsw_ale_get_port_mask(ale_entry);
@@ -342,12 +375,13 @@ int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
342 return 0; 375 return 0;
343} 376}
344 377
345int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask) 378int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
379 int flags, u16 vid)
346{ 380{
347 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0}; 381 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
348 int idx; 382 int idx;
349 383
350 idx = cpsw_ale_match_addr(ale, addr); 384 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
351 if (idx < 0) 385 if (idx < 0)
352 return -EINVAL; 386 return -EINVAL;
353 387
@@ -362,6 +396,55 @@ int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask)
362 return 0; 396 return 0;
363} 397}
364 398
399int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
400 int reg_mcast, int unreg_mcast)
401{
402 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
403 int idx;
404
405 idx = cpsw_ale_match_vlan(ale, vid);
406 if (idx >= 0)
407 cpsw_ale_read(ale, idx, ale_entry);
408
409 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
410 cpsw_ale_set_vlan_id(ale_entry, vid);
411
412 cpsw_ale_set_vlan_untag_force(ale_entry, untag);
413 cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast);
414 cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast);
415 cpsw_ale_set_vlan_member_list(ale_entry, port);
416
417 if (idx < 0)
418 idx = cpsw_ale_match_free(ale);
419 if (idx < 0)
420 idx = cpsw_ale_find_ageable(ale);
421 if (idx < 0)
422 return -ENOMEM;
423
424 cpsw_ale_write(ale, idx, ale_entry);
425 return 0;
426}
427
428int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
429{
430 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
431 int idx;
432
433 idx = cpsw_ale_match_vlan(ale, vid);
434 if (idx < 0)
435 return -ENOENT;
436
437 cpsw_ale_read(ale, idx, ale_entry);
438
439 if (port_mask)
440 cpsw_ale_set_vlan_member_list(ale_entry, port_mask);
441 else
442 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
443
444 cpsw_ale_write(ale, idx, ale_entry);
445 return 0;
446}
447
365struct ale_control_info { 448struct ale_control_info {
366 const char *name; 449 const char *name;
367 int offset, port_offset; 450 int offset, port_offset;
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index 2bd09cbce522..a002417f952b 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 {
64}; 64};
65 65
66/* ALE unicast entry flags - passed into cpsw_ale_add_ucast() */ 66/* ALE unicast entry flags - passed into cpsw_ale_add_ucast() */
67#define ALE_SECURE 1 67#define ALE_SECURE BIT(0)
68#define ALE_BLOCKED 2 68#define ALE_BLOCKED BIT(1)
69#define ALE_SUPER BIT(2)
70#define ALE_VLAN BIT(3)
69 71
70#define ALE_MCAST_FWD 0 72#define ALE_MCAST_FWD 0
71#define ALE_MCAST_BLOCK_LEARN_FWD 1 73#define ALE_MCAST_BLOCK_LEARN_FWD 1
@@ -81,11 +83,17 @@ void cpsw_ale_stop(struct cpsw_ale *ale);
81int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout); 83int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout);
82int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask); 84int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask);
83int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask); 85int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask);
84int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags); 86int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port,
85int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port); 87 int flags, u16 vid);
88int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port,
89 int flags, u16 vid);
86int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask, 90int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
87 int super, int mcast_state); 91 int flags, u16 vid, int mcast_state);
88int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask); 92int cpsw_ale_del_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
93 int flags, u16 vid);
94int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
95 int reg_mcast, int unreg_mcast);
96int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port);
89 97
90int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control); 98int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
91int cpsw_ale_control_set(struct cpsw_ale *ale, int port, 99int cpsw_ale_control_set(struct cpsw_ale *ale, int port,