[ofa-general] [PATCH 4/6] nes: Cosmetic changes; support virtual WQs and PPC
Glenn Grundstrom NetEffect
glenn at lists.openfabrics.org
Wed Nov 14 14:37:25 PST 2007
Updated code for the NetEffect NE020 adapter.
Updates include:
- Support for userspace/virtual WQs.
- PowerPC
- Support for multiple debugging levels
- Many, many cosmetic changes inline with kernel.org standards
Diffs for nes_nic.c
Signed-off-by: Glenn Grundstrom <ggrundstrom at neteffect.com>
---
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 2d759c4..d75b327 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -92,7 +92,40 @@ static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
| NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
static int debug = -1;
-static int rdma_enabled = 0;
+extern atomic_t cm_connects;
+extern atomic_t cm_accepts;
+extern atomic_t cm_disconnects;
+extern atomic_t cm_closes;
+extern atomic_t cm_connecteds;
+extern atomic_t cm_connect_reqs;
+extern atomic_t cm_rejects;
+extern atomic_t mod_qp_timouts;
+extern atomic_t qps_created;
+extern atomic_t qps_destroyed;
+extern atomic_t sw_qps_destroyed;
+extern u32 mh_detected;
+extern u32 mh_pauses_sent;
+extern u32 cm_packets_sent;
+extern u32 cm_packets_bounced;
+extern u32 cm_packets_created;
+extern u32 cm_packets_received;
+extern u32 cm_packets_dropped;
+extern u32 cm_packets_retrans;
+extern u32 cm_listens_created;
+extern u32 cm_listens_destroyed;
+extern u32 cm_backlog_drops;
+extern atomic_t cm_nodes_created;
+extern atomic_t cm_nodes_destroyed;
+extern atomic_t cm_accel_dropped_pkts;
+extern atomic_t cm_resets_recvd;
+extern u32 int_mod_timer_init;
+extern u32 int_mod_cq_depth_256;
+extern u32 int_mod_cq_depth_128;
+extern u32 int_mod_cq_depth_32;
+extern u32 int_mod_cq_depth_24;
+extern u32 int_mod_cq_depth_16;
+extern u32 int_mod_cq_depth_4;
+extern u32 int_mod_cq_depth_1;
static int nes_netdev_open(struct net_device *);
static int nes_netdev_stop(struct net_device *);
@@ -122,7 +155,7 @@ static int nes_netdev_poll(struct net_device* netdev, int* budget)
netdev->quota -= nesvnic->rx_cqes_completed;
*budget -= nesvnic->rx_cqes_completed;
- if (0 == nesvnic->cqes_pending) {
+ if (nesvnic->cqes_pending == 0) {
netif_rx_complete(netdev);
/* clear out completed cqes and arm */
nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
@@ -136,7 +169,7 @@ static int nes_netdev_poll(struct net_device* netdev, int* budget)
nesvnic->netdev->name);
}
- return((0 == nesvnic->cqes_pending) ? 0 : 1);
+ return (nesvnic->cqes_pending == 0) ? 0 : 1;
}
#endif
@@ -190,9 +223,9 @@ static int nes_netdev_open(struct net_device *netdev)
nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_ACTIVE);
nic_active |= nic_active_bit;
nes_write_indexed(nesdev, NES_IDX_NIC_ACTIVE, nic_active);
- nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
+ nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE);
nic_active |= nic_active_bit;
- nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
+ nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE, nic_active);
nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON);
nic_active |= nic_active_bit;
nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);
@@ -204,7 +237,6 @@ static int nes_netdev_open(struct net_device *netdev)
macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
macaddr_low += (u32)netdev->dev_addr[5];
-#define NES_MAX_PORT_COUNT 4
/* Program the various MAC regs */
for (i = 0; i < NES_MAX_PORT_COUNT; i++) {
if (nesvnic->qp_nic_index[i] == 0xf) {
@@ -264,8 +296,9 @@ static int nes_netdev_stop(struct net_device *netdev)
u32 nic_active_mask;
u32 nic_active;
- nes_debug(NES_DBG_SHUTDOWN, "\n");
- if (0 == nesvnic->netdev_open)
+ nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n",
+ nesvnic, nesdev, netdev, netdev->name);
+ if (nesvnic->netdev_open == 0)
return 0;
if (netif_msg_ifdown(nesvnic))
@@ -273,7 +306,7 @@ static int nes_netdev_stop(struct net_device *netdev)
/* Disable network packets */
netif_stop_queue(netdev);
- if ((nesdev->netdev[0] == netdev)&(nesvnic->logical_port == nesdev->mac_index)) {
+ if ((nesdev->netdev[0] == netdev) & (nesvnic->logical_port == nesdev->mac_index)) {
nes_write_indexed(nesdev,
NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff);
}
@@ -287,6 +320,12 @@ static int nes_netdev_stop(struct net_device *netdev)
nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
nic_active &= nic_active_mask;
nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
+ nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE);
+ nic_active &= nic_active_mask;
+ nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE, nic_active);
+ nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
+ nic_active &= nic_active_mask;
+ nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON);
nic_active &= nic_active_mask;
nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);
@@ -296,7 +335,6 @@ static int nes_netdev_stop(struct net_device *netdev)
nes_destroy_ofa_device(nesvnic->nesibdev);
nesvnic->nesibdev = NULL;
nesvnic->of_device_registered = 0;
- rdma_enabled = 0;
}
nes_destroy_nic_qp(nesvnic);
@@ -317,9 +355,7 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev)
struct nes_hw_nic_sq_wqe *nic_sqe;
#ifdef NETIF_F_TSO
struct tcphdr *tcph;
- /* struct udphdr *udph; */
#endif
-// u64 *wqe_fragment_address;
u16 *wqe_fragment_length;
u32 wqe_misc;
u16 wqe_fragment_index = 1; /* first fragment (0) is used by copy buffer */
@@ -343,18 +379,14 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev)
/* wqe_fragment_address = (u64 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX]; */
if (skb->ip_summed == CHECKSUM_PARTIAL) {
-#ifdef OFED_1_2
- tcph = skb->h.th;
-#else
tcph = tcp_hdr(skb);
-#endif
if (1) {
#ifdef NETIF_F_TSO
- if (nes_skb_is_gso(skb)) {
+ if (skb_is_gso(skb)) {
/* nes_debug(NES_DBG_NIC_TX, "%s: TSO request... seg size = %u\n",
- netdev->name, nes_skb_is_gso(skb)); */
+ netdev->name, skb_is_gso(skb)); */
wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE |
- NES_NIC_SQ_WQE_COMPLETION | (u16)nes_skb_is_gso(skb);
+ NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb);
nic_sqe->wqe_words[NES_NIC_SQ_WQE_LSO_INFO_IDX] =
cpu_to_le32(((u32)tcph->doff) |
(((u32)(((unsigned char *)tcph) - skb->data)) << 4));
@@ -383,6 +415,7 @@ static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev)
nesvnic->tx_sw_dropped++;
return NETDEV_TX_LOCKED;
}
+ set_bit(nesnic->sq_head, nesnic->first_frag_overflow);
bus_address = pci_map_single(nesdev->pcidev, skb->data + NES_FIRST_FRAG_SIZE,
skb_headlen(skb) - NES_FIRST_FRAG_SIZE, PCI_DMA_TODEVICE);
wqe_fragment_length[wqe_fragment_index++] =
@@ -444,6 +477,7 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
#define NES_MAX_TSO_FRAGS 18
/* 64K segment plus overflow on each side */
dma_addr_t tso_bus_address[NES_MAX_TSO_FRAGS];
+ dma_addr_t bus_address;
u32 tso_frag_index;
u32 tso_frag_count;
u32 tso_wqe_length;
@@ -454,6 +488,8 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
struct iphdr *iph;
unsigned long flags;
u16 *wqe_fragment_length;
+ u32 nr_frags;
+ u32 original_first_length;
// u64 *wqe_fragment_address;
/* first fragment (0) is used by copy buffer */
u16 wqe_fragment_index=1;
@@ -466,12 +502,11 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
u32 old_head;
u32 wqe_misc;
- if (nes_debug_level & NES_DBG_NIC_TX) {
- nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
- " (%u frags), tso_size=%u\n",
- netdev->name, skb->len, skb_headlen(skb),
- skb_shinfo(skb)->nr_frags, nes_skb_is_gso(skb));
- }
+ /* nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
+ " (%u frags), tso_size=%u\n",
+ netdev->name, skb->len, skb_headlen(skb),
+ skb_shinfo(skb)->nr_frags, skb_is_gso(skb));
+ */
local_irq_save(flags);
if (!spin_trylock(&nesnic->sq_lock)) {
local_irq_restore(flags);
@@ -487,16 +522,20 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_BUSY;
}
+ nr_frags = skb_shinfo(skb)->nr_frags;
+ if (skb_headlen(skb) > NES_FIRST_FRAG_SIZE) {
+ nr_frags++;
+ }
/* Check if too many fragments */
- if (unlikely((skb_shinfo(skb)->nr_frags) > 4)) {
+ if (unlikely((nr_frags > 4))) {
#ifdef NETIF_F_TSO
- if (nes_skb_is_gso(skb) && (skb_headlen(skb) <= NES_FIRST_FRAG_SIZE)) {
+ if (skb_is_gso(skb)) {
nesvnic->segmented_tso_requests++;
nesvnic->tso_requests++;
old_head = nesnic->sq_head;
/* Basically 4 fragments available per WQE with extended fragments */
- wqes_needed = skb_shinfo(skb)->nr_frags >> 2;
- wqes_needed += (skb_shinfo(skb)->nr_frags&3)?1:0;
+ wqes_needed = nr_frags >> 2;
+ wqes_needed += (nr_frags&3)?1:0;
wqes_available = (((nesnic->sq_tail+nesnic->sq_size)-nesnic->sq_head) - 1) &
(nesnic->sq_size - 1);
@@ -519,18 +558,10 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
}
tso_frag_index = 0;
-#ifdef OFED_1_2
- curr_tcp_seq = ntohl(skb->h.th->seq);
-#else
curr_tcp_seq = ntohl(tcp_hdr(skb)->seq);
-#endif
-#ifdef OFED_1_2
- hoffset = skb->h.raw - skb->data;
- nhoffset = skb->nh.raw - skb->data;
-#else
hoffset = skb_transport_header(skb) - skb->data;
nhoffset = skb_network_header(skb) - skb->data;
-#endif
+ original_first_length = hoffset + ((((struct tcphdr *)skb_transport_header(skb))->doff)<<2);
for (wqe_count=0; wqe_count<((u32)wqes_needed); wqe_count++) {
tso_wqe_length = 0;
@@ -548,22 +579,20 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
/* bump past the vlan tag */
wqe_fragment_length++;
-// wqe_fragment_address =
-// (u64 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX];
/* Assumes header totally fits in allocated buffer and is in first fragment */
- if (skb_headlen(skb) > NES_FIRST_FRAG_SIZE) {
- nes_debug(NES_DBG_NIC_TX, "ERROR: SKB header too big, skb_headlen=%u, FIRST_FRAG_SIZE=%u\n",
- skb_headlen(skb), NES_FIRST_FRAG_SIZE);
+ if (original_first_length > NES_FIRST_FRAG_SIZE) {
+ nes_debug(NES_DBG_NIC_TX, "ERROR: SKB header too big, headlen=%u, FIRST_FRAG_SIZE=%u\n",
+ original_first_length, NES_FIRST_FRAG_SIZE);
nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
" (%u frags), tso_size=%u\n",
netdev->name,
skb->len, skb_headlen(skb),
- skb_shinfo(skb)->nr_frags, nes_skb_is_gso(skb));
+ skb_shinfo(skb)->nr_frags, skb_is_gso(skb));
}
memcpy(&nesnic->first_frag_vbase[nesnic->sq_head].buffer,
skb->data, min(((unsigned int)NES_FIRST_FRAG_SIZE),
- skb_headlen(skb)));
+ original_first_length));
iph = (struct iphdr *)
(&nesnic->first_frag_vbase[nesnic->sq_head].buffer[nhoffset]);
tcph = (struct tcphdr *)
@@ -579,9 +608,21 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
}
tcph->seq = htonl(curr_tcp_seq);
wqe_fragment_length[0] = cpu_to_le16(min(((unsigned int)NES_FIRST_FRAG_SIZE),
- skb_headlen(skb)));
-
- for (wqe_fragment_index = 1; wqe_fragment_index < 5;) {
+ original_first_length));
+
+ wqe_fragment_index = 1;
+ if ((wqe_count==0) && (skb_headlen(skb) > original_first_length)) {
+ set_bit(nesnic->sq_head, nesnic->first_frag_overflow);
+ bus_address = pci_map_single(nesdev->pcidev, skb->data + original_first_length,
+ skb_headlen(skb) - original_first_length, PCI_DMA_TODEVICE);
+ wqe_fragment_length[wqe_fragment_index++] =
+ cpu_to_le16(skb_headlen(skb) - original_first_length);
+ wqe_fragment_length[wqe_fragment_index] = 0;
+ nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG1_LOW_IDX] = cpu_to_le32((u32)((u64)(bus_address)));
+ nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG1_HIGH_IDX] = cpu_to_le32((u32)(((u64)(bus_address))>>32));
+ tso_wqe_length += skb_headlen(skb) - original_first_length;
+ }
+ while (wqe_fragment_index < 5) {
wqe_fragment_length[wqe_fragment_index] =
cpu_to_le16(skb_shinfo(skb)->frags[tso_frag_index].size);
nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index)] =
@@ -600,19 +641,19 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
} else {
nesnic->tx_skb[nesnic->sq_head] = NULL;
}
- wqe_misc |= NES_NIC_SQ_WQE_COMPLETION | (u16)nes_skb_is_gso(skb);
- if ((tso_wqe_length + skb_headlen(skb)) > nes_skb_is_gso(skb)) {
- wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE;
- } else {
- iph->tot_len = htons(tso_wqe_length + skb_headlen(skb) - nhoffset);
- }
+ wqe_misc |= NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb);
+ if ((tso_wqe_length + original_first_length) > skb_is_gso(skb)) {
+ wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE;
+ } else {
+ iph->tot_len = htons(tso_wqe_length + original_first_length - nhoffset);
+ }
nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] = cpu_to_le32(wqe_misc);
nic_sqe->wqe_words[NES_NIC_SQ_WQE_LSO_INFO_IDX] =
cpu_to_le32(((u32)tcph->doff) | (((u32)hoffset) << 4));
nic_sqe->wqe_words[NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX] =
- cpu_to_le32(tso_wqe_length+skb_headlen(skb));
+ cpu_to_le32(tso_wqe_length+original_first_length);
curr_tcp_seq += tso_wqe_length;
nesnic->sq_head++;
nesnic->sq_head &= nesnic->sq_size-1;
@@ -620,21 +661,11 @@ static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
} else {
#endif
nesvnic->linearized_skbs++;
-#ifdef OFED_1_2
- hoffset = skb->h.raw - skb->data;
- nhoffset = skb->nh.raw - skb->data;
-#else
hoffset = skb_transport_header(skb) - skb->data;
nhoffset = skb_network_header(skb) - skb->data;
-#endif
- nes_skb_linearize(skb);
-#ifdef OFED_1_2
- skb->h.raw = skb->data + hoffset;
- skb->nh.raw = skb->data + nhoffset;
-#else
+ skb_linearize(skb);
skb_set_transport_header(skb, hoffset);
skb_set_network_header(skb, nhoffset);
-#endif
send_rc = nes_nic_send(skb, netdev);
if (send_rc != NETDEV_TX_OK) {
spin_unlock_irqrestore(&nesnic->sq_lock, flags);
@@ -767,28 +798,158 @@ static void nes_netdev_tx_timeout(struct net_device *netdev)
}
+#ifdef HAVE_SET_MAC_ADDR
/**
* nes_netdev_set_mac_address
*/
static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)
{
- return -1;
+ struct nes_vnic *nesvnic = netdev_priv(netdev);
+ struct nes_device *nesdev = nesvnic->nesdev;
+ struct sockaddr *mac_addr = p;
+ int i;
+ u32 macaddr_low;
+ u16 macaddr_high;
+
+ if (!is_valid_ether_addr(mac_addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(netdev->dev_addr, mac_addr->sa_data, netdev->addr_len);
+ printk(PFX "%s: Address length = %d, Address = %02X%02X%02X%02X%02X%02X..\n",
+ __FUNCTION__, netdev->addr_len,
+ mac_addr->sa_data[0], mac_addr->sa_data[1],
+ mac_addr->sa_data[2], mac_addr->sa_data[3],
+ mac_addr->sa_data[4], mac_addr->sa_data[5]);
+ macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
+ macaddr_high += (u16)netdev->dev_addr[1];
+ macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
+ macaddr_low += ((u32)netdev->dev_addr[3]) << 16;
+ macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
+ macaddr_low += (u32)netdev->dev_addr[5];
+
+ for (i = 0; i < NES_MAX_PORT_COUNT; i++) {
+ if (nesvnic->qp_nic_index[i] == 0xf) {
+ break;
+ }
+ nes_write_indexed(nesdev,
+ NES_IDX_PERFECT_FILTER_LOW + (nesvnic->qp_nic_index[i] * 8),
+ macaddr_low);
+ nes_write_indexed(nesdev,
+ NES_IDX_PERFECT_FILTER_HIGH + (nesvnic->qp_nic_index[i] * 8),
+ (u32)macaddr_high | NES_MAC_ADDR_VALID |
+ ((((u32)nesvnic->nic_index) << 16)));
+ }
+ return 0;
}
+#endif
+#ifdef HAVE_MULTICAST
/**
- * nes_netdev_change_mtu
+ * nes_netdev_set_multicast_list
*/
-static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
+void nes_netdev_set_multicast_list(struct net_device *netdev)
{
struct nes_vnic *nesvnic = netdev_priv(netdev);
- int ret = 0;
+ struct nes_device *nesdev = nesvnic->nesdev;
+ struct dev_mc_list *multicast_addr;
+ u32 nic_active_bit;
+ u32 nic_active;
+ u32 perfect_filter_register_address;
+ u32 macaddr_low;
+ u16 macaddr_high;
+ u8 mc_all_on = 0;
+ u8 mc_index;
+
+ nic_active_bit = 1 << nesvnic->nic_index;
+
+ if (netdev->flags & IFF_PROMISC) {
+ nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
+ nic_active |= nic_active_bit;
+ nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
+ nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
+ nic_active |= nic_active_bit;
+ nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
+ mc_all_on = 1;
+ } else if ((netdev->flags & IFF_ALLMULTI) || (netdev->mc_count > NES_MULTICAST_PF_MAX) ||
+ (nesvnic->nic_index > 3)) {
+ nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
+ nic_active |= nic_active_bit;
+ nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
+ nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
+ nic_active &= ~nic_active_bit;
+ nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
+ mc_all_on = 1;
+ } else {
+ nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
+ nic_active &= ~nic_active_bit;
+ nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
+ nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
+ nic_active &= ~nic_active_bit;
+ nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
+ }
+
+ nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n",
+ netdev->mc_count, (netdev->flags & IFF_PROMISC)?1:0,
+ (netdev->flags & IFF_ALLMULTI)?1:0);
+ if (!mc_all_on) {
+ multicast_addr = netdev->mc_list;
+ perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW + 0x80;
+ perfect_filter_register_address += nesvnic->nic_index*0x40;
+ for (mc_index=0; mc_index < NES_MULTICAST_PF_MAX; mc_index++) {
+ if (multicast_addr) {
+ nes_debug(NES_DBG_NIC_RX, "Assigning MC Address = %02X%02X%02X%02X%02X%02X to register 0x%04X\n",
+ multicast_addr->dmi_addr[0], multicast_addr->dmi_addr[1],
+ multicast_addr->dmi_addr[2], multicast_addr->dmi_addr[3],
+ multicast_addr->dmi_addr[4], multicast_addr->dmi_addr[5],
+ perfect_filter_register_address+(mc_index * 8));
+ macaddr_high = ((u16)multicast_addr->dmi_addr[0]) << 8;
+ macaddr_high += (u16)multicast_addr->dmi_addr[1];
+ macaddr_low = ((u32)multicast_addr->dmi_addr[2]) << 24;
+ macaddr_low += ((u32)multicast_addr->dmi_addr[3]) << 16;
+ macaddr_low += ((u32)multicast_addr->dmi_addr[4]) << 8;
+ macaddr_low += (u32)multicast_addr->dmi_addr[5];
+ nes_write_indexed(nesdev,
+ perfect_filter_register_address+(mc_index * 8),
+ macaddr_low);
+ nes_write_indexed(nesdev,
+ perfect_filter_register_address+4+(mc_index * 8),
+ (u32)macaddr_high | NES_MAC_ADDR_VALID |
+ ((((u32)(1<<nesvnic->nic_index)) << 16)));
+ multicast_addr = multicast_addr->next;
+ } else {
+ nes_debug(NES_DBG_NIC_RX, "Clearing MC Address at register 0x%04X\n",
+ perfect_filter_register_address+(mc_index * 8));
+ nes_write_indexed(nesdev,
+ perfect_filter_register_address+4+(mc_index * 8),
+ 0);
+ }
+ }
+ }
+}
+#endif
- if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu))
+
+/**
+ * nes_netdev_change_mtu
+ */
+static int nes_netdev_change_mtu(struct net_device *netdev, int new_mtu)
+{
+ struct nes_vnic *nesvnic = netdev_priv(netdev);
+ struct nes_device *nesdev = nesvnic->nesdev;
+ int ret = 0;
+ u8 jumbomode=0;
+
+ if ((new_mtu < ETH_ZLEN) || (new_mtu > max_mtu))
return -EINVAL;
- netdev->mtu = new_mtu;
- nesvnic->max_frame_size = new_mtu+ETH_HLEN;
+ netdev->mtu = new_mtu;
+ nesvnic->max_frame_size = new_mtu+ETH_HLEN;
+
+ if (netdev->mtu > 1500) {
+ jumbomode=1;
+ }
+ nes_nic_init_timer_defaults(nesdev, jumbomode);
if (netif_running(netdev)) {
nes_netdev_stop(netdev);
@@ -813,7 +974,6 @@ void nes_netdev_exit(struct nes_vnic *nesvnic)
if ((nesvnic->rdma_enabled)&&(nesvnic->of_device_registered)) {
nes_destroy_ofa_device( nesibdev );
nesvnic->of_device_registered = 0;
- rdma_enabled = 0;
nesvnic->nesibdev = NULL;
}
unregister_netdev(netdev);
@@ -821,7 +981,7 @@ void nes_netdev_exit(struct nes_vnic *nesvnic)
}
-#define NES_ETHTOOL_STAT_COUNT 52
+#define NES_ETHTOOL_STAT_COUNT 54
static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN] = {
"Link Change Interrupts",
"Linearized SKBs",
@@ -869,12 +1029,14 @@ static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN]
"CM Nodes Destroyed",
"CM Accel Drops",
"CM Resets Received",
- "CQP Req Allocs",
- "CQP Req Deallocs",
- "CQP Req Dynamic Allocs",
- "CQP Req Dynamic Deallocs",
- "CQP Req Queues",
- "CQP Req Redrives",
+ "Timer Inits",
+ "CQ Depth 1",
+ "CQ Depth 4",
+ "CQ Depth 16",
+ "CQ Depth 24",
+ "CQ Depth 32",
+ "CQ Depth 128",
+ "CQ Depth 256",
};
@@ -1052,12 +1214,14 @@ static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
target_stat_values[43] = atomic_read(&cm_nodes_destroyed);
target_stat_values[44] = atomic_read(&cm_accel_dropped_pkts);
target_stat_values[45] = atomic_read(&cm_resets_recvd);
- target_stat_values[46] = atomic_read(&cqp_reqs_allocated);
- target_stat_values[47] = atomic_read(&cqp_reqs_freed);
- target_stat_values[48] = atomic_read(&cqp_reqs_dynallocated);
- target_stat_values[49] = atomic_read(&cqp_reqs_dynfreed);
- target_stat_values[50] = atomic_read(&cqp_reqs_queued);
- target_stat_values[51] = atomic_read(&cqp_reqs_redriven);
+ target_stat_values[46] = int_mod_timer_init;
+ target_stat_values[47] = int_mod_cq_depth_1;
+ target_stat_values[48] = int_mod_cq_depth_4;
+ target_stat_values[49] = int_mod_cq_depth_16;
+ target_stat_values[50] = int_mod_cq_depth_24;
+ target_stat_values[51] = int_mod_cq_depth_32;
+ target_stat_values[52] = int_mod_cq_depth_128;
+ target_stat_values[53] = int_mod_cq_depth_256;
}
@@ -1085,16 +1249,48 @@ static void nes_netdev_get_drvinfo(struct net_device *netdev,
* nes_netdev_set_coalesce
*/
static int nes_netdev_set_coalesce(struct net_device *netdev,
- struct ethtool_coalesce *et_coalesce)
+ struct ethtool_coalesce *et_coalesce)
{
- struct nes_vnic *nesvnic = netdev_priv(netdev);
- struct nes_device *nesdev = nesvnic->nesdev;
+ struct nes_vnic *nesvnic = netdev_priv(netdev);
+ struct nes_device *nesdev = nesvnic->nesdev;
+ struct nes_adapter *nesadapter = nesdev->nesadapter;
+ struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
+ if (et_coalesce->rx_max_coalesced_frames_low) {
+ shared_timer->threshold_low = et_coalesce->rx_max_coalesced_frames_low;
+ }
+ if (et_coalesce->rx_max_coalesced_frames_irq) {
+ shared_timer->threshold_target = et_coalesce->rx_max_coalesced_frames_irq;
+ }
+ if (et_coalesce->rx_max_coalesced_frames_high) {
+ shared_timer->threshold_high = et_coalesce->rx_max_coalesced_frames_high;
+ }
+ if (et_coalesce->rx_coalesce_usecs_low) {
+ shared_timer->timer_in_use_min = et_coalesce->rx_coalesce_usecs_low;
+ }
+ if (et_coalesce->rx_coalesce_usecs_high) {
+ shared_timer->timer_in_use_max = et_coalesce->rx_coalesce_usecs_high;
+ }
+ spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
/* using this to drive total interrupt moderation */
- nesvnic->nesdev->et_rx_coalesce_usecs_irq = et_coalesce->rx_coalesce_usecs_irq;
- if (nesdev->et_rx_coalesce_usecs_irq) {
- nes_write32(nesdev->regs+NES_PERIODIC_CONTROL,
- 0x80000000 | ((u32)(nesdev->et_rx_coalesce_usecs_irq*8)));
+ nesadapter->et_rx_coalesce_usecs_irq = et_coalesce->rx_coalesce_usecs_irq;
+ if (et_coalesce->use_adaptive_rx_coalesce) {
+ nesadapter->et_use_adaptive_rx_coalesce = 1;
+ nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;
+ nesadapter->et_rx_coalesce_usecs_irq = 0;
+ if (et_coalesce->pkt_rate_low) {
+ nesadapter->et_pkt_rate_low = et_coalesce->pkt_rate_low;
+ }
+ } else {
+ nesadapter->et_use_adaptive_rx_coalesce = 0;
+ nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT;
+ if (nesadapter->et_rx_coalesce_usecs_irq) {
+ nes_write32(nesdev->regs+NES_PERIODIC_CONTROL,
+ 0x80000000 | ((u32)(nesadapter->et_rx_coalesce_usecs_irq*8)));
+ }
}
return 0;
}
@@ -1104,18 +1300,33 @@ static int nes_netdev_set_coalesce(struct net_device *netdev,
* nes_netdev_get_coalesce
*/
static int nes_netdev_get_coalesce(struct net_device *netdev,
- struct ethtool_coalesce *et_coalesce)
+ struct ethtool_coalesce *et_coalesce)
{
- struct nes_vnic *nesvnic = netdev_priv(netdev);
- struct ethtool_coalesce temp_et_coalesce;
+ struct nes_vnic *nesvnic = netdev_priv(netdev);
+ struct nes_device *nesdev = nesvnic->nesdev;
+ struct nes_adapter *nesadapter = nesdev->nesadapter;
+ struct ethtool_coalesce temp_et_coalesce;
+ struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
+ unsigned long flags;
memset(&temp_et_coalesce, 0, sizeof(temp_et_coalesce));
- temp_et_coalesce.rx_coalesce_usecs_irq = nesvnic->nesdev->et_rx_coalesce_usecs_irq;
- memcpy(et_coalesce, &temp_et_coalesce, sizeof(*et_coalesce));
+ temp_et_coalesce.rx_coalesce_usecs_irq = nesadapter->et_rx_coalesce_usecs_irq;
+ temp_et_coalesce.use_adaptive_rx_coalesce = nesadapter->et_use_adaptive_rx_coalesce;
+ temp_et_coalesce.rate_sample_interval = nesadapter->et_rate_sample_interval;
+ temp_et_coalesce.pkt_rate_low = nesadapter->et_pkt_rate_low;
+ spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
+ temp_et_coalesce.rx_max_coalesced_frames_low = shared_timer->threshold_low;
+ temp_et_coalesce.rx_max_coalesced_frames_irq = shared_timer->threshold_target;
+ temp_et_coalesce.rx_max_coalesced_frames_high = shared_timer->threshold_high;
+ temp_et_coalesce.rx_coalesce_usecs_low = shared_timer->timer_in_use_min;
+ temp_et_coalesce.rx_coalesce_usecs_high = shared_timer->timer_in_use_max;
+ spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
+ memcpy(et_coalesce, &temp_et_coalesce, sizeof(*et_coalesce));
return 0;
}
+
/**
* nes_netdev_get_pauseparam
*/
@@ -1125,8 +1336,8 @@ static void nes_netdev_get_pauseparam(struct net_device *netdev,
struct nes_vnic *nesvnic = netdev_priv(netdev);
et_pauseparam->autoneg = 0;
- et_pauseparam->rx_pause = (nesvnic->nesdev->disable_rx_flow_control==0)?1:0;
- et_pauseparam->tx_pause = (nesvnic->nesdev->disable_tx_flow_control==0)?1:0;
+ et_pauseparam->rx_pause = (nesvnic->nesdev->disable_rx_flow_control == 0) ? 1:0;
+ et_pauseparam->tx_pause = (nesvnic->nesdev->disable_tx_flow_control == 0) ? 1:0;
}
@@ -1144,14 +1355,14 @@ static int nes_netdev_set_pauseparam(struct net_device *netdev,
/* TODO: should return unsupported */
return 0;
}
- if ((et_pauseparam->tx_pause==1) && (nesdev->disable_tx_flow_control==1)) {
+ if ((et_pauseparam->tx_pause == 1) && (nesdev->disable_tx_flow_control == 1)) {
u32temp = nes_read_indexed(nesdev,
NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200));
u32temp |= NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE;
nes_write_indexed(nesdev,
NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp);
nesdev->disable_tx_flow_control = 0;
- } else if ((et_pauseparam->tx_pause==0) && (nesdev->disable_tx_flow_control==0)) {
+ } else if ((et_pauseparam->tx_pause == 0) && (nesdev->disable_tx_flow_control == 0)) {
u32temp = nes_read_indexed(nesdev,
NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200));
u32temp &= ~NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE;
@@ -1159,14 +1370,14 @@ static int nes_netdev_set_pauseparam(struct net_device *netdev,
NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp);
nesdev->disable_tx_flow_control = 1;
}
- if ((et_pauseparam->rx_pause==1) && (nesdev->disable_rx_flow_control==1)) {
+ if ((et_pauseparam->rx_pause == 1) && (nesdev->disable_rx_flow_control == 1)) {
u32temp = nes_read_indexed(nesdev,
NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40));
u32temp &= ~NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE;
nes_write_indexed(nesdev,
NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40), u32temp);
nesdev->disable_rx_flow_control = 0;
- } else if ((et_pauseparam->rx_pause==0) && (nesdev->disable_rx_flow_control==0)) {
+ } else if ((et_pauseparam->rx_pause == 0) && (nesdev->disable_rx_flow_control == 0)) {
u32temp = nes_read_indexed(nesdev,
NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40));
u32temp |= NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE;
@@ -1190,6 +1401,7 @@ static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd
u16 phy_data;
et_cmd->duplex = DUPLEX_FULL;
+ et_cmd->port = PORT_MII;
if (nesadapter->OneG_Mode) {
et_cmd->supported = SUPPORTED_1000baseT_Full|SUPPORTED_Autoneg;
et_cmd->advertising = ADVERTISED_1000baseT_Full|ADVERTISED_Autoneg;
@@ -1204,14 +1416,21 @@ static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd
et_cmd->transceiver = XCVR_EXTERNAL;
et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index];
} else {
- et_cmd->supported = SUPPORTED_10000baseT_Full;
- et_cmd->advertising = ADVERTISED_10000baseT_Full;
+ if (nesadapter->phy_type[nesvnic->logical_port] == NES_PHY_TYPE_IRIS) {
+ et_cmd->transceiver = XCVR_EXTERNAL;
+ et_cmd->port = PORT_FIBRE;
+ et_cmd->supported = SUPPORTED_FIBRE;
+ et_cmd->advertising = ADVERTISED_FIBRE;
+ et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index];
+ } else {
+ et_cmd->transceiver = XCVR_INTERNAL;
+ et_cmd->supported = SUPPORTED_10000baseT_Full;
+ et_cmd->advertising = ADVERTISED_10000baseT_Full;
+ et_cmd->phy_address = nesdev->mac_index;
+ }
et_cmd->speed = SPEED_10000;
et_cmd->autoneg = AUTONEG_DISABLE;
- et_cmd->transceiver = XCVR_INTERNAL;
- et_cmd->phy_address = nesdev->mac_index;
}
- et_cmd->port = PORT_MII;
et_cmd->maxtxpkt = 511;
et_cmd->maxrxpkt = 511;
return 0;
@@ -1246,25 +1465,6 @@ static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd
}
-/**
- * nes_netdev_get_msglevel
- */
-static u32 nes_netdev_get_msglevel(struct net_device *netdev)
-{
- return nes_debug_level;
-}
-
-
-/**
- * nes_netdev_set_msglevel
- */
-static void nes_netdev_set_msglevel(struct net_device *netdev, u32 level)
-{
- nes_debug(NES_DBG_NETDEV, "Setting message level to: %u\n", level);
- nes_debug_level = level;
-}
-
-
static struct ethtool_ops nes_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_settings = nes_netdev_get_settings,
@@ -1280,8 +1480,6 @@ static struct ethtool_ops nes_ethtool_ops = {
.set_coalesce = nes_netdev_set_coalesce,
.get_pauseparam = nes_netdev_get_pauseparam,
.set_pauseparam = nes_netdev_set_pauseparam,
- .get_msglevel = nes_netdev_get_msglevel,
- .set_msglevel = nes_netdev_set_msglevel,
.set_tx_csum = ethtool_op_set_tx_csum,
.set_rx_csum = nes_netdev_set_rx_csum,
.set_sg = ethtool_op_set_sg,
@@ -1324,6 +1522,8 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
struct net_device *netdev;
struct nic_qp_map *curr_qp_map;
u32 u32temp;
+ u16 phy_data;
+ u16 temp_phy_data;
netdev = alloc_etherdev(sizeof(struct nes_vnic));
if (!netdev) {
@@ -1331,7 +1531,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
return NULL;
}
- nes_debug(NES_DBG_INIT, "netdev = %p.\n", netdev);
+ nes_debug(NES_DBG_INIT, "netdev = %p, %s\n", netdev, netdev->name);
SET_NETDEV_DEV(netdev, &nesdev->pcidev->dev);
@@ -1341,6 +1541,9 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
netdev->get_stats = nes_netdev_get_stats;
netdev->tx_timeout = nes_netdev_tx_timeout;
netdev->set_mac_address = nes_netdev_set_mac_address;
+#ifdef HAVE_MULTICAST
+ netdev->set_multicast_list = nes_netdev_set_multicast_list;
+#endif
netdev->change_mtu = nes_netdev_change_mtu;
netdev->watchdog_timeo = NES_TX_TIMEOUT;
netdev->irq = nesdev->pcidev->irq;
@@ -1389,16 +1592,17 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
netdev->dev_addr[3] = (u8)(u64temp>>16);
netdev->dev_addr[4] = (u8)(u64temp>>8);
netdev->dev_addr[5] = (u8)u64temp;
+ memcpy(netdev->perm_addr, netdev->dev_addr, 6);
if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV)) {
#ifdef NETIF_F_TSO
- netdev->features |= NETIF_F_TSO | NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_IP_CSUM;
+ netdev->features |= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
#endif
#ifdef NETIF_F_GSO
netdev->features |= NETIF_F_GSO | NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
#endif
} else {
- netdev->features |= NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_IP_CSUM;
+ netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
}
nes_debug(NES_DBG_INIT, "nesvnic = %p, reported features = 0x%lX, QPid = %d,"
@@ -1431,11 +1635,8 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
}
nesvnic->next_qp_nic_index = 0;
- if (0 == nesdev->netdev_count) {
- if (rdma_enabled == 0) {
- rdma_enabled = 1;
- nesvnic->rdma_enabled = 1;
- }
+ if (nesdev->netdev_count == 0) {
+ nesvnic->rdma_enabled = 1;
} else {
nesvnic->rdma_enabled = 0;
}
@@ -1447,7 +1648,7 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
nesvnic, nesdev->mac_index);
list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]);
- if ((0 == nesdev->netdev_count) &&
+ if ((nesdev->netdev_count == 0) &&
(PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) {
nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n",
NES_IDX_PHY_PCS_CONTROL_STATUS0+(0x200*(nesvnic->logical_port&1)));
@@ -1458,9 +1659,32 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
(0x200*(nesvnic->logical_port&1)), u32temp);
u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
(0x200*(nesvnic->logical_port&1)) );
- if (0x0f0f0000 == (u32temp&0x0f1f0000)) {
- nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
- nesvnic->linkup = 1;
+ if ((u32temp&0x0f1f0000) == 0x0f0f0000) {
+ if (nesdev->nesadapter->phy_type[nesvnic->logical_port] == NES_PHY_TYPE_IRIS) {
+ nes_read_10G_phy_reg(nesdev, 1,
+ nesdev->nesadapter->phy_index[nesvnic->logical_port]);
+ temp_phy_data = (u16)nes_read_indexed(nesdev,
+ NES_IDX_MAC_MDIO_CONTROL);
+ u32temp = 20;
+ do {
+ nes_read_10G_phy_reg(nesdev, 1,
+ nesdev->nesadapter->phy_index[nesvnic->logical_port]);
+ phy_data = (u16)nes_read_indexed(nesdev,
+ NES_IDX_MAC_MDIO_CONTROL);
+ if ((phy_data == temp_phy_data) || (!(--u32temp)))
+ break;
+ temp_phy_data = phy_data;
+ } while (1);
+ if (phy_data & 4) {
+ nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
+ nesvnic->linkup = 1;
+ } else {
+ nes_debug(NES_DBG_INIT, "The Link is DOWN!!.\n");
+ }
+ } else {
+ nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
+ nesvnic->linkup = 1;
+ }
}
nes_debug(NES_DBG_INIT, "Setting up MAC interrupt mask.\n");
/* clear the MAC interrupt status, assumes direct logical to physical mapping */
@@ -1513,4 +1737,3 @@ int nes_nic_cm_xmit(struct sk_buff *skb, struct net_device *netdev)
return ret;
}
-
More information about the general
mailing list