* [PATCH 12/15] ehea: Add 64bit statistics
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_17.patch --]
[-- Type: text/plain, Size: 1226 bytes --]
Switch to using ndo_get_stats64 to get 64bit statistics.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-net/drivers/net/ehea/ehea_main.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_main.c 2011-05-12 07:48:00.220284417 +1000
+++ linux-net/drivers/net/ehea/ehea_main.c 2011-05-12 07:48:02.700323737 +1000
@@ -321,10 +321,10 @@ out:
spin_unlock_irqrestore(&ehea_bcmc_regs.lock, flags);
}
-static struct net_device_stats *ehea_get_stats(struct net_device *dev)
+static struct rtnl_link_stats64 *ehea_get_stats64(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
{
struct ehea_port *port = netdev_priv(dev);
- struct net_device_stats *stats = &port->stats;
struct hcp_ehea_port_cb2 *cb2;
u64 hret, rx_packets, tx_packets, rx_bytes = 0, tx_bytes = 0;
int i;
@@ -3034,7 +3034,7 @@ static const struct net_device_ops ehea_
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ehea_netpoll,
#endif
- .ndo_get_stats = ehea_get_stats,
+ .ndo_get_stats64 = ehea_get_stats64,
.ndo_set_mac_address = ehea_set_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = ehea_set_multicast_list,
^ permalink raw reply
* [PATCH 01/15] ehea: Remove NETIF_F_LLTX
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_1.patch --]
[-- Type: text/plain, Size: 2365 bytes --]
Remove the deprecated NETIF_F_LLTX feature. Since the network stack
now provides the locking we can remove the driver specific
pr->xmit_lock.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-net/drivers/net/ehea/ehea_main.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_main.c 2011-05-11 14:39:08.443817605 +1000
+++ linux-net/drivers/net/ehea/ehea_main.c 2011-05-11 14:39:10.113846069 +1000
@@ -1536,7 +1536,6 @@ static int ehea_init_port_res(struct ehe
pr->rx_packets = rx_packets;
pr->port = port;
- spin_lock_init(&pr->xmit_lock);
spin_lock_init(&pr->netif_queue);
pr->eq = ehea_create_eq(adapter, eq_type, EHEA_MAX_ENTRIES_EQ, 0);
@@ -2261,14 +2260,9 @@ static int ehea_start_xmit(struct sk_buf
pr = &port->port_res[ehea_hash_skb(skb, port->num_tx_qps)];
- if (!spin_trylock(&pr->xmit_lock))
+ if (pr->queue_stopped)
return NETDEV_TX_BUSY;
- if (pr->queue_stopped) {
- spin_unlock(&pr->xmit_lock);
- return NETDEV_TX_BUSY;
- }
-
swqe = ehea_get_swqe(pr->qp, &swqe_index);
memset(swqe, 0, SWQE_HEADER_SIZE);
atomic_dec(&pr->swqe_avail);
@@ -2332,8 +2326,6 @@ static int ehea_start_xmit(struct sk_buf
}
spin_unlock_irqrestore(&pr->netif_queue, flags);
}
- dev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */
- spin_unlock(&pr->xmit_lock);
return NETDEV_TX_OK;
}
@@ -3267,7 +3259,7 @@ struct ehea_port *ehea_setup_single_port
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
| NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
| NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
- | NETIF_F_LLTX | NETIF_F_RXCSUM;
+ | NETIF_F_RXCSUM;
dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
if (use_lro)
Index: linux-net/drivers/net/ehea/ehea.h
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea.h 2011-05-11 14:39:08.433817435 +1000
+++ linux-net/drivers/net/ehea/ehea.h 2011-05-11 14:39:10.113846069 +1000
@@ -363,7 +363,6 @@ struct ehea_port_res {
struct port_stats p_stats;
struct ehea_mr send_mr; /* send memory region */
struct ehea_mr recv_mr; /* receive memory region */
- spinlock_t xmit_lock;
struct ehea_port *port;
char int_recv_name[EHEA_IRQ_NAME_SIZE];
char int_send_name[EHEA_IRQ_NAME_SIZE];
^ permalink raw reply
* [PATCH 10/15] ehea: Simplify type 3 transmit routine
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_13.patch --]
[-- Type: text/plain, Size: 1366 bytes --]
If a nonlinear skb fits within the immediate area, use skb_copy_bits
instead of copying the frags by hand.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-net/drivers/net/ehea/ehea_main.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_main.c 2011-05-12 07:47:59.140267294 +1000
+++ linux-net/drivers/net/ehea/ehea_main.c 2011-05-12 07:48:00.220284417 +1000
@@ -2091,29 +2091,14 @@ static void ehea_xmit2(struct sk_buff *s
static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
struct ehea_swqe *swqe)
{
- int nfrags = skb_shinfo(skb)->nr_frags;
u8 *imm_data = &swqe->u.immdata_nodesc.immediate_data[0];
- skb_frag_t *frag;
- int i;
xmit_common(skb, swqe);
- if (nfrags == 0) {
+ if (!skb->data_len)
skb_copy_from_linear_data(skb, imm_data, skb->len);
- } else {
- skb_copy_from_linear_data(skb, imm_data,
- skb_headlen(skb));
- imm_data += skb_headlen(skb);
-
- /* ... then copy data from the fragments */
- for (i = 0; i < nfrags; i++) {
- frag = &skb_shinfo(skb)->frags[i];
- memcpy(imm_data,
- page_address(frag->page) + frag->page_offset,
- frag->size);
- imm_data += frag->size;
- }
- }
+ else
+ skb_copy_bits(skb, 0, imm_data, skb->len);
swqe->immediate_data_length = skb->len;
dev_kfree_skb(skb);
^ permalink raw reply
* [PATCH 08/15] ehea: Simplify ehea_xmit2 and ehea_xmit3
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_11.patch --]
[-- Type: text/plain, Size: 6028 bytes --]
Based on a patch from Michael Ellerman, clean up a significant
portion of the transmit path. There was a lot of duplication here.
Even worse, we were always checksumming tx packets and ignoring the
skb->ip_summed field.
Also remove NETIF_F_FRAGLIST from dev->features, I'm not sure why
it was enabled.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-net/drivers/net/ehea/ehea_main.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_main.c 2011-05-12 07:47:55.870215448 +1000
+++ linux-net/drivers/net/ehea/ehea_main.c 2011-05-12 07:47:58.020249537 +1000
@@ -1677,37 +1677,6 @@ static int ehea_clean_portres(struct ehe
return ret;
}
-/*
- * The write_* functions store information in swqe which is used by
- * the hardware to calculate the ip/tcp/udp checksum
- */
-
-static inline void write_ip_start_end(struct ehea_swqe *swqe,
- const struct sk_buff *skb)
-{
- swqe->ip_start = skb_network_offset(skb);
- swqe->ip_end = (u8)(swqe->ip_start + ip_hdrlen(skb) - 1);
-}
-
-static inline void write_tcp_offset_end(struct ehea_swqe *swqe,
- const struct sk_buff *skb)
-{
- swqe->tcp_offset =
- (u8)(swqe->ip_end + 1 + offsetof(struct tcphdr, check));
-
- swqe->tcp_end = (u16)skb->len - 1;
-}
-
-static inline void write_udp_offset_end(struct ehea_swqe *swqe,
- const struct sk_buff *skb)
-{
- swqe->tcp_offset =
- (u8)(swqe->ip_end + 1 + offsetof(struct udphdr, check));
-
- swqe->tcp_end = (u16)skb->len - 1;
-}
-
-
static void write_swqe2_TSO(struct sk_buff *skb,
struct ehea_swqe *swqe, u32 lkey)
{
@@ -2109,41 +2078,46 @@ static int ehea_change_mtu(struct net_de
return 0;
}
-static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
- struct ehea_swqe *swqe, u32 lkey)
+static void xmit_common(struct sk_buff *skb, struct ehea_swqe *swqe)
{
- if (skb->protocol == htons(ETH_P_IP)) {
- const struct iphdr *iph = ip_hdr(skb);
+ swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT | EHEA_SWQE_CRC;
- /* IPv4 */
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IP_CHECKSUM
- | EHEA_SWQE_TCP_CHECKSUM
- | EHEA_SWQE_IMM_DATA_PRESENT
- | EHEA_SWQE_DESCRIPTORS_PRESENT;
-
- write_ip_start_end(swqe, skb);
-
- if (iph->protocol == IPPROTO_UDP) {
- if ((iph->frag_off & IP_MF) ||
- (iph->frag_off & IP_OFFSET))
- /* IP fragment, so don't change cs */
- swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
- else
- write_udp_offset_end(swqe, skb);
- } else if (iph->protocol == IPPROTO_TCP) {
- write_tcp_offset_end(swqe, skb);
- }
+ if (skb->protocol != htons(ETH_P_IP))
+ return;
- /* icmp (big data) and ip segmentation packets (all other ip
- packets) do not require any special handling */
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ swqe->tx_control |= EHEA_SWQE_IP_CHECKSUM;
- } else {
- /* Other Ethernet Protocol */
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IMM_DATA_PRESENT
- | EHEA_SWQE_DESCRIPTORS_PRESENT;
+ swqe->ip_start = skb_network_offset(skb);
+ swqe->ip_end = swqe->ip_start + ip_hdrlen(skb) - 1;
+
+ switch (ip_hdr(skb)->protocol) {
+ case IPPROTO_UDP:
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ swqe->tx_control |= EHEA_SWQE_TCP_CHECKSUM;
+
+ swqe->tcp_offset = swqe->ip_end + 1 +
+ offsetof(struct udphdr, check);
+ swqe->tcp_end = skb->len - 1;
+ break;
+
+ case IPPROTO_TCP:
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ swqe->tx_control |= EHEA_SWQE_TCP_CHECKSUM;
+
+ swqe->tcp_offset = swqe->ip_end + 1 +
+ offsetof(struct tcphdr, check);
+ swqe->tcp_end = skb->len - 1;
+ break;
}
+}
+
+static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
+ struct ehea_swqe *swqe, u32 lkey)
+{
+ swqe->tx_control |= EHEA_SWQE_DESCRIPTORS_PRESENT;
+
+ xmit_common(skb, swqe);
write_swqe2_data(skb, dev, swqe, lkey);
}
@@ -2156,51 +2130,11 @@ static void ehea_xmit3(struct sk_buff *s
skb_frag_t *frag;
int i;
- if (skb->protocol == htons(ETH_P_IP)) {
- const struct iphdr *iph = ip_hdr(skb);
-
- /* IPv4 */
- write_ip_start_end(swqe, skb);
+ xmit_common(skb, swqe);
- if (iph->protocol == IPPROTO_TCP) {
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IP_CHECKSUM
- | EHEA_SWQE_TCP_CHECKSUM
- | EHEA_SWQE_IMM_DATA_PRESENT;
-
- write_tcp_offset_end(swqe, skb);
-
- } else if (iph->protocol == IPPROTO_UDP) {
- if ((iph->frag_off & IP_MF) ||
- (iph->frag_off & IP_OFFSET))
- /* IP fragment, so don't change cs */
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IMM_DATA_PRESENT;
- else {
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IP_CHECKSUM
- | EHEA_SWQE_TCP_CHECKSUM
- | EHEA_SWQE_IMM_DATA_PRESENT;
-
- write_udp_offset_end(swqe, skb);
- }
- } else {
- /* icmp (big data) and
- ip segmentation packets (all other ip packets) */
- swqe->tx_control |= EHEA_SWQE_CRC
- | EHEA_SWQE_IP_CHECKSUM
- | EHEA_SWQE_IMM_DATA_PRESENT;
- }
- } else {
- /* Other Ethernet Protocol */
- swqe->tx_control |= EHEA_SWQE_CRC | EHEA_SWQE_IMM_DATA_PRESENT;
- }
- /* copy (immediate) data */
if (nfrags == 0) {
- /* data is in a single piece */
skb_copy_from_linear_data(skb, imm_data, skb->len);
} else {
- /* first copy data from the skb->data buffer ... */
skb_copy_from_linear_data(skb, imm_data,
skb_headlen(skb));
imm_data += skb_headlen(skb);
@@ -2214,6 +2148,7 @@ static void ehea_xmit3(struct sk_buff *s
imm_data += frag->size;
}
}
+
swqe->immediate_data_length = skb->len;
dev_kfree_skb(skb);
}
@@ -3217,7 +3152,7 @@ struct ehea_port *ehea_setup_single_port
dev->netdev_ops = &ehea_netdev_ops;
ehea_set_ethtool_ops(dev);
- dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
+ dev->hw_features = NETIF_F_SG | NETIF_F_TSO
| NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_LRO;
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
| NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
^ permalink raw reply
* [PATCH 13/15] ehea: Remove LRO support
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_20.patch --]
[-- Type: text/plain, Size: 6743 bytes --]
In preparation for adding GRO to ehea, remove LRO.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-net/drivers/net/ehea/ehea_main.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_main.c 2011-05-12 07:48:02.700323737 +1000
+++ linux-net/drivers/net/ehea/ehea_main.c 2011-05-12 07:48:03.810341336 +1000
@@ -61,8 +61,6 @@ static int rq2_entries = EHEA_DEF_ENTRIE
static int rq3_entries = EHEA_DEF_ENTRIES_RQ3;
static int sq_entries = EHEA_DEF_ENTRIES_SQ;
static int use_mcs = 1;
-static int use_lro;
-static int lro_max_aggr = EHEA_LRO_MAX_AGGR;
static int prop_carrier_state;
module_param(msg_level, int, 0);
@@ -72,8 +70,6 @@ module_param(rq3_entries, int, 0);
module_param(sq_entries, int, 0);
module_param(prop_carrier_state, int, 0);
module_param(use_mcs, int, 0);
-module_param(use_lro, int, 0);
-module_param(lro_max_aggr, int, 0);
MODULE_PARM_DESC(msg_level, "msg_level");
MODULE_PARM_DESC(prop_carrier_state, "Propagate carrier state of physical "
@@ -92,11 +88,6 @@ MODULE_PARM_DESC(sq_entries, " Number of
__MODULE_STRING(EHEA_DEF_ENTRIES_SQ) ")");
MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");
-MODULE_PARM_DESC(lro_max_aggr, " LRO: Max packets to be aggregated. Default = "
- __MODULE_STRING(EHEA_LRO_MAX_AGGR));
-MODULE_PARM_DESC(use_lro, " Large Receive Offload, 1: enable, 0: disable, "
- "Default = 0");
-
static int port_name_cnt;
static LIST_HEAD(adapter_list);
static unsigned long ehea_driver_flags;
@@ -646,58 +637,16 @@ static int ehea_treat_poll_error(struct
return 0;
}
-static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
- void **tcph, u64 *hdr_flags, void *priv)
-{
- struct ehea_cqe *cqe = priv;
- unsigned int ip_len;
- struct iphdr *iph;
-
- /* non tcp/udp packets */
- if (!cqe->header_length)
- return -1;
-
- /* non tcp packet */
- skb_reset_network_header(skb);
- iph = ip_hdr(skb);
- if (iph->protocol != IPPROTO_TCP)
- return -1;
-
- ip_len = ip_hdrlen(skb);
- skb_set_transport_header(skb, ip_len);
- *tcph = tcp_hdr(skb);
-
- /* check if ip header and tcp header are complete */
- if (ntohs(iph->tot_len) < ip_len + tcp_hdrlen(skb))
- return -1;
-
- *hdr_flags = LRO_IPV4 | LRO_TCP;
- *iphdr = iph;
-
- return 0;
-}
-
static void ehea_proc_skb(struct ehea_port_res *pr, struct ehea_cqe *cqe,
struct sk_buff *skb)
{
int vlan_extracted = ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) &&
pr->port->vgrp);
- if (skb->dev->features & NETIF_F_LRO) {
- if (vlan_extracted)
- lro_vlan_hwaccel_receive_skb(&pr->lro_mgr, skb,
- pr->port->vgrp,
- cqe->vlan_tag,
- cqe);
- else
- lro_receive_skb(&pr->lro_mgr, skb, cqe);
- } else {
- if (vlan_extracted)
- vlan_hwaccel_receive_skb(skb, pr->port->vgrp,
- cqe->vlan_tag);
- else
- netif_receive_skb(skb);
- }
+ if (vlan_extracted)
+ vlan_hwaccel_receive_skb(skb, pr->port->vgrp, cqe->vlan_tag);
+ else
+ netif_receive_skb(skb);
}
static int ehea_proc_rwqes(struct net_device *dev,
@@ -787,8 +736,6 @@ static int ehea_proc_rwqes(struct net_de
}
cqe = ehea_poll_rq1(qp, &wqe_index);
}
- if (dev->features & NETIF_F_LRO)
- lro_flush_all(&pr->lro_mgr);
pr->rx_packets += processed;
pr->rx_bytes += processed_bytes;
@@ -1612,15 +1559,6 @@ static int ehea_init_port_res(struct ehe
netif_napi_add(pr->port->netdev, &pr->napi, ehea_poll, 64);
- pr->lro_mgr.max_aggr = pr->port->lro_max_aggr;
- pr->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
- pr->lro_mgr.lro_arr = pr->lro_desc;
- pr->lro_mgr.get_skb_header = get_skb_hdr;
- pr->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
- pr->lro_mgr.dev = port->netdev;
- pr->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
- pr->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
-
ret = 0;
goto out;
@@ -3113,9 +3051,6 @@ struct ehea_port *ehea_setup_single_port
NETIF_F_IP_CSUM;
dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
- if (use_lro)
- dev->features |= NETIF_F_LRO;
-
INIT_WORK(&port->reset_task, ehea_reset_port);
init_waitqueue_head(&port->swqe_avail_wq);
@@ -3127,8 +3062,6 @@ struct ehea_port *ehea_setup_single_port
goto out_unreg_port;
}
- port->lro_max_aggr = lro_max_aggr;
-
ret = ehea_get_jumboframe_status(port, &jumbo);
if (ret)
netdev_err(dev, "failed determining jumbo frame status\n");
Index: linux-net/drivers/net/ehea/ehea.h
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea.h 2011-05-12 07:47:56.980233047 +1000
+++ linux-net/drivers/net/ehea/ehea.h 2011-05-12 07:48:03.810341336 +1000
@@ -33,7 +33,6 @@
#include <linux/ethtool.h>
#include <linux/vmalloc.h>
#include <linux/if_vlan.h>
-#include <linux/inet_lro.h>
#include <asm/ibmebus.h>
#include <asm/abs_addr.h>
@@ -58,7 +57,6 @@
#define EHEA_MIN_ENTRIES_QP 127
#define EHEA_SMALL_QUEUES
-#define EHEA_LRO_MAX_AGGR 64
#ifdef EHEA_SMALL_QUEUES
#define EHEA_MAX_CQE_COUNT 1023
@@ -85,8 +83,6 @@
#define EHEA_RQ2_PKT_SIZE 2048
#define EHEA_L_PKT_SIZE 256 /* low latency */
-#define MAX_LRO_DESCRIPTORS 8
-
/* Send completion signaling */
/* Protection Domain Identifier */
@@ -382,8 +378,6 @@ struct ehea_port_res {
u64 tx_bytes;
u64 rx_packets;
u64 rx_bytes;
- struct net_lro_mgr lro_mgr;
- struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS];
int sq_restart_flag;
};
@@ -468,7 +462,6 @@ struct ehea_port {
u32 msg_enable;
u32 sig_comp_iv;
u32 state;
- u32 lro_max_aggr;
u8 phy_link;
u8 full_duplex;
u8 autoneg;
Index: linux-net/drivers/net/ehea/ehea_ethtool.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_ethtool.c 2011-05-12 07:47:49.640116670 +1000
+++ linux-net/drivers/net/ehea/ehea_ethtool.c 2011-05-12 07:48:03.810341336 +1000
@@ -205,9 +205,6 @@ static char ehea_ethtool_stats_keys[][ET
{"PR13 free_swqes"},
{"PR14 free_swqes"},
{"PR15 free_swqes"},
- {"LRO aggregated"},
- {"LRO flushed"},
- {"LRO no_desc"},
};
static void ehea_get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@ -264,19 +261,6 @@ static void ehea_get_ethtool_stats(struc
for (k = 0; k < 16; k++)
data[i++] = atomic_read(&port->port_res[k].swqe_avail);
-
- for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
- tmp |= port->port_res[k].lro_mgr.stats.aggregated;
- data[i++] = tmp;
-
- for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
- tmp |= port->port_res[k].lro_mgr.stats.flushed;
- data[i++] = tmp;
-
- for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
- tmp |= port->port_res[k].lro_mgr.stats.no_desc;
- data[i++] = tmp;
-
}
const struct ethtool_ops ehea_ethtool_ops = {
^ permalink raw reply
* [PATCH 03/15] ehea: Remove force_irq logic in napi poll routine
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_3.patch --]
[-- Type: text/plain, Size: 2097 bytes --]
commit 18604c548545 (ehea: NAPI multi queue TX/RX path for SMP) added
driver specific logic for exiting napi mode. I'm not sure what it was
trying to solve and it should be up to the network stack to decide when
we are done polling so remove it.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-net/drivers/net/ehea/ehea_main.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_main.c 2011-05-12 07:47:49.640116670 +1000
+++ linux-net/drivers/net/ehea/ehea_main.c 2011-05-12 07:47:51.960153456 +1000
@@ -927,7 +927,6 @@ static struct ehea_cqe *ehea_proc_cqes(s
return cqe;
}
-#define EHEA_NAPI_POLL_NUM_BEFORE_IRQ 16
#define EHEA_POLL_MAX_CQES 65535
static int ehea_poll(struct napi_struct *napi, int budget)
@@ -937,18 +936,13 @@ static int ehea_poll(struct napi_struct
struct net_device *dev = pr->port->netdev;
struct ehea_cqe *cqe;
struct ehea_cqe *cqe_skb = NULL;
- int force_irq, wqe_index;
+ int wqe_index;
int rx = 0;
- force_irq = (pr->poll_counter > EHEA_NAPI_POLL_NUM_BEFORE_IRQ);
cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
+ rx += ehea_proc_rwqes(dev, pr, budget - rx);
- if (!force_irq)
- rx += ehea_proc_rwqes(dev, pr, budget - rx);
-
- while ((rx != budget) || force_irq) {
- pr->poll_counter = 0;
- force_irq = 0;
+ while ((rx != budget)) {
napi_complete(napi);
ehea_reset_cq_ep(pr->recv_cq);
ehea_reset_cq_ep(pr->send_cq);
@@ -968,7 +962,6 @@ static int ehea_poll(struct napi_struct
rx += ehea_proc_rwqes(dev, pr, budget - rx);
}
- pr->poll_counter++;
return rx;
}
Index: linux-net/drivers/net/ehea/ehea.h
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea.h 2011-05-12 07:47:49.640116670 +1000
+++ linux-net/drivers/net/ehea/ehea.h 2011-05-12 07:47:51.960153456 +1000
@@ -383,7 +383,6 @@ struct ehea_port_res {
u64 tx_bytes;
u64 rx_packets;
u64 rx_bytes;
- u32 poll_counter;
struct net_lro_mgr lro_mgr;
struct net_lro_desc lro_desc[MAX_LRO_DESCRIPTORS];
int sq_restart_flag;
^ permalink raw reply
* [PATCH 04/15] ehea: Remove num_tx_qps module option
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_5.patch --]
[-- Type: text/plain, Size: 7457 bytes --]
The num_tx_qps module option allows a user to configure a different
number of tx and rx queues. Now the networking stack is multiqueue
aware it makes little sense just to enable the tx queues and not the
rx queues so remove the option.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-net/drivers/net/ehea/ehea.h
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea.h 2011-05-12 07:47:51.960153456 +1000
+++ linux-net/drivers/net/ehea/ehea.h 2011-05-12 07:47:53.490177714 +1000
@@ -58,7 +58,6 @@
#define EHEA_MIN_ENTRIES_QP 127
#define EHEA_SMALL_QUEUES
-#define EHEA_NUM_TX_QP 1
#define EHEA_LRO_MAX_AGGR 64
#ifdef EHEA_SMALL_QUEUES
@@ -460,8 +459,6 @@ struct ehea_port {
char int_aff_name[EHEA_IRQ_NAME_SIZE];
int allmulti; /* Indicates IFF_ALLMULTI state */
int promisc; /* Indicates IFF_PROMISC state */
- int num_tx_qps;
- int num_add_tx_qps;
int num_mcs;
int resets;
unsigned long flags;
Index: linux-net/drivers/net/ehea/ehea_main.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_main.c 2011-05-12 07:47:51.960153456 +1000
+++ linux-net/drivers/net/ehea/ehea_main.c 2011-05-12 07:47:53.490177714 +1000
@@ -63,7 +63,6 @@ static int sq_entries = EHEA_DEF_ENTRIES
static int use_mcs = 1;
static int use_lro;
static int lro_max_aggr = EHEA_LRO_MAX_AGGR;
-static int num_tx_qps = EHEA_NUM_TX_QP;
static int prop_carrier_state;
module_param(msg_level, int, 0);
@@ -75,9 +74,7 @@ module_param(prop_carrier_state, int, 0)
module_param(use_mcs, int, 0);
module_param(use_lro, int, 0);
module_param(lro_max_aggr, int, 0);
-module_param(num_tx_qps, int, 0);
-MODULE_PARM_DESC(num_tx_qps, "Number of TX-QPS");
MODULE_PARM_DESC(msg_level, "msg_level");
MODULE_PARM_DESC(prop_carrier_state, "Propagate carrier state of physical "
"port to stack. 1:yes, 0:no. Default = 0 ");
@@ -172,7 +169,7 @@ static void ehea_update_firmware_handles
continue;
num_ports++;
- num_portres += port->num_def_qps + port->num_add_tx_qps;
+ num_portres += port->num_def_qps;
}
}
@@ -198,9 +195,7 @@ static void ehea_update_firmware_handles
(num_ports == 0))
continue;
- for (l = 0;
- l < port->num_def_qps + port->num_add_tx_qps;
- l++) {
+ for (l = 0; l < port->num_def_qps; l++) {
struct ehea_port_res *pr = &port->port_res[l];
arr[i].adh = adapter->handle;
@@ -360,7 +355,7 @@ static struct net_device_stats *ehea_get
}
tx_packets = 0;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
tx_packets += port->port_res[i].tx_packets;
tx_bytes += port->port_res[i].tx_bytes;
}
@@ -811,7 +806,7 @@ static void reset_sq_restart_flag(struct
{
int i;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
struct ehea_port_res *pr = &port->port_res[i];
pr->sq_restart_flag = 0;
}
@@ -824,7 +819,7 @@ static void check_sqs(struct ehea_port *
int swqe_index;
int i, k;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
struct ehea_port_res *pr = &port->port_res[i];
int ret;
k = 0;
@@ -1113,13 +1108,6 @@ int ehea_sense_port_attr(struct ehea_por
goto out_free;
}
- port->num_tx_qps = num_tx_qps;
-
- if (port->num_def_qps >= port->num_tx_qps)
- port->num_add_tx_qps = 0;
- else
- port->num_add_tx_qps = port->num_tx_qps - port->num_def_qps;
-
ret = 0;
out_free:
if (ret || netif_msg_probe(port))
@@ -1360,7 +1348,7 @@ static int ehea_reg_interrupts(struct ne
port->qp_eq->attr.ist1);
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
pr = &port->port_res[i];
snprintf(pr->int_send_name, EHEA_IRQ_NAME_SIZE - 1,
"%s-queue%d", dev->name, i);
@@ -1403,7 +1391,7 @@ static void ehea_free_interrupts(struct
/* send */
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
pr = &port->port_res[i];
ibmebus_free_irq(pr->eq->attr.ist1, pr);
netif_info(port, intr, dev,
@@ -2472,8 +2460,7 @@ out:
return ret;
}
-static int ehea_port_res_setup(struct ehea_port *port, int def_qps,
- int add_tx_qps)
+static int ehea_port_res_setup(struct ehea_port *port, int def_qps)
{
int ret, i;
struct port_res_cfg pr_cfg, pr_cfg_small_rx;
@@ -2506,7 +2493,7 @@ static int ehea_port_res_setup(struct eh
if (ret)
goto out_clean_pr;
}
- for (i = def_qps; i < def_qps + add_tx_qps; i++) {
+ for (i = def_qps; i < def_qps; i++) {
ret = ehea_init_port_res(port, &port->port_res[i],
&pr_cfg_small_rx, i);
if (ret)
@@ -2529,7 +2516,7 @@ static int ehea_clean_all_portres(struct
int ret = 0;
int i;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
+ for (i = 0; i < port->num_def_qps; i++)
ret |= ehea_clean_portres(port, &port->port_res[i]);
ret |= ehea_destroy_eq(port->qp_eq);
@@ -2561,8 +2548,7 @@ static int ehea_up(struct net_device *de
if (port->state == EHEA_PORT_UP)
return 0;
- ret = ehea_port_res_setup(port, port->num_def_qps,
- port->num_add_tx_qps);
+ ret = ehea_port_res_setup(port, port->num_def_qps);
if (ret) {
netdev_err(dev, "port_res_failed\n");
goto out;
@@ -2581,7 +2567,7 @@ static int ehea_up(struct net_device *de
goto out_clean_pr;
}
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
ret = ehea_activate_qp(port->adapter, port->port_res[i].qp);
if (ret) {
netdev_err(dev, "activate_qp failed\n");
@@ -2627,7 +2613,7 @@ static void port_napi_disable(struct ehe
{
int i;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
+ for (i = 0; i < port->num_def_qps; i++)
napi_disable(&port->port_res[i].napi);
}
@@ -2635,7 +2621,7 @@ static void port_napi_enable(struct ehea
{
int i;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
+ for (i = 0; i < port->num_def_qps; i++)
napi_enable(&port->port_res[i].napi);
}
@@ -2721,7 +2707,7 @@ static void ehea_flush_sq(struct ehea_po
{
int i;
- for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ for (i = 0; i < port->num_def_qps; i++) {
struct ehea_port_res *pr = &port->port_res[i];
int swqe_max = pr->sq_skba_size - 2 - pr->swqe_ll_count;
int ret;
@@ -2755,7 +2741,7 @@ int ehea_stop_qps(struct net_device *dev
goto out;
}
- for (i = 0; i < (port->num_def_qps + port->num_add_tx_qps); i++) {
+ for (i = 0; i < (port->num_def_qps); i++) {
struct ehea_port_res *pr = &port->port_res[i];
struct ehea_qp *qp = pr->qp;
@@ -2857,7 +2843,7 @@ int ehea_restart_qps(struct net_device *
goto out;
}
- for (i = 0; i < (port->num_def_qps + port->num_add_tx_qps); i++) {
+ for (i = 0; i < (port->num_def_qps); i++) {
struct ehea_port_res *pr = &port->port_res[i];
struct ehea_qp *qp = pr->qp;
@@ -3217,8 +3203,7 @@ struct ehea_port *ehea_setup_single_port
goto out_free_mc_list;
netif_set_real_num_rx_queues(dev, port->num_def_qps);
- netif_set_real_num_tx_queues(dev, port->num_def_qps +
- port->num_add_tx_qps);
+ netif_set_real_num_tx_queues(dev, port->num_def_qps);
port_dev = ehea_register_port(port, dn);
if (!port_dev)
^ permalink raw reply
* [PATCH 15/15] ehea: Remove unused tcp_end field in send WQ
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_22.patch --]
[-- Type: text/plain, Size: 1328 bytes --]
The tcp_end field is not actually used by the hardware, so there
is no need to set it.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-net/drivers/net/ehea/ehea_main.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_main.c 2011-05-12 07:48:05.100361788 +1000
+++ linux-net/drivers/net/ehea/ehea_main.c 2011-05-12 07:48:06.380382084 +1000
@@ -1995,7 +1995,6 @@ static void xmit_common(struct sk_buff *
swqe->tcp_offset = swqe->ip_end + 1 +
offsetof(struct udphdr, check);
- swqe->tcp_end = skb->len - 1;
break;
case IPPROTO_TCP:
@@ -2004,7 +2003,6 @@ static void xmit_common(struct sk_buff *
swqe->tcp_offset = swqe->ip_end + 1 +
offsetof(struct tcphdr, check);
- swqe->tcp_end = skb->len - 1;
break;
}
}
Index: linux-net/drivers/net/ehea/ehea_qmr.h
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_qmr.h 2011-05-12 07:47:05.399415238 +1000
+++ linux-net/drivers/net/ehea/ehea_qmr.h 2011-05-12 07:48:06.380382084 +1000
@@ -106,7 +106,7 @@ struct ehea_swqe {
u8 immediate_data_length;
u8 tcp_offset;
u8 reserved2;
- u16 tcp_end;
+ u16 reserved2b;
u8 wrap_tag;
u8 descriptors; /* number of valid descriptors in WQE */
u16 reserved3;
^ permalink raw reply
* [PATCH 14/15] ehea: Add GRO support
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_21.patch --]
[-- Type: text/plain, Size: 1782 bytes --]
Add GRO support to the ehea driver.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
v2:
- Removed use of vlan_gro_receive as suggested by Jesse Gross
Index: linux-net/drivers/net/ehea/ehea_main.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_main.c 2011-05-12 07:48:03.810341336 +1000
+++ linux-net/drivers/net/ehea/ehea_main.c 2011-05-12 07:48:05.100361788 +1000
@@ -637,18 +637,6 @@ static int ehea_treat_poll_error(struct
return 0;
}
-static void ehea_proc_skb(struct ehea_port_res *pr, struct ehea_cqe *cqe,
- struct sk_buff *skb)
-{
- int vlan_extracted = ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) &&
- pr->port->vgrp);
-
- if (vlan_extracted)
- vlan_hwaccel_receive_skb(skb, pr->port->vgrp, cqe->vlan_tag);
- else
- netif_receive_skb(skb);
-}
-
static int ehea_proc_rwqes(struct net_device *dev,
struct ehea_port_res *pr,
int budget)
@@ -725,7 +713,12 @@ static int ehea_proc_rwqes(struct net_de
}
processed_bytes += skb->len;
- ehea_proc_skb(pr, cqe, skb);
+
+ if ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT) &&
+ pr->port->vgrp)
+ __vlan_hwaccel_put_tag(skb, cqe->vlan_tag);
+
+ napi_gro_receive(&pr->napi, skb);
} else {
pr->p_stats.poll_receive_errors++;
port_reset = ehea_treat_poll_error(pr, rq, cqe,
@@ -3041,7 +3034,7 @@ struct ehea_port *ehea_setup_single_port
dev->netdev_ops = &ehea_netdev_ops;
ehea_set_ethtool_ops(dev);
- dev->hw_features = NETIF_F_SG | NETIF_F_TSO
+ dev->hw_features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_GRO
| NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_LRO;
dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
| NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
^ permalink raw reply
* [PATCH 05/15] ehea: Dont check NETIF_F_TSO in TX path
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_6.patch --]
[-- Type: text/plain, Size: 808 bytes --]
It seems like the ehea xmit routine and an ethtool change of TSO
mode could race, resulting in corrupt packets. Checking gso_size
is enough and we can use the helper function.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-net/drivers/net/ehea/ehea_main.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_main.c 2011-05-12 07:47:53.490177714 +1000
+++ linux-net/drivers/net/ehea/ehea_main.c 2011-05-12 07:47:54.730197374 +1000
@@ -1788,7 +1788,7 @@ static inline void write_swqe2_data(stru
swqe->descriptors = 0;
sg1entry_contains_frag_data = 0;
- if ((dev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size)
+ if (skb_is_gso(skb))
write_swqe2_TSO(skb, swqe, lkey);
else
write_swqe2_nonTSO(skb, swqe, lkey);
^ permalink raw reply
* [PATCH 07/15] ehea: Allocate large enough skbs to avoid partial cacheline DMA writes
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_8.patch --]
[-- Type: text/plain, Size: 1471 bytes --]
The ehea adapter has a mode where it will avoid partial cacheline DMA
writes on receive by always padding packets to fall on a cacheline
boundary.
Unfortunately we currently aren't allocating enough space for a full
ethernet MTU packet to be rounded up, so this optimisation doesn't hit.
It's unfortunate that the next largest packet size exposed by the
hypervisor interface is 2kB, meaning our skb allocation comes out of a
4kB SLAB. However the performance increase due to this optimisation is
quite large and my TCP stream numbers increase from 900MB to 1000MB/sec.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
Index: linux-net/drivers/net/ehea/ehea.h
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea.h 2011-05-12 07:47:53.490177714 +1000
+++ linux-net/drivers/net/ehea/ehea.h 2011-05-12 07:47:56.980233047 +1000
@@ -82,7 +82,7 @@
#define EHEA_SG_RQ3 0
#define EHEA_MAX_PACKET_SIZE 9022 /* for jumbo frames */
-#define EHEA_RQ2_PKT_SIZE 1522
+#define EHEA_RQ2_PKT_SIZE 2048
#define EHEA_L_PKT_SIZE 256 /* low latency */
#define MAX_LRO_DESCRIPTORS 8
@@ -93,7 +93,7 @@
#define EHEA_PD_ID 0xaabcdeff
#define EHEA_RQ2_THRESHOLD 1
-#define EHEA_RQ3_THRESHOLD 9 /* use RQ3 threshold of 1522 bytes */
+#define EHEA_RQ3_THRESHOLD 4 /* use RQ3 threshold of 2048 bytes */
#define EHEA_SPEED_10G 10000
#define EHEA_SPEED_1G 1000
^ permalink raw reply
* [PATCH 02/15] ehea: Update multiqueue support
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
In-Reply-To: <20110512005213.897432612@samba.org>
[-- Attachment #1: ehea_2.patch --]
[-- Type: text/plain, Size: 11212 bytes --]
The ehea driver had some multiqueue support but was missing the last
few years of networking stack improvements:
- Use skb_record_rx_queue to record which queue an skb came in on.
- Remove the driver specific netif_queue lock and use the networking
stack transmit lock instead.
- Remove the driver specific transmit queue hashing and use
skb_get_queue_mapping instead.
- Use netif_tx_{start|stop|wake}_queue where appropriate. We can also
remove pr->queue_stopped and just check the queue status directly.
- Print all 16 queues in the ethtool stats.
We now enable multiqueue by default since it is a clear win on all my
testing so far.
Signed-off-by: Anton Blanchard <anton@samba.org>
---
v2: Review from Michael Ellerman:
- Move skb_record_rx_queue into ehea_fill_skb
- Fix unlock issue when stopping a transmit queue in ehea_proc_cqes.
For my penance I cut the queue down to force the stop/start logic
to be exercised. Over a million queue stop/start operations completed
successfully while running a TCP RR benchmark.
Index: linux-net/drivers/net/ehea/ehea_main.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_main.c 2011-05-12 07:47:48.840103988 +1000
+++ linux-net/drivers/net/ehea/ehea_main.c 2011-05-12 07:47:49.640116670 +1000
@@ -60,7 +60,7 @@ static int rq1_entries = EHEA_DEF_ENTRIE
static int rq2_entries = EHEA_DEF_ENTRIES_RQ2;
static int rq3_entries = EHEA_DEF_ENTRIES_RQ3;
static int sq_entries = EHEA_DEF_ENTRIES_SQ;
-static int use_mcs;
+static int use_mcs = 1;
static int use_lro;
static int lro_max_aggr = EHEA_LRO_MAX_AGGR;
static int num_tx_qps = EHEA_NUM_TX_QP;
@@ -93,7 +93,7 @@ MODULE_PARM_DESC(rq1_entries, "Number of
MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue "
"[2^x - 1], x = [6..14]. Default = "
__MODULE_STRING(EHEA_DEF_ENTRIES_SQ) ")");
-MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0 ");
+MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 1 ");
MODULE_PARM_DESC(lro_max_aggr, " LRO: Max packets to be aggregated. Default = "
__MODULE_STRING(EHEA_LRO_MAX_AGGR));
@@ -542,7 +542,8 @@ static inline int ehea_check_cqe(struct
}
static inline void ehea_fill_skb(struct net_device *dev,
- struct sk_buff *skb, struct ehea_cqe *cqe)
+ struct sk_buff *skb, struct ehea_cqe *cqe,
+ struct ehea_port_res *pr)
{
int length = cqe->num_bytes_transfered - 4; /*remove CRC */
@@ -556,6 +557,8 @@ static inline void ehea_fill_skb(struct
skb->csum = csum_unfold(~cqe->inet_checksum_value);
} else
skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ skb_record_rx_queue(skb, pr - &pr->port->port_res[0]);
}
static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
@@ -752,7 +755,7 @@ static int ehea_proc_rwqes(struct net_de
}
skb_copy_to_linear_data(skb, ((char *)cqe) + 64,
cqe->num_bytes_transfered - 4);
- ehea_fill_skb(dev, skb, cqe);
+ ehea_fill_skb(dev, skb, cqe, pr);
} else if (rq == 2) {
/* RQ2 */
skb = get_skb_by_index(skb_arr_rq2,
@@ -762,7 +765,7 @@ static int ehea_proc_rwqes(struct net_de
"rq2: skb=NULL\n");
break;
}
- ehea_fill_skb(dev, skb, cqe);
+ ehea_fill_skb(dev, skb, cqe, pr);
processed_rq2++;
} else {
/* RQ3 */
@@ -773,7 +776,7 @@ static int ehea_proc_rwqes(struct net_de
"rq3: skb=NULL\n");
break;
}
- ehea_fill_skb(dev, skb, cqe);
+ ehea_fill_skb(dev, skb, cqe, pr);
processed_rq3++;
}
@@ -859,7 +862,8 @@ static struct ehea_cqe *ehea_proc_cqes(s
int cqe_counter = 0;
int swqe_av = 0;
int index;
- unsigned long flags;
+ struct netdev_queue *txq = netdev_get_tx_queue(pr->port->netdev,
+ pr - &pr->port->port_res[0]);
cqe = ehea_poll_cq(send_cq);
while (cqe && (quota > 0)) {
@@ -909,14 +913,15 @@ static struct ehea_cqe *ehea_proc_cqes(s
ehea_update_feca(send_cq, cqe_counter);
atomic_add(swqe_av, &pr->swqe_avail);
- spin_lock_irqsave(&pr->netif_queue, flags);
-
- if (pr->queue_stopped && (atomic_read(&pr->swqe_avail)
- >= pr->swqe_refill_th)) {
- netif_wake_queue(pr->port->netdev);
- pr->queue_stopped = 0;
+ if (unlikely(netif_tx_queue_stopped(txq) &&
+ (atomic_read(&pr->swqe_avail) >= pr->swqe_refill_th))) {
+ __netif_tx_lock(txq, smp_processor_id());
+ if (netif_tx_queue_stopped(txq) &&
+ (atomic_read(&pr->swqe_avail) >= pr->swqe_refill_th))
+ netif_tx_wake_queue(txq);
+ __netif_tx_unlock(txq);
}
- spin_unlock_irqrestore(&pr->netif_queue, flags);
+
wake_up(&pr->port->swqe_avail_wq);
return cqe;
@@ -1253,7 +1258,7 @@ static void ehea_parse_eqe(struct ehea_a
netif_info(port, link, dev,
"Logical port down\n");
netif_carrier_off(dev);
- netif_stop_queue(dev);
+ netif_tx_disable(dev);
}
if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PORT_UP, eqe)) {
@@ -1284,7 +1289,7 @@ static void ehea_parse_eqe(struct ehea_a
case EHEA_EC_PORT_MALFUNC:
netdev_info(dev, "Port malfunction\n");
netif_carrier_off(dev);
- netif_stop_queue(dev);
+ netif_tx_disable(dev);
break;
default:
netdev_err(dev, "unknown event code %x, eqe=0x%llX\n", ec, eqe);
@@ -1536,7 +1541,6 @@ static int ehea_init_port_res(struct ehe
pr->rx_packets = rx_packets;
pr->port = port;
- spin_lock_init(&pr->netif_queue);
pr->eq = ehea_create_eq(adapter, eq_type, EHEA_MAX_ENTRIES_EQ, 0);
if (!pr->eq) {
@@ -2233,35 +2237,17 @@ static void ehea_xmit3(struct sk_buff *s
dev_kfree_skb(skb);
}
-static inline int ehea_hash_skb(struct sk_buff *skb, int num_qps)
-{
- struct tcphdr *tcp;
- u32 tmp;
-
- if ((skb->protocol == htons(ETH_P_IP)) &&
- (ip_hdr(skb)->protocol == IPPROTO_TCP)) {
- tcp = (struct tcphdr *)(skb_network_header(skb) +
- (ip_hdr(skb)->ihl * 4));
- tmp = (tcp->source + (tcp->dest << 16)) % 31;
- tmp += ip_hdr(skb)->daddr % 31;
- return tmp % num_qps;
- } else
- return 0;
-}
-
static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ehea_port *port = netdev_priv(dev);
struct ehea_swqe *swqe;
- unsigned long flags;
u32 lkey;
int swqe_index;
struct ehea_port_res *pr;
+ struct netdev_queue *txq;
- pr = &port->port_res[ehea_hash_skb(skb, port->num_tx_qps)];
-
- if (pr->queue_stopped)
- return NETDEV_TX_BUSY;
+ pr = &port->port_res[skb_get_queue_mapping(skb)];
+ txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
swqe = ehea_get_swqe(pr->qp, &swqe_index);
memset(swqe, 0, SWQE_HEADER_SIZE);
@@ -2311,20 +2297,15 @@ static int ehea_start_xmit(struct sk_buf
ehea_dump(swqe, 512, "swqe");
if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
- netif_stop_queue(dev);
+ netif_tx_stop_queue(txq);
swqe->tx_control |= EHEA_SWQE_PURGE;
}
ehea_post_swqe(pr->qp, swqe);
if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
- spin_lock_irqsave(&pr->netif_queue, flags);
- if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
- pr->p_stats.queue_stopped++;
- netif_stop_queue(dev);
- pr->queue_stopped = 1;
- }
- spin_unlock_irqrestore(&pr->netif_queue, flags);
+ pr->p_stats.queue_stopped++;
+ netif_tx_stop_queue(txq);
}
return NETDEV_TX_OK;
@@ -2677,7 +2658,7 @@ static int ehea_open(struct net_device *
ret = ehea_up(dev);
if (!ret) {
port_napi_enable(port);
- netif_start_queue(dev);
+ netif_tx_start_all_queues(dev);
}
mutex_unlock(&port->port_lock);
@@ -2721,7 +2702,7 @@ static int ehea_stop(struct net_device *
set_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
cancel_work_sync(&port->reset_task);
mutex_lock(&port->port_lock);
- netif_stop_queue(dev);
+ netif_tx_stop_all_queues(dev);
port_napi_disable(port);
ret = ehea_down(dev);
mutex_unlock(&port->port_lock);
@@ -2945,7 +2926,7 @@ static void ehea_reset_port(struct work_
mutex_lock(&dlpar_mem_lock);
port->resets++;
mutex_lock(&port->port_lock);
- netif_stop_queue(dev);
+ netif_tx_disable(dev);
port_napi_disable(port);
@@ -2961,7 +2942,7 @@ static void ehea_reset_port(struct work_
port_napi_enable(port);
- netif_wake_queue(dev);
+ netif_tx_wake_all_queues(dev);
out:
mutex_unlock(&port->port_lock);
mutex_unlock(&dlpar_mem_lock);
@@ -2988,7 +2969,7 @@ static void ehea_rereg_mrs(void)
if (dev->flags & IFF_UP) {
mutex_lock(&port->port_lock);
- netif_stop_queue(dev);
+ netif_tx_disable(dev);
ehea_flush_sq(port);
ret = ehea_stop_qps(dev);
if (ret) {
@@ -3033,7 +3014,7 @@ static void ehea_rereg_mrs(void)
if (!ret) {
check_sqs(port);
port_napi_enable(port);
- netif_wake_queue(dev);
+ netif_tx_wake_all_queues(dev);
} else {
netdev_err(dev, "Unable to restart QPS\n");
}
@@ -3210,7 +3191,7 @@ struct ehea_port *ehea_setup_single_port
int jumbo;
/* allocate memory for the port structures */
- dev = alloc_etherdev(sizeof(struct ehea_port));
+ dev = alloc_etherdev_mq(sizeof(struct ehea_port), EHEA_MAX_PORT_RES);
if (!dev) {
pr_err("no mem for net_device\n");
@@ -3242,6 +3223,10 @@ struct ehea_port *ehea_setup_single_port
if (ret)
goto out_free_mc_list;
+ netif_set_real_num_rx_queues(dev, port->num_def_qps);
+ netif_set_real_num_tx_queues(dev, port->num_def_qps +
+ port->num_add_tx_qps);
+
port_dev = ehea_register_port(port, dn);
if (!port_dev)
goto out_free_mc_list;
Index: linux-net/drivers/net/ehea/ehea.h
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea.h 2011-05-12 07:47:48.840103988 +1000
+++ linux-net/drivers/net/ehea/ehea.h 2011-05-12 07:47:49.640116670 +1000
@@ -375,8 +375,6 @@ struct ehea_port_res {
struct ehea_q_skb_arr rq3_skba;
struct ehea_q_skb_arr sq_skba;
int sq_skba_size;
- spinlock_t netif_queue;
- int queue_stopped;
int swqe_refill_th;
atomic_t swqe_avail;
int swqe_ll_count;
Index: linux-net/drivers/net/ehea/ehea_ethtool.c
===================================================================
--- linux-net.orig/drivers/net/ehea/ehea_ethtool.c 2011-05-12 07:47:10.869501966 +1000
+++ linux-net/drivers/net/ehea/ehea_ethtool.c 2011-05-12 07:47:49.640116670 +1000
@@ -189,7 +189,6 @@ static char ehea_ethtool_stats_keys[][ET
{"IP cksum errors"},
{"Frame cksum errors"},
{"num SQ stopped"},
- {"SQ stopped"},
{"PR0 free_swqes"},
{"PR1 free_swqes"},
{"PR2 free_swqes"},
@@ -198,6 +197,14 @@ static char ehea_ethtool_stats_keys[][ET
{"PR5 free_swqes"},
{"PR6 free_swqes"},
{"PR7 free_swqes"},
+ {"PR8 free_swqes"},
+ {"PR9 free_swqes"},
+ {"PR10 free_swqes"},
+ {"PR11 free_swqes"},
+ {"PR12 free_swqes"},
+ {"PR13 free_swqes"},
+ {"PR14 free_swqes"},
+ {"PR15 free_swqes"},
{"LRO aggregated"},
{"LRO flushed"},
{"LRO no_desc"},
@@ -255,11 +262,7 @@ static void ehea_get_ethtool_stats(struc
tmp += port->port_res[k].p_stats.queue_stopped;
data[i++] = tmp;
- for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
- tmp |= port->port_res[k].queue_stopped;
- data[i++] = tmp;
-
- for (k = 0; k < 8; k++)
+ for (k = 0; k < 16; k++)
data[i++] = atomic_read(&port->port_res[k].swqe_avail);
for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
^ permalink raw reply
* [PATCH 00/15] ehea updates v2
From: Anton Blanchard @ 2011-05-12 0:52 UTC (permalink / raw)
To: leitao, michael, jesse, bhutchings; +Cc: netdev
Ben, Jesse, Michael: thanks for the review. Here is an updated set of
patches based on the comments.
Anton
^ permalink raw reply
* Re: [PATCH net-next-2.6] net/bonding: adjust codingstyle for bond_3ad files
From: Joe Perches @ 2011-05-12 0:59 UTC (permalink / raw)
To: Rafael Aquini
Cc: Jay Vosburgh, kernel-janitors, David Miller, Andy Gospodarek,
shemminger, Nicolas Kaiser, netdev
In-Reply-To: <20110512001858.GA2435@x61.tchesoft.com>
On Wed, 2011-05-11 at 21:18 -0300, Rafael Aquini wrote:
> My bad, sorry. I'll be re-posting soon.
When you repost, it's considered useful and polite to have a
version # in the [PATCH net-next-2.6 v#] subject line
And add a changelog describing what's different in this version
below your sign-off is also good form.
The changelog doesn't get put into git history, but it's useful
for others to see what you've changed so reviewers can skip over
stuff that's been previously commented on and find the new stuff
easier.
Generally the email body contains
verbose patch description
Signed-off-by: you
Any Acks/Reviewed-bys: others
--- ( <- 3 dashes as a separator)
patch changelog if it exists
patch
cheers, Joe
^ permalink raw reply
* Re: [PATCH net-next-2.6] net/bonding: adjust codingstyle for bond_3ad files
From: Rafael Aquini @ 2011-05-12 0:48 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Jay Vosburgh, Joe Perches, kernel-janitors, David Miller,
Andy Gospodarek, netdev, Nicolas Kaiser
In-Reply-To: <20110511172814.714e2f2a@nehalam>
Howdy Stephen,
On Wed, May 11, 2011 at 05:28:14PM -0700, Stephen Hemminger wrote:
>
> This should be split into three separate patches.
>
> Always assume your change will break something for somebody and it will
> be necessary for some later investigation to bisect out the cause.
I'd like to know what are your suggestios to split it.
1. patch for comments;
2. patch for simplification (Nicolas);
3. patch for other adjusts (macro replacement, uninitialized vars...)
Would this approach really be productive?
Thanks in advance.
Cheers!
--
Rafael Aquini <aquini@linux.com>
^ permalink raw reply
* Re: [PATCH 03/16] add driver for C64x+ ethernet driver
From: Joe Perches @ 2011-05-12 0:49 UTC (permalink / raw)
To: Mark Salter, netdev; +Cc: linux-kernel
In-Reply-To: <1305144843-5058-4-git-send-email-msalter@redhat.com>
On Wed, 2011-05-11 at 16:13 -0400, Mark Salter wrote:
> From: Aurelien Jacquiot <a-jacquiot@ti.com>
>
> This patch adds a network driver to support the ethernet interface found on
> several Texas Instruments C64X+ based System on Chips. In particular, this
> driver has been tested on the TMS320C6455, TMS320C6457, TMS320C6472, and
> TMS320C6474 parts.
I'd rather you put this in a new ti_c6x subdirectory in drivers/net/
Please CC network drivers to netdev@vger.kernel.org (added)
And some comments below.
> Signed-off-by: Aurelien Jacquiot <a-jacquiot@ti.com>
> Signed-off-by: Mark Salter <msalter@redhat.com>
> ---
> drivers/net/Kconfig | 8 +
> drivers/net/Makefile | 2 +
> drivers/net/c6x_gemac.c | 1582 +++++++++++++++++++++++++++++++++++++++++++++++
> drivers/net/c6x_gmdio.c | 514 +++++++++++++++
> 4 files changed, 2106 insertions(+), 0 deletions(-)
> create mode 100644 drivers/net/c6x_gemac.c
> create mode 100644 drivers/net/c6x_gmdio.c
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index dc280bc..5eb46a1 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -2910,6 +2910,14 @@ config BNA
>
> <http://support.brocade.com>
>
> +config TMS320C64X_GEMAC
> + tristate "TMS320C64X GEMAC Ethernet Driver Support"
> + depends on TMS320C64XPLUS
> + default n
> + help
> + This driver supports the C64X+ SoC family ethernet
> + interface.
> +
> source "drivers/net/sfc/Kconfig"
>
> source "drivers/net/benet/Kconfig"
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index 01b604a..d768fde 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -259,6 +259,8 @@ obj-$(CONFIG_MLX4_CORE) += mlx4/
> obj-$(CONFIG_ENC28J60) += enc28j60.o
> obj-$(CONFIG_ETHOC) += ethoc.o
> obj-$(CONFIG_GRETH) += greth.o
> +obj-$(CONFIG_TMS320C64X_GEMAC) += gemac.o
> +gemac-objs := c6x_gemac.o c6x_gmdio.o
>
> obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
>
> diff --git a/drivers/net/c6x_gemac.c b/drivers/net/c6x_gemac.c
> new file mode 100644
> index 0000000..40124df
> --- /dev/null
> +++ b/drivers/net/c6x_gemac.c
> @@ -0,0 +1,1582 @@
> +/*
> + * Port on Texas Instruments TMS320C6x architecture
> + *
> + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Texas Instruments Incorporated
> + * Authors: Nicolas Videau (nicolas.videau@virtuallogix.com)
> + * Aurelien Jacquiot (a-jacquiot@ti.com)
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
Add #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/init.h>
> +#include <linux/slab.h>
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +#include <linux/skbuff.h>
> +#include <linux/spinlock.h>
> +#include <linux/timer.h>
> +#include <linux/platform_device.h>
> +#include <linux/io.h>
> +
> +#include <asm/setup.h>
> +#include <asm/irq.h>
> +#include <asm/gmdio.h>
> +#include <asm/gemac.h>
> +
> +#undef EMAC_DEBUG
> +
> +#ifdef EMAC_DEBUG
> +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "GEMAC: [%s] " fmt, __func__, ## args)
pr_debug(foo)
> +#define ASSERT(cond) if (!(cond)) DPRINTK("ASSERT %s FAILURE\n", # cond)
> +#else
> +#define ASSERT(cond)
> +#define DPRINTK(fmt, args...)
> +#endif
> +
> +static int emac_open(struct net_device *dev);
> +static int emac_close(struct net_device *dev);
> +static int emac_reset(struct net_device *dev, int reset_mode);
> +static void emac_set_modes(struct net_device *dev);
> +static void emac_fixup_modes(struct net_device *dev);
> +static void emac_reset_filter(struct net_device *dev,
> + int channel,
> + int reset_mode);
> +static void emac_set_filter(struct net_device *dev, int channel);
> +static int emac_reconfigure_device(struct net_device *dev);
> +
> +#ifdef EMAC_TIMER_TICK_MDIO
> +static struct timer_list emac_timer;
> +#endif
> +
> +static struct emac_config config = { 0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
> +
> +static int emac_shared;
> +static int emac_idx;
> +
> +inline long _hex_chartol(char c)
> +{
> + if (c >= '0' && c <= '9')
> + return c - '0';
> + if (c >= 'A' && c <= 'F')
> + return c - 'A' + 10;
> + if (c >= 'a' && c <= 'f')
> + return c - 'a' + 10;
> +
> + return -1;
> +}
kstrtol
> +
> +static unsigned long _hex_strtoul(const char *str, const char **end)
> +{
> + unsigned long ul = 0;
> + long ud;
> + while ((ud = _hex_chartol(*str)) >= 0) {
> + ul = (ul << 4) | ud;
> + str++;
> + }
> + *end = str;
> + return ul;
> +}
kstrtoul
> +
> +static int __init get_mac_addr_from_cmdline(char *str)
> +{
> + const char *start = (const char *) str;
> + const char *end;
> + int count;
> +
> + for (count = 0; count < 6; count++) {
> + config.enetaddr[count] = _hex_strtoul(start, &end);
> + if (end == start)
> + return 0;
> + if ((*end != ':') && (count != 5))
> + return 0;
> + start = end + 1;
> + }
> + return 1;
> +}
> +
> +__setup("emac_addr=", get_mac_addr_from_cmdline);
> +
> +static int __init set_emac_shared(char *str)
> +{
> + emac_shared = 1;
> + return 1;
> +}
> +
> +__setup("emac_shared", set_emac_shared);
> +
> +/*
> + * Get the device statistic
> + */
> +static struct net_device_stats *emac_get_stats(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> + unsigned int reg;
> + unsigned int dummy;
> + int i;
> +
> + emac_set_stat(dev->stats.multicast, EMAC_RXMCASTFRAMES);
> + emac_set_stat(dev->stats.collisions, EMAC_TXCOLLISION);
> + emac_set_stat(dev->stats.rx_length_errors, EMAC_RXOVERSIZED);
> + emac_set_stat(dev->stats.rx_length_errors, EMAC_RXUNDERSIZED);
> + emac_set_stat(dev->stats.rx_crc_errors, EMAC_RXCRCERRORS);
> + emac_set_stat(dev->stats.rx_frame_errors, EMAC_RXALIGNCODEERRORS);
> + emac_set_stat(dev->stats.tx_carrier_errors, EMAC_TXCARRIERSLOSS);
> + emac_set_stat(dev->stats.tx_fifo_errors, EMAC_TXUNDERRUN);
> + emac_set_stat(dev->stats.tx_window_errors, EMAC_TXLATECOLL);
> +
> + /* ACK statistic by write-to-decrement */
> + reg = EMAC_RXGOODFRAMES;
> + for (i = 0; i < EMAC_NUM_STATREGS; i++) {
> + dummy = emac_get_reg(reg);
> + emac_set_reg(reg, dummy);
> + reg += 4;
> + }
> +
> + return &dev->stats;
> +}
> +
> +/*
> + * Receive packets
> + */
> +static int emac_rx(struct net_device *dev, struct emac_desc *desc_ack)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> + volatile struct emac_desc *desc = ep->cur_rx;
> + ushort pkt_len;
> + u32 pkt_flags = desc->packet_flags_len & 0xffff0000;
> + int loop = 1;
> + struct sk_buff *skb, *skb_old;
> +
> + DPRINTK("%s: RX desc_ack = 0x%x, cur_rx = 0x%x, num = %d\n",
> + dev->name, desc_ack, desc, (desc_ack - desc));
netdev_dbg(dev, etc)
> +
> + if ((desc == desc_ack) && (desc->packet_flags_len == EMAC_DESC_FLAG_OWNER))
> + loop = 0;
> +
> + while (loop) {
> + skb_old = ep->rx_skbuff[ep->skb_rx_dirty];
> +
> + pkt_len = desc->packet_flags_len & EMAC_PACKET_LEN_MASK;
> + pkt_flags = desc->packet_flags_len & 0xffff0000;
> +
> + skb = netdev_alloc_skb_ip_align(dev, ep->packet_mtu);
> + if (skb != NULL) {
> + /* Prepare old sk_buff */
> + skb_old->dev = dev;
> + skb_put(skb_old, pkt_len);
> +
> + /* No coherency is assumed between EDMA and L2 cache */
> + L2_cache_block_invalidate((u32) desc->buff,
> + (u32) desc->buff + pkt_len);
> +
> + skb_old->protocol = eth_type_trans(skb_old, dev);
> +
> + /* Attach new sk_buff to RX ring */
> + desc->buff = (u8 *) skb->data;
> + ep->rx_skbuff[ep->skb_rx_dirty] = skb;
> +
> + DPRINTK("%s: receiving packet of %d len, proto 0x%x\n",
> + dev->name, pkt_len, skb->protocol);
> +
> + /* Give back old sk_buff */
> + netif_rx(skb_old);
> + dev->last_rx = jiffies;
> +
> + /* Fill statistic */
> + dev->stats.rx_packets++;
> + dev->stats.rx_bytes += pkt_len;
> + } else {
> + printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
netdev_warn(dev, "Memory squeeze, dropping packet\n");
Maybe ratelimited too.
> + dev->stats.rx_dropped++;
> + }
> +
> + /* Update RX dirty */
> + if (ep->skb_rx_dirty >= RX_RING_MOD_MAX)
> + ep->skb_rx_dirty = 0;
> + else
> + ep->skb_rx_dirty = ep->skb_rx_dirty + 1;
> +
> + /* Descriptor is now available */
> + desc->buff_offset_len = ep->packet_mtu;
> + desc->packet_flags_len = EMAC_DESC_FLAG_OWNER;
> +
> + /* Check if it is the last descriptor which has been received */
> + if (desc == desc_ack)
> + loop = 0;
> +
> + /* Loop in the ring */
> + desc = HW_TO_PTR(desc->next);
> + }
> + ep->cur_rx = (struct emac_desc *) desc;
> +
> + /* Check if the receiver stopped */
> + if (pkt_flags & EMAC_DESC_FLAG_EOQ)
> + emac_set_reg(EMAC_RX0HDP + (IDX_TO_CHAN(emac_idx) << 2),
> + PTR_TO_HW((u32) ep->cur_rx));
> +
> + return 0;
> +}
> +
> +/*
> + * Transmit packets ACK
> + */
> +static int emac_tx(struct net_device *dev, struct emac_desc *desc_ack)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> + volatile struct emac_desc *desc = ep->dirty_tx;
> + int loop = 1;
> +
> + while (loop) {
> + DPRINTK("%s: TX desc_ack = 0x%x, desc = 0x%x, num = %d\n",
> + dev->name, desc_ack, desc, (desc_ack - desc));
> +
> + if (ep->tx_skbuff[ep->skb_tx_dirty] == NULL) {
> + printk(KERN_ERR "%s: SKB NULL desc =%p desc_ack =%p, skb_tx_dirty=%ld count=%ld\n",
> + dev->name, desc, desc_ack, ep->skb_tx_dirty, ep->count_tx);
netdev_err("SKB NULL, etc...
Almost all of your printks should use netdev_<level>
> + break;
> + }
> +
> + /* Free the skbuff associated to this packet */
> + dev_kfree_skb_irq(ep->tx_skbuff[ep->skb_tx_dirty]);
> +
> + ep->tx_skbuff[ep->skb_tx_dirty] = NULL;
> + ep->skb_tx_dirty = (ep->skb_tx_dirty + 1) & TX_RING_MOD_MASK;
> + ep->count_tx--;
> +
> + /* Check if it is the last acknowledged descriptor */
> + if (desc++ == desc_ack)
> + loop = 0;
> +
> + /* Check end of the ring */
> + if (desc > ep->tx_desc_base + (TX_RING_SIZE - 1))
> + desc = ep->tx_desc_base;
> + }
> +
> + if (netif_running(dev))
> + netif_wake_queue(dev);
> +
> + /* Since we have freed up a buffer, the ring is no longer full */
> + if (ep->tx_full) {
> + ep->tx_full = 0;
> +
> + DPRINTK("%s: wake up queue count_tx = %d cur_tx = 0x%x head_tx\n",
> + dev->name, ep->count_tx, ep->cur_tx, ep->head_tx);
> +
> + if (netif_queue_stopped(dev))
> + netif_wake_queue(dev);
> + }
> +
> + /* If this is the end of the queue */
> + if (desc_ack->packet_flags_len & EMAC_DESC_FLAG_EOQ) {
> +
> + /* If there are some waiting packets, start the new queue */
> + if (ep->count_tx > 0)
> + emac_set_reg(EMAC_TX0HDP + (IDX_TO_CHAN(emac_idx) << 2),
> + PTR_TO_HW(ep->head_tx));
> +
> + /* Set the new head */
> + ep->head_tx = ep->cur_tx;
> + }
> +
> + /* Update dirty tx */
> + ep->dirty_tx = (struct emac_desc *) desc;
> +
> + return NETDEV_TX_OK;
> +}
> +
> +/*
> + * Transmit the content of a skbuff
> + */
> +static int emac_start_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> + volatile struct emac_desc *desc;
> + volatile struct emac_desc *prev_desc = NULL;
> + ushort pkt_len = skb->len;
> + unsigned long flags;
> +
> + if (ep->tx_full) {
> + printk(KERN_WARNING "%s: tx queue full\n", dev->name);
> + dev->stats.tx_dropped++;
> + return NETDEV_TX_BUSY;
> + }
> +
> + /* Pad short frame */
> + if (unlikely(pkt_len < ETH_ZLEN)) {
> + if (skb_padto(skb, ETH_ZLEN)) {
> + netif_wake_queue(dev);
> + return NETDEV_TX_OK;
> + }
> + pkt_len = ETH_ZLEN;
> + }
> +
> + spin_lock_irqsave(&ep->lock, flags);
> +
> + desc = ep->cur_tx;
> +
> + /* Set buffer length and pointer */
> + desc->buff = skb->data;
> + desc->packet_flags_len = pkt_len;
> + desc->buff_offset_len = pkt_len;
> + desc->next = NULL; /* close the queue*/
> +
> + /* No coherency is assumed between EDMA and L2 cache */
> + L2_cache_block_writeback((u32) skb->data,
> + (u32) skb->data + pkt_len);
> +
> + DPRINTK("%s: sending packet of %d len, skb_cur = %x, buffer = 0x%x\n",
> + dev->name, pkt_len, ep->skb_cur, skb->data);
> +
> + /* Save skb */
> + ep->tx_skbuff[ep->skb_cur] = skb;
> + ep->skb_cur = (ep->skb_cur + 1) & TX_RING_MOD_MASK;
> + dev->stats.tx_packets++;
> + dev->stats.tx_bytes += pkt_len;
> + dev->trans_start = jiffies;
> +
> + desc->packet_flags_len |= EMAC_DESC_FLAG_SOP
> + | EMAC_DESC_FLAG_EOP
> + | EMAC_DESC_FLAG_OWNER;
> +
> + /* Get the previous element of the ring if we are not the head */
> + if (desc != ep->head_tx) {
> + if (desc == ep->tx_desc_base)
> + prev_desc = ep->tx_desc_base + (TX_RING_SIZE - 1);
> + else
> + prev_desc = desc - 1;
> +
> + /* Link the buffer to the previous one in the list */
> + prev_desc->next = (struct emac_desc *) PTR_TO_HW(desc);
> + }
> +
> + ep->count_tx++;
> +
> + /* Update current pointer */
> + ep->cur_tx = (struct emac_desc *) desc + 1;
> +
> + /* Check end of ring */
> + if (ep->cur_tx > ep->tx_desc_base + (TX_RING_SIZE - 1))
> + ep->cur_tx = ep->tx_desc_base;
> +
> + /*
> + * If we are the new head and there is no descriptor to acknowledge, start
> + * the new head.
> + */
> + if ((desc == ep->head_tx) && (ep->count_tx == 1)) {
> + emac_set_reg(EMAC_TX0HDP + (IDX_TO_CHAN(emac_idx) << 2),
> + PTR_TO_HW(ep->head_tx));
> + ep->head_tx = ep->cur_tx; /* set the new head */
> + }
> +
> + /* Check ring oll over: do not reach the not yet acknowledged packets */
> + if (ep->count_tx == TX_RING_SIZE) {
> + ep->tx_full = 1;
> +
> + DPRINTK("%s: tx queue full count_tx = %d cur_tx = 0x%x head_tx\n",
> + dev->name, ep->count_tx, ep->cur_tx, ep->head_tx);
> +
> + netif_stop_queue(dev);
> + }
> + spin_unlock_irqrestore(&ep->lock, flags);
> +
> + return NETDEV_TX_OK;
> +}
> +
> +static void emac_handle_host_interrupt(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> + unsigned long status;
> +
> + /* Handle host error */
> + status = emac_get_reg(EMAC_MACSTATUS);
> +
> + /* Check if the problem occurs on our channel when we are slave */
> + if ((ep->slave)
> + && (((status & EMAC_M_RXERRCH) >> EMAC_S_RXERRCH) != IDX_TO_CHAN(emac_idx))
> + && (((status & EMAC_M_TXERRCH) >> EMAC_S_TXERRCH) != IDX_TO_CHAN(emac_idx)))
> + return;
> +
> + if ((status & EMAC_M_RXERRCODE) == (EMAC_V_OWNERSHIP << EMAC_S_RXERRCODE)) {
> + printk(KERN_ERR "%s: EMAC rx ring full\n", dev->name);
> + dev->stats.rx_fifo_errors++;
> + } else
> + printk(KERN_ERR "%s: EMAC fatal host error 0x%lx\n",
> + dev->name, status);
> +
> + DPRINTK(KERN_ERR "%s: Error head=%p desc=%p dirty=%p skb_tx_dirty=%ld count=%ld\n",
> + dev->name, ep->head_tx, ep->cur_tx,
> + ep->dirty_tx, ep->skb_tx_dirty, ep->count_tx);
> +
> + if (!ep->slave) {
> + /* Reconfigure the device */
> + ep->fatal_error = 1;
> + emac_reconfigure_device(dev);
> + }
> +}
> +
> +/*
> + * Receive EMAC interrupt management
> + */
> +
> +#ifdef EMAC_HAS_SEPARATE_RXTX_IRQS
> +
> +static irqreturn_t emac_rx_interrupt(int irq, void *netdev_id)
> +{
> + struct net_device *dev = netdev_id;
> + struct emac_private *ep = netdev_priv(dev);
> + struct emac_desc *desc;
> + unsigned long irq_flags;
> +
> + ectl_arch_rx_irq_enter(IDX_TO_CHAN(emac_idx));
> +
> + irq_flags = emac_arch_get_int_vector();
> +
> + if (irq_flags & EMAC_B_STATPEND)
> + (void) emac_get_stats(dev);
> +
> + if (irq_flags & EMAC_B_HOSTPEND)
> + emac_handle_host_interrupt(dev);
> +
> + if (emac_arch_get_pending_irq(irq_flags,
> + EMAC_B_RXPEND0,
> + IDX_TO_CHAN(emac_idx))) {
> +
> + /* ACK the interrupt */
> + desc = (struct emac_desc *) emac_get_reg(EMAC_RX0INTACK
> + + (IDX_TO_CHAN(emac_idx) << 2));
> + emac_set_reg(EMAC_RX0INTACK + (IDX_TO_CHAN(emac_idx) << 2), desc);
> +
> + /* Handle receive event */
> + emac_rx(netdev_id, HW_TO_PTR(desc));
> + }
> +
> + ectl_arch_rx_irq_leave(IDX_TO_CHAN(emac_idx));
> +
> + return IRQ_HANDLED;
> +}
> +
> +/*
> + * Transmit EMAC interrupt management
> + */
> +static irqreturn_t emac_tx_interrupt(int irq, void *netdev_id)
> +{
> + struct net_device *dev = netdev_id;
> + struct emac_private *ep = netdev_priv(dev);
> + struct emac_desc *desc;
> + unsigned long irq_flags;
> +
> + ectl_arch_tx_irq_enter(IDX_TO_CHAN(emac_idx));
> +
> + irq_flags = emac_arch_get_int_vector();
> +
> + if (irq_flags & EMAC_B_STATPEND)
> + (void) emac_get_stats(dev);
> +
> + if (irq_flags & EMAC_B_HOSTPEND)
> + emac_handle_host_interrupt(dev);
> +
> + if (emac_arch_get_pending_irq(irq_flags,
> + EMAC_B_TXPEND0,
> + IDX_TO_CHAN(emac_idx))) {
> +
> + /* ACK the interrupt */
> + desc = (struct emac_desc *) emac_get_reg(EMAC_TX0INTACK
> + + (IDX_TO_CHAN(emac_idx) << 2));
> + emac_set_reg(EMAC_TX0INTACK + (IDX_TO_CHAN(emac_idx) << 2), desc);
> +
> + /* Handle transmit ACK event */
> + emac_tx(netdev_id, HW_TO_PTR(desc));
> + }
> +
> + ectl_arch_tx_irq_leave(IDX_TO_CHAN(emac_idx));
> +
> + return IRQ_HANDLED;
> +}
> +
> +#else
> +
> +/*
> + * Main EMAC interrupt management
> + */
> +static irqreturn_t emac_interrupt(int irq, void *netdev_id)
> +{
> + struct net_device *dev = netdev_id;
> + struct emac_private *ep = netdev_priv(dev);
> + struct emac_desc *desc;
> + unsigned long irq_flags;
> +
> + /* Disable EMAC/MDIO interrupts */
> + emac_clearbit_reg(EMAC_EWCTL, EMAC_B_INTEN);
> +
> + irq_flags = emac_get_reg(EMAC_MACINVECTOR);
> +
> + if (irq_flags & EMAC_B_STATPEND)
> + (void) emac_get_stats(dev);
> +
> + if (irq_flags & EMAC_B_HOSTPEND) {
> + emac_handle_host_interrupt(dev);
> +
> + /* EMAC/MDIO interrupts already enabled by emac_open() */
> + return IRQ_HANDLED;
> + }
> +
> + if (irq_flags & EMAC_B_TXPEND0) {
> + /* ACK the interrupt */
> + desc = (struct emac_desc *) emac_get_reg(EMAC_TX0INTACK);
> + emac_set_reg(EMAC_TX0INTACK, desc);
> +
> + /* Handle transmit ACK event */
> + emac_tx(netdev_id, desc);
> + }
> +
> + if (irq_flags & EMAC_B_RXPEND0) {
> + /* ACK the interrupt */
> + desc = (struct emac_desc *) emac_get_reg(EMAC_RX0INTACK);
> + emac_set_reg(EMAC_RX0INTACK, desc);
> +
> + /* Handle receive event */
> + emac_rx(netdev_id, desc);
> + }
> +
> + /* Enable EMAC/MDIO interrupts */
> + emac_setbit_reg(EMAC_EWCTL, EMAC_B_INTEN);
> +
> + return IRQ_HANDLED;
> +}
> +#endif
> +
> +#ifdef CONFIG_NET_POLL_CONTROLLER
> +/*
> + * EMAC poll
> + */
> +static void emac_poll(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> +
> + ectl_arch_disable_irq(IDX_TO_CHAN(emac_idx));
> +
> +#ifdef EMAC_HAS_SEPARATE_RXTX_IRQS
> + emac_tx_interrupt(dev->irq + 1, dev);
> + emac_rx_interrupt(dev->irq, dev);
> +#else
> + emac_interrupt(dev->irq, dev);
> +#endif
> +
> + ectl_arch_enable_irq(IDX_TO_CHAN(emac_idx), !ep->slave);
> +}
> +#endif
> +
> +/*
> + * Register the MAC address
> + */
> +
> +static void emac_register_mac_addr(struct net_device *dev, int idx)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> + u32 val;
> + int i;
> +
> + /* Copy the config MAC address to the dev_addr */
> + for (i = 4; i >= 0; i--)
> + dev->dev_addr[i] = config.enetaddr[i];
> + /*
> + * Compute MAC addr low for all for the given EMAC instances if several.
> + * Each device consume n MAC addresses where n is the number cores.
> + * This value is for GEM0, this value + 2 is for GEM1, etc
> + * The number programmed in this field will be incremented by n * 2 from
> + * device to device
> + */
> + dev->dev_addr[5] = (config.enetaddr[5] +
> + (IDX_TO_MAC(idx)) + DEV_TO_MAC(dev->dev_id)) & 0xff;
> +
> + /* Choose MAC address index between 0 and 31 */
> + emac_arch_set_mac_addr_index(idx);
> +
> + /* Compute and store MAC addr high */
> + val = 0;
> + for (i = 3; i >= 0; i--)
> + val = (val << 8) | dev->dev_addr[i];
Inconsistent style with low portion below
and function emac_reset.
This might be better as:
val = (dev->dev_addr[3] << 24) |
(dev->dev_addr[2] << 16) |
(dev->dev_addr[1] << 8) |
(dev->dev_addr[0] << 0);
> + emac_arch_set_mac_addr_high(val);
> +
> + val = (dev->dev_addr[5] << 8) | dev->dev_addr[4];
> + val |= (1 << EMAC_S_VALID)
> + | (1 << EMAC_S_MATCHFILTER)
> + | (IDX_TO_CHAN(idx) << EMAC_S_CHANNEL);
> +
> + emac_arch_set_mac_addr_low(val);
> +}
> +
> +/*
> + * Reset the EMAC software ring.
> + */
> +static void emac_reset_ring(struct emac_private *ep)
> +{
> + struct emac_desc *desc;
> + int i;
> +
> + desc = (struct emac_desc *) ep->emac_dsc_base;
> +
> + /* Reset rx ring */
> + ep->cur_rx = desc;
> + ep->skb_rx_dirty = 0;
> +
> + for (i = 0; i < RX_RING_SIZE; desc++, i++)
> + desc->packet_flags_len = EMAC_DESC_FLAG_OWNER;
> +
> + /* Reset tx ring */
> + desc = (struct emac_desc *) (ep->emac_dsc_base + (RX_RING_SIZE << 4));
> + ep->cur_tx = desc;
> + ep->dirty_tx = desc;
> + ep->head_tx = desc;
> + ep->skb_cur = 0;
> + ep->skb_tx_dirty = 0;
> + ep->tx_full = 0;
> + ep->fatal_error = 0;
> + ep->count_tx = 0;
> +
> + for (i = 0; i < TX_RING_SIZE; i++) {
> + desc->buff = NULL;
> + desc->buff_offset_len = 0;
> + desc->packet_flags_len = 0;
> + desc->next = NULL;
> + ep->tx_skbuff[i] = NULL;
memset?
> + desc++;
> + }
> +}
> +
> +/*
> + * Reconfigure the EMAC device
> + */
> +static int emac_reconfigure_device(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> +
> + if (!ep->slave) {
> + unsigned int hash1;
> + unsigned int hash2;
> + unsigned int promisc;
> + unsigned int control;
> + unsigned int rx_intmask;
> + unsigned int tx_intmask;
> + unsigned int unicast;
> + unsigned int *mac_ctx;
> + int i;
> +
> + /* Get state */
> + hash1 = emac_arch_get_hash1();
> + hash2 = emac_arch_get_hash2();
> + promisc = emac_arch_get_promisc();
> + control = emac_arch_get_control();
> +
> + unicast = emac_get_reg(EMAC_RXUNICASTSET);
> + rx_intmask = emac_get_reg(EMAC_RXINTMASKSET);
> + tx_intmask = emac_get_reg(EMAC_TXINTMASKSET);
> +
> + /* Save MAC addresses */
> + mac_ctx = kmalloc((sizeof(u32) << 1) * MAC_ADDR_NUM, GFP_KERNEL);
> + for (i = 0; i < MAC_ADDR_NUM; i++) {
> + emac_arch_set_mac_addr_index(i);
> + mac_ctx[i << 1] = emac_arch_get_mac_addr_high();
> + mac_ctx[(i << 1) + 1] = emac_arch_get_mac_addr_low();
> + }
> +
> + /* Reset the EMAC */
> + if (netif_running(dev)) {
> + emac_close(dev);
> + emac_reset(dev, GEMAC_RESET_WARM);
> + emac_open(dev);
> + } else {
> + emac_reset(dev, GEMAC_RESET_WARM);
> + }
> +
> + /* Restore MAC addresses */
> + for (i = 0; i < MAC_ADDR_NUM; i++) {
> + emac_arch_set_mac_addr_index(i);
> + emac_arch_set_mac_addr_high(mac_ctx[i << 1]);
> + emac_arch_set_mac_addr_low(mac_ctx[(i << 1) + 1]);
> + }
> + kfree(mac_ctx);
> +
> + /* Restore state */
> + emac_arch_set_hash1(hash1);
> + emac_arch_set_hash2(hash2);
> + emac_arch_set_promisc(hash2);
> + emac_arch_set_control(hash2);
> +
> + emac_set_reg(EMAC_RXINTMASKSET, rx_intmask);
> + emac_set_reg(EMAC_TXINTMASKSET, tx_intmask);
> + emac_set_reg(EMAC_RXUNICASTSET, unicast);
> + } else
> + /* Only master core can reset the device */
> + return -EBUSY;
> +
> + return 0;
> +}
> +
> +/*
> + * Reset the EMAC hardware.
> + */
> +static int emac_reset(struct net_device *dev, int reset_mode)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> + volatile u32 *preg;
volatile?
> + int i;
> +
> + if (!ep->slave) {
> +
> + if (reset_mode == GEMAC_RESET_COLD) {
> + /* Reset integrated switch if any */
> + emac_arch_reset_switch();
> +
> + /* Reset EMAC control Module */
> + emac_arch_reset_ectl();
> + }
> +
> + /* Reset EMAC */
> + emac_setbit_reg(EMAC_SOFTRESET, EMAC_B_SOFTRST);
> +
> + /* Wait until reset has occured or timeout */
> + for (i = 0; i <= HZ / 2; i++) {
> + if (emac_get_reg(EMAC_SOFTRESET) == 0x0)
> + break;
> + if (i == HZ / 2)
> + return 1;
> + msleep_interruptible(1);
> + }
> + }
> +
> + /* Set interrupt pacing */
> + emac_arch_set_pacing();
> +
> + if (!ep->slave) {
> + /* Reset MAC, TX, RX Control */
> + emac_set_reg(EMAC_MACCONTROL, 0);
> + emac_set_reg(EMAC_TXCONTROL, 0);
> + emac_set_reg(EMAC_RXCONTROL, 0);
> +
> + if (reset_mode == GEMAC_RESET_COLD) {
> +#ifdef EMAC_DO_INIT_MDIO
> + /* MII/MDIO setup */
> + mdio_init(emac_get_reg(EMAC_TXIDVER));
> +#endif
> +
> + /* Init HDPs to NULL for all channels */
> + emac_set_reg(EMAC_TX0HDP, 0);
> + emac_set_reg(EMAC_TX1HDP, 0);
> + emac_set_reg(EMAC_TX2HDP, 0);
> + emac_set_reg(EMAC_TX3HDP, 0);
> + emac_set_reg(EMAC_TX4HDP, 0);
> + emac_set_reg(EMAC_TX5HDP, 0);
> + emac_set_reg(EMAC_TX6HDP, 0);
> + emac_set_reg(EMAC_TX7HDP, 0);
> + emac_set_reg(EMAC_RX0HDP, 0);
> + emac_set_reg(EMAC_RX1HDP, 0);
> + emac_set_reg(EMAC_RX2HDP, 0);
> + emac_set_reg(EMAC_RX3HDP, 0);
> + emac_set_reg(EMAC_RX4HDP, 0);
> + emac_set_reg(EMAC_RX5HDP, 0);
> + emac_set_reg(EMAC_RX6HDP, 0);
> + emac_set_reg(EMAC_RX7HDP, 0);
> +
> + /* Clear statistic registers */
> + if (reset_mode == GEMAC_RESET_COLD) {
> + preg = emac_addr_reg(EMAC_RXGOODFRAMES);
> + for (i = 0; i < EMAC_NUM_STATREGS; i++)
> + *preg++ = 0;
> + }
> +
> + /* Clear all MAC addresses */
> + emac_arch_clear_mac_addr();
> + }
> + }
> +
> + /* Register my MAC address */
> + emac_register_mac_addr(dev, emac_idx);
> +
> + if (!ep->slave) {
> +
> + /* Used for pause frame (IEEE 802.3x) but not working for MC */
> + emac_set_reg(EMAC_MACSRCADDRLO,
> + (dev->dev_addr[0] << 8) | dev->dev_addr[1]);
> + emac_set_reg(EMAC_MACSRCADDRHI,
> + (dev->dev_addr[2] << 24) | (dev->dev_addr[3] << 16) |
> + (dev->dev_addr[4] << 8) | (dev->dev_addr[5]));
> +
> + if (reset_mode == GEMAC_RESET_COLD) {
> +
> + /* Init completion pointers to NULL */
> + emac_set_reg(EMAC_RX0INTACK, 0x0);
> + emac_set_reg(EMAC_RX1INTACK, 0x0);
> + emac_set_reg(EMAC_RX2INTACK, 0x0);
> + emac_set_reg(EMAC_RX3INTACK, 0x0);
> + emac_set_reg(EMAC_RX4INTACK, 0x0);
> + emac_set_reg(EMAC_RX5INTACK, 0x0);
> + emac_set_reg(EMAC_RX6INTACK, 0x0);
> + emac_set_reg(EMAC_RX7INTACK, 0x0);
> + emac_set_reg(EMAC_TX0INTACK, 0x0);
> + emac_set_reg(EMAC_TX1INTACK, 0x0);
> + emac_set_reg(EMAC_TX2INTACK, 0x0);
> + emac_set_reg(EMAC_TX3INTACK, 0x0);
> + emac_set_reg(EMAC_TX4INTACK, 0x0);
> + emac_set_reg(EMAC_TX5INTACK, 0x0);
> + emac_set_reg(EMAC_TX6INTACK, 0x0);
> + emac_set_reg(EMAC_TX7INTACK, 0x0);
> + }
> +
> + /* Reset unicast, multicast, broadcast Rx */
> + emac_reset_filter(dev, IDX_TO_CHAN(emac_idx), reset_mode);
> +
> + /* Set device modes */
> + emac_set_modes(dev);
> +
> + /* Disable all channel interrupts */
> + if (reset_mode == GEMAC_RESET_COLD) {
> + emac_set_reg(EMAC_RXINTMASKCLEAR, 0xff);
> + emac_set_reg(EMAC_TXINTMASKCLEAR, 0xff);
> + }
> +
> + /* Enable host and stat interrupts */
> + emac_set_reg(EMAC_MACINTMASKSET, EMAC_B_HOSTINT | EMAC_B_STATINT);
> + } else {
> + /* Fixup mode according to hw configuration */
> + emac_fixup_modes(dev);
> + }
> +
> + /* Enable TX and RX interrupts for a given channel */
> + emac_arch_enable_irq(EMAC_TXINTMASKSET, IDX_TO_CHAN(emac_idx));
> + emac_arch_enable_irq(EMAC_RXINTMASKSET, IDX_TO_CHAN(emac_idx));
> +
> + /* Reset transmit/receive buffers */
> + if (reset_mode == GEMAC_RESET_WARM)
> + (void) emac_reset_ring(ep);
> +
> + /* Set default receive filter: unicast, multicast and broadcast */
> + emac_set_filter(dev, IDX_TO_CHAN(emac_idx));
> +
> + return 0;
> +}
> +
> +/*
> + * Open the device
> + */
> +static int emac_open(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> +
> + if (!ep->slave) {
> + /* Set MAC mode (Gigabyte, xxMII, pacing, etc) */
> + emac_arch_init_control(ep->mode_flags & EMAC_CONFIG_PACING);
> +
> + /* Enable RX and TX */
> + emac_set_reg(EMAC_TXCONTROL, 1);
> + emac_set_reg(EMAC_RXCONTROL, 1);
> + }
> +
> + /* Ready for RX */
> + emac_set_reg(EMAC_RX0HDP + (IDX_TO_CHAN(emac_idx) << 2),
> + PTR_TO_HW(ep->cur_rx));
> +
> + /* Enable interrupts at the ECTL level (misc int only for master) */
> + ectl_arch_enable_irq(IDX_TO_CHAN(emac_idx), !ep->slave);
> +
> + netif_start_queue(dev);
> +
> + return 0;
> +}
> +
> +/*
> + * Close the device
> + */
> +static int emac_close(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> +
> + netif_stop_queue(dev);
> +
> + /* Disable interrupt at the ECTL level */
> + ectl_arch_disable_irq(IDX_TO_CHAN(emac_idx));
> +
> + /* Teardown RX and TX */
> + emac_set_reg(EMAC_RXTEARDOWN, IDX_TO_CHAN(emac_idx));
> + emac_set_reg(EMAC_TXTEARDOWN, IDX_TO_CHAN(emac_idx));
> +
> + if (!ep->fatal_error) {
> + unsigned int tmp;
> +
> + /* Wait for the teardown to complete */
> + for (tmp = 0; tmp != 0xfffffffc;
> + tmp = emac_get_reg(EMAC_RX0INTACK + \
Don't use line continuations unnecessarily please.
> + (IDX_TO_CHAN(emac_idx) << 2)))
> + emac_set_reg(EMAC_RX0INTACK + \
> + (IDX_TO_CHAN(emac_idx) << 2), tmp);
> +
> + for (tmp = 0; tmp != 0xfffffffc;
> + tmp = emac_get_reg(EMAC_TX0INTACK + \
> + (IDX_TO_CHAN(emac_idx) << 2)))
> + emac_set_reg(EMAC_TX0INTACK + \
> + (IDX_TO_CHAN(emac_idx) << 2), tmp);
> + }
> +
> + if (!ep->slave) {
> + /* Disable Rx, Tx and MII */
> + emac_set_reg(EMAC_TXCONTROL, 0);
> + emac_set_reg(EMAC_RXCONTROL, 0);
> + emac_set_reg(EMAC_MACCONTROL, 0);
> + }
> +
> + /* Clean up the software ring */
> + emac_reset_ring(ep);
> +
> + return 0;
> +}
> +
> +/*
> + * Initialize the EMAC software ring.
> + * For the rx ring, we initialize the packet descriptors with pre-allocated
> + * skbuff to the packet MTU size.
> + * For the tx ring, we only initialize it with NULL values.
> + */
> +static int emac_setup_ring(struct emac_private *ep)
> +{
> + struct emac_desc *desc;
> + int i;
> + struct sk_buff *skb;
> +
> + /* Setup rx ring*/
> + desc = (struct emac_desc *) ep->emac_dsc_base;
> + ep->rx_desc_base = desc;
> + ep->cur_rx = desc;
> + ep->skb_rx_dirty = 0;
> +
> + /* Allocate ring buffers via sk buffers */
> + for (i = 0; i < RX_RING_SIZE; i++) {
> + skb = netdev_alloc_skb_ip_align(ep->dev, ep->packet_mtu);
> + if (!skb)
> + return 1;
> +
> + ep->rx_skbuff[i] = skb;
> + desc->buff = (u8 *) skb->data;
> + desc->buff_offset_len = ep->packet_mtu;
> + desc->packet_flags_len = EMAC_DESC_FLAG_OWNER;
> + desc->next = PTR_TO_HW(desc + 1);
> + desc++;
> + }
> +
> + /* Loop the ring */
> + (desc - 1)->next = PTR_TO_HW(ep->rx_desc_base);
> +
> + /* Setup tx ring */
> + desc = (struct emac_desc *) (ep->emac_dsc_base + (RX_RING_SIZE << 4));
> + ep->tx_desc_base = desc;
> + ep->cur_tx = desc;
> + ep->dirty_tx = desc;
> + ep->head_tx = desc;
> + ep->skb_cur = 0;
> + ep->skb_tx_dirty = 0;
> + ep->tx_full = 0;
> + ep->fatal_error = 0;
> + ep->count_tx = 0;
> +
> + for (i = 0; i < TX_RING_SIZE; i++) {
> + desc->buff = NULL;
> + desc->buff_offset_len = 0;
> + desc->packet_flags_len = 0;
> + desc->next = NULL;
> + ep->tx_skbuff[i] = NULL;
> + desc++;
> + }
> + return 0;
> +}
> +
> +/*
> + * Called by the kernel to send a packet out into the void
> + * of the net.
> + */
> +static void emac_timeout(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> +
> + printk(KERN_WARNING "%s: transmit timed out\n", dev->name);
> + dev->stats.tx_errors++;
> + dev->trans_start = jiffies;
> + if (!ep->tx_full)
> + netif_wake_queue(dev);
> +}
> +
> +/*
> + * Set or clear the multicast filter for this adaptor.
> + */
> +#ifdef EMAC_HAS_ALE_SUPPORT
> +static void emac_reset_filter(struct net_device *dev,
> + int channel,
> + int reset_mode)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> + int i;
> +
> + if (reset_mode == GEMAC_RESET_COLD) {
> + /* Alloc mcast list */
> + ep->mcast_infos = kmalloc(3 * EMAC_V_ALE_MAX_MCAST, GFP_KERNEL);
> + /* Init mcast table */
> + if (ep->mcast_infos) {
> + memset(ep->mcast_infos, 0x0, 3 * EMAC_V_ALE_MAX_MCAST);
> + /* Clear device multicast list */
> + for (i = 0; i < EMAC_V_ALE_MAX_MCAST; i++) {
> + emac_set_reg(EMAC_ALETBLW0, 0);
> + emac_set_reg(EMAC_ALETBLW1, 0);
> + emac_set_reg(EMAC_ALETBLW2, 0);
> + emac_set_reg(EMAC_ALETBLCTL,
> + i | EMAC_B_ALE_WRITE_RDZ);
> + }
> + }
> + }
> + if ((reset_mode == GEMAC_RESET_WARM) && (ep->mcast_infos)) {
> + /* Re-set device multicast list */
> + for (i = 0; i < ep->mcast_valid_len; i++) {
> + emac_set_reg(EMAC_ALETBLW0, ep->mcast_infos[3*i]);
> + emac_set_reg(EMAC_ALETBLW1, ep->mcast_infos[3*i+1]);
> + emac_set_reg(EMAC_ALETBLW2, ep->mcast_infos[3*i+2]);
> + emac_set_reg(EMAC_ALETBLCTL,
> + i | EMAC_B_ALE_WRITE_RDZ);
> + }
> + /* Set mcast mode if needed */
> + if (ep->mcast_valid_len)
> + emac_setbit_reg(EMAC_ALEUNKNOWNVLAN,
> + EMAC_B_REG_MCAST_FLOOD_ON);
> + }
> +}
> +
> +static void emac_set_modes(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> +
> + if (ep->mode_flags & EMAC_CONFIG_RXCRC)
> + ep->packet_mtu = PKT_MTU_CRC;
> + else
> + ep->packet_mtu = PKT_MTU_NOCRC;
> +
> + /* If PASSERROR is set, enable both ERROR and short frames */
> + if (ep->mode_flags & EMAC_CONFIG_PASSERROR)
> + emac_setbit_reg(EMAC_MACCONTROL,
> + EMAC_B_RXCEFEN | EMAC_B_RXCSFEN);
> +
> + /* If PASSCONTROL is set, enable control frames */
> + if (ep->mode_flags & EMAC_CONFIG_PASSCONTROL)
> + emac_setbit_reg(EMAC_MACCONTROL, EMAC_B_RXCMFEN);
> +
> + /* Set MAC loopback if requested */
> + if (ep->mode_flags & EMAC_CONFIG_MACLOOPBACK)
> + emac_setbit_reg(EMAC_MACCONTROL, EMAC_B_LOOPBACK);
> +}
> +
> +static void emac_set_filter(struct net_device *dev, int channel)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> +
> + emac_set_reg(CPSW_SW_CTL, 0x000000F4); /* Enable switch flow control */
> + emac_set_reg(CPSW_RX_CH_MAP, 0x11110000); /* RX switch priority */
> +
> + emac_set_reg(EMAC_ALECONTROL, 0x80000004); /* ALE enable and bypass */
> + emac_set_reg(EMAC_ALEPRESCALE, 0x0); /* no mcat/broadcast limit */
> + emac_set_reg(EMAC_ALEUNKNOWNVLAN, 0x07030307); /* need it!!! */
> + emac_set_reg(EMAC_ALEPORTCTL0, 0x3); /* Port 0 in forward state */
> + emac_set_reg(EMAC_ALEPORTCTL1, 0x3); /* Port 1 in forward state */
> + emac_set_reg(EMAC_ALEPORTCTL2, 0x3); /* Port 2 in forward state */
> +}
> +
> +static void emac_set_rx_mode(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> + struct dev_mc_list *dmi = dev->mc_list;
> + u8 hashval, tmpval;
> + u32 info0, info1, info2;
> + int i;
> +
> + /* Only master can use promiscuous or multicast */
> + if (ep->slave)
> + return;
> +
> + if (dev->flags & IFF_PROMISC)
> + /* Set promiscuous mode */
> + emac_setbit_reg(EMAC_ALECONTROL, EMAC_B_ALEBYPASS);
> + else
> + /* Reset promiscuous mode */
> + emac_clearbit_reg(EMAC_ALECONTROL, EMAC_B_ALEBYPASS);
> +
> + /* Clear multicast config */
> + emac_clearbit_reg(EMAC_ALEUNKNOWNVLAN, EMAC_B_MCAST_FLOOD_ON |
> + EMAC_B_REG_MCAST_FLOOD_ON);
> +
> + /* Clear old multicast list that will not be reused */
> + for (i = dev->mc_count; i < ep->mcast_valid_len; i++) {
> + emac_setbit_reg(EMAC_ALETBLW0, 0);
> + emac_setbit_reg(EMAC_ALETBLW1, 0);
> + emac_setbit_reg(EMAC_ALETBLW2, 0);
> + emac_setbit_reg(EMAC_ALETBLCTL,
> + i | EMAC_B_ALE_WRITE_RDZ);
> + }
> +
> + if ((dev->flags & IFF_ALLMULTI) ||
> + (dev->mc_count > EMAC_V_ALE_MAX_MCAST)) {
> + /* Set all multicast */
> + emac_setbit_reg(EMAC_ALEUNKNOWNVLAN, EMAC_B_MCAST_FLOOD_ON |
> + EMAC_B_REG_MCAST_FLOOD_ON);
> + } else {
> + /* Set mcast from a list */
> + for (i = 0; i < dev->mc_count; i++, dmi = dmi->next) {
> + u8 *p_dmi = dmi->dmi_addr;
> +
> + info0 = (((p_dmi[2]&0x0ff)<<24) |
> + ((p_dmi[3]&0x0ff)<<16) |
> + ((p_dmi[4]&0x0ff)<<8) | ((p_dmi[5]&0x0ff)<<0));
> + info1 = ((3<<30) | (0<<29) | (1<<28) |
> + ((0&0x0fff)<<16) |
> + ((p_dmi[0]&0x0ff)<<8) | ((p_dmi[1]&0x0ff)<<0));
> + info2 = (0 << 3) | (7 & 0x7);
> +
> + /* Only support group multicast */
> + if (!(*p_dmi & 1)) {
> + /* don't use this entry */
> + info0 = 0;
> + info1 = 1;
> + info2 = 2;
> + }
> +
> + emac_set_reg(EMAC_ALETBLW0, info0);
> + emac_set_reg(EMAC_ALETBLW1, info1);
> + emac_set_reg(EMAC_ALETBLW2, info2);
> + emac_set_reg(EMAC_ALETBLCTL,
> + i | EMAC_B_ALE_WRITE_RDZ);
> +
> + /* Copy mcast list */
> + if (ep->mcast_infos) {
> + ep->mcast_infos[3*i] = info0;
> + ep->mcast_infos[3*i+1] = info1;
> + ep->mcast_infos[3*i+2] = info2;
> + }
> + }
> +
> + /* set multicast mode if needed */
> + if (dev->mc_count)
> + emac_setbit_reg(EMAC_ALEUNKNOWNVLAN,
> + EMAC_B_REG_MCAST_FLOOD_ON);
> +
> + /* Remember mcast valid addrs count */
> + ep->mcast_valid_len = dev->mc_count;
> + }
> +}
> +
> +#else /* !EMAC_HAS_ALE_SUPPORT */
> +
> +static void emac_reset_filter(struct net_device *dev,
> + int channel,
> + int reset_mode)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> +
> + /* Reset multicast hash table */
> + emac_set_reg(EMAC_MACHASH1, 0);
> + emac_set_reg(EMAC_MACHASH2, 0);
> +
> + /* Set buffer offset */
> + emac_set_reg(EMAC_RXBUFFEROFFSET, 0);
> +
> + /* Reset RX (M)ulticast (B)roadcast (P)romiscuous Enable register */
> + emac_set_reg(EMAC_RXMBPENABLE, 0);
> +
> + if (reset_mode == GEMAC_RESET_COLD) {
> + /* Clear unicast RX on channel 0-7 */
> + emac_set_reg(EMAC_RXUNICASTCLEAR, 0xff);
> + } else
> + emac_set_reg(EMAC_RXUNICASTCLEAR, (1 << channel));
> +}
> +
> +static void emac_fixup_modes(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> +
> + if (emac_get_reg(EMAC_RXMBPENABLE) & EMAC_B_RXPASSCRC)
> + ep->packet_mtu = PKT_MTU_CRC;
> + else
> + ep->packet_mtu = PKT_MTU_NOCRC;
> +}
> +
> +static void emac_set_modes(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> +
> + if (ep->slave)
> + return;
> +
> + if (ep->mode_flags & EMAC_CONFIG_RXCRC) {
> + emac_setbit_reg(EMAC_RXMBPENABLE, EMAC_B_RXPASSCRC);
> + ep->packet_mtu = PKT_MTU_CRC;
> + } else
> + ep->packet_mtu = PKT_MTU_NOCRC;
> +
> + /* If PASSERROR is set, enable both ERROR and short frames */
> + if (ep->mode_flags & EMAC_CONFIG_PASSERROR)
> + emac_setbit_reg(EMAC_RXMBPENABLE,
> + EMAC_B_RXCEFEN | EMAC_B_RXCSFEN);
> +
> + /* If PASSCONTROL is set, enable control frames */
> + if (ep->mode_flags & EMAC_CONFIG_PASSCONTROL)
> + emac_setbit_reg(EMAC_RXMBPENABLE, EMAC_B_RXCMFEN);
> +
> + /* Set the channel configuration to priority if requested */
> + if (ep->mode_flags & EMAC_CONFIG_CHPRIORITY)
> + emac_setbit_reg(EMAC_MACCONTROL, EMAC_B_TXPTYPE);
> +
> + /* Set MAC loopback if requested */
> + if (ep->mode_flags & EMAC_CONFIG_MACLOOPBACK)
> + emac_setbit_reg(EMAC_MACCONTROL, EMAC_B_LOOPBACK);
> +}
> +
> +static void emac_set_filter(struct net_device *dev, int channel)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> +
> + /* Set unicast for the given channel */
> + emac_set_reg(EMAC_RXUNICASTSET, 1 << channel);
> +
> + if (!ep->slave) {
> + emac_set_reg(EMAC_RXMBPENABLE, 0);
> + emac_setbit_reg(EMAC_RXMBPENABLE, EMAC_B_MULTEN);
> + emac_setbit_reg(EMAC_RXMBPENABLE, EMAC_B_BROADEN);
> + emac_setbit_reg(EMAC_RXMBPENABLE, (channel | (channel << 8)));
> + }
> +}
> +
> +static void emac_set_rx_mode(struct net_device *dev)
> +{
> + struct emac_private *ep = netdev_priv(dev);
> + struct netdev_hw_addr *ha;
> + u8 hashval, tmpval;
> + u32 machash1, machash2;
> + int i;
> +
> + /* Only master can use promiscuous or multicast */
> + if (ep->slave)
> + return;
> +
> + if (dev->flags & IFF_PROMISC) {
> + /* Set promiscuous mode */
> + emac_setbit_reg(EMAC_RXMBPENABLE, EMAC_B_RXCAFEN);
> + } else {
> + /* Reset promiscuous mode */
> + emac_clearbit_reg(EMAC_RXMBPENABLE, EMAC_B_RXCAFEN);
> + }
> +
> + if (dev->flags & IFF_ALLMULTI) {
> +
> + /* Set all multicast filter */
> + emac_setbit_reg(EMAC_MACHASH1, 0xffffffff);
> + emac_setbit_reg(EMAC_MACHASH2, 0xffffffff);
> +
> + } else {
> +
> + hashval = 0;
> + machash1 = 0;
> + machash2 = 0;
> +
> + netdev_for_each_mc_addr(ha, dev) {
> + u8 *addr = ha->addr;
> +
> + /* Only support group multicast */
> + if (!(*addr & 1))
> + continue;
I believe you don't need to test the multicast address again.
If you _really_ do, is_multicast_ether_addr.
> +
> + for (i = 0; i < 2; i++) {
> + tmpval = (u8) *addr++;
> + hashval ^= (u8) (tmpval >> 2) ^ (tmpval << 4);
> + tmpval = (u8) *addr++;
> + hashval ^= (u8) (tmpval >> 4) ^ (tmpval << 2);
> + tmpval = (u8) *addr++;
> + hashval ^= (u8) (tmpval >> 6) ^ (tmpval);
> + }
> +
> + if (hashval & 0x20)
> + machash2 |= (1 << (hashval & 0x1f));
> + else
> + machash1 |= (1 << (hashval & 0x1f));
> + }
> +
> + /* Set computed multicast filter */
> + emac_setbit_reg(EMAC_MACHASH1, machash1);
> + emac_setbit_reg(EMAC_MACHASH2, machash2);
> + }
> +}
> +#endif /* !EMAC_HAS_ALE_SUPPORT */
> +
> +#ifdef EMAC_TIMER_TICK_MDIO
> +/*
> + * This function should be called for each device in the system on a
> + * periodic basis of 100mS (10 times a second). It is used to check the
> + * status of the EMAC and MDIO device.
> + */
> +static void emac_timer_tick(unsigned long data)
> +{
> + struct net_device *dev = (struct net_device *)data;
> + struct emac_private *ep = netdev_priv(dev);
> + unsigned int link_status;
> + unsigned int link_event = mdio_timer_tick();
> + unsigned int intfmacsel = mdio_get_macsel();
> +
> + /*
> + * Signal the MDIO
> + */
> + if (link_event == MDIO_EVENT_LINKUP) {
> + link_status = mdio_get_status();
> + if (link_status == MDIO_LINKSTATUS_FD10 ||
> + link_status == MDIO_LINKSTATUS_FD100 ||
> + link_status == MDIO_LINKSTATUS_FD1000) {
> + emac_setbit_reg(EMAC_MACCONTROL, EMAC_B_FULLDUPLEX);
> + if (intfmacsel == DEVSTAT_MACSEL_RMII)
> + emac_setbit_reg(EMAC_MACCONTROL,
> + EMAC_B_RMIIDUPLEXMODE);
> + } else {
> + emac_clearbit_reg(EMAC_MACCONTROL, EMAC_B_FULLDUPLEX);
> + if (intfmacsel == DEVSTAT_MACSEL_RMII)
> + emac_clearbit_reg(EMAC_MACCONTROL,
> + EMAC_B_RMIIDUPLEXMODE);
> + }
> +
> + if (link_status == MDIO_LINKSTATUS_FD1000)
> + emac_setbit_reg(EMAC_MACCONTROL, EMAC_B_GIG);
> +
> + if ((link_status == MDIO_LINKSTATUS_FD10 ||
> + link_status == MDIO_LINKSTATUS_HD10) &&
> + (intfmacsel == DEVSTAT_MACSEL_RMII))
> + /* Clear bit to set clock to 2.5 MHz */
> + emac_clearbit_reg(EMAC_MACCONTROL, EMAC_B_RMIISPEED);
> +
> + if ((link_status == MDIO_LINKSTATUS_FD100 ||
> + link_status == MDIO_LINKSTATUS_HD100) &&
> + (intfmacsel == DEVSTAT_MACSEL_RMII))
> + /* Set bit to set clock to 25 MHz */
> + emac_setbit_reg(EMAC_MACCONTROL, EMAC_B_RMIISPEED);
> +
> + /* eventually call platform hook for RMII out of reset */
> + rmii_arch_fix();
> +
> + /* Put RGMII in forced link mode */
> + if (intfmacsel == DEVSTAT_MACSEL_RGMII)
> + emac_clearbit_reg(EMAC_MACCONTROL, EMAC_B_RGMIIEN);
> + }
> + mod_timer(&emac_timer, jiffies + EMAC_TIMER_PERIOD);
> +}
> +#endif /* EMAC_TIMER_TICK_MDIO */
> +
> +static const char emac_driver_name[] = "EMAC";
EMAC? Shouldn't this be c6x_gmac?
> +static const struct net_device_ops gemac_netdev_ops = {
> + .ndo_open = emac_open,
> + .ndo_stop = emac_close,
> + .ndo_start_xmit = emac_start_xmit,
> + .ndo_tx_timeout = emac_timeout,
> + .ndo_set_multicast_list = emac_set_rx_mode,
> + .ndo_set_mac_address = eth_mac_addr,
> + .ndo_get_stats = emac_get_stats,
> +#ifdef CONFIG_NET_POLL_CONTROLLER
> + .ndo_poll_controller = emac_poll,
> +#endif
> + .ndo_change_mtu = eth_change_mtu,
> + .ndo_validate_addr = eth_validate_addr,
> +};
> +
> +static const struct ethtool_ops gemac_ethtool_ops = {
> +};
> +
> +static int __init emac_probe(struct platform_device *pdev)
> +{
> + struct net_device *netdev;
> + struct emac_private *ep;
> + int res = -EINVAL;
> + int i;
> +#ifdef EMAC_ARCH_HAS_MAC_ADDR
> + char hw_emac_addr[6];
> +#endif
> + struct resource *cur_res;
> + static int ndevs;
> + int irq = 0;
> +
> + emac_idx = get_emac_idx();
> +
> + if (ndevs >= EMAC_MAX_INSTANCE) {
> + printk(KERN_ERR "gemac: Invalid instance: %d (max=%d)\n",
> + ndevs, EMAC_MAX_INSTANCE);
pr_err("Invalid instance: %d (max=%d)\n",
ndevs, EMAC_MAX_INSTANCE);
> + return -EINVAL;
> + }
> +
> + /* Allocate private information */
> + netdev = alloc_etherdev(sizeof(struct emac_private));
> + if (!netdev)
> + return -ENOMEM;
> +
> + SET_NETDEV_DEV(netdev, &pdev->dev);
> +
> + ep = netdev_priv(netdev);
> + ep->dev = netdev;
> +
> + spin_lock_init(&ep->lock);
> +
> + /* Get irqs numbers */
> + cur_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "IRQ_SRC");
> + if (cur_res)
> + irq = cur_res->start;
> +
> + /* Get EMAC I/O addresses */
> + ep->emac_reg_base = 0;
> + ep->ectl_reg_base = 0;
> + ep->emac_dsc_base = 0;
> + ep->mdio_reg_base = 0;
> +
> + cur_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> + "EMAC_REG_BASE");
> + if (cur_res)
> + ep->emac_reg_base = cur_res->start;
> +
> + cur_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> + "ECTL_REG_BASE");
> + if (cur_res)
> + ep->ectl_reg_base = cur_res->start;
> +
> + cur_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> + "EMAC_DSC_BASE");
> + if (cur_res)
> + ep->emac_dsc_base = cur_res->start
> + + ((IDX_TO_CHAN(emac_idx) * QUEUE_DESC_NUM) << 4);
> +
> +#ifdef EMAC_DO_INIT_MDIO
> + cur_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
> + "MDIO_REG_BASE");
> + if (cur_res)
> + ep->mdio_reg_base = cur_res->start;
> +#endif
> +
> + if (!irq || !ep->emac_reg_base || !ep->ectl_reg_base || !ep->emac_dsc_base) {
> + printk(KERN_ERR "%s: Unable to get hardware resources\n",
> + netdev->name);
> + goto error;
> + }
> +
> + ep->mode_flags = config.flags;
> +
> + if (emac_check_shared_capability())
> + ep->slave = emac_shared;
> +
> + netdev->base_addr = ep->emac_reg_base;
> + netdev->dev_id = pdev->id;
> +
> +#ifdef EMAC_ARCH_HAS_MAC_ADDR
> + /* SoC or board hw has MAC address */
> + if (config.enetaddr[0] == 0 && config.enetaddr[1] == 0 &&
> + config.enetaddr[2] == 0 && config.enetaddr[3] == 0 &&
> + config.enetaddr[4] == 0 && config.enetaddr[5] == 0) {
> + if (!emac_arch_get_mac_addr(hw_emac_addr))
> + for (i = 0; i <= 5; i++)
> + config.enetaddr[i] = hw_emac_addr[i] & 0xff;
> + }
> +#endif
> + /* Setup the device */
> + res = emac_reset(netdev, GEMAC_RESET_COLD);
> + if (res) {
> + free_netdev(netdev);
> + goto error;
> + }
> +
> + /* driver system function */
> + ether_setup(netdev);
> +
> + /* Set generic Ethernet operations */
> + netdev->netdev_ops = &gemac_netdev_ops;
> + netdev->watchdog_timeo = TX_TIMEOUT;
> + netdev->ethtool_ops = &gemac_ethtool_ops;
> +
> + platform_set_drvdata(pdev, netdev);
> +
> + /* Register Ethernet device */
> + res = register_netdev(netdev);
> + if (res) {
> + printk(KERN_ERR "%s: Unable to register netdev\n",
> + netdev->name);
> + goto error;
> + }
> +
> + /* Setup transmit/receive buffers */
> + res = emac_setup_ring(ep);
> + if (res) {
> + printk(KERN_ERR "%s: Unable to allocate memory\n",
> + netdev->name);
> + goto error;
> + }
> +
> +#ifdef EMAC_TIMER_TICK_MDIO
> + /* Set EMAC timer */
> + init_timer(&emac_timer);
> + emac_timer.function = emac_timer_tick;
> + emac_timer.data = (unsigned long)netdev;
> + mod_timer(&emac_timer, jiffies + EMAC_TIMER_PERIOD);
> +#endif
> +
> + /* Install our interrupt handler(s) */
> +#ifdef EMAC_HAS_SEPARATE_RXTX_IRQS
> + if ((request_irq(irq, emac_rx_interrupt, _INTFLAG, "GEMAC RX", netdev) == 0) &&
> + (request_irq(irq + 1, emac_tx_interrupt, _INTFLAG, "GEMAC TX", netdev) == 0))
> + netdev->irq = irq;
> +#else
> + if (request_irq(irq, emac_interrupt, 0, "GEMAC", netdev) == 0)
> + netdev->irq = irq;
> +#endif
> +
> + printk(KERN_INFO "%s: EMAC(%d) driver version 2.1 IRQ=%d queue=%d %s",
> + netdev->name, pdev->id, netdev->irq, IDX_TO_CHAN(emac_idx),
> + emac_shared ? "shared\n" : "\n");
> +
> + printk(KERN_INFO "%s: MAC address=", netdev->name);
> + for (i = 0; i < 5; i++)
> + printk(KERN_CONT "%02x:", netdev->dev_addr[i]);
> +#ifdef CONFIG_SGMII
> + printk(KERN_CONT "%02x PHY=SGMII\n", netdev->dev_addr[i]);
> +#else
> + printk(KERN_CONT "%02x PHY=%s%sMII\n", netdev->dev_addr[i],
> + ((mdio_get_macsel() & DEVSTAT_MACSEL_RMII) ? "R" : ""),
> + ((mdio_get_macsel() & DEVSTAT_MACSEL_GMII) ? "G" : ""));
> +#endif
> + ++ndevs;
> + return 0;
> +
> + error:
> + free_netdev(netdev);
> + return res;
> +}
> +
> +static struct platform_driver emac_driver = {
> + .driver = {
> + .name = (char *) emac_driver_name,
> + .owner = THIS_MODULE,
> + },
> + .probe = emac_probe,
> +};
> +
> +static void __exit emac_cleanup(void)
> +{
> + platform_driver_unregister(&emac_driver);
> +}
> +module_exit(emac_cleanup);
> +
> +/*
> + * Initialize GEMAC controller
> + */
> +static int emac_init(void)
> +{
> + return platform_driver_register(&emac_driver);
> +}
> +
> +module_init(emac_init);
> +
> diff --git a/drivers/net/c6x_gmdio.c b/drivers/net/c6x_gmdio.c
> new file mode 100644
> index 0000000..6a82519
> --- /dev/null
> +++ b/drivers/net/c6x_gmdio.c
> @@ -0,0 +1,514 @@
> +/*
> + * Port on Texas Instruments TMS320C6x architecture
> + *
> + * Copyright (C) 2006, 2009, 2010 Texas Instruments Incorporated
> + * Author: Nicolas Videau (nicolas.videau@jaluna.com)
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/spinlock.h>
> +#include <linux/io.h>
> +
> +#include <asm/setup.h>
> +#include <asm/irq.h>
> +#include <asm/gmdio.h>
> +#include <asm/pll.h>
> +
> +static struct mdio_status mdios;
> +
> +/*
> + * Tick counts for timeout of each state
> + * Note that NWAYSTART falls through to NWAYWAIT which falls through
> + * to LINKWAIT. The timeout is not reset progressing from one state
> + * to the next, so the system has 5 seconds total to find a link.
> + */
> +static unsigned int phy_timeout[] = { 2, /* MDIO_PHY_MDIOINIT - min-delay */
> + 6, /* MDIO_PHY_RESET - .5 sec max */
> + 41, /* MDIO_PHY_NWAYSTART - 4 seconds */
> + 41, /* MDIO_PHY_NWAYWAIT - 4 seconds */
> + 51, /* MDIO_PHY_LINKWAIT - 5 seconds */
> + 0 };/* MDIO_PHY_LINKED - no timeout */
> +
> +static void mdio_init_state_machine(void)
> +{
> + mdios.phy_addr = 0;
> + mdios.phy_state = MDIO_PHY_MDIOINIT;
> + mdios.phy_ticks = 0;
> + mdios.link_status = MDIO_LINKSTATUS_NOLINK;
> +}
> +
> +/*
> + * Initialize the MDIO
> + */
> +int mdio_init(unsigned int txid_version)
> +{
> +#ifdef CONFIG_SOC_TMS320C6455
> + /* Get MAC interface */
> + mdios.macsel = (DSCR_DEVSTAT >> DEVSTAT_MACSEL_OFFSET) &
> + DEVSTAT_MACSEL_MASK;
> +#else
> + /* Default (no gigabit support) */
> + mdios.macsel = DEVSTAT_MACSEL_MII;
> +#endif
> +
> + /* Get Transmit identification and version */
> + mdios.emac_txidver = txid_version;
> +
> + mdios.mode = MDIO_MODE_AUTONEG; /* autonegotiate */
> + mdio_init_state_machine();
> + mdio_set_reg(MDIO_CONTROL, EMAC_B_ENABLE | (VBUSCLK & EMAC_M_CLKDIV));
> + return 0;
> +}
> +
> +/*
> + * Return the current MDIO/PHY status
> + */
> +unsigned int mdio_get_status(void)
> +{
> + return mdios.link_status;
> +}
> +
> +/*
> + * Return the current MDIO/PHY interface
> + */
> +unsigned int mdio_get_macsel(void)
> +{
> + mdios.macsel = (DSCR_DEVSTAT >> DEVSTAT_MACSEL_OFFSET) &
> + DEVSTAT_MACSEL_MASK;
> +
> + return mdios.macsel;
> +}
> +
> +/*
> + * Force a switch to the specified PHY, and start the negotiation process
> + */
> +static unsigned int mdio_init_phy_1(volatile unsigned int phy_addr)
> +{
> + unsigned short val, ack;
> + unsigned int lval;
> + unsigned int i;
> +
> + mdios.phy_addr = phy_addr;
> + mdios.link_status = MDIO_LINKSTATUS_NOLINK;
> +
> + /* Shutdown all other PHYs */
> + lval = mdio_get_reg(MDIO_ALIVE);
> + for (i = 0; lval; i++, lval >>= 1)
> + if ((lval & 1) && (i != phy_addr)) {
> + mdio_phy_write(MDIO_PHY_REG_CONTROL,
> + i,
> + (MDIO_PHY_B_ISOLATE |
> + MDIO_PHY_B_POWERDOWN));
> + mdio_phy_wait();
> + }
> +
> +#ifdef CONFIG_ARCH_BOARD_DSK6455
> + /* Settings for Broadcom phys */
> + if (mdios.macsel == DEVSTAT_MACSEL_RGMII) {
> + /* Put phy in copper mode */
> + mdio_phy_write(MDIO_PHY_REG_ACCESS, phy_addr,
> + MDIO_PHY_B_COPPER);
> + mdio_phy_wait_res_ack(val, ack);
> +
> + /* If the PHY did not ACK the write, return zero */
> + if (!ack)
> + return 0;
> +
> + mdio_phy_write(0x10, phy_addr, 0x0000);
> + mdio_phy_wait();
> +
> + /* Put phy in RGMII mode/in-band status data for PG 2.0 */
> + if (mdios.emac_txidver != 0x000C1207) {
> + mdio_phy_write(MDIO_PHY_REG_SHADOW, phy_addr,
> + MDIO_PHY_B_INBAND);
> + mdio_phy_wait_res_ack(val, ack);
> +
> + /* If the PHY did not ACK the write, return zero */
> + if (!ack)
> + return 0;
> + }
> +
> + /* Patch for (older) board revB with R822 soldered */
> + mdio_phy_write(MDIO_PHY_REG_ACCESS, phy_addr, 0x8C00);
> + mdio_phy_wait_res_ack(val, ack);
> + /* End of patch */
> + }
> +#endif
> +
> + if (mdios.macsel == DEVSTAT_MACSEL_GMII) {
> + /* Put phy in copper mode */
> + mdio_phy_write(MDIO_PHY_REG_ACCESS, phy_addr,
> + MDIO_PHY_B_COPPER);
> + mdio_phy_wait_res_ack(val, ack);
> +
> + /* If the PHY did not ACK the write, return zero */
> + if (!ack)
> + return 0;
> + }
> +
> + /* Ready for next init step */
> + mdios.phy_state = MDIO_PHY_RESET;
> + mdios.phy_ticks = 0;
> +
> + return 1;
> +}
> +
> +static unsigned int mdio_init_phy_2(volatile unsigned int phy_addr)
> +{
> + unsigned short val, val2, valgig = 0;
> +
> + mdios.phy_addr = phy_addr;
> +
> + /* Read the STATUS reg to check autonegotiation capability */
> + mdio_phy_read(MDIO_PHY_REG_STATUS, phy_addr);
> + mdio_phy_wait_res(val);
> +
> + if ((mdios.macsel == DEVSTAT_MACSEL_GMII) ||
> + (mdios.macsel == DEVSTAT_MACSEL_RGMII)) {
> + mdio_phy_read(MDIO_PHY_REG_EXTSTATUS, phy_addr);
> + mdio_phy_wait_res(valgig);
> + }
> +
> + /* See if we auto-neg or not */
> + if ((mdios.mode & MDIO_MODE_AUTONEG) &&
> + (val & MDIO_PHY_B_AUTOCAPABLE)) {
> + /* We will use NWAY */
> +
> + /* Advertise 1000 for supported interfaces */
> + if ((mdios.macsel == DEVSTAT_MACSEL_GMII) ||
> + (mdios.macsel == DEVSTAT_MACSEL_RGMII)) {
> + valgig >>= 4;
> + valgig &= MDIO_PHY_ADV_FD1000;
> +
> + mdio_phy_write(MDIO_PHY_REG_1000CONTROL, phy_addr,
> + valgig);
> + mdio_phy_wait();
> + }
> +
> + /* Shift down the capability bits */
> + val >>= 6;
> +
> + /* Mask with the capabilities */
> + val &= (MDIO_PHY_B_AFD100 | MDIO_PHY_B_AHD100 |
> + MDIO_PHY_B_AFD10 | MDIO_PHY_B_AHD10);
> +
> + /* Set Ethernet message bit */
> + val |= MDIO_PHY_B_MSG;
> +
> + /* Write out advertisement */
> + mdio_phy_write(MDIO_PHY_REG_ADVERTISE, phy_addr, val);
> + mdio_phy_wait();
> +
> + /* Start NWAY */
> + mdio_phy_write(MDIO_PHY_REG_CONTROL,
> + phy_addr,
> + MDIO_PHY_B_AUTONEGEN);
> + mdio_phy_wait();
> +
> + mdio_phy_write(MDIO_PHY_REG_CONTROL,
> + phy_addr,
> + (MDIO_PHY_B_AUTONEGEN | MDIO_PHY_B_AUTORESTART));
> + mdio_phy_wait();
> +
> + /* Setup current state */
> + mdios.mode |= MDIO_MODE_NWAYACTIVE;
> + mdios.phy_state = MDIO_PHY_NWAYSTART;
> + mdios.phy_ticks = 0;
> +
> + } else {
> + /* Otherwise use a fixed configuration */
> +
> + /* Shift down the capability bits */
> + val >>= 10;
> +
> + /* Mask with possible modes */
> + val &= (MDIO_MODE_HD10 | MDIO_MODE_FD10 |
> + MDIO_MODE_HD100 | MDIO_MODE_FD100);
> +
> + if ((mdios.macsel == DEVSTAT_MACSEL_GMII) ||
> + (mdios.macsel == DEVSTAT_MACSEL_RGMII)) {
> + valgig >>= 8;
> + valgig &= MDIO_MODE_FD1000;
> +
> + valgig &= mdios.mode;
> + }
> +
> + /* Mask with what the User wants to allow */
> + val &= mdios.mode;
> +
> + /* If nothing if left, move on */
> + if ((!val) && (!valgig))
> + return 0;
> +
> + /* Setup Control word and pending status */
> + if (valgig) {
> + val2 = MDIO_PHY_B_SPEEDMSB | MDIO_PHY_B_DUPLEXFULL;
> + mdios.pending_status = MDIO_LINKSTATUS_FD1000;
> + } else if (val & MDIO_MODE_FD100) {
> + val2 = MDIO_PHY_B_SPEEDLSB | MDIO_PHY_B_DUPLEXFULL;
> + mdios.pending_status = MDIO_LINKSTATUS_FD100;
> + } else if (val & MDIO_MODE_HD100) {
> + val2 = MDIO_PHY_B_SPEEDLSB;
> + mdios.pending_status = MDIO_LINKSTATUS_HD100;
> + } else if (val & MDIO_MODE_FD10) {
> + val2 = MDIO_PHY_B_DUPLEXFULL;
> + mdios.pending_status = MDIO_PHY_B_FD10;
> + } else {
> + val2 = 0;
> + mdios.pending_status = MDIO_LINKSTATUS_HD10;
> + }
> +
> + /* Add in loopback if user wanted it */
> + if (mdios.mode & MDIO_MODE_LOOPBACK)
> + val2 |= MDIO_PHY_B_LOOPBACK;
> +
> + /* Configure PHY */
> + mdio_phy_write(MDIO_PHY_REG_CONTROL, phy_addr,
> + (val2 | MDIO_PHY_B_AUTORESTART));
> + mdio_phy_wait();
> +
> + /* Add in external loopback with plug if user wanted it */
> + if (mdios.mode & MDIO_MODE_EXTLOOPBACK) {
> + mdio_phy_write(MDIO_PHY_REG_SHADOW, phy_addr,
> + MDIO_PHY_B_EXTLOOPBACK);
> + mdio_phy_wait();
> + }
> +
> + /* Setup current state */
> + mdios.mode &= ~MDIO_MODE_NWAYACTIVE;
> + mdios.phy_state = MDIO_PHY_LINKWAIT;
> + mdios.phy_ticks = 0;
> + }
> + return 1;
> +}
> +
> +
> +/*
> + * Called each 100mS to check if MDIO status has changed.
> + * A MDIO event is returned.
> + */
> +unsigned int mdio_timer_tick(void)
> +{
> + unsigned int res = MDIO_EVENT_NOCHANGE;
> + unsigned short val, val2, valgig = 0, valgig2 = 0, ack;
> + unsigned int lval;
> +
> + if (mdios.phy_state == MDIO_PHY_LINKED) {
> + /*
> + * Check for a "link-change" status indication or a link
> + * down indication.
> + */
> + lval = mdio_get_reg(MDIO_LINKINTRAW) & 1;
> + mdio_set_reg(MDIO_LINKINTRAW, lval);
> + if (lval || !(mdio_get_reg(MDIO_LINK) & (1 << mdios.phy_addr))) {
> +
> + mdios.link_status = MDIO_LINKSTATUS_NOLINK;
> + mdios.phy_ticks = 0;
> + res = MDIO_EVENT_LINKDOWN;
> +
> + /* If not NWAY, just wait for link */
> + if (!(mdios.mode & MDIO_MODE_NWAYACTIVE))
> + mdios.phy_state = MDIO_PHY_LINKWAIT;
> + else {
> + /* Handle NWAY condition */
> + mdio_phy_read(MDIO_PHY_REG_STATUS,
> + mdios.phy_addr);
> + mdio_phy_wait();
> + mdio_phy_read(MDIO_PHY_REG_STATUS,
> + mdios.phy_addr);
> + mdio_phy_wait_res_ack(val, ack);
> + if (!ack)
> + mdio_init_state_machine();
> +
> + else if (!(val & MDIO_PHY_B_LINKSTATUS)) {
> + /* No Link - restart NWAY */
> + mdios.phy_state = MDIO_PHY_NWAYSTART;
> +
> + mdio_phy_write(MDIO_PHY_REG_CONTROL,
> + mdios.phy_addr,
> + (MDIO_PHY_B_AUTONEGEN |
> + MDIO_PHY_B_AUTORESTART));
> + mdio_phy_wait();
> + } else
> + /* We have a Link - re-read NWAY params */
> + mdios.phy_state = MDIO_PHY_NWAYWAIT;
> + }
> + }
> + }
> +
> + if (mdios.phy_state != MDIO_PHY_LINKED) {
> + /* Bump the time counter */
> + mdios.phy_ticks++;
> +
> + /* Process differently based on state */
> + switch (mdios.phy_state) {
> +#if !(defined(CONFIG_SOC_TMS3206472) || defined(CONFIG_SOC_TMS3206474)) && \
> + !defined(CONFIG_SOC_TMS3206457)
> + case MDIO_PHY_RESET:
> + /* Don't read reset status for the first 100 to 200 ms */
> + if (mdios.phy_ticks < 2)
> + break;
> +
> + /* See if the PHY has come out of reset */
> + mdio_phy_read(MDIO_PHY_REG_CONTROL,
> + mdios.phy_addr);
> + mdio_phy_wait_res_ack(val, ack);
> +
> + if (ack && !(val & MDIO_PHY_B_RESET)) {
> + /* PHY is not reset.
> + * If the PHY init is going well, break out */
> + if (mdio_init_phy_2(mdios.phy_addr))
> + break;
> + /* Else, this PHY is toast.
> + * Manually trigger a timeout */
> + mdios.phy_ticks = phy_timeout[mdios.phy_state];
> + }
> +
> + /* Fall through to timeout check */
> +#endif
> + case MDIO_PHY_MDIOINIT:
> + check_timeout:
> + /* Here we just check timeout and try to find a PHY */
> + if (mdios.phy_ticks >= phy_timeout[mdios.phy_state]) {
> + /* Try the next PHY if anything but
> + * a MDIOINIT condition */
> + if (mdios.phy_state != MDIO_PHY_MDIOINIT)
> + if (++mdios.phy_addr == 32)
> + mdios.phy_addr = 0;
> +
> + lval = mdio_get_reg(MDIO_ALIVE);
> +
> + for (val = 0; val < 32; val++) {
> +
> + if ((lval & (1 << mdios.phy_addr)) &&
> + (mdio_init_phy_1(mdios.phy_addr)))
> + break;
> +
> + if (++mdios.phy_addr == 32)
> + mdios.phy_addr = 0;
> + }
> +
> + /* If we didn't find a PHY, try again */
> + if (val == 32) {
> + mdios.phy_addr = 0;
> + mdios.phy_state = MDIO_PHY_MDIOINIT;
> + mdios.phy_ticks = 0;
> + res = MDIO_EVENT_PHYERROR;
> + }
> + }
> + break;
> +
> + case MDIO_PHY_NWAYSTART:
> + /* Start NWAY */
> +
> + /* Read the CONTROL reg to verify "restart" is not set */
> + mdio_phy_read(MDIO_PHY_REG_CONTROL, mdios.phy_addr);
> + mdio_phy_wait_res_ack(val, ack);
> + if (!ack) {
> + mdio_init_state_machine();
> + break;
> + }
> +
> + if (val & MDIO_PHY_B_AUTORESTART)
> + goto check_timeout;
> +
> + /* Flush latched "link status" from the STATUS reg */
> + mdio_phy_read(MDIO_PHY_REG_STATUS, mdios.phy_addr);
> + mdio_phy_wait();
> +
> + mdios.phy_state = MDIO_PHY_NWAYWAIT;
> +
> + /* Fallthrough */
> +
> + case MDIO_PHY_NWAYWAIT:
> + /* Waiting NWAY to complete */
> +
> + /* Read the STATUS reg to check for "complete" */
> + mdio_phy_read(MDIO_PHY_REG_STATUS, mdios.phy_addr);
> + mdio_phy_wait_res_ack(val, ack);
> + if (!ack) {
> + mdio_init_state_machine();
> + break;
> + }
> +
> + if (!(val & MDIO_PHY_B_AUTOCOMPLETE))
> + goto check_timeout;
> +#if !(defined(CONFIG_SOC_TMS3206472) || defined(CONFIG_SOC_TMS3206474)) && !defined(CONFIG_SOC_TMS3206457)
> + /* We can now check the negotiation results */
> + if ((mdios.macsel == DEVSTAT_MACSEL_GMII) ||
> + (mdios.macsel == DEVSTAT_MACSEL_RGMII)) {
> + mdio_phy_read(MDIO_PHY_REG_1000CONTROL,
> + mdios.phy_addr);
> + mdio_phy_wait_res(valgig);
> + mdio_phy_read(MDIO_PHY_REG_1000STATUS,
> + mdios.phy_addr);
> + mdio_phy_wait_res(valgig2);
> + }
> +#endif
> + mdio_phy_read(MDIO_PHY_REG_ADVERTISE, mdios.phy_addr);
> + mdio_phy_wait_res(val);
> + mdio_phy_read(MDIO_PHY_REG_PARTNER, mdios.phy_addr);
> + mdio_phy_wait_res(val2);
> +
> + val2 &= val;
> +#if !(defined(CONFIG_SOC_TMS3206472) || defined(CONFIG_SOC_TMS3206474)) && !defined(CONFIG_SOC_TMS3206457)
> + if ((valgig & MDIO_PHY_ADV_FD1000) &&
> + (valgig2 & MDIO_PHY_PRT_FD1000))
> + mdios.pending_status = MDIO_LINKSTATUS_FD1000;
> + else if (val2 & MDIO_PHY_B_AFD100)
> + mdios.pending_status = MDIO_LINKSTATUS_FD100;
> +#else
> + if (val2 & MDIO_PHY_B_AFD100)
> + mdios.pending_status = MDIO_LINKSTATUS_FD100;
> +#endif
> + else if (val2 & MDIO_PHY_B_AHD100)
> + mdios.pending_status = MDIO_LINKSTATUS_HD100;
> + else if (val2 & MDIO_PHY_B_AFD10)
> + mdios.pending_status = MDIO_LINKSTATUS_FD10;
> + else if (val2 & MDIO_PHY_B_AHD10)
> + mdios.pending_status = MDIO_LINKSTATUS_HD10;
> + else if (val & MDIO_PHY_B_AHD100)
> + mdios.pending_status = MDIO_LINKSTATUS_HD100;
> + else
> + mdios.pending_status = MDIO_LINKSTATUS_HD10;
> +
> + mdios.phy_state = MDIO_PHY_LINKWAIT;
> +
> + case MDIO_PHY_LINKWAIT:
> + /* Waiting for LINK */
> + mdio_phy_read(MDIO_PHY_REG_STATUS, mdios.phy_addr);
> + mdio_phy_wait_res_ack(val, ack);
> + if (!ack) {
> + mdio_init_state_machine();
> + break;
> + }
> +
> + if (!(val & MDIO_PHY_B_LINKSTATUS))
> + goto check_timeout;
> +
> + /* Make sure we're linked in the MDIO module as well */
> + lval = mdio_get_reg(MDIO_LINK);
> + if (!(lval & (1 << mdios.phy_addr)))
> + goto check_timeout;
> +
> + /* Start monitoring this PHY */
> + mdio_set_reg(MDIO_USERPHYSEL0, mdios.phy_addr);
> +
> + /* Clear the link change flag so we can detect a "re-link" later */
> + mdio_set_reg(MDIO_LINKINTRAW, 1);
> +
> + /* Setup our linked state */
> + mdios.phy_state = MDIO_PHY_LINKED;
> + mdios.link_status = mdios.pending_status;
> + res = MDIO_EVENT_LINKUP;
> + break;
> + }
> + }
> + return res;
> +}
^ permalink raw reply
* Re: [PATCH net-next-2.6] net/bonding: adjust codingstyle for bond_3ad files
From: Rafael Aquini @ 2011-05-12 0:39 UTC (permalink / raw)
To: Nicolas Kaiser
Cc: Jay Vosburgh, Joe Perches, kernel-janitors, David Miller,
Andy Gospodarek, shemminger, netdev
Howdy,
While I was studying what bond_3ad has under its hood, I realized its coding
style did not follow all Documentation/CodingStyle recommendations. As a tiny
collaboration I did some mods there, in an attempt to make that code stick as
closely as possible with Kernel's coding style. Also, Nicolas Kaiser has kindly
suggested some conditional simplifications integrated in this patch.
Modifications:
* switched all comments from C99-style to C89-style;
* replaced MAC_ADDRESS_COMPARE macro for compare_ether_addr();
* print info out on unexpected status checkings;
* simplify conditionals:
(a || (!a && !b)) => (a || !b)
(!(!a && b)) => (a || !b)
Signed-off-by: Nicolas Kaiser <nikai@nikai.net>
Signed-off-by: Rafael Aquini <aquini@linux.com>
---
drivers/net/bonding/bond_3ad.c | 907 +++++++++++++++++++++++-----------------
drivers/net/bonding/bond_3ad.h | 195 +++++----
2 files changed, 625 insertions(+), 477 deletions(-)
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index c7537abc..3f6f8ee 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -34,14 +34,14 @@
#include "bonding.h"
#include "bond_3ad.h"
-// General definitions
+/* General definitions */
#define AD_SHORT_TIMEOUT 1
#define AD_LONG_TIMEOUT 0
#define AD_STANDBY 0x2
#define AD_MAX_TX_IN_SECOND 3
#define AD_COLLECTOR_MAX_DELAY 0
-// Timer definitions(43.4.4 in the 802.3ad standard)
+/* Timer definitions (43.4.4 in the 802.3ad standard) */
#define AD_FAST_PERIODIC_TIME 1
#define AD_SLOW_PERIODIC_TIME 30
#define AD_SHORT_TIMEOUT_TIME (3*AD_FAST_PERIODIC_TIME)
@@ -49,7 +49,7 @@
#define AD_CHURN_DETECTION_TIME 60
#define AD_AGGREGATE_WAIT_TIME 2
-// Port state definitions(43.4.2.2 in the 802.3ad standard)
+/* Port state definitions (43.4.2.2 in the 802.3ad standard) */
#define AD_STATE_LACP_ACTIVITY 0x1
#define AD_STATE_LACP_TIMEOUT 0x2
#define AD_STATE_AGGREGATION 0x4
@@ -59,7 +59,9 @@
#define AD_STATE_DEFAULTED 0x40
#define AD_STATE_EXPIRED 0x80
-// Port Variables definitions used by the State Machines(43.4.7 in the 802.3ad standard)
+/* Port Variables definitions used by the State Machines
+ * (43.4.7 in the 802.3ad standard)
+ */
#define AD_PORT_BEGIN 0x1
#define AD_PORT_LACP_ENABLED 0x2
#define AD_PORT_ACTOR_CHURN 0x4
@@ -71,27 +73,23 @@
#define AD_PORT_SELECTED 0x100
#define AD_PORT_MOVED 0x200
-// Port Key definitions
-// key is determined according to the link speed, duplex and
-// user key(which is yet not supported)
-// ------------------------------------------------------------
-// Port key : | User key | Speed |Duplex|
-// ------------------------------------------------------------
-// 16 6 1 0
+/* Port Key definitions:
+ * key is determined according to the link speed, duplex and
+ * user key (which is yet not supported)
+ * ------------------------------------------------------------
+ * Port key: | User key | Speed |Duplex|
+ * ------------------------------------------------------------
+ * 16 6 1 0
+ */
#define AD_DUPLEX_KEY_BITS 0x1
#define AD_SPEED_KEY_BITS 0x3E
#define AD_USER_KEY_BITS 0xFFC0
-//dalloun
#define AD_LINK_SPEED_BITMASK_1MBPS 0x1
#define AD_LINK_SPEED_BITMASK_10MBPS 0x2
#define AD_LINK_SPEED_BITMASK_100MBPS 0x4
#define AD_LINK_SPEED_BITMASK_1000MBPS 0x8
#define AD_LINK_SPEED_BITMASK_10000MBPS 0x10
-//endalloun
-
-// compare MAC addresses
-#define MAC_ADDRESS_COMPARE(A, B) memcmp(A, B, ETH_ALEN)
static struct mac_addr null_mac_addr = { { 0, 0, 0, 0, 0, 0 } };
static u16 ad_ticks_per_sec;
@@ -99,7 +97,7 @@ static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
static const u8 lacpdu_mcast_addr[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
-// ================= main 802.3ad protocol functions ==================
+/* ================= main 802.3ad protocol functions ================== */
static int ad_lacpdu_send(struct port *port);
static int ad_marker_send(struct port *port, struct bond_marker *marker);
static void ad_mux_machine(struct port *port);
@@ -113,14 +111,12 @@ static void ad_initialize_agg(struct aggregator *aggregator);
static void ad_initialize_port(struct port *port, int lacp_fast);
static void ad_enable_collecting_distributing(struct port *port);
static void ad_disable_collecting_distributing(struct port *port);
-static void ad_marker_info_received(struct bond_marker *marker_info, struct port *port);
-static void ad_marker_response_received(struct bond_marker *marker, struct port *port);
-
-
-/////////////////////////////////////////////////////////////////////////////////
-// ================= api to bonding and kernel code ==================
-/////////////////////////////////////////////////////////////////////////////////
+static void ad_marker_info_received(struct bond_marker *marker_info,
+ struct port *port);
+static void ad_marker_response_received(struct bond_marker *marker,
+ struct port *port);
+/* ================= api to bonding and kernel code ================== */
/**
* __get_bond_by_port - get the port's bonding struct
* @port: the port we're looking at
@@ -161,7 +157,7 @@ static inline struct port *__get_next_port(struct port *port)
struct bonding *bond = __get_bond_by_port(port);
struct slave *slave = port->slave;
- // If there's no bond for this port, or this is the last slave
+ /* If there's no bond for this port, or this is the last slave */
if ((bond == NULL) || (slave->next == bond->first_slave))
return NULL;
@@ -179,7 +175,7 @@ static inline struct aggregator *__get_first_agg(struct port *port)
{
struct bonding *bond = __get_bond_by_port(port);
- // If there's no bond for this port, or bond has no slaves
+ /* If there's no bond for this port, or bond has no slaves */
if ((bond == NULL) || (bond->slave_cnt == 0))
return NULL;
@@ -198,7 +194,7 @@ static inline struct aggregator *__get_next_agg(struct aggregator *aggregator)
struct slave *slave = aggregator->slave;
struct bonding *bond = bond_get_bond_by_slave(slave);
- // If there's no bond for this aggregator, or this is the last slave
+ /* If there's no bond for this aggregator, or this is the last slave */
if ((bond == NULL) || (slave->next == bond->first_slave))
return NULL;
@@ -316,10 +312,9 @@ static u16 __get_link_speed(struct port *port)
struct slave *slave = port->slave;
u16 speed;
- /* this if covers only a special case: when the configuration starts with
- * link down, it sets the speed to 0.
- * This is done in spite of the fact that the e100 driver reports 0 to be
- * compatible with MVT in the future.*/
+ /* handling a special case:
+ * when the configuration starts with link down, it sets the speed to 0
+ */
if (slave->link != BOND_LINK_UP)
speed = 0;
else {
@@ -341,7 +336,9 @@ static u16 __get_link_speed(struct port *port)
break;
default:
- speed = 0; // unknown speed value from ethtool. shouldn't happen
+ /* unknown speed value from ethtool. shouldn't happen */
+ pr_debug("Unexpected slave->speed: %d\n", slave->speed);
+ speed = 0;
break;
}
}
@@ -362,13 +359,13 @@ static u16 __get_link_speed(struct port *port)
static u8 __get_duplex(struct port *port)
{
struct slave *slave = port->slave;
+ u8 retval = 0x0;
- u8 retval;
-
- // handling a special case: when the configuration starts with
- // link down, it sets the duplex to 0.
+ /* handling a special case:
+ * when the configuration starts with link down, it sets the duplex to 0
+ */
if (slave->link != BOND_LINK_UP)
- retval = 0x0;
+ goto out;
else {
switch (slave->duplex) {
case DUPLEX_FULL:
@@ -384,6 +381,7 @@ static u8 __get_duplex(struct port *port)
break;
}
}
+out:
return retval;
}
@@ -394,12 +392,9 @@ static u8 __get_duplex(struct port *port)
*/
static inline void __initialize_port_locks(struct port *port)
{
- // make sure it isn't called twice
spin_lock_init(&(SLAVE_AD_INFO(port->slave).state_machine_lock));
}
-//conversions
-
/**
* __ad_timer_to_ticks - convert a given timer type to AD module ticks
* @timer_type: which timer to operate
@@ -411,36 +406,36 @@ static inline void __initialize_port_locks(struct port *port)
*/
static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
{
- u16 retval = 0; /* to silence the compiler */
+ u16 retval;
switch (timer_type) {
- case AD_CURRENT_WHILE_TIMER: // for rx machine usage
+ case AD_CURRENT_WHILE_TIMER: /* for rx machine usage */
if (par)
- retval = (AD_SHORT_TIMEOUT_TIME*ad_ticks_per_sec); // short timeout
+ retval = (AD_SHORT_TIMEOUT_TIME*ad_ticks_per_sec);
else
- retval = (AD_LONG_TIMEOUT_TIME*ad_ticks_per_sec); // long timeout
+ retval = (AD_LONG_TIMEOUT_TIME*ad_ticks_per_sec);
break;
- case AD_ACTOR_CHURN_TIMER: // for local churn machine
+ case AD_ACTOR_CHURN_TIMER: /* for local churn machine */
retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec);
break;
- case AD_PERIODIC_TIMER: // for periodic machine
- retval = (par*ad_ticks_per_sec); // long timeout
+ case AD_PERIODIC_TIMER: /* for periodic machine */
+ retval = (par*ad_ticks_per_sec);
break;
- case AD_PARTNER_CHURN_TIMER: // for remote churn machine
+ case AD_PARTNER_CHURN_TIMER: /* for remote churn machine */
retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec);
break;
- case AD_WAIT_WHILE_TIMER: // for selection machine
+ case AD_WAIT_WHILE_TIMER: /* for selection machine */
retval = (AD_AGGREGATE_WAIT_TIME*ad_ticks_per_sec);
break;
+ default:
+ pr_warn("Unexpected AD timer_type: %d\n", timer_type);
+ retval = 0;
+ break;
}
return retval;
}
-
-/////////////////////////////////////////////////////////////////////////////////
-// ================= ad_rx_machine helper functions ==================
-/////////////////////////////////////////////////////////////////////////////////
-
+/* ================= ad_rx_machine helper functions ================== */
/**
* __choose_matched - update a port's matched variable from a received lacpdu
* @lacpdu: the lacpdu we've received
@@ -466,17 +461,17 @@ static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
*/
static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
{
- // check if all parameters are alike
+ /* check if all parameters are alike */
if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
(ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
- !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
+ !compare_ether_addr((const u8 *)&(lacpdu->partner_system), (const u8 *)&(port->actor_system)) &&
(ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
(ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
- // or this is individual link(aggregation == FALSE)
+ /* or this is individual link(aggregation == FALSE) */
((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
) {
- // update the state machine Matched variable
+ /* update the state machine Matched variable */
port->sm_vars |= AD_PORT_MATCHED;
} else {
port->sm_vars &= ~AD_PORT_MATCHED;
@@ -498,7 +493,7 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
struct port_params *partner = &port->partner_oper;
__choose_matched(lacpdu, port);
- // record the new parameter values for the partner operational
+ /* record the new values for the operational partner */
partner->port_number = ntohs(lacpdu->actor_port);
partner->port_priority = ntohs(lacpdu->actor_port_priority);
partner->system = lacpdu->actor_system;
@@ -506,12 +501,14 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
partner->key = ntohs(lacpdu->actor_key);
partner->port_state = lacpdu->actor_state;
- // set actor_oper_port_state.defaulted to FALSE
+ /* set actor_oper_port_state.defaulted to FALSE */
port->actor_oper_port_state &= ~AD_STATE_DEFAULTED;
- // set the partner sync. to on if the partner is sync. and the port is matched
- if ((port->sm_vars & AD_PORT_MATCHED)
- && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION))
+ /* set the partner sync to on if the partner is sync
+ * and the port is matched.
+ */
+ if ((port->sm_vars & AD_PORT_MATCHED) &&
+ (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION))
partner->port_state |= AD_STATE_SYNCHRONIZATION;
else
partner->port_state &= ~AD_STATE_SYNCHRONIZATION;
@@ -529,11 +526,8 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
static void __record_default(struct port *port)
{
if (port) {
- // record the partner admin parameters
memcpy(&port->partner_oper, &port->partner_admin,
sizeof(struct port_params));
-
- // set actor_oper_port_state.defaulted to true
port->actor_oper_port_state |= AD_STATE_DEFAULTED;
}
}
@@ -556,14 +550,13 @@ static void __update_selected(struct lacpdu *lacpdu, struct port *port)
if (lacpdu && port) {
const struct port_params *partner = &port->partner_oper;
- // check if any parameter is different
if (ntohs(lacpdu->actor_port) != partner->port_number ||
ntohs(lacpdu->actor_port_priority) != partner->port_priority ||
- MAC_ADDRESS_COMPARE(&lacpdu->actor_system, &partner->system) ||
+ compare_ether_addr((const u8 *)&lacpdu->actor_system, (const u8 *)&partner->system) ||
ntohs(lacpdu->actor_system_priority) != partner->system_priority ||
ntohs(lacpdu->actor_key) != partner->key ||
(lacpdu->actor_state & AD_STATE_AGGREGATION) != (partner->port_state & AD_STATE_AGGREGATION)) {
- // update the state machine Selected variable
+ /* update the state machine Selected variable */
port->sm_vars &= ~AD_PORT_SELECTED;
}
}
@@ -587,15 +580,15 @@ static void __update_default_selected(struct port *port)
const struct port_params *admin = &port->partner_admin;
const struct port_params *oper = &port->partner_oper;
- // check if any parameter is different
if (admin->port_number != oper->port_number ||
admin->port_priority != oper->port_priority ||
- MAC_ADDRESS_COMPARE(&admin->system, &oper->system) ||
+ compare_ether_addr((const u8 *)&admin->system,
+ (const u8 *)&oper->system) ||
admin->system_priority != oper->system_priority ||
admin->key != oper->key ||
(admin->port_state & AD_STATE_AGGREGATION)
!= (oper->port_state & AD_STATE_AGGREGATION)) {
- // update the state machine Selected variable
+ /* update the state machine Selected variable */
port->sm_vars &= ~AD_PORT_SELECTED;
}
}
@@ -615,12 +608,10 @@ static void __update_default_selected(struct port *port)
*/
static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
{
- // validate lacpdu and port
if (lacpdu && port) {
- // check if any parameter is different
if ((ntohs(lacpdu->partner_port) != port->actor_port_number) ||
(ntohs(lacpdu->partner_port_priority) != port->actor_port_priority) ||
- MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) ||
+ compare_ether_addr((const u8 *)&(lacpdu->partner_system), (const u8 *)&(port->actor_system)) ||
(ntohs(lacpdu->partner_system_priority) != port->actor_system_priority) ||
(ntohs(lacpdu->partner_key) != port->actor_oper_port_key) ||
((lacpdu->partner_state & AD_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY)) ||
@@ -628,7 +619,6 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
((lacpdu->partner_state & AD_STATE_SYNCHRONIZATION) != (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) ||
((lacpdu->partner_state & AD_STATE_AGGREGATION) != (port->actor_oper_port_state & AD_STATE_AGGREGATION))
) {
-
port->ntt = true;
}
}
@@ -644,9 +634,7 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
*/
static void __attach_bond_to_agg(struct port *port)
{
- port = NULL; /* just to satisfy the compiler */
- // This function does nothing since the parser/multiplexer of the receive
- // and the parser/multiplexer of the aggregator are already combined
+ port = NULL;
}
/**
@@ -659,9 +647,7 @@ static void __attach_bond_to_agg(struct port *port)
*/
static void __detach_bond_from_agg(struct port *port)
{
- port = NULL; /* just to satisfy the compiler */
- // This function does nothing sience the parser/multiplexer of the receive
- // and the parser/multiplexer of the aggregator are already combined
+ port = NULL;
}
/**
@@ -675,7 +661,9 @@ static int __agg_ports_are_ready(struct aggregator *aggregator)
int retval = 1;
if (aggregator) {
- // scan all ports in this aggregator to verfy if they are all ready
+ /* scan all ports in this aggregator
+ * to verify if they are all ready.
+ */
for (port = aggregator->lag_ports;
port;
port = port->next_port_in_aggregator) {
@@ -715,28 +703,32 @@ static void __set_agg_ports_ready(struct aggregator *aggregator, int val)
*/
static u32 __get_agg_bandwidth(struct aggregator *aggregator)
{
- u32 bandwidth = 0;
+ u32 bandwidth;
- if (aggregator->num_of_ports) {
- switch (__get_link_speed(aggregator->lag_ports)) {
- case AD_LINK_SPEED_BITMASK_1MBPS:
- bandwidth = aggregator->num_of_ports;
- break;
- case AD_LINK_SPEED_BITMASK_10MBPS:
- bandwidth = aggregator->num_of_ports * 10;
- break;
- case AD_LINK_SPEED_BITMASK_100MBPS:
- bandwidth = aggregator->num_of_ports * 100;
- break;
- case AD_LINK_SPEED_BITMASK_1000MBPS:
- bandwidth = aggregator->num_of_ports * 1000;
- break;
- case AD_LINK_SPEED_BITMASK_10000MBPS:
- bandwidth = aggregator->num_of_ports * 10000;
- break;
- default:
- bandwidth = 0; /*to silence the compiler ....*/
- }
+ if (!aggregator->num_of_ports)
+ return 0;
+
+ switch (__get_link_speed(aggregator->lag_ports)) {
+ case AD_LINK_SPEED_BITMASK_1MBPS:
+ bandwidth = aggregator->num_of_ports;
+ break;
+ case AD_LINK_SPEED_BITMASK_10MBPS:
+ bandwidth = aggregator->num_of_ports * 10;
+ break;
+ case AD_LINK_SPEED_BITMASK_100MBPS:
+ bandwidth = aggregator->num_of_ports * 100;
+ break;
+ case AD_LINK_SPEED_BITMASK_1000MBPS:
+ bandwidth = aggregator->num_of_ports * 1000;
+ break;
+ case AD_LINK_SPEED_BITMASK_10000MBPS:
+ bandwidth = aggregator->num_of_ports * 10000;
+ break;
+ default:
+ pr_debug("Unexpected aggregator link speed: %d\n",
+ __get_link_speed(aggregator->lag_ports));
+ bandwidth = 0;
+ break;
}
return bandwidth;
}
@@ -807,10 +799,7 @@ static inline void __update_lacpdu_from_port(struct port *port)
*/
}
-//////////////////////////////////////////////////////////////////////////////////////
-// ================= main 802.3ad protocol code ======================================
-//////////////////////////////////////////////////////////////////////////////////////
-
+/* ================= main 802.3ad protocol code ================= */
/**
* ad_lacpdu_send - send out a lacpdu packet on a given port
* @port: the port we're looking at
@@ -839,11 +828,12 @@ static int ad_lacpdu_send(struct port *port)
memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
/* Note: source address is set to be the member's PERMANENT address,
- because we use it to identify loopback lacpdus in receive. */
+ * because we use it to identify loopback lacpdus in receive.
+ */
memcpy(lacpdu_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU;
- lacpdu_header->lacpdu = port->lacpdu; // struct copy
+ lacpdu_header->lacpdu = port->lacpdu; /* struct copy */
dev_queue_xmit(skb);
@@ -884,7 +874,7 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
memcpy(marker_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
marker_header->hdr.h_proto = PKT_TYPE_LACPDU;
- marker_header->marker = *marker; // struct copy
+ marker_header->marker = *marker; /* struct copy */
dev_queue_xmit(skb);
@@ -900,80 +890,103 @@ static void ad_mux_machine(struct port *port)
{
mux_states_t last_state;
- // keep current State Machine state to compare later if it was changed
last_state = port->sm_mux_state;
if (port->sm_vars & AD_PORT_BEGIN) {
- port->sm_mux_state = AD_MUX_DETACHED; // next state
+ port->sm_mux_state = AD_MUX_DETACHED;
} else {
switch (port->sm_mux_state) {
case AD_MUX_DETACHED:
- if ((port->sm_vars & AD_PORT_SELECTED)
- || (port->sm_vars & AD_PORT_STANDBY))
+ if ((port->sm_vars & AD_PORT_SELECTED) ||
+ (port->sm_vars & AD_PORT_STANDBY))
/* if SELECTED or STANDBY */
- port->sm_mux_state = AD_MUX_WAITING; // next state
+ port->sm_mux_state = AD_MUX_WAITING;
break;
case AD_MUX_WAITING:
- // if SELECTED == FALSE return to DETACH state
- if (!(port->sm_vars & AD_PORT_SELECTED)) { // if UNSELECTED
+ /* if SELECTED == FALSE return to DETACH state */
+ if (!(port->sm_vars & AD_PORT_SELECTED)) {
port->sm_vars &= ~AD_PORT_READY_N;
- // in order to withhold the Selection Logic to check all ports READY_N value
- // every callback cycle to update ready variable, we check READY_N and update READY here
- __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
- port->sm_mux_state = AD_MUX_DETACHED; // next state
+ /* in order to withhold the Selection Logic
+ * to check all ports READY_N value at every
+ * callback cycle to update ready variable,
+ * we check READY_N and update READY here
+ */
+ __set_agg_ports_ready(port->aggregator,
+ __agg_ports_are_ready(port->aggregator));
+ port->sm_mux_state = AD_MUX_DETACHED;
break;
}
- // check if the wait_while_timer expired
- if (port->sm_mux_timer_counter
- && !(--port->sm_mux_timer_counter))
+ /* check if the wait_while_timer expired */
+ if (port->sm_mux_timer_counter &&
+ !(--port->sm_mux_timer_counter))
port->sm_vars |= AD_PORT_READY_N;
- // in order to withhold the selection logic to check all ports READY_N value
- // every callback cycle to update ready variable, we check READY_N and update READY here
- __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
-
- // if the wait_while_timer expired, and the port is in READY state, move to ATTACHED state
- if ((port->sm_vars & AD_PORT_READY)
- && !port->sm_mux_timer_counter)
- port->sm_mux_state = AD_MUX_ATTACHED; // next state
+ /* in order to withhold the selection logic
+ * to check all ports READY_N value at every
+ * callback cycle to update ready variable,
+ * we check READY_N and update READY here
+ */
+ __set_agg_ports_ready(port->aggregator,
+ __agg_ports_are_ready(port->aggregator));
+
+ /* if the wait_while_timer expired, and the port
+ * is in READY state, move to ATTACHED state
+ */
+ if ((port->sm_vars & AD_PORT_READY) &&
+ !port->sm_mux_timer_counter)
+ port->sm_mux_state = AD_MUX_ATTACHED;
break;
case AD_MUX_ATTACHED:
- // check also if agg_select_timer expired(so the edable port will take place only after this timer)
- if ((port->sm_vars & AD_PORT_SELECTED) && (port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) && !__check_agg_selection_timer(port)) {
- port->sm_mux_state = AD_MUX_COLLECTING_DISTRIBUTING;// next state
- } else if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) { // if UNSELECTED or STANDBY
+ /* check also if agg_select_timer expired
+ * so the enable port will take place
+ * only after this timer
+ */
+ if ((port->sm_vars & AD_PORT_SELECTED) &&
+ (port->partner_oper.port_state &
+ AD_STATE_SYNCHRONIZATION) &&
+ !__check_agg_selection_timer(port)) {
+ port->sm_mux_state =
+ AD_MUX_COLLECTING_DISTRIBUTING;
+ } else if (!(port->sm_vars & AD_PORT_SELECTED) ||
+ (port->sm_vars & AD_PORT_STANDBY)) {
+ /* if UNSELECTED or STANDBY */
port->sm_vars &= ~AD_PORT_READY_N;
- // in order to withhold the selection logic to check all ports READY_N value
- // every callback cycle to update ready variable, we check READY_N and update READY here
- __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
- port->sm_mux_state = AD_MUX_DETACHED;// next state
+ /* in order to withhold the Selection Logic
+ * to check all ports READY_N value at every
+ * callback cycle to update ready variable,
+ * we check READY_N and update READY here
+ */
+ __set_agg_ports_ready(port->aggregator,
+ __agg_ports_are_ready(port->aggregator));
+ port->sm_mux_state = AD_MUX_DETACHED;
}
break;
case AD_MUX_COLLECTING_DISTRIBUTING:
- if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY) ||
- !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION)
- ) {
- port->sm_mux_state = AD_MUX_ATTACHED;// next state
-
+ if (!(port->sm_vars & AD_PORT_SELECTED) ||
+ (port->sm_vars & AD_PORT_STANDBY) ||
+ !(port->partner_oper.port_state &
+ AD_STATE_SYNCHRONIZATION)) {
+ port->sm_mux_state = AD_MUX_ATTACHED;
} else {
- // if port state hasn't changed make
- // sure that a collecting distributing
- // port in an active aggregator is enabled
+ /* if port state hasn't changed make
+ * sure that a collecting distributing
+ * port in an active aggregator is enabled
+ */
if (port->aggregator &&
port->aggregator->is_active &&
- !__port_is_enabled(port)) {
-
+ !__port_is_enabled(port))
__enable_port(port);
- }
}
break;
- default: //to silence the compiler
+ default:
+ pr_debug("Unexpected port->sm_mux_state: %d\n",
+ port->sm_mux_state);
break;
}
}
- // check if the state machine was changed
+ /* check if the state machine was changed */
if (port->sm_mux_state != last_state) {
pr_debug("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n",
port->actor_port_number, last_state,
@@ -981,14 +994,16 @@ static void ad_mux_machine(struct port *port)
switch (port->sm_mux_state) {
case AD_MUX_DETACHED:
__detach_bond_from_agg(port);
- port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
+ port->actor_oper_port_state &=
+ ~AD_STATE_SYNCHRONIZATION;
ad_disable_collecting_distributing(port);
port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
port->ntt = true;
break;
case AD_MUX_WAITING:
- port->sm_mux_timer_counter = __ad_timer_to_ticks(AD_WAIT_WHILE_TIMER, 0);
+ port->sm_mux_timer_counter =
+ __ad_timer_to_ticks(AD_WAIT_WHILE_TIMER, 0);
break;
case AD_MUX_ATTACHED:
__attach_bond_to_agg(port);
@@ -1004,7 +1019,9 @@ static void ad_mux_machine(struct port *port)
ad_enable_collecting_distributing(port);
port->ntt = true;
break;
- default: //to silence the compiler
+ default:
+ pr_debug("Unexpected port->sm_mux_state: %d\n",
+ port->sm_mux_state);
break;
}
}
@@ -1021,61 +1038,65 @@ static void ad_mux_machine(struct port *port)
*/
static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
{
- rx_states_t last_state;
+ rx_states_t last_state = port->sm_rx_state;
- // keep current State Machine state to compare later if it was changed
- last_state = port->sm_rx_state;
-
- // check if state machine should change state
- // first, check if port was reinitialized
+ /* check if state machine should change state
+ * first, check if port was reinitialized
+ */
if (port->sm_vars & AD_PORT_BEGIN)
/* next state */
port->sm_rx_state = AD_RX_INITIALIZE;
- // check if port is not enabled
- else if (!(port->sm_vars & AD_PORT_BEGIN)
- && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED))
+ /* check if port is not enabled */
+ else if (!(port->sm_vars & AD_PORT_BEGIN) &&
+ !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED))
/* next state */
port->sm_rx_state = AD_RX_PORT_DISABLED;
- // check if new lacpdu arrived
- else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) || (port->sm_rx_state == AD_RX_DEFAULTED) || (port->sm_rx_state == AD_RX_CURRENT))) {
- port->sm_rx_timer_counter = 0; // zero timer
+ /* check if new lacpdu arrived */
+ else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) ||
+ (port->sm_rx_state == AD_RX_DEFAULTED) ||
+ (port->sm_rx_state == AD_RX_CURRENT))) {
+ port->sm_rx_timer_counter = 0; /* zero timer */
port->sm_rx_state = AD_RX_CURRENT;
} else {
- // if timer is on, and if it is expired
- if (port->sm_rx_timer_counter && !(--port->sm_rx_timer_counter)) {
+ /* if timer is on, and if it is expired */
+ if (port->sm_rx_timer_counter &&
+ !(--port->sm_rx_timer_counter)) {
switch (port->sm_rx_state) {
case AD_RX_EXPIRED:
- port->sm_rx_state = AD_RX_DEFAULTED; // next state
+ port->sm_rx_state = AD_RX_DEFAULTED;
break;
case AD_RX_CURRENT:
- port->sm_rx_state = AD_RX_EXPIRED; // next state
+ port->sm_rx_state = AD_RX_EXPIRED;
break;
- default: //to silence the compiler
+ default:
+ pr_warn("Unexpected port->sm_rx_state: %d\n",
+ port->sm_rx_state);
break;
}
} else {
- // if no lacpdu arrived and no timer is on
+ /* if no lacpdu arrived and no timer is on */
switch (port->sm_rx_state) {
case AD_RX_PORT_DISABLED:
if (port->sm_vars & AD_PORT_MOVED)
- port->sm_rx_state = AD_RX_INITIALIZE; // next state
- else if (port->is_enabled
- && (port->sm_vars
- & AD_PORT_LACP_ENABLED))
- port->sm_rx_state = AD_RX_EXPIRED; // next state
- else if (port->is_enabled
- && ((port->sm_vars
- & AD_PORT_LACP_ENABLED) == 0))
- port->sm_rx_state = AD_RX_LACP_DISABLED; // next state
+ port->sm_rx_state = AD_RX_INITIALIZE;
+ else if (port->is_enabled &&
+ (port->sm_vars &
+ AD_PORT_LACP_ENABLED))
+ port->sm_rx_state = AD_RX_EXPIRED;
+ else if (port->is_enabled &&
+ ((port->sm_vars &
+ AD_PORT_LACP_ENABLED) == 0))
+ port->sm_rx_state = AD_RX_LACP_DISABLED;
break;
- default: //to silence the compiler
+ default:
+ pr_warn("Unexpected port->sm_rx_state: %d\n",
+ port->sm_rx_state);
break;
-
}
}
}
- // check if the State machine was changed or new lacpdu arrived
+ /* check if the State machine was changed or new lacpdu arrived */
if ((port->sm_rx_state != last_state) || (lacpdu)) {
pr_debug("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n",
port->actor_port_number, last_state,
@@ -1090,7 +1111,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
__record_default(port);
port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
port->sm_vars &= ~AD_PORT_MOVED;
- port->sm_rx_state = AD_RX_PORT_DISABLED; // next state
+ port->sm_rx_state = AD_RX_PORT_DISABLED;
/*- Fall Through -*/
@@ -1105,14 +1126,20 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
break;
case AD_RX_EXPIRED:
- //Reset of the Synchronization flag. (Standard 43.4.12)
- //This reset cause to disable this port in the COLLECTING_DISTRIBUTING state of the
- //mux machine in case of EXPIRED even if LINK_DOWN didn't arrive for the port.
- port->partner_oper.port_state &= ~AD_STATE_SYNCHRONIZATION;
+ /* Reset of the Synchronization flag. (Standard 43.4.12)
+ * This reset cause to disable this port in the
+ * COLLECTING_DISTRIBUTING state of the mux machine
+ * in case of EXPIRED even if LINK_DOWN didn't arrive
+ * for the port.
+ */
+ port->partner_oper.port_state &=
+ ~AD_STATE_SYNCHRONIZATION;
port->sm_vars &= ~AD_PORT_MATCHED;
port->partner_oper.port_state |=
AD_STATE_LACP_ACTIVITY;
- port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT));
+ port->sm_rx_timer_counter =
+ __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER,
+ (u16)(AD_SHORT_TIMEOUT));
port->actor_oper_port_state |= AD_STATE_EXPIRED;
break;
case AD_RX_DEFAULTED:
@@ -1122,12 +1149,13 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
break;
case AD_RX_CURRENT:
- // detect loopback situation
- if (!MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->actor_system))) {
- // INFO_RECEIVED_LOOPBACK_FRAMES
+ /* detect loopback situation */
+ if (!compare_ether_addr((const u8 *)&(lacpdu->actor_system), (const u8 *)&(port->actor_system))) {
+ /* INFO_RECEIVED_LOOPBACK_FRAMES */
pr_err("%s: An illegal loopback occurred on adapter (%s).\n"
"Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
- port->slave->dev->master->name, port->slave->dev->name);
+ port->slave->dev->master->name,
+ port->slave->dev->name);
return;
}
__update_selected(lacpdu, port);
@@ -1135,15 +1163,21 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
__record_pdu(lacpdu, port);
port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT));
port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
- // verify that if the aggregator is enabled, the port is enabled too.
- //(because if the link goes down for a short time, the 802.3ad will not
- // catch it, and the port will continue to be disabled)
+
+ /* verify that if the aggregator is enabled,
+ * so the port is enabled too.
+ * because if the link goes down for a short time,
+ * the 802.3ad will not catch it,
+ * and the port will continue to be disabled
+ */
if (port->aggregator
&& port->aggregator->is_active
&& !__port_is_enabled(port))
__enable_port(port);
break;
- default: //to silence the compiler
+ default:
+ pr_warn("Unexpected port->sm_rx_state: %d\n",
+ port->sm_rx_state);
break;
}
}
@@ -1156,9 +1190,11 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
*/
static void ad_tx_machine(struct port *port)
{
- // check if tx timer expired, to verify that we do not send more than 3 packets per second
+ /* check if tx timer has expired,
+ * to verify that we do not send more than 3 packets per second
+ */
if (port->sm_tx_timer_counter && !(--port->sm_tx_timer_counter)) {
- // check if there is something to send
+ /* check if there is something to send */
if (port->ntt && (port->sm_vars & AD_PORT_LACP_ENABLED)) {
__update_lacpdu_from_port(port);
@@ -1166,14 +1202,17 @@ static void ad_tx_machine(struct port *port)
pr_debug("Sent LACPDU on port %d\n",
port->actor_port_number);
- /* mark ntt as false, so it will not be sent again until
- demanded */
+ /* mark ntt as false,
+ * so it won't be sent again until demanded
+ */
port->ntt = false;
}
}
- // restart tx timer(to verify that we will not exceed AD_MAX_TX_IN_SECOND
+ /* restart tx timer
+ * to verify that we won't exceed AD_MAX_TX_IN_SECOND
+ */
port->sm_tx_timer_counter =
- ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
+ ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
}
}
@@ -1187,76 +1226,96 @@ static void ad_periodic_machine(struct port *port)
{
periodic_states_t last_state;
- // keep current state machine state to compare later if it was changed
+ /* keep current state machine state to compare later if it was changed*/
last_state = port->sm_periodic_state;
- // check if port was reinitialized
- if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) ||
- (!(port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & AD_STATE_LACP_ACTIVITY))
- ) {
- port->sm_periodic_state = AD_NO_PERIODIC; // next state
+ /* check if port was reinitialized */
+ if (((port->sm_vars & AD_PORT_BEGIN) ||
+ !(port->sm_vars & AD_PORT_LACP_ENABLED) ||
+ !port->is_enabled) ||
+ (!(port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY) &&
+ !(port->partner_oper.port_state & AD_STATE_LACP_ACTIVITY))) {
+ port->sm_periodic_state = AD_NO_PERIODIC; /* next state */
}
- // check if state machine should change state
+ /* check if state machine should change state */
else if (port->sm_periodic_timer_counter) {
- // check if periodic state machine expired
+ /* check if periodic state machine expired */
if (!(--port->sm_periodic_timer_counter)) {
- // if expired then do tx
- port->sm_periodic_state = AD_PERIODIC_TX; // next state
+ /* if expired then do tx, next state */
+ port->sm_periodic_state = AD_PERIODIC_TX;
} else {
- // If not expired, check if there is some new timeout parameter from the partner state
+ /* If not expired, check if there is some
+ * new timeout parameter from the partner state
+ */
switch (port->sm_periodic_state) {
case AD_FAST_PERIODIC:
if (!(port->partner_oper.port_state
& AD_STATE_LACP_TIMEOUT))
- port->sm_periodic_state = AD_SLOW_PERIODIC; // next state
+ port->sm_periodic_state = AD_SLOW_PERIODIC;
break;
case AD_SLOW_PERIODIC:
- if ((port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
- // stop current timer
+ if ((port->partner_oper.port_state &
+ AD_STATE_LACP_TIMEOUT)) {
+ /* stop current timer */
port->sm_periodic_timer_counter = 0;
- port->sm_periodic_state = AD_PERIODIC_TX; // next state
+ port->sm_periodic_state = AD_PERIODIC_TX;
}
break;
- default: //to silence the compiler
+ default:
+ /* unexpected port->sm_sm_periodic_state */
+ pr_debug("Unexpected port->sm_periodic_state: %d\n",
+ port->sm_periodic_state);
break;
}
}
} else {
switch (port->sm_periodic_state) {
case AD_NO_PERIODIC:
- port->sm_periodic_state = AD_FAST_PERIODIC; // next state
+ port->sm_periodic_state = AD_FAST_PERIODIC;
break;
case AD_PERIODIC_TX:
- if (!(port->partner_oper.port_state
- & AD_STATE_LACP_TIMEOUT))
- port->sm_periodic_state = AD_SLOW_PERIODIC; // next state
+ if (!(port->partner_oper.port_state &
+ AD_STATE_LACP_TIMEOUT))
+ port->sm_periodic_state = AD_SLOW_PERIODIC;
else
- port->sm_periodic_state = AD_FAST_PERIODIC; // next state
+ port->sm_periodic_state = AD_FAST_PERIODIC;
break;
- default: //to silence the compiler
+ default:
+ /* unexpected port->sm_sm_periodic_state */
+ pr_debug("Unexpected port->sm_periodic_state: %d\n",
+ port->sm_periodic_state);
break;
}
}
- // check if the state machine was changed
+ /* check if the state machine was changed */
if (port->sm_periodic_state != last_state) {
pr_debug("Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n",
port->actor_port_number, last_state,
port->sm_periodic_state);
switch (port->sm_periodic_state) {
case AD_NO_PERIODIC:
- port->sm_periodic_timer_counter = 0; // zero timer
+ port->sm_periodic_timer_counter = 0;
break;
case AD_FAST_PERIODIC:
- port->sm_periodic_timer_counter = __ad_timer_to_ticks(AD_PERIODIC_TIMER, (u16)(AD_FAST_PERIODIC_TIME))-1; // decrement 1 tick we lost in the PERIODIC_TX cycle
+ /* decrement 1 tick we lost in PERIODIC_TX cycle */
+ port->sm_periodic_timer_counter =
+ __ad_timer_to_ticks(AD_PERIODIC_TIMER,
+ (u16)(AD_FAST_PERIODIC_TIME))-1;
break;
case AD_SLOW_PERIODIC:
- port->sm_periodic_timer_counter = __ad_timer_to_ticks(AD_PERIODIC_TIMER, (u16)(AD_SLOW_PERIODIC_TIME))-1; // decrement 1 tick we lost in the PERIODIC_TX cycle
+ /* decrement 1 tick we lost in PERIODIC_TX cycle */
+ port->sm_periodic_timer_counter =
+ __ad_timer_to_ticks(AD_PERIODIC_TIMER,
+ (u16)(AD_SLOW_PERIODIC_TIME))-1;
break;
case AD_PERIODIC_TX:
port->ntt = true;
break;
- default: //to silence the compiler
+ default:
+ /* unexpected port->sm_sm_periodic_state */
+ pr_debug("Unexpected port->sm_periodic_state: %d\n",
+ port->sm_periodic_state);
break;
}
}
@@ -1272,46 +1331,58 @@ static void ad_periodic_machine(struct port *port)
*/
static void ad_port_selection_logic(struct port *port)
{
- struct aggregator *aggregator, *free_aggregator = NULL, *temp_aggregator;
+ struct aggregator *aggregator, *temp_aggregator;
+ struct aggregator *free_aggregator = NULL;
struct port *last_port = NULL, *curr_port;
int found = 0;
- // if the port is already Selected, do nothing
+ /* if the port is already Selected, do nothing */
if (port->sm_vars & AD_PORT_SELECTED)
return;
- // if the port is connected to other aggregator, detach it
+ /* if the port is connected to other aggregator, detach it */
if (port->aggregator) {
- // detach the port from its former aggregator
+ /* detach the port from its former aggregator */
temp_aggregator = port->aggregator;
for (curr_port = temp_aggregator->lag_ports; curr_port;
last_port = curr_port,
curr_port = curr_port->next_port_in_aggregator) {
if (curr_port == port) {
temp_aggregator->num_of_ports--;
- if (!last_port) {// if it is the first port attached to the aggregator
+ if (!last_port) {
+ /* if it is the first port attached
+ to the aggregator */
temp_aggregator->lag_ports =
port->next_port_in_aggregator;
- } else {// not the first port attached to the aggregator
+ } else {
+ /* not the first port attached
+ to the aggregator */
last_port->next_port_in_aggregator =
port->next_port_in_aggregator;
}
- // clear the port's relations to this aggregator
+ /* clear the port's relations
+ to this aggregator */
port->aggregator = NULL;
port->next_port_in_aggregator = NULL;
port->actor_port_aggregator_identifier = 0;
pr_debug("Port %d left LAG %d\n",
- port->actor_port_number,
- temp_aggregator->aggregator_identifier);
- // if the aggregator is empty, clear its parameters, and set it ready to be attached
+ port->actor_port_number,
+ temp_aggregator->aggregator_identifier);
+ /* if the aggregator is empty,
+ * clear its parameters, and set it ready
+ * to be attached
+ */
if (!temp_aggregator->lag_ports)
ad_clear_agg(temp_aggregator);
break;
}
}
- if (!curr_port) { // meaning: the port was related to an aggregator but was not on the aggregator port list
+ if (!curr_port) {
+ /* meaning: the port was related to an aggregator
+ * but was not on the aggregator port list.
+ */
pr_warning("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n",
port->slave->dev->master->name,
port->actor_port_number,
@@ -1319,27 +1390,34 @@ static void ad_port_selection_logic(struct port *port)
port->aggregator->aggregator_identifier);
}
}
- // search on all aggregators for a suitable aggregator for this port
+ /* search on all aggregators for a suitable aggregator for this port */
for (aggregator = __get_first_agg(port); aggregator;
aggregator = __get_next_agg(aggregator)) {
- // keep a free aggregator for later use(if needed)
+ /* keep a free aggregator for later use (if needed) */
if (!aggregator->lag_ports) {
if (!free_aggregator)
free_aggregator = aggregator;
continue;
}
- // check if current aggregator suits us
- if (((aggregator->actor_oper_aggregator_key == port->actor_oper_port_key) && // if all parameters match AND
- !MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(port->partner_oper.system)) &&
+
+ /* check if current aggregator suits us
+ * a suitable aggregator must fit the following requirements,
+ * tested here:
+ * i. match all parameters;
+ * ii. has partner answers;
+ * iii. it is not individual
+ */
+ if (((aggregator->actor_oper_aggregator_key == port->actor_oper_port_key) &&
+ !compare_ether_addr((const u8 *)&(aggregator->partner_system), (const u8 *)&(port->partner_oper.system)) &&
(aggregator->partner_system_priority == port->partner_oper.system_priority) &&
(aggregator->partner_oper_aggregator_key == port->partner_oper.key)
) &&
- ((MAC_ADDRESS_COMPARE(&(port->partner_oper.system), &(null_mac_addr)) && // partner answers
- !aggregator->is_individual) // but is not individual OR
+ ((compare_ether_addr((const u8 *)&(port->partner_oper.system), (const u8 *)&(null_mac_addr)) &&
+ !aggregator->is_individual)
)
) {
- // attach to the founded aggregator
+ /* attach to the founded aggregator */
port->aggregator = aggregator;
port->actor_port_aggregator_identifier =
port->aggregator->aggregator_identifier;
@@ -1350,42 +1428,45 @@ static void ad_port_selection_logic(struct port *port)
port->actor_port_number,
port->aggregator->aggregator_identifier);
- // mark this port as selected
+ /* mark this port as selected */
port->sm_vars |= AD_PORT_SELECTED;
found = 1;
break;
}
}
- // the port couldn't find an aggregator - attach it to a new aggregator
+ /* the port couldn't find an aggregator, attach it to a new aggregator*/
if (!found) {
if (free_aggregator) {
- // assign port a new aggregator
+ /* assign port a new aggregator */
port->aggregator = free_aggregator;
port->actor_port_aggregator_identifier =
port->aggregator->aggregator_identifier;
- // update the new aggregator's parameters
- // if port was responsed from the end-user
+ /* update the new aggregator's parameters
+ if port was replied from the end-user */
if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)
/* if port is full duplex */
port->aggregator->is_individual = false;
else
port->aggregator->is_individual = true;
- port->aggregator->actor_admin_aggregator_key = port->actor_admin_port_key;
- port->aggregator->actor_oper_aggregator_key = port->actor_oper_port_key;
+ port->aggregator->actor_admin_aggregator_key =
+ port->actor_admin_port_key;
+ port->aggregator->actor_oper_aggregator_key =
+ port->actor_oper_port_key;
port->aggregator->partner_system =
- port->partner_oper.system;
+ port->partner_oper.system;
port->aggregator->partner_system_priority =
- port->partner_oper.system_priority;
- port->aggregator->partner_oper_aggregator_key = port->partner_oper.key;
+ port->partner_oper.system_priority;
+ port->aggregator->partner_oper_aggregator_key =
+ port->partner_oper.key;
port->aggregator->receive_state = 1;
port->aggregator->transmit_state = 1;
port->aggregator->lag_ports = port;
port->aggregator->num_of_ports++;
- // mark this port as selected
+ /* mark this port as selected */
port->sm_vars |= AD_PORT_SELECTED;
pr_debug("Port %d joined LAG %d(new LAG)\n",
@@ -1397,16 +1478,18 @@ static void ad_port_selection_logic(struct port *port)
port->actor_port_number, port->slave->dev->name);
}
}
- // if all aggregator's ports are READY_N == TRUE, set ready=TRUE in all aggregator's ports
- // else set ready=FALSE in all aggregator's ports
- __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
+ /* if all aggregator's ports are READY_N == TRUE,
+ * set ready=TRUE in all aggregator's ports
+ * else set ready=FALSE in all aggregator's ports
+ */
+ __set_agg_ports_ready(port->aggregator,
+ __agg_ports_are_ready(port->aggregator));
aggregator = __get_first_agg(port);
ad_agg_selection_logic(aggregator);
}
-/*
- * Decide if "agg" is a better choice for the new active aggregator that
+/* Decide if "agg" is a better choice for the new active aggregator that
* the current best, according to the ad_select policy.
*/
static struct aggregator *ad_agg_selection_test(struct aggregator *best,
@@ -1531,18 +1614,16 @@ static void ad_agg_selection_logic(struct aggregator *agg)
if (best &&
__get_agg_selection_mode(best->lag_ports) == BOND_AD_STABLE) {
- /*
- * For the STABLE policy, don't replace the old active
- * aggregator if it's still active (it has an answering
- * partner) or if both the best and active don't have an
- * answering partner.
+
+ /* For the STABLE policy, don't replace the old active
+ * aggregator if it's still active (it has an answering partner)
+ * or if both the best and active don't have answering partners
*/
if (active && active->lag_ports &&
active->lag_ports->is_enabled &&
- (__agg_has_partner(active) ||
- (!__agg_has_partner(active) && !__agg_has_partner(best)))) {
- if (!(!active->actor_oper_aggregator_key &&
- best->actor_oper_aggregator_key)) {
+ (__agg_has_partner(active) || !__agg_has_partner(best))) {
+ if (active->actor_oper_aggregator_key ||
+ !best->actor_oper_aggregator_key) {
best = NULL;
active->is_active = 1;
}
@@ -1554,7 +1635,7 @@ static void ad_agg_selection_logic(struct aggregator *agg)
active->is_active = 1;
}
- // if there is new best aggregator, activate it
+ /* if there is new best aggregator, activate it */
if (best) {
pr_debug("best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
best->aggregator_identifier, best->num_of_ports,
@@ -1575,7 +1656,7 @@ static void ad_agg_selection_logic(struct aggregator *agg)
agg->is_individual, agg->is_active);
}
- // check if any partner replys
+ /* check if any partner replies */
if (best->is_individual) {
pr_warning("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n",
best->slave ? best->slave->dev->master->name : "NULL");
@@ -1590,7 +1671,9 @@ static void ad_agg_selection_logic(struct aggregator *agg)
best->partner_oper_aggregator_key,
best->is_individual, best->is_active);
- // disable the ports that were related to the former active_aggregator
+ /* disable the ports that were related to
+ * the former active_aggregator
+ */
if (active) {
for (port = active->lag_ports; port;
port = port->next_port_in_aggregator) {
@@ -1599,8 +1682,7 @@ static void ad_agg_selection_logic(struct aggregator *agg)
}
}
- /*
- * if the selected aggregator is of join individuals
+ /* if the selected aggregator is of join individuals
* (partner_system is NULL), enable their ports
*/
active = __get_active_agg(origin);
@@ -1699,8 +1781,10 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
port->ntt = false;
port->actor_admin_port_key = 1;
port->actor_oper_port_key = 1;
- port->actor_admin_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
- port->actor_oper_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
+ port->actor_admin_port_state =
+ AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
+ port->actor_oper_port_state =
+ AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
if (lacp_fast)
port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
@@ -1709,7 +1793,7 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
memcpy(&port->partner_oper, &tmpl, sizeof(tmpl));
port->is_enabled = true;
- // ****** private parameters ******
+ /* ****** private parameters ****** */
port->sm_vars = 0x3;
port->sm_rx_state = 0;
port->sm_rx_timer_counter = 0;
@@ -1751,7 +1835,9 @@ static void ad_enable_collecting_distributing(struct port *port)
*/
static void ad_disable_collecting_distributing(struct port *port)
{
- if (port->aggregator && MAC_ADDRESS_COMPARE(&(port->aggregator->partner_system), &(null_mac_addr))) {
+ if (port->aggregator &&
+ compare_ether_addr((const u8 *)&(port->aggregator->partner_system),
+ (const u8 *)&(null_mac_addr))) {
pr_debug("Disabling port %d(LAG %d)\n",
port->actor_port_number,
port->aggregator->aggregator_identifier);
@@ -1773,27 +1859,28 @@ static void ad_marker_info_send(struct port *port)
struct bond_marker marker;
u16 index;
- // fill the marker PDU with the appropriate values
+ /* fill the marker PDU with the appropriate values */
marker.subtype = 0x02;
marker.version_number = 0x01;
marker.tlv_type = AD_MARKER_INFORMATION_SUBTYPE;
marker.marker_length = 0x16;
- // convert requester_port to Big Endian
- marker.requester_port = (((port->actor_port_number & 0xFF) << 8) |((u16)(port->actor_port_number & 0xFF00) >> 8));
+ /* convert requester_port to Big Endian */
+ marker.requester_port = (((port->actor_port_number & 0xFF) << 8) |
+ ((u16)(port->actor_port_number & 0xFF00) >> 8));
marker.requester_system = port->actor_system;
- // convert requester_port(u32) to Big Endian
+ /* convert requester_port(u32) to Big Endian */
marker.requester_transaction_id =
- (((++port->transaction_id & 0xFF) << 24)
- | ((port->transaction_id & 0xFF00) << 8)
- | ((port->transaction_id & 0xFF0000) >> 8)
- | ((port->transaction_id & 0xFF000000) >> 24));
+ (((++port->transaction_id & 0xFF) << 24) |
+ ((port->transaction_id & 0xFF00) << 8) |
+ ((port->transaction_id & 0xFF0000) >> 8) |
+ ((port->transaction_id & 0xFF000000) >> 24));
marker.pad = 0;
marker.tlv_type_terminator = 0x00;
marker.terminator_length = 0x00;
for (index = 0; index < 90; index++)
marker.reserved_90[index] = 0;
- // send the marker information
+ /* send the marker information */
if (ad_marker_send(port, &marker) >= 0) {
pr_debug("Sent Marker Information on port %d\n",
port->actor_port_number);
@@ -1812,12 +1899,13 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
{
struct bond_marker marker;
- // copy the received marker data to the response marker
- //marker = *marker_info;
+ /* copy the received marker data to the response marker
+ * marker = *marker_info;
+ */
memcpy(&marker, marker_info, sizeof(struct bond_marker));
- // change the marker subtype to marker response
+ /* change the marker subtype to marker response */
marker.tlv_type = AD_MARKER_RESPONSE_SUBTYPE;
- // send the marker response
+ /* send the marker response */
if (ad_marker_send(port, &marker) >= 0) {
pr_debug("Sent Marker Response on port %d\n",
@@ -1837,16 +1925,13 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
static void ad_marker_response_received(struct bond_marker *marker,
struct port *port)
{
- marker = NULL; /* just to satisfy the compiler */
- port = NULL; /* just to satisfy the compiler */
- // DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW
+ marker = NULL;
+ port = NULL;
}
-//////////////////////////////////////////////////////////////////////////////////////
-// ================= AD exported functions to the main bonding code ==================
-//////////////////////////////////////////////////////////////////////////////////////
+/* ============= AD exported functions to the main bonding code ============ */
-// Check aggregators status in team every T seconds
+/* Check aggregators status in team every T seconds */
#define AD_AGGREGATOR_SELECTION_TIMER 8
/*
@@ -1874,17 +1959,20 @@ static u16 aggregator_identifier;
*/
void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast)
{
- // check that the bond is not initialized yet
- if (MAC_ADDRESS_COMPARE(&(BOND_AD_INFO(bond).system.sys_mac_addr),
+ /* check that the bond is not initialized yet */
+ if (compare_ether_addr((const u8 *)&(BOND_AD_INFO(bond).system.sys_mac_addr),
bond->dev->dev_addr)) {
aggregator_identifier = 0;
BOND_AD_INFO(bond).lacp_fast = lacp_fast;
BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
- BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
+ BOND_AD_INFO(bond).system.sys_mac_addr =
+ *((struct mac_addr *)bond->dev->dev_addr);
- // initialize how many times this module is called in one second(should be about every 100ms)
+ /* initialize how many times this module is
+ * called in one second(should be about every 100ms)
+ */
ad_ticks_per_sec = tick_resolution;
bond_3ad_initiate_agg_selection(bond,
@@ -1912,31 +2000,37 @@ int bond_3ad_bind_slave(struct slave *slave)
return -1;
}
- //check that the slave has not been initialized yet.
+ /* check that the slave has not been initialized yet. */
if (SLAVE_AD_INFO(slave).port.slave != slave) {
- // port initialization
+ /* port initialization */
port = &(SLAVE_AD_INFO(slave).port);
ad_initialize_port(port, BOND_AD_INFO(bond).lacp_fast);
port->slave = slave;
port->actor_port_number = SLAVE_AD_INFO(slave).id;
- // key is determined according to the link speed, duplex and user key(which is yet not supported)
- // ------------------------------------------------------------
- // Port key : | User key | Speed |Duplex|
- // ------------------------------------------------------------
- // 16 6 1 0
- port->actor_admin_port_key = 0; // initialize this parameter
+ /* key is determined according to the link speed,
+ * duplex and user key(which is yet not supported)
+ * Port key:
+ * ------------------------------------------------------------
+ * | User key | Speed |Duplex|
+ * ------------------------------------------------------------
+ * 16 6 1 0
+ */
+ port->actor_admin_port_key = 0; /* initialize this parameter */
port->actor_admin_port_key |= __get_duplex(port);
port->actor_admin_port_key |= (__get_link_speed(port) << 1);
port->actor_oper_port_key = port->actor_admin_port_key;
- // if the port is not full duplex, then the port should be not lacp Enabled
+ /* if the port is not full duplex,
+ * then the port should be not lacp Enabled
+ */
if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS))
port->sm_vars &= ~AD_PORT_LACP_ENABLED;
- // actor system is the bond's system
+ /* actor system is the bond's system */
port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr;
- // tx timer(to verify that no more than MAX_TX_IN_SECOND lacpdu's are sent in one second)
+
+ /* certify that no more than MAX_TX_IN_SECOND lacpdu sent/sec */
port->sm_tx_timer_counter = ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
port->aggregator = NULL;
port->next_port_in_aggregator = NULL;
@@ -1945,12 +2039,13 @@ int bond_3ad_bind_slave(struct slave *slave)
__initialize_port_locks(port);
- // aggregator initialization
+ /* aggregator initialization */
aggregator = &(SLAVE_AD_INFO(slave).aggregator);
ad_initialize_agg(aggregator);
- aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr);
+ aggregator->aggregator_mac_address =
+ *((struct mac_addr *)bond->dev->dev_addr);
aggregator->aggregator_identifier = (++aggregator_identifier);
aggregator->slave = slave;
aggregator->is_active = 0;
@@ -1974,13 +2069,13 @@ void bond_3ad_unbind_slave(struct slave *slave)
struct aggregator *aggregator, *new_aggregator, *temp_aggregator;
int select_new_active_agg = 0;
- // find the aggregator related to this slave
+ /* find the aggregator related to this slave */
aggregator = &(SLAVE_AD_INFO(slave).aggregator);
- // find the port related to this slave
+ /* find the port related to this slave */
port = &(SLAVE_AD_INFO(slave).port);
- // if slave is null, the whole port is not initialized
+ /* if slave is null, the whole port is not initialized */
if (!port->slave) {
pr_warning("Warning: %s: Trying to unbind an uninitialized port on %s\n",
slave->dev->master->name, slave->dev->name);
@@ -1995,32 +2090,43 @@ void bond_3ad_unbind_slave(struct slave *slave)
__update_lacpdu_from_port(port);
ad_lacpdu_send(port);
- // check if this aggregator is occupied
+ /* check if this aggregator is occupied */
if (aggregator->lag_ports) {
- // check if there are other ports related to this aggregator except
- // the port related to this slave(thats ensure us that there is a
- // reason to search for new aggregator, and that we will find one
- if ((aggregator->lag_ports != port) || (aggregator->lag_ports->next_port_in_aggregator)) {
- // find new aggregator for the related port(s)
+ /* check if there are other ports related to this aggregator
+ * except the port related to this slave
+ * (it ensures us that there is a reason to search for
+ * new aggregator, and that we will find one)
+ */
+ if ((aggregator->lag_ports != port) ||
+ (aggregator->lag_ports->next_port_in_aggregator)) {
+ /* find new aggregator for the related port(s) */
new_aggregator = __get_first_agg(port);
- for (; new_aggregator; new_aggregator = __get_next_agg(new_aggregator)) {
- // if the new aggregator is empty, or it is connected to our port only
- if (!new_aggregator->lag_ports
- || ((new_aggregator->lag_ports == port)
- && !new_aggregator->lag_ports->next_port_in_aggregator))
+ for (; new_aggregator;
+ new_aggregator = __get_next_agg(new_aggregator)) {
+ /* if the new aggregator is empty,
+ or it is connected to our port only */
+ if (!new_aggregator->lag_ports ||
+ ((new_aggregator->lag_ports == port) &&
+ !new_aggregator->lag_ports->next_port_in_aggregator))
break;
}
- // if new aggregator found, copy the aggregator's parameters
- // and connect the related lag_ports to the new aggregator
- if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
- pr_debug("Some port(s) related to LAG %d - replaceing with LAG %d\n",
+ /* if new aggregator found, copy the aggregator's
+ * parameters and connect the related lag_ports to the
+ * new aggregator
+ */
+ if ((new_aggregator) &&
+ ((!new_aggregator->lag_ports) ||
+ ((new_aggregator->lag_ports == port) &&
+ !new_aggregator->lag_ports->next_port_in_aggregator))) {
+ pr_debug("Some port(s) related to LAG %d - replacing with LAG %d\n",
aggregator->aggregator_identifier,
new_aggregator->aggregator_identifier);
- if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
+ if ((new_aggregator->lag_ports == port) &&
+ new_aggregator->is_active) {
pr_info("%s: Removing an active aggregator\n",
aggregator->slave->dev->master->name);
- // select new active aggregator
+ /* select new active aggregator */
select_new_active_agg = 1;
}
@@ -2036,14 +2142,15 @@ void bond_3ad_unbind_slave(struct slave *slave)
new_aggregator->is_active = aggregator->is_active;
new_aggregator->num_of_ports = aggregator->num_of_ports;
- // update the information that is written on the ports about the aggregator
- for (temp_port = aggregator->lag_ports; temp_port;
- temp_port = temp_port->next_port_in_aggregator) {
+ /* update the information that is written on
+ * the ports about the aggregator
+ */
+ for (temp_port = aggregator->lag_ports; temp_port; temp_port = temp_port->next_port_in_aggregator) {
temp_port->aggregator = new_aggregator;
temp_port->actor_port_aggregator_identifier = new_aggregator->aggregator_identifier;
}
- // clear the aggregator
+ /* clear the aggregator */
ad_clear_agg(aggregator);
if (select_new_active_agg)
@@ -2052,42 +2159,50 @@ void bond_3ad_unbind_slave(struct slave *slave)
pr_warning("%s: Warning: unbinding aggregator, and could not find a new aggregator for its ports\n",
slave->dev->master->name);
}
- } else { // in case that the only port related to this aggregator is the one we want to remove
+ } else {
+ /* in case that the only port related to this
+ * aggregator is the one we want to remove
+ */
select_new_active_agg = aggregator->is_active;
- // clear the aggregator
+ /* clear the aggregator */
ad_clear_agg(aggregator);
if (select_new_active_agg) {
pr_info("%s: Removing an active aggregator\n",
slave->dev->master->name);
- // select new active aggregator
+ /* select new active aggregator */
ad_agg_selection_logic(__get_first_agg(port));
}
}
}
pr_debug("Unbinding port %d\n", port->actor_port_number);
- // find the aggregator that this port is connected to
+ /* find the aggregator that this port is connected to */
temp_aggregator = __get_first_agg(port);
- for (; temp_aggregator; temp_aggregator = __get_next_agg(temp_aggregator)) {
+ for (; temp_aggregator;
+ temp_aggregator = __get_next_agg(temp_aggregator)) {
prev_port = NULL;
- // search the port in the aggregator's related ports
+ /* search the port in the aggregator's related ports */
for (temp_port = temp_aggregator->lag_ports; temp_port;
prev_port = temp_port,
temp_port = temp_port->next_port_in_aggregator) {
- if (temp_port == port) { // the aggregator found - detach the port from this aggregator
+ if (temp_port == port) {
+ /* the aggregator found
+ detach the port from this aggregator */
if (prev_port)
- prev_port->next_port_in_aggregator = temp_port->next_port_in_aggregator;
+ prev_port->next_port_in_aggregator =
+ temp_port->next_port_in_aggregator;
else
- temp_aggregator->lag_ports = temp_port->next_port_in_aggregator;
+ temp_aggregator->lag_ports =
+ temp_port->next_port_in_aggregator;
temp_aggregator->num_of_ports--;
if (temp_aggregator->num_of_ports == 0) {
select_new_active_agg = temp_aggregator->is_active;
- // clear the aggregator
+ /* clear the aggregator */
ad_clear_agg(temp_aggregator);
if (select_new_active_agg) {
pr_info("%s: Removing an active aggregator\n",
slave->dev->master->name);
- // select new active aggregator
+ /* select new active aggreg */
ad_agg_selection_logic(__get_first_agg(port));
}
}
@@ -2123,13 +2238,14 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
if (bond->kill_timers)
goto out;
- //check if there are any slaves
+ /* check if there are any slaves */
if (bond->slave_cnt == 0)
goto re_arm;
- // check if agg_select_timer timer after initialize is timed out
- if (BOND_AD_INFO(bond).agg_select_timer && !(--BOND_AD_INFO(bond).agg_select_timer)) {
- // select the active aggregator for the bond
+ /* check if agg_select_timer timer after initialize is timed out */
+ if (BOND_AD_INFO(bond).agg_select_timer &&
+ !(--BOND_AD_INFO(bond).agg_select_timer)) {
+ /* select the active aggregator for the bond */
if ((port = __get_first_port(bond))) {
if (!port->slave) {
pr_warning("%s: Warning: bond's first port is uninitialized\n",
@@ -2143,17 +2259,18 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
bond_3ad_set_carrier(bond);
}
- // for each port run the state machines
- for (port = __get_first_port(bond); port; port = __get_next_port(port)) {
+ /* for each port run the state machines */
+ for (port = __get_first_port(bond); port;
+ port = __get_next_port(port)) {
if (!port->slave) {
pr_warning("%s: Warning: Found an uninitialized port\n",
bond->dev->name);
goto re_arm;
}
- /* Lock around state machines to protect data accessed
- * by all (e.g., port->sm_vars). ad_rx_machine may run
- * concurrently due to incoming LACPDU.
+ /* Lock around state machines to protect data accessed by all
+ * (e.g., port->sm_vars).
+ * ad_rx_machine may run concurrently due to incoming LACPDU.
*/
__get_state_machine_lock(port);
@@ -2163,7 +2280,7 @@ void bond_3ad_state_machine_handler(struct work_struct *work)
ad_mux_machine(port);
ad_tx_machine(port);
- // turn off the BEGIN bit, since we already handled it
+ /* turn off the BEGIN bit, since we already handled it */
if (port->sm_vars & AD_PORT_BEGIN)
port->sm_vars &= ~AD_PORT_BEGIN;
@@ -2196,7 +2313,8 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
if (!port->slave) {
pr_warning("%s: Warning: port of slave %s is uninitialized\n",
- slave->dev->name, slave->dev->master->name);
+ slave->dev->name,
+ slave->dev->master->name);
return;
}
@@ -2211,7 +2329,9 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
break;
case AD_TYPE_MARKER:
- // No need to convert fields to Little Endian since we don't use the marker's fields.
+ /* No need to convert fields to Little Endian
+ * since we don't use the marker's fields.
+ */
switch (((struct bond_marker *)lacpdu)->tlv_type) {
case AD_MARKER_INFORMATION_SUBTYPE:
@@ -2246,19 +2366,22 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
port = &(SLAVE_AD_INFO(slave).port);
- // if slave is null, the whole port is not initialized
+ /* if slave is null, the whole port is not initialized */
if (!port->slave) {
pr_warning("Warning: %s: speed changed for uninitialized port on %s\n",
- slave->dev->master->name, slave->dev->name);
+ slave->dev->master->name,
+ slave->dev->name);
return;
}
port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
port->actor_oper_port_key = port->actor_admin_port_key |=
(__get_link_speed(port) << 1);
+
pr_debug("Port %d changed speed\n", port->actor_port_number);
- // there is no need to reselect a new aggregator, just signal the
- // state machines to reinitialize
+ /* there is no need to reselect a new aggregator,
+ * just signal the state machines to reinitialize
+ */
port->sm_vars |= AD_PORT_BEGIN;
}
@@ -2274,7 +2397,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
port = &(SLAVE_AD_INFO(slave).port);
- // if slave is null, the whole port is not initialized
+ /* if slave is null, the whole port is not initialized */
if (!port->slave) {
pr_warning("%s: Warning: duplex changed for uninitialized port on %s\n",
slave->dev->master->name, slave->dev->name);
@@ -2284,9 +2407,11 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
port->actor_oper_port_key = port->actor_admin_port_key |=
__get_duplex(port);
+
pr_debug("Port %d changed duplex\n", port->actor_port_number);
- // there is no need to reselect a new aggregator, just signal the
- // state machines to reinitialize
+ /* there is no need to reselect a new aggregator,
+ * just signal the state machines to reinitialize
+ */
port->sm_vars |= AD_PORT_BEGIN;
}
@@ -2303,15 +2428,18 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
port = &(SLAVE_AD_INFO(slave).port);
- // if slave is null, the whole port is not initialized
+ /* if slave is null, the whole port is not initialized */
if (!port->slave) {
pr_warning("Warning: %s: link status changed for uninitialized port on %s\n",
slave->dev->master->name, slave->dev->name);
return;
}
- // on link down we are zeroing duplex and speed since some of the adaptors(ce1000.lan) report full duplex/speed instead of N/A(duplex) / 0(speed)
- // on link up we are forcing recheck on the duplex and speed since some of he adaptors(ce1000.lan) report
+ /* on link down we are zeroing duplex and speed
+ * since some of the adapters (ce1000.lan) report full duplex/speed
+ * instead of N/A (duplex) / 0(speed)
+ * on link up we are forcing recheck on the duplex and speed
+ */
if (link == BOND_LINK_UP) {
port->is_enabled = true;
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
@@ -2327,9 +2455,15 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
port->actor_oper_port_key = (port->actor_admin_port_key &=
~AD_SPEED_KEY_BITS);
}
- //BOND_PRINT_DBG(("Port %d changed link status to %s", port->actor_port_number, ((link == BOND_LINK_UP)?"UP":"DOWN")));
- // there is no need to reselect a new aggregator, just signal the
- // state machines to reinitialize
+
+ /* BOND_PRINT_DBG(("Port %d changed link status to %s",
+ * port->actor_port_number,
+ * ((link == BOND_LINK_UP)?"UP":"DOWN")));
+ */
+
+ /* there is no need to reselect a new aggregator,
+ * just signal the state machines to reinitialize
+ */
port->sm_vars |= AD_PORT_BEGIN;
}
@@ -2385,7 +2519,8 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
ad_info->ports = aggregator->num_of_ports;
ad_info->actor_key = aggregator->actor_oper_aggregator_key;
ad_info->partner_key = aggregator->partner_oper_aggregator_key;
- memcpy(ad_info->partner_system, aggregator->partner_system.mac_addr_value, ETH_ALEN);
+ memcpy(ad_info->partner_system,
+ aggregator->partner_system.mac_addr_value, ETH_ALEN);
return 0;
}
@@ -2432,7 +2567,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
if (slave_agg_no >= 0) {
pr_err("%s: Error: Couldn't find a slave to tx on for aggregator ID %d\n",
- dev->name, agg_id);
+ dev->name, agg_id);
goto out;
}
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index 291dbd4..83117ec 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -28,7 +28,7 @@
#include <linux/netdevice.h>
#include <linux/if_ether.h>
-// General definitions
+/* General definitions */
#define PKT_TYPE_LACPDU cpu_to_be16(ETH_P_SLOW)
#define AD_TIMER_INTERVAL 100 /*msec*/
@@ -47,54 +47,54 @@ enum {
BOND_AD_COUNT = 2,
};
-// rx machine states(43.4.11 in the 802.3ad standard)
+/* rx machine states (43.4.11 in the 802.3ad standard) */
typedef enum {
AD_RX_DUMMY,
- AD_RX_INITIALIZE, // rx Machine
- AD_RX_PORT_DISABLED, // rx Machine
- AD_RX_LACP_DISABLED, // rx Machine
- AD_RX_EXPIRED, // rx Machine
- AD_RX_DEFAULTED, // rx Machine
- AD_RX_CURRENT // rx Machine
+ AD_RX_INITIALIZE,
+ AD_RX_PORT_DISABLED,
+ AD_RX_LACP_DISABLED,
+ AD_RX_EXPIRED,
+ AD_RX_DEFAULTED,
+ AD_RX_CURRENT
} rx_states_t;
-// periodic machine states(43.4.12 in the 802.3ad standard)
+/* periodic machine states (43.4.12 in the 802.3ad standard) */
typedef enum {
AD_PERIODIC_DUMMY,
- AD_NO_PERIODIC, // periodic machine
- AD_FAST_PERIODIC, // periodic machine
- AD_SLOW_PERIODIC, // periodic machine
- AD_PERIODIC_TX // periodic machine
+ AD_NO_PERIODIC,
+ AD_FAST_PERIODIC,
+ AD_SLOW_PERIODIC,
+ AD_PERIODIC_TX
} periodic_states_t;
-// mux machine states(43.4.13 in the 802.3ad standard)
+/* mux machine states (43.4.13 in the 802.3ad standard) */
typedef enum {
AD_MUX_DUMMY,
- AD_MUX_DETACHED, // mux machine
- AD_MUX_WAITING, // mux machine
- AD_MUX_ATTACHED, // mux machine
- AD_MUX_COLLECTING_DISTRIBUTING // mux machine
+ AD_MUX_DETACHED,
+ AD_MUX_WAITING,
+ AD_MUX_ATTACHED,
+ AD_MUX_COLLECTING_DISTRIBUTING
} mux_states_t;
-// tx machine states(43.4.15 in the 802.3ad standard)
+/* tx machine states (43.4.15 in the 802.3ad standard) */
typedef enum {
AD_TX_DUMMY,
- AD_TRANSMIT // tx Machine
+ AD_TRANSMIT
} tx_states_t;
-// rx indication types
+/* rx indication types */
typedef enum {
- AD_TYPE_LACPDU = 1, // type lacpdu
- AD_TYPE_MARKER // type marker
+ AD_TYPE_LACPDU = 1,
+ AD_TYPE_MARKER
} pdu_type_t;
-// rx marker indication types
+/* rx marker indication types */
typedef enum {
- AD_MARKER_INFORMATION_SUBTYPE = 1, // marker imformation subtype
- AD_MARKER_RESPONSE_SUBTYPE // marker response subtype
+ AD_MARKER_INFORMATION_SUBTYPE = 1,
+ AD_MARKER_RESPONSE_SUBTYPE
} bond_marker_subtype_t;
-// timers types(43.4.9 in the 802.3ad standard)
+/* timers types (43.4.9 in the 802.3ad standard) */
typedef enum {
AD_CURRENT_WHILE_TIMER,
AD_ACTOR_CHURN_TIMER,
@@ -105,35 +105,37 @@ typedef enum {
#pragma pack(1)
-// Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard)
+/* Link Aggregation Control Protocol (LACP) data unit structure
+ * (43.4.2.2 in the 802.3ad standard)
+ */
typedef struct lacpdu {
- u8 subtype; // = LACP(= 0x01)
+ u8 subtype; /* = LACP(= 0x01) */
u8 version_number;
- u8 tlv_type_actor_info; // = actor information(type/length/value)
- u8 actor_information_length; // = 20
+ u8 tlv_type_actor_info; /* = actor info(type/length/value)*/
+ u8 actor_information_length; /* = 20 */
__be16 actor_system_priority;
struct mac_addr actor_system;
__be16 actor_key;
__be16 actor_port_priority;
__be16 actor_port;
u8 actor_state;
- u8 reserved_3_1[3]; // = 0
- u8 tlv_type_partner_info; // = partner information
- u8 partner_information_length; // = 20
+ u8 reserved_3_1[3]; /* = 0 */
+ u8 tlv_type_partner_info; /* = partner information */
+ u8 partner_information_length; /* = 20 */
__be16 partner_system_priority;
struct mac_addr partner_system;
__be16 partner_key;
__be16 partner_port_priority;
__be16 partner_port;
u8 partner_state;
- u8 reserved_3_2[3]; // = 0
- u8 tlv_type_collector_info; // = collector information
- u8 collector_information_length; // = 16
+ u8 reserved_3_2[3]; /* = 0 */
+ u8 tlv_type_collector_info; /* = collector information */
+ u8 collector_information_length; /* = 16 */
__be16 collector_max_delay;
u8 reserved_12[12];
- u8 tlv_type_terminator; // = terminator
- u8 terminator_length; // = 0
- u8 reserved_50[50]; // = 0
+ u8 tlv_type_terminator; /* = terminator */
+ u8 terminator_length; /* = 0 */
+ u8 reserved_50[50]; /* = 0 */
} lacpdu_t;
typedef struct lacpdu_header {
@@ -141,20 +143,22 @@ typedef struct lacpdu_header {
struct lacpdu lacpdu;
} lacpdu_header_t;
-// Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard)
+/* Marker Protocol Data Unit(PDU) structure
+ * (43.5.3.2 in the 802.3ad standard)
+ */
typedef struct bond_marker {
- u8 subtype; // = 0x02 (marker PDU)
- u8 version_number; // = 0x01
- u8 tlv_type; // = 0x01 (marker information)
- // = 0x02 (marker response information)
- u8 marker_length; // = 0x16
- u16 requester_port; // The number assigned to the port by the requester
- struct mac_addr requester_system; // The requester's system id
- u32 requester_transaction_id; // The transaction id allocated by the requester,
- u16 pad; // = 0
- u8 tlv_type_terminator; // = 0x00
- u8 terminator_length; // = 0x00
- u8 reserved_90[90]; // = 0
+ u8 subtype; /* = 0x02 (marker PDU) */
+ u8 version_number; /* = 0x01 */
+ u8 tlv_type; /* = 0x01 (marker information)
+ * = 0x02 (marker response info */
+ u8 marker_length; /* = 0x16 */
+ u16 requester_port;
+ struct mac_addr requester_system; /* The requester's system id */
+ u32 requester_transaction_id;
+ u16 pad; /* = 0 */
+ u8 tlv_type_terminator; /* = 0x00 */
+ u8 terminator_length; /* = 0x00 */
+ u8 reserved_90[90]; /* = 0 */
} bond_marker_t;
typedef struct bond_marker_header {
@@ -173,7 +177,7 @@ struct port;
#pragma pack(8)
#endif
-// aggregator structure(43.4.5 in the 802.3ad standard)
+/* aggregator structure (43.4.5 in the 802.3ad standard) */
typedef struct aggregator {
struct mac_addr aggregator_mac_address;
u16 aggregator_identifier;
@@ -183,12 +187,13 @@ typedef struct aggregator {
struct mac_addr partner_system;
u16 partner_system_priority;
u16 partner_oper_aggregator_key;
- u16 receive_state; // BOOLEAN
- u16 transmit_state; // BOOLEAN
+ u16 receive_state; /* BOOLEAN */
+ u16 transmit_state; /* BOOLEAN */
struct port *lag_ports;
- // ****** PRIVATE PARAMETERS ******
- struct slave *slave; // pointer to the bond slave that this aggregator belongs to
- u16 is_active; // BOOLEAN. Indicates if this aggregator is active
+ /* ****** PRIVATE PARAMETERS ****** */
+ struct slave *slave; /* pointer to the bond slave
+ that this aggregator belongs to */
+ u16 is_active; /* BOOLEAN. Indicates if the aggregator is active*/
u16 num_of_ports;
} aggregator_t;
@@ -201,12 +206,18 @@ struct port_params {
u16 port_state;
};
-// port structure(43.4.6 in the 802.3ad standard)
+/* port structure (43.4.6 in the 802.3ad standard) */
typedef struct port {
u16 actor_port_number;
u16 actor_port_priority;
- struct mac_addr actor_system; // This parameter is added here although it is not specified in the standard, just for simplification
- u16 actor_system_priority; // This parameter is added here although it is not specified in the standard, just for simplification
+
+ /* in a attempt to simplify operations the
+ * following two elements were included here
+ * despite they are not specified in the standard
+ */
+ struct mac_addr actor_system;
+ u16 actor_system_priority;
+
u16 actor_port_aggregator_identifier;
bool ntt;
u16 actor_admin_port_key;
@@ -219,24 +230,24 @@ typedef struct port {
bool is_enabled;
- // ****** PRIVATE PARAMETERS ******
- u16 sm_vars; // all state machines variables for this port
- rx_states_t sm_rx_state; // state machine rx state
- u16 sm_rx_timer_counter; // state machine rx timer counter
- periodic_states_t sm_periodic_state;// state machine periodic state
- u16 sm_periodic_timer_counter; // state machine periodic timer counter
- mux_states_t sm_mux_state; // state machine mux state
- u16 sm_mux_timer_counter; // state machine mux timer counter
- tx_states_t sm_tx_state; // state machine tx state
- u16 sm_tx_timer_counter; // state machine tx timer counter(allways on - enter to transmit state 3 time per second)
- struct slave *slave; // pointer to the bond slave that this port belongs to
- struct aggregator *aggregator; // pointer to an aggregator that this port related to
- struct port *next_port_in_aggregator; // Next port on the linked list of the parent aggregator
- u32 transaction_id; // continuous number for identification of Marker PDU's;
- struct lacpdu lacpdu; // the lacpdu that will be sent for this port
+ /* ****** PRIVATE PARAMETERS ****** */
+ u16 sm_vars;
+ rx_states_t sm_rx_state;
+ u16 sm_rx_timer_counter;
+ periodic_states_t sm_periodic_state;
+ u16 sm_periodic_timer_counter;
+ mux_states_t sm_mux_state;
+ u16 sm_mux_timer_counter;
+ tx_states_t sm_tx_state;
+ u16 sm_tx_timer_counter;
+ struct slave *slave;
+ struct aggregator *aggregator;
+ struct port *next_port_in_aggregator;
+ u32 transaction_id;
+ struct lacpdu lacpdu;
} port_t;
-// system structure
+/* system structure */
struct ad_system {
u16 sys_priority;
struct mac_addr sys_mac_addr;
@@ -246,30 +257,32 @@ struct ad_system {
#pragma pack()
#endif
-// ================= AD Exported structures to the main bonding code ==================
+/* ============ AD Exported structures to the main bonding code ============ */
#define BOND_AD_INFO(bond) ((bond)->ad_info)
#define SLAVE_AD_INFO(slave) ((slave)->ad_info)
struct ad_bond_info {
- struct ad_system system; /* 802.3ad system structure */
- u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes
- u32 agg_select_mode; // Mode of selection of active aggregator(bandwidth/count)
- int lacp_fast; /* whether fast periodic tx should be
- * requested
- */
+ struct ad_system system; /* 802.3ad system structure */
+ u32 agg_select_timer; /* Timer to select aggregator after
+ all adapter's hand shakes */
+ u32 agg_select_mode; /* Selection mode of active aggregator
+ (bandwidth/count) */
+ int lacp_fast; /* whether fast periodic tx should be
+ requested */
struct timer_list ad_timer;
};
struct ad_slave_info {
- struct aggregator aggregator; // 802.3ad aggregator structure
- struct port port; // 802.3ad port structure
- spinlock_t state_machine_lock; /* mutex state machines vs.
+ struct aggregator aggregator; /* 802.3ad aggregator structure */
+ struct port port; /* 802.3ad port structure */
+ spinlock_t state_machine_lock; /* mutex state machines vs.
incoming LACPDU */
u16 id;
};
-// ================= AD Exported functions to the main bonding code ==================
-void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast);
+/* ============= AD Exported functions to the main bonding code ============ */
+void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution,
+ int lacp_fast);
int bond_3ad_bind_slave(struct slave *slave);
void bond_3ad_unbind_slave(struct slave *slave);
void bond_3ad_state_machine_handler(struct work_struct *);
@@ -277,7 +290,7 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
void bond_3ad_adapter_speed_changed(struct slave *slave);
void bond_3ad_adapter_duplex_changed(struct slave *slave);
void bond_3ad_handle_link_change(struct slave *slave, char link);
-int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
+int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info);
int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev);
void bond_3ad_lacpdu_recv(struct sk_buff *skb, struct bonding *bond,
struct slave *slave);
--
1.7.4.4
--
Rafael Aquini <aquini@linux.com>
^ permalink raw reply related
* Re: [PATCH net-next-2.6] net/bonding: adjust codingstyle for bond_3ad files
From: Stephen Hemminger @ 2011-05-12 0:28 UTC (permalink / raw)
To: aquini
Cc: Jay Vosburgh, Joe Perches, kernel-janitors, David Miller,
Andy Gospodarek, netdev, Nicolas Kaiser
In-Reply-To: <20110511225208.GA18851@x61.tchesoft.com>
On Wed, 11 May 2011 19:52:21 -0300
Rafael Aquini <aquini@linux.com> wrote:
> Howdy,
>
> While I was studying what bond_3ad has under its hood, I realized its coding
> style did not follow all Documentation/CodingStyle recommendations. As a tiny
> collaboration I did some mods there, in an attempt to make that code stick as
> closely as possible with Kernel's coding style. Also, Nicolas Kaiser has kindly
> suggested some conditional simplifications integrated in this patch.
> Modifications:
> * switched all comments from C99-style to C89-style;
> * replaced MAC_ADDRESS_COMPARE macro for compare_ether_addr();
> * print info out on unexpected status checkings;
> * simplify conditionals:
> (a || (!a && !b)) => (a || !b)
> (!(!a && b)) => (a || !b)
>
> Signed-off-by: Nicolas Kaiser <nikai@nikai.net>
> Signed-off-by: Rafael Aquini <aquini@linux.com>
This should be split into three separate patches.
Always assume your change will break something for somebody and it will
be necessary for some later investigation to bisect out the cause.
--
^ permalink raw reply
* Re: [PATCH net-next-2.6] net/bonding: adjust codingstyle for bond_3ad files
From: Rafael Aquini @ 2011-05-12 0:18 UTC (permalink / raw)
To: Nicolas Kaiser
Cc: Jay Vosburgh, Joe Perches, kernel-janitors, David Miller,
Andy Gospodarek, shemminger, netdev
In-Reply-To: <20110512015237.32d6d92b@absol.kitzblitz>
Howdy Nicolas,
On Thu, May 12, 2011 at 01:52:37AM +0200, Nicolas Kaiser wrote:
> > -// ================= AD Exported functions to the main bonding code ==================
> > -void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast);
> > +// ============= AD Exported functions to the main bonding code ============ */
> ^^
> /*
My bad, sorry. I'll be re-posting soon.
Thanks!
--
Rafael Aquini <aquini@linux.com>
^ permalink raw reply
* Re: [PATCH net-next-2.6] net/bonding: adjust codingstyle for bond_3ad files
From: Nicolas Kaiser @ 2011-05-11 23:52 UTC (permalink / raw)
To: Rafael Aquini
Cc: Jay Vosburgh, Joe Perches, kernel-janitors, David Miller,
Andy Gospodarek, shemminger, netdev
In-Reply-To: <20110511225208.GA18851@x61.tchesoft.com>
* Rafael Aquini <aquini@linux.com>:
> * switched all comments from C99-style to C89-style;
> diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
> index 291dbd4..bc437c3 100644
> --- a/drivers/net/bonding/bond_3ad.h
> +++ b/drivers/net/bonding/bond_3ad.h
> @@ -246,30 +257,32 @@ struct ad_system {
> #pragma pack()
> #endif
>
> -// ================= AD Exported structures to the main bonding code ==================
> +/* ============ AD Exported structures to the main bonding code ============ */
> #define BOND_AD_INFO(bond) ((bond)->ad_info)
> #define SLAVE_AD_INFO(slave) ((slave)->ad_info)
> -// ================= AD Exported functions to the main bonding code ==================
> -void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fast);
> +// ============= AD Exported functions to the main bonding code ============ */
^^
/*
Cheers,
Nicolas Kaiser
^ permalink raw reply
* Re: [PATCH 4/10] ipvs: Use IP_VS_RT_MODE_* instead of magic constants.
From: Julian Anastasov @ 2011-05-11 23:32 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20110510.153051.71135029.davem@davemloft.net>
Hello,
On Tue, 10 May 2011, David Miller wrote:
> > Following patch can be used after patch 4, eg. as
> > number 6 because patches 4 and 5 are ok and we are going to replace
> > patches 6 and 7.
>
> Thanks Julian.
>
> What I'm going to do is hold back the IPVS parts of the patches I
> posted last night. In particular, I'll integrate this into the
> original patch #4.
>
> And then we can work through the reimplementation ideas you posted to
> me in private email.
My simple tests do not show any problems with patches
4, 5 and the new 6 and 7. I tested TUN mode for rt_src/rt_dst
and DR/NAT for rt_dst replacement, related ICMP is relayed properly.
So, we should be ok but I'll do more tests in the following
days because the list with possible combinations for testing
is too long: different forwarding mode (DR/TUN/NAT),
local or remote real server, local or remote client,
In or Out related ICMP, Passive or Active FTP...
Regards
--
Julian Anastasov <ja@ssi.bg>
^ permalink raw reply
* Re: pull request: wireless-2.6 2011-05-11
From: David Miller @ 2011-05-11 23:16 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20110511192742.GG2490@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Wed, 11 May 2011 15:27:42 -0400
> Here are a few more late-breakers that I would like to see in 2.6.39.
> The one from Luca fixes a problem that can cause devices to be unable
> to (re-)associate after a disconnect. The ath9k fix from Mohammed
> fixes a WARNING, the one from Paul fixes a locking issue that can
> lead to data corruption, and the one from Stanislaw fixes a crash
> documented in bug 34452. All are small and all but one are contained
> within their respective drivers.
>
> Please let me know if there are problems!
Pulled, but I can't guarentee that this will make it to 2.6.39-final
at this point.
Thanks!
^ permalink raw reply
* Re: [PATCH net-next-2.6 0/5] be2net: patch series
From: David Miller @ 2011-05-11 23:11 UTC (permalink / raw)
To: padmanabh.ratnakar; +Cc: netdev
In-Reply-To: <63728a21-82b6-4233-9051-af735cd6c5c3@exht1.ad.emulex.com>
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Date: Tue, 10 May 2011 20:42:00 +0530
> Please apply.
> Thanks,
> Padmanabh
>
> Padmanabh Ratnakar (5):
> be2net: Handle error completion in Lancer
> be2net: Disable coalesce water mark mode of CQ for Lancer
> be2net: be2net: In case of UE, do not dump registers for Lancer
> be2net: Use NTWK_RX_FILTER command for promiscous mode
> be2net: Fix to prevent flooding of TX queue
All applied, thanks.
^ permalink raw reply
* Re: [PATCHv1] e1000e: Allow ethtool to enable/disable loopback.
From: Mahesh Bandewar @ 2011-05-11 23:11 UTC (permalink / raw)
To: Michał Mirosław; +Cc: e1000-devel, netdev, Tom Herbert, David Miller
In-Reply-To: <BANLkTikXbL2arWSYW1aPV02C8dDdHTUG6Q@mail.gmail.com>
On Wed, May 11, 2011 at 12:15 PM, Michał Mirosław <mirqus@gmail.com> wrote:
> 2011/5/11 Mahesh Bandewar <maheshb@google.com>:
>> This patch adds e1000_set_features() to handle loopback mode. When loopback
>> is enabled, it enables internal-MAC loopback.
>
> Please wait for this driver's conversion to hw_features. One comment
> below, though.
>
This is not intrusive so should not create problems when that happens.
> [...]
>> --- a/drivers/net/e1000e/netdev.c
>> +++ b/drivers/net/e1000e/netdev.c
> [...]
>> +static int e1000_set_features(struct net_device *dev, u32 features)
>> +{
>> + u32 changed = dev->features ^ features;
>> +
>> + if ((changed & NETIF_F_LOOPBACK) && netif_running(dev))
>> + e1000_set_loopback(dev, features);
>> +
>> + return 0;
>> +}
> [...]
>
> If e1000_set_loopback() fails, this should set dev->features to passed
> features (but keeping NETIF_F_LOOPBACK unchanged in dev->features) to
> keep the state consistent.
>
set_features() can return the return code of set_loopback() instead of
0; this way the consistency will be maintained.
Thanks,
--mahesh..
> Best Regards,
> Michał Mirosław
>
------------------------------------------------------------------------------
Achieve unprecedented app performance and reliability
What every C/C++ and Fortran developer should know.
Learn how Intel has extended the reach of its next-generation tools
to help boost performance applications - inlcuding clusters.
http://p.sf.net/sfu/intel-dev2devmay
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* [PATCHv3 net-next-2.6] ethtool: Added support for FW dump
From: Anirban Chakraborty @ 2011-05-11 22:54 UTC (permalink / raw)
To: netdev; +Cc: Ben Hutchings, David Miller, Anirban Chakraborty
In-Reply-To: <1305154448-9687-1-git-send-email-anirban.chakraborty@qlogic.com>
Added code to take FW dump via ethtool. Dump level can be controlled via setting the
dump flag. A get function is provided to query the current setting of the dump flag.
Dump data is obtained from the driver via a separate get function.
Changes from v2:
Provided separate commands for get flag and data.
Check for minimum of the two buffer length obtained via ethtool and driver and
use that for dump buffer
Pass up the driver return error codes up to the caller.
Added kernel doc comments.
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
---
include/linux/ethtool.h | 28 +++++++++++++++
net/core/ethtool.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+), 0 deletions(-)
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index bd0b50b..5ac7e18 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -601,6 +601,24 @@ struct ethtool_flash {
char data[ETHTOOL_FLASH_MAX_FILENAME];
};
+/**
+ * struct ethtool_dump - used for retrieving, setting device dump
+ * @cmd: Command number - %ETHTOOL_GET_DUMP_FLAG, %ETHTOOL_GET_DUMP_DATA, or
+ * %ETHTOOL_SET_DUMP
+ * @version: FW version of the dump, filled in by driver
+ * @flag: driver dependent flag for dump setting, filled in by driver during
+ * get and filled in by ethtool for set operation
+ * @len: length of dump data, returned by driver for get operation
+ * @data: data collected for get dump data operation
+ */
+struct ethtool_dump {
+ __u32 cmd;
+ __u32 version;
+ __u32 flag;
+ __u32 len;
+ u8 data[0];
+};
+
/* for returning and changing feature sets */
/**
@@ -853,6 +871,9 @@ bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
* @get_channels: Get number of channels.
* @set_channels: Set number of channels. Returns a negative error code or
* zero.
+ * @get_dump_flag: Get dump flag indicating current dump settings of the device.
+ * @get_dump_data: Get dump data.
+ * @set_dump: Set dump specific flags to the device.
*
* All operations are optional (i.e. the function pointer may be set
* to %NULL) and callers must take this into account. Callers must
@@ -927,6 +948,10 @@ struct ethtool_ops {
const struct ethtool_rxfh_indir *);
void (*get_channels)(struct net_device *, struct ethtool_channels *);
int (*set_channels)(struct net_device *, struct ethtool_channels *);
+ int (*get_dump_flag)(struct net_device *, struct ethtool_dump *);
+ int (*get_dump_data)(struct net_device *,
+ struct ethtool_dump *, void *);
+ int (*set_dump)(struct net_device *, struct ethtool_dump *);
};
#endif /* __KERNEL__ */
@@ -998,6 +1023,9 @@ struct ethtool_ops {
#define ETHTOOL_SFEATURES 0x0000003b /* Change device offload settings */
#define ETHTOOL_GCHANNELS 0x0000003c /* Get no of channels */
#define ETHTOOL_SCHANNELS 0x0000003d /* Set no of channels */
+#define ETHTOOL_SET_DUMP 0x0000003e /* Set dump settings */
+#define ETHTOOL_GET_DUMP_FLAG 0x0000003f /* Get dump settings */
+#define ETHTOOL_GET_DUMP_DATA 0x00000040 /* Get dump data */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index b6f4058..01819d8 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1823,6 +1823,85 @@ static noinline_for_stack int ethtool_flash_device(struct net_device *dev,
return dev->ethtool_ops->flash_device(dev, &efl);
}
+static int ethtool_set_dump(struct net_device *dev,
+ void __user *useraddr)
+{
+ struct ethtool_dump dump;
+
+ if (!dev->ethtool_ops->set_dump)
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&dump, useraddr, sizeof(dump)))
+ return -EFAULT;
+
+ return dev->ethtool_ops->set_dump(dev, &dump);
+}
+
+static int ethtool_get_dump_flag(struct net_device *dev,
+ void __user *useraddr)
+{
+ int ret;
+ struct ethtool_dump dump;
+ const struct ethtool_ops *ops = dev->ethtool_ops;
+
+ if (!dev->ethtool_ops->get_dump_flag)
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&dump, useraddr, sizeof(dump)))
+ return -EFAULT;
+
+ ret = ops->get_dump_flag(dev, &dump);
+ if (ret)
+ return ret;
+
+ if (copy_to_user(useraddr, &dump, sizeof(dump)))
+ return -EFAULT;
+ return 0;
+}
+
+static int ethtool_get_dump_data(struct net_device *dev,
+ void __user *useraddr)
+{
+ int ret;
+ __u32 len;
+ struct ethtool_dump dump, tmp;
+ const struct ethtool_ops *ops = dev->ethtool_ops;
+ void *data = NULL;
+
+ if (!dev->ethtool_ops->get_dump_data ||
+ !dev->ethtool_ops->get_dump_flag)
+ return -EOPNOTSUPP;
+
+ if (copy_from_user(&dump, useraddr, sizeof(dump)))
+ return -EFAULT;
+
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.cmd = dump.cmd;
+ ret = ops->get_dump_flag(dev, &tmp);
+ if (ret)
+ return ret;
+
+ len = (tmp.len > dump.len) ? dump.len : tmp.len;
+
+ data = vzalloc(len);
+ if (!data)
+ return -ENOMEM;
+ ret = ops->get_dump_data(dev, &dump, data);
+ if (ret)
+ goto out;
+
+ if (copy_to_user(useraddr, &dump, sizeof(dump))) {
+ ret = -EFAULT;
+ goto out;
+ }
+ useraddr += offsetof(struct ethtool_dump, data);
+ if (copy_to_user(useraddr, data, len))
+ ret = -EFAULT;
+out:
+ vfree(data);
+ return ret;
+}
+
/* The main entry point in this file. Called from net/core/dev.c */
int dev_ethtool(struct net *net, struct ifreq *ifr)
@@ -2039,6 +2118,15 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
case ETHTOOL_SCHANNELS:
rc = ethtool_set_channels(dev, useraddr);
break;
+ case ETHTOOL_SET_DUMP:
+ rc = ethtool_set_dump(dev, useraddr);
+ break;
+ case ETHTOOL_GET_DUMP_FLAG:
+ rc = ethtool_get_dump_flag(dev, useraddr);
+ break;
+ case ETHTOOL_GET_DUMP_DATA:
+ rc = ethtool_get_dump_data(dev, useraddr);
+ break;
default:
rc = -EOPNOTSUPP;
}
--
1.7.4.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox