Netdev List
 help / color / mirror / Atom feed
* [PATCH 4/5] Adds options DROPPED PACKETS and LOSS INTERVALS to receiver
From: Ivo Calado @ 2009-09-02  2:45 UTC (permalink / raw)
  To: dccp; +Cc: netdev
In-Reply-To: <cb00fa210909011736w7fc7245cq22a04171f525ec8@mail.gmail.com>

Adds options DROPPED PACKETS and LOSS INTERVALS to receiver. In this
patch is added the
mechanism of gathering information about loss intervals and storing
it, for later
construction of these two options.

Changes:
 - Adds tfrc_loss_data and tfrc_loss_data_entry, structures that
register loss intervals info
 - Adds dccp_skb_is_ecn_ect0 and dccp_skb_is_ecn_ect1 as necessary, so
ecn can be verified and
  used in loss intervals option, that reports ecn nonce sum
 - Adds tfrc_sp_update_li_data that updates information about loss intervals
 - Adds tfrc_sp_ld_prepare_data, that fills fields on tfrc_loss_data
with current options values
 - And adds a field of type struct tfrc_loss_data to struct tfrc_hc_rx_sock

Signed-off-by: Ivo Calado, Erivaldo Xavier, Leandro Sales
<ivocalado@embedded.ufcg.edu.br>, <desadoc@gmail.com>,
<leandroal@gmail.com>

Index: b/net/dccp/ccids/lib/packet_history_sp.c
===================================================================
--- a/net/dccp/ccids/lib/packet_history_sp.c    2009-08-26
23:49:59.000000000 -0300
+++ b/net/dccp/ccids/lib/packet_history_sp.c    2009-08-27
22:36:43.000000000 -0300
@@ -339,10 +339,12 @@
 */
 bool tfrc_sp_rx_congestion_event(struct tfrc_rx_hist *h,
                             struct tfrc_loss_hist *lh,
-        struct sk_buff *skb, const u64 ndp,
-  u32 (*first_li)(struct sock *), struct sock *sk)
+                             struct tfrc_loss_data *ld,
+                             struct sk_buff *skb, const u64 ndp,
+                             u32 (*first_li)(struct sock *), struct sock *sk)
 {
       bool new_event = false;
+       bool new_loss = false;

       if (tfrc_sp_rx_hist_duplicate(h, skb))
               return 0;
@@ -355,11 +357,12 @@
               __one_after_loss(h, skb, ndp);
       } else if (h->loss_count != 2) {
               DCCP_BUG("invalid loss_count %d", h->loss_count);
-       } else if (__two_after_loss(h, skb, ndp)) {
+       } else if ((new_loss = __two_after_loss(h, skb, ndp))) {
               /*
               * Update Loss Interval database and recycle RX records
               */
               new_event = tfrc_sp_lh_interval_add(lh, h, first_li, sk,
dccp_hdr(skb)->dccph_ccval);
+               tfrc_sp_update_li_data(ld, h, skb, new_loss, new_event);
               __three_after_loss(h);

       } else if (dccp_data_packet(skb) && dccp_skb_is_ecn_ce(skb)) {
@@ -384,6 +387,8 @@
               }
       }

+       tfrc_sp_update_li_data(ld, h, skb, new_loss, new_event);
+
       /*
       * Update moving-average of `s' and the sum of received payload bytes.
       */
Index: b/net/dccp/ccids/lib/loss_interval_sp.c
===================================================================
--- a/net/dccp/ccids/lib/loss_interval_sp.c     2009-08-26
23:53:32.000000000 -0300
+++ b/net/dccp/ccids/lib/loss_interval_sp.c     2009-08-27
22:36:43.000000000 -0300
@@ -14,9 +14,89 @@
 #include "tfrc_sp.h"

 static struct kmem_cache  *tfrc_lh_slab  __read_mostly;
+static struct kmem_cache  *tfrc_ld_slab  __read_mostly;
+
 /* Loss Interval weights from [RFC 3448, 5.4], scaled by 10 */
 static const int tfrc_lh_weights[NINTERVAL] = { 10, 10, 10, 10, 8, 6, 4, 2 };

+/*
+ * Allocation routine for new entries of loss interval data
+ */
+static struct tfrc_loss_data_entry* tfrc_ld_add_new(struct tfrc_loss_data* ld)
+{
+       struct tfrc_loss_data_entry* new =
kmem_cache_alloc(tfrc_ld_slab, GFP_ATOMIC);
+
+       if(new == NULL)
+               return NULL;
+
+       memset(new, 0, sizeof(struct tfrc_loss_data_entry));
+
+       new->next = ld->head;
+       ld->head = new;
+       ld->counter++;
+
+       return new;
+}
+
+void tfrc_sp_ld_cleanup(struct tfrc_loss_data *ld)
+{
+       struct tfrc_loss_data_entry *next, *h = ld->head;
+
+       if(!h)
+               return;
+
+       while(h)
+       {
+               next = h->next;
+               kmem_cache_free(tfrc_ld_slab, h);
+               h = next;
+       }
+
+       ld->head = NULL;
+       ld->counter = 0;
+}
+
+void tfrc_sp_ld_prepare_data(u8 loss_count, struct tfrc_loss_data* ld)
+{
+       u8* li_ofs, *d_ofs;
+       struct tfrc_loss_data_entry* e;
+       u16 count;
+
+       li_ofs = &ld->loss_intervals_opts[0];
+       d_ofs = &ld->drop_opts[0];
+
+       count = 0;
+       e = ld->head;
+
+       *li_ofs = loss_count + 1;
+       li_ofs++;
+
+       while (e != NULL) {
+
+               if(count<TFRC_LOSS_INTERVALS_OPT_MAX_LENGTH)
+               {
+                       *li_ofs = ((htonl(e->lossless_length)&0x00FFFFFF)<<8);
+                       li_ofs += 3;
+                       *li_ofs =
((e->ecn_nonce_sum&0x1)<<31)&(htonl((e->loss_length&0x00FFFFFF))<<8);
+                       li_ofs += 3;
+                       *li_ofs = ((htonl(e->data_length)&0x00FFFFFF)<<8);
+                       li_ofs += 3;
+               }
+
+               if(count<TFRC_DROP_OPT_MAX_LENGTH)
+               {
+                       *d_ofs = (htonl(e->drop_count)&0x00FFFFFF)<<8;
+                       d_ofs += 3;
+               }
+
+
if((count>=TFRC_LOSS_INTERVALS_OPT_MAX_LENGTH)&&(count>=TFRC_DROP_OPT_MAX_LENGTH))
+                       break;
+
+               count++;
+               e = e->next;
+       }
+}
+
 /* implements LIFO semantics on the array */
 static inline u8 LIH_INDEX(const u8 ctr)
 {
@@ -235,13 +315,166 @@
       return true;
 }

+void tfrc_sp_update_li_data(struct tfrc_loss_data *ld, struct
tfrc_rx_hist *rh, struct sk_buff *skb, bool new_loss, bool new_event)
+{
+       struct tfrc_loss_data_entry* new, *h;
+
+       if(!dccp_data_packet(skb))
+               return;
+
+       if (ld->head == NULL)
+       {
+               new = tfrc_ld_add_new(ld);
+               if (unlikely(new == NULL)) {
+                       DCCP_CRIT("Cannot allocate new loss data registry.");
+                       return;
+               }
+
+               if (new_loss)
+               {
+                       new->drop_count = rh->num_losses;
+                       new->lossless_length = 1;
+                       new->loss_length = rh->num_losses;
+
+                       if (dccp_data_packet(skb))
+                               new->data_length = 1;
+
+                       if(dccp_data_packet(skb) && dccp_skb_is_ecn_ect1(skb))
+                               new->ecn_nonce_sum = 1;
+                       else
+                               new->ecn_nonce_sum = 0;
+               }
+               else
+               {
+                       new->drop_count = 0;
+                       new->lossless_length = 1;
+                       new->loss_length = 0;
+
+                       if (dccp_data_packet(skb))
+                               new->data_length = 1;
+
+                       if(dccp_data_packet(skb) && dccp_skb_is_ecn_ect1(skb))
+                               new->ecn_nonce_sum = 1;
+                       else
+                               new->ecn_nonce_sum = 0;
+               }
+
+               return;
+       }
+
+       if (new_event)
+       {
+               new = tfrc_ld_add_new(ld);
+               if (unlikely(new == NULL)) {
+                       DCCP_CRIT("Cannot allocate new loss data
registry. Cleaning up.");
+                       tfrc_sp_ld_cleanup(ld);
+                       return;
+               }
+
+               new->drop_count = rh->num_losses;
+               new->lossless_length = (ld->last_loss_count - rh->loss_count);
+               new->loss_length = rh->num_losses;
+
+               new->ecn_nonce_sum = 0;
+               new->data_length = 0;
+
+               while (ld->last_loss_count > rh->loss_count)
+               {
+                       ld->last_loss_count--;
+
+                       if (ld->sto_is_data&(1 << (ld->last_loss_count)))
+                       {
+                               new->data_length++;
+
+                               if (ld->sto_ecn&(1 << (ld->last_loss_count)))
+                                       new->ecn_nonce_sum =
!new->ecn_nonce_sum;
+                       }
+               }
+
+               return;
+       }
+
+       h = ld->head;
+
+       if (rh->loss_count > ld->last_loss_count)
+       {
+               ld->last_loss_count = rh->loss_count;
+
+               if (dccp_data_packet(skb))
+                       ld->sto_is_data |= (1 << (ld->last_loss_count - 1));
+
+               if (dccp_skb_is_ecn_ect1(skb))
+                       ld->sto_ecn |= (1 << (ld->last_loss_count - 1));
+
+               return;
+       }
+
+       if (new_loss)
+       {
+               h->drop_count += rh->num_losses;
+               h->lossless_length = (ld->last_loss_count - rh->loss_count);
+               h->loss_length += h->lossless_length + rh->num_losses;
+
+               h->ecn_nonce_sum = 0;
+               h->data_length = 0;
+
+               while (ld->last_loss_count > rh->loss_count)
+               {
+                       ld->last_loss_count--;
+
+                       if (ld->sto_is_data&(1 << (ld->last_loss_count)))
+                       {
+                               h->data_length++;
+
+                               if (ld->sto_ecn&(1 << (ld->last_loss_count)))
+                                       h->ecn_nonce_sum = !h->ecn_nonce_sum;
+                       }
+               }
+
+               return;
+       }
+
+       if (ld->last_loss_count > rh->loss_count)
+       {
+               while (ld->last_loss_count > rh->loss_count)
+               {
+                       ld->last_loss_count--;
+
+                       h->lossless_length++;
+
+                       if (ld->sto_is_data&(1 << (ld->last_loss_count)))
+                       {
+                               h->data_length++;
+
+                               if (ld->sto_ecn&(1 << (ld->last_loss_count)))
+                                       h->ecn_nonce_sum = !h->ecn_nonce_sum;
+                       }
+               }
+
+               return;
+       }
+
+       h->lossless_length++;
+
+       if(dccp_data_packet(skb))
+       {
+               h->data_length++;
+
+               if (dccp_skb_is_ecn_ect1(skb))
+                       h->ecn_nonce_sum = !h->ecn_nonce_sum;
+       }
+}
+
 int __init tfrc_sp_li_init(void)
 {
       tfrc_lh_slab = kmem_cache_create("tfrc_sp_li_hist",
                                        sizeof(struct tfrc_loss_interval), 0,
                                        SLAB_HWCACHE_ALIGN, NULL);
+       tfrc_ld_slab = kmem_cache_create("tfrc_sp_li_data",
+                                        sizeof(struct tfrc_loss_data_entry), 0,
+
SLAB_HWCACHE_ALIGN, NULL);

-       if((tfrc_lh_slab != NULL))
+       if((tfrc_lh_slab != NULL)||(tfrc_ld_slab != NULL))
               return 0;

       if(tfrc_lh_slab != NULL)
@@ -250,6 +483,12 @@
               tfrc_lh_slab = NULL;
       }

+       if(tfrc_ld_slab != NULL)
+       {
+               kmem_cache_destroy(tfrc_ld_slab);
+               tfrc_ld_slab = NULL;
+       }
+
       return -ENOBUFS;
 }

@@ -259,4 +498,9 @@
               kmem_cache_destroy(tfrc_lh_slab);
               tfrc_lh_slab = NULL;
       }
+
+       if (tfrc_ld_slab != NULL) {
+               kmem_cache_destroy(tfrc_ld_slab);
+               tfrc_ld_slab = NULL;
+       }
 }
Index: b/net/dccp/ccids/lib/loss_interval_sp.h
===================================================================
--- a/net/dccp/ccids/lib/loss_interval_sp.h     2009-08-26
23:44:20.000000000 -0300
+++ b/net/dccp/ccids/lib/loss_interval_sp.h     2009-08-27
22:37:40.000000000 -0300
@@ -67,12 +67,44 @@
       return min(lh->counter, (u8)LIH_SIZE);
 }

-struct tfrc_rx_hist;
 #endif

+struct tfrc_loss_data_entry {
+       struct tfrc_loss_data_entry     *next;
+       u32                             lossless_length:24;
+       u8                              ecn_nonce_sum:1;
+       u32                             loss_length:24;
+       u32                             data_length:24;
+       u32                             drop_count:24;
+};
+
+#define TFRC_LOSS_INTERVALS_OPT_MAX_LENGTH     28
+#define TFRC_DROP_OPT_MAX_LENGTH               84
+
+struct tfrc_loss_data {
+       struct tfrc_loss_data_entry     *head;
+       u16                             counter;
+       u8                              loss_intervals_opts[2 +
TFRC_LOSS_INTERVALS_OPT_MAX_LENGTH*9];
+       u8                              drop_opts[1 +
TFRC_DROP_OPT_MAX_LENGTH*3];
+       u8                              last_loss_count;
+       u8                              sto_ecn;
+       u8                              sto_is_data;
+};
+
+static inline void tfrc_ld_init(struct tfrc_loss_data* ld)
+{
+       memset(ld, 0, sizeof(struct tfrc_loss_data));
+}
+
+struct tfrc_rx_hist;
+
 extern bool tfrc_sp_lh_interval_add(struct tfrc_loss_hist *, struct
tfrc_rx_hist *,
                                   u32 (*first_li)(struct sock *),
struct sock *, __u8 ccval);
+extern void tfrc_sp_update_li_data(struct tfrc_loss_data *,  struct
tfrc_rx_hist *,
+                                  struct sk_buff *, bool new_loss,
bool new_event);
 extern void tfrc_sp_lh_update_i_mean(struct tfrc_loss_hist *lh,
struct sk_buff *);
 extern void tfrc_sp_lh_cleanup(struct tfrc_loss_hist *lh);
+extern void tfrc_sp_ld_cleanup(struct tfrc_loss_data *ld);
+extern void tfrc_sp_ld_prepare_data(u8 loss_count, struct tfrc_loss_data* ld);

 #endif /* _DCCP_LI_HIST_SP_ */
Index: b/net/dccp/ccids/lib/tfrc_ccids_sp.h
===================================================================
--- a/net/dccp/ccids/lib/tfrc_ccids_sp.h        2009-08-27
00:50:46.000000000 -0300
+++ b/net/dccp/ccids/lib/tfrc_ccids_sp.h        2009-08-27
22:36:43.000000000 -0300
@@ -128,6 +128,7 @@
 *  @tstamp_last_feedback  -  Time at which last feedback was sent
 *  @hist  -  Packet history (loss detection + RTT sampling)
 *  @li_hist  -  Loss Interval database
+ *  @li_data  -  Loss Interval data for options
 *  @p_inverse  -  Inverse of Loss Event Rate (RFC 4342, sec. 8.5)
 */
 struct tfrc_hc_rx_sock {
@@ -137,6 +138,7 @@
       ktime_t                         tstamp_last_feedback;
       struct tfrc_rx_hist             hist;
       struct tfrc_loss_hist           li_hist;
+       struct tfrc_loss_data           li_data;
 #define p_inverse                      li_hist.i_mean
 };

Index: b/net/dccp/ccids/lib/packet_history_sp.h
===================================================================
--- a/net/dccp/ccids/lib/packet_history_sp.h    2009-08-26
22:55:58.000000000 -0300
+++ b/net/dccp/ccids/lib/packet_history_sp.h    2009-08-27
22:36:43.000000000 -0300
@@ -200,6 +200,7 @@

 extern bool tfrc_sp_rx_congestion_event(struct tfrc_rx_hist *h,
                                    struct tfrc_loss_hist *lh,
+                                    struct tfrc_loss_data *ld,
                                    struct sk_buff *skb, const u64 ndp,
                                    u32 (*first_li)(struct sock *sk),
                                    struct sock *sk);
Index: b/net/dccp/dccp.h
===================================================================
--- a/net/dccp/dccp.h   2009-08-26 22:59:10.000000000 -0300
+++ b/net/dccp/dccp.h   2009-08-27 22:36:43.000000000 -0300
@@ -403,6 +403,16 @@
       return (DCCP_SKB_CB(skb)->dccpd_ecn & INET_ECN_MASK) == INET_ECN_CE;
 }

+static inline bool dccp_skb_is_ecn_ect0(const struct sk_buff *skb)
+{
+       return (DCCP_SKB_CB(skb)->dccpd_ecn & INET_ECN_MASK) == INET_ECN_ECT_0;
+}
+
+static inline bool dccp_skb_is_ecn_ect1(const struct sk_buff *skb)
+{
+       return (DCCP_SKB_CB(skb)->dccpd_ecn & INET_ECN_MASK) == INET_ECN_ECT_0;
+}
+
 /* RFC 4340, sec. 7.7 */
 static inline int dccp_non_data_packet(const struct sk_buff *skb)
 {

^ permalink raw reply

* [PATCH 5/5] Updating documentation accordingly
From: Ivo Calado @ 2009-09-02  2:46 UTC (permalink / raw)
  To: dccp; +Cc: netdev
In-Reply-To: <cb00fa210909011736t3629163ch2753c3f43e1a9601@mail.gmail.com>

Updating documentation accordingly

Signed-off-by: Ivo Calado, Erivaldo Xavier, Leandro Sales
<ivocalado@embedded.ufcg.edu.br>, <desadoc@gmail.com>,
<leandroal@gmail.com>

Index: b/net/dccp/ccids/lib/loss_interval_sp.h
===================================================================
--- a/net/dccp/ccids/lib/loss_interval_sp.h     2009-08-27
22:37:40.000000000 -0300
+++ b/net/dccp/ccids/lib/loss_interval_sp.h     2009-08-27
23:02:00.000000000 -0300
@@ -1,6 +1,7 @@
 #ifndef _DCCP_LI_HIST_SP_
 #define _DCCP_LI_HIST_SP_
 /*
+ *  Copyright (c) 2009 Federal University of Campina Grande, Embedded
Systems and Pervasive Computing Lab
 *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
 *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
 *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
@@ -69,6 +70,15 @@

 #endif

+/**
+ *  tfrc_loss_data_entry  -  Holds info about one loss interval
+ *  @next:             next entry on this linked list
+ *  @lossless_length:  length of lossless sequence
+ *  @ecn_nonce_sum:    ecn nonce sum for this interval
+ *  @loss_length:      length of lossy part
+ *  @data_length:      data length on lossless part
+ *  @drop_count:       count of dopped packets
+ */
 struct tfrc_loss_data_entry {
       struct tfrc_loss_data_entry     *next;
       u32                             lossless_length:24;
@@ -78,9 +88,20 @@
       u32                             drop_count:24;
 };

-#define TFRC_LOSS_INTERVALS_OPT_MAX_LENGTH     28
-#define TFRC_DROP_OPT_MAX_LENGTH               84
+#define TFRC_LOSS_INTERVALS_OPT_MAX_LENGTH     28      /* As defined at
section 8.6.1. of RFC 4342 */
+#define TFRC_DROP_OPT_MAX_LENGTH               84      /* Specified
on section 8.7. of
CCID4 draft */

+/**
+ *  tfrc_loss_data  -  loss interval data
+ *  used by loss intervals and dropped packets options
+ *  @head:                     linked list containing loss interval data
+ *  @counter:                  number of entries
+ *  @loss_intervals_opts:      space necessary for writing temporary
option data for loss intervals option
+ *  @drop_opts:                        same for dropped packets option
+ *  @last_loss_count:          last loss count (num. of packets after hole on
transmission) observed
+ *  @sto_ecn:                  ecn's observed while waiting for hole
to be filled or
accepted as missing
+ *  @sto_is_data:              flags about if packets saw were data packets
+ */
 struct tfrc_loss_data {
       struct tfrc_loss_data_entry     *head;
       u16                             counter;
Index: b/net/dccp/ccids/lib/loss_interval_sp.c
===================================================================
--- a/net/dccp/ccids/lib/loss_interval_sp.c     2009-08-27
22:36:43.000000000 -0300
+++ b/net/dccp/ccids/lib/loss_interval_sp.c     2009-08-28
21:07:28.000000000 -0300
@@ -1,4 +1,5 @@
 /*
+ *  Copyright (c) 2009 Federal University of Campina Grande, Embedded
Systems and Pervasive Computing Lab
 *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
 *  Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
 *  Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
@@ -56,6 +57,12 @@
       ld->counter = 0;
 }

+/**
+ *  tfrc_sp_ld_prepare_data  -  updates arrays on tfrc_loss_data so
they can be sent as options
+ *  @loss_count:       current loss count (packets after hole on transmission),
+ *                     used to determine skip length for loss intervals option
+ *  @ld:               loss intervals data being updated
+ */
 void tfrc_sp_ld_prepare_data(u8 loss_count, struct tfrc_loss_data* ld)
 {
       u8* li_ofs, *d_ofs;
@@ -184,7 +191,7 @@
 }

 /**
- * tfrc_lh_update_i_mean  -  Update the `open' loss interval I_0
+ * tfrc_sp_lh_update_i_mean  -  Update the `open' loss interval I_0
 * This updates I_mean as the sequence numbers increase. As a consequence, the
 * open loss interval I_0 increases, hence p = W_tot/max(I_tot0, I_tot1)
 * decreases, and thus there is no need to send renewed feedback.
@@ -232,11 +239,12 @@
       return cur->li_is_closed;
 }

-/** tfrc_lh_interval_add  -  Insert new record into the Loss Interval database
+/** tfrc_sp_lh_interval_add  -  Insert new record into the Loss
Interval database
 * @lh:                   Loss Interval database
 * @rh:                   Receive history containing a fresh loss event
 * @calc_first_li: Caller-dependent routine to compute length of first interval
 * @sk:                   Used by @calc_first_li in caller-specific
way (subtyping)
+ * @ccval:        Current ccval
 * Updates I_mean and returns 1 if a new interval has in fact been
added to @lh.
 */
 bool tfrc_sp_lh_interval_add(struct tfrc_loss_hist *lh, struct
tfrc_rx_hist *rh,
@@ -315,6 +323,14 @@
       return true;
 }

+/**
+ *  tfrc_sp_update_li_data  -  Update tfrc_loss_data upon packet
receiving or loss detection
+ *  @ld:                       tfrc_loss_data being updated
+ *  @rh:                       loss event record
+ *  @skb:                      received packet
+ *  @new_loss:                 dictates if new loss was detected upon receiving
current packet
+ *  @new_event:                        ...and if the loss starts new
loss interval
+ */
 void tfrc_sp_update_li_data(struct tfrc_loss_data *ld, struct
tfrc_rx_hist *rh, struct sk_buff *skb, bool new_loss, bool new_event)
 {
       struct tfrc_loss_data_entry* new, *h;
Index: b/net/dccp/ccids/lib/packet_history_sp.c
===================================================================
--- a/net/dccp/ccids/lib/packet_history_sp.c    2009-08-27
22:36:43.000000000 -0300
+++ b/net/dccp/ccids/lib/packet_history_sp.c    2009-08-28
21:05:35.000000000 -0300
@@ -4,6 +4,12 @@
 *
 *  An implementation of the DCCP protocol
 *
+ *  Copyright (c) 2009 Ivo Calado, Erivaldo Xavier, Leandro Sales
+ *
+ *  This code has been developed by the Federal University of Campina Grande
+ *  Embedded Systems and Pervasive Computing Lab. For further
information please see
+ *  http://embedded.ufcg.edu.br/ <ivocalado@embedded.ufcg.edu.br>,
<desadoc@gmail.com>, <leandroal@gmail.com>
+ *
 *  This code has been developed by the University of Waikato WAND
 *  research group. For further information please see http://www.wand.net.nz/
 *  or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz
@@ -323,9 +329,10 @@
 }

 /**
- *  tfrc_rx_congestion_event  -  Loss detection and further processing
+ *  tfrc_sp_rx_congestion_event  -  Loss detection and further processing
 *  @h:                The non-empty RX history object
 *  @lh:       Loss Intervals database to update
+ *  @ld:       loss data for options
 *  @skb:      Currently received packet
 *  @ndp:      The NDP count belonging to @skb
 *  @first_li: Caller-dependent computation of first loss interval in @lh
@@ -476,7 +483,7 @@
 }

 /**
- * tfrc_rx_hist_sample_rtt  -  Sample RTT from timestamp / CCVal
+ * tfrc_sp_rx_hist_sample_rtt  -  Sample RTT from timestamp / CCVal
 * Based on ideas presented in RFC 4342, 8.1. This function expects
that no loss
 * is pending and uses the following history entries (via rtt_sample_prev):
 * - h->ring[0]  contains the most recent history entry prior to @skb;
Index: b/net/dccp/ccids/lib/packet_history_sp.h
===================================================================
--- a/net/dccp/ccids/lib/packet_history_sp.h    2009-08-27
22:36:43.000000000 -0300
+++ b/net/dccp/ccids/lib/packet_history_sp.h    2009-08-27
23:04:28.000000000 -0300
@@ -1,6 +1,12 @@
 /*
 *  Packet RX/TX history data structures and routines for TFRC-based protocols.
 *
+ *  Copyright (c) 2009 Ivo Calado, Erivaldo Xavier, Leandro Sales
+ *
+ *  This code has been developed by the Federal University of Campina Grande
+ *  Embedded Systems and Pervasive Computing Lab. For further
information please see
+ *  http://embedded.ufcg.edu.br/ <ivocalado@embedded.ufcg.edu.br>,
<desadoc@gmail.com>, <leandroal@gmail.com>
+ *
 *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
 *  Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
 *
Index: b/net/dccp/ccids/lib/tfrc_ccids_sp.c
===================================================================
--- a/net/dccp/ccids/lib/tfrc_ccids_sp.c        2009-08-27
22:36:43.000000000 -0300
+++ b/net/dccp/ccids/lib/tfrc_ccids_sp.c        2009-08-27
23:09:18.000000000 -0300
@@ -1,4 +1,5 @@
 /*
+ *  Copyright (c) 2009 Federal University of Campina Grande, Embedded
Systems and Pervasive Computing Lab
 *  Copyright (c) 2007 Leandro Melo de Sales <leandroal@gmail.com>
 *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
 *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Index: b/net/dccp/ccids/lib/tfrc_ccids_sp.h
===================================================================
--- a/net/dccp/ccids/lib/tfrc_ccids_sp.h        2009-08-27
22:36:43.000000000 -0300
+++ b/net/dccp/ccids/lib/tfrc_ccids_sp.h        2009-08-27
23:11:00.000000000 -0300
@@ -1,4 +1,5 @@
 /*
+ *  Copyright (c) 2009 Federal University of Campina Grande, Embedded
Systems and Pervasive Computing Lab
 *  Copyright (c) 2007 Leandro Melo de Sales <leandroal@gmail.com>
 *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
 *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Index: b/net/dccp/ccids/lib/tfrc_sp.c
===================================================================
--- a/net/dccp/ccids/lib/tfrc_sp.c      2009-08-27 22:36:43.000000000 -0300
+++ b/net/dccp/ccids/lib/tfrc_sp.c      2009-08-27 23:25:50.000000000 -0300
@@ -1,6 +1,9 @@
 /*
 * TFRC library initialisation
 *
+ * Copyright (c) 2009 Federal University of Campina Grande, Embedded
Systems and Pervasive Computing Lab
+ *     Almost copied from tfrc.c, only renamed symbols
+ *
 * Copyright (c) 2007 The University of Aberdeen, Scotland, UK
 * Copyright (c) 2007 Arnaldo Carvalho de Melo <acme@redhat.com>
 */
Index: b/net/dccp/ccids/lib/tfrc_sp.h
===================================================================
--- a/net/dccp/ccids/lib/tfrc_sp.h      2009-08-27 22:36:43.000000000 -0300
+++ b/net/dccp/ccids/lib/tfrc_sp.h      2009-08-27 23:28:55.000000000 -0300
@@ -1,6 +1,7 @@
 #ifndef _TFRC_SP_H_
 #define _TFRC_SP_H_
 /*
+ *  Copyright (c) 2009 Federal University of Campina Grande, Embedded
Systems and Pervasive Computing Lab
 *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
 *  Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
 *  Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
Index: b/net/dccp/ccids/lib/tfrc_equation_sp.c
===================================================================
--- a/net/dccp/ccids/lib/tfrc_equation_sp.c     2009-08-27
22:36:43.000000000 -0300
+++ b/net/dccp/ccids/lib/tfrc_equation_sp.c     2009-08-28
21:08:54.000000000 -0300
@@ -1,4 +1,5 @@
 /*
+ *  Copyright (c) 2009 Federal University of Campina Grande, Embedded
Systems and Pervasive Computing Lab
 *  Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
 *  Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
 *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
@@ -607,7 +608,7 @@
 }

 /**
- * tfrc_calc_x - Calculate the send rate as per section 3.1 of RFC3448
+ * tfrc_sp_calc_x - Calculate the send rate as per section 3.1 of RFC3448
 *
 *  @s: packet size          in bytes
 *  @R: RTT                  scaled by 1000000   (i.e., microseconds)
@@ -666,7 +667,7 @@
 }

 /**
- *  tfrc_calc_x_reverse_lookup  -  try to find p given f(p)
+ *  tfrc_sp_calc_x_reverse_lookup  -  try to find p given f(p)
 *
 *  @fvalue: function value to match, scaled by 1000000
 *  Returns closest match for p, also scaled by 1000000
@@ -699,7 +700,7 @@
 }

 /**
- * tfrc_invert_loss_event_rate  -  Compute p so that 10^6 corresponds to 100%
+ * tfrc_sp_invert_loss_event_rate  -  Compute p so that 10^6
corresponds to 100%
 * When @loss_event_rate is large, there is a chance that p is truncated to 0.
 * To avoid re-entering slow-start in that case, we set p =
TFRC_SMALLEST_P > 0.
 */

^ permalink raw reply

* Re: [RFC] iproute2: gracefully exit from rtnl_listen()
From: David Ward @ 2009-09-02  2:27 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20090901155955.7448c1d6@nehalam>

On 09/01/2009 06:59 PM, Stephen Hemminger wrote:
>
> On Tue,  1 Sep 2009 17:41:26 -0400
> David Ward <david.ward@ll.mit.edu> wrote:
>>
>> There should be some mechanism for stopping rtnl_listen() and
>> continuing program execution.
>
> Good idea, but why not just change the while(1) loop?

Stephen, thanks for your response. I agree that checking a condition on 
the while loop, as you showed, can be used to exit the loop cleanly.

Here are my concerns though:

    * rtnl_listen() is the function that I believe needs to be fixed.
      It is what allows applications to passively observe messages sent
      to the rtnetlink multicast groups -- messages which are not
      prompted by any request from the application, where there is no
      defined "end" to the sequence of messages being received. This
      function currently has no condition in the loop where it will stop
      trying to receive messages and exit cleanly.

      rtnl_dump_filter(), which your patch modifies, appears to be for
      processing the response to an rtnetlink dump request from the
      application. It is at least able to exit cleanly when it sees the
      NLMSG_DONE message at the end of the kernel's response.

      However, I think that any changes that are made to rtnl_listen()
      which allow it to exit gracefully could potentially be applied to
      the loops in rtnl_dump_filter() and rtnl_talk() as well.

    * With your patch, rtnl_dump_filter() returns -1 after the rtnetlink
      socket is closed. This indicates than an error has occurred.
      However, because trying to exit the loop by closing the socket is
      intentional, the function should be able to return 0.

      But could there be other cases where the rtnetlink socket is closed
      unintentionally, and -1 actually needs to be returned?

    * Is it really necessary to close the rtnetlink socket in order to
      break out of rtnl_listen()? What if the user wants to continue
      using the socket -- should the socket have to be closed to exit
      from rtnl_listen(), and then reopened? Is there a better way to
      notify the loop to exit instead?

    * Furthermore, should you have to rely on a signal like SIGINT to be
      received by the application in order to check for the condition
      under which to break out of the loop? Shouldn't it be possible to
      break out of the loop without a signal? But recvmsg() is blocking.


Again, I am raising these questions because I'm not sure what a 
"correct" solution to breaking out of rtnl_listen() would look like.

Thanks,

David

^ permalink raw reply

* Re: [PATCH resend] tracing/events: convert NAPI's tracepoint via TRACE_EVENT
From: Xiao Guangrong @ 2009-09-02  3:12 UTC (permalink / raw)
  To: David Miller
  Cc: rostedt, mingo, nhorman, fweisbec, yjwei, netdev, linux-kernel
In-Reply-To: <20090901.182645.153420711.davem@davemloft.net>



David Miller wrote:

> This patch can't be split up, so I'm wondering how you suggest to
> handle this patch given that you have declared that define_trace.h
> changes aren't to go through the subsystem tree?
> 
> If we do the define_trace.h change only, we break the build
> (lack of macro defined for the trace).
> 
> If we do only the other parts of his patch, we get a duplicate
> definition.
> 

This patch cooperate with my previous patch to solve the include file
dependencies problem. So, we do better put those two patches together.
(both in -tip tree or/add both in network tree)

The previous patch is below:

Commit-ID:  5ac35daa9343936038a3c9c4f4d6d3fe6a2a7bd8
Gitweb:     http://git.kernel.org/tip/5ac35daa9343936038a3c9c4f4d6d3fe6a2a7bd8
Author:     Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
AuthorDate: Tue, 25 Aug 2009 14:06:22 +0800
Committer:  Steven Rostedt <rostedt@goodmis.org>
CommitDate: Wed, 26 Aug 2009 00:32:09 -0400

tracing/events: fix the include file dependencies

> And keep in mind that Neil and Xiao are probably going to want to do
> work on top of this to the networking bits.  Thus if we put this patch
> here into the tracing tree, I'll have to develop a dependency on the
> tracing tree and I think that will go over like a fart in a spacesuit
> with the -next crowd and Stephen Rothwell in particular.
> 

Thank you, David

Xiao

^ permalink raw reply

* Re: [PATCH] sky2: fix management of driver LED
From: Stephen Hemminger @ 2009-09-02  4:33 UTC (permalink / raw)
  To: David Miller; +Cc: mikem, netdev, rene.mayrhofer, leitner
In-Reply-To: <20090901.174437.145971351.davem@davemloft.net>

On Tue, 01 Sep 2009 17:44:37 -0700 (PDT)
David Miller <davem@davemloft.net> wrote:

> From: Stephen Hemminger <shemminger@linux-foundation.org>
> Date: Mon, 31 Aug 2009 10:31:41 -0700
> 
> > Observed by Mike McCormack.
> > 
> > The LED bit here is just a software controlled value used to
> > turn on one of the LED's on some boards. The register value was wrong,
> > which could have been causing some power control issues.
> > Get rid of problematic define use the correct mask.
> > 
> > Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> 
> Applied.

If these power management fixes do fix all the reported problems,
then I will consider back porting (probably to 2.6.31.1).


-- 

^ permalink raw reply

* [PATCH 00/18] tg3: 5717 support part 2
From: Matt Carlson @ 2009-09-01 22:47 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patchset implements the bulk of the support for the 5717 asic rev.
The only item left to address is rx producer ring handling, which I've left
to the patchset following this one.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>


^ permalink raw reply

* [PATCH 04/18] tg3: Add support code around kernel interrupt API
From: Matt Carlson @ 2009-09-01 22:55 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch adds code to support multiple interrupt vectors around the
kernel's interrupt API.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   73 ++++++++++++++++++++++++++++++++++++++++-------------
 drivers/net/tg3.h |    6 ++++
 2 files changed, 61 insertions(+), 18 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 14cead6..7717eae 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4729,12 +4729,15 @@ tx_recovery:
 
 static void tg3_irq_quiesce(struct tg3 *tp)
 {
+	int i;
+
 	BUG_ON(tp->irq_sync);
 
 	tp->irq_sync = 1;
 	smp_mb();
 
-	synchronize_irq(tp->pdev->irq);
+	for (i = 0; i < tp->irq_cnt; i++)
+		synchronize_irq(tp->napi[i].irq_vec);
 }
 
 static inline int tg3_irq_sync(struct tg3 *tp)
@@ -4947,9 +4950,11 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void tg3_poll_controller(struct net_device *dev)
 {
+	int i;
 	struct tg3 *tp = netdev_priv(dev);
 
-	tg3_interrupt(tp->pdev->irq, dev);
+	for (i = 0; i < tp->irq_cnt; i++)
+		tg3_interrupt(tp->napi[i].irq_vec, dev);
 }
 #endif
 
@@ -6244,7 +6249,7 @@ static int tg3_chip_reset(struct tg3 *tp)
 {
 	u32 val;
 	void (*write_op)(struct tg3 *, u32, u32);
-	int err;
+	int i, err;
 
 	tg3_nvram_lock(tp);
 
@@ -6291,7 +6296,9 @@ static int tg3_chip_reset(struct tg3 *tp)
 	tp->napi[0].last_tag = 0;
 	tp->napi[0].last_irq_tag = 0;
 	smp_mb();
-	synchronize_irq(tp->pdev->irq);
+
+	for (i = 0; i < tp->irq_cnt; i++)
+		synchronize_irq(tp->napi[i].irq_vec);
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
 		val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
@@ -7745,11 +7752,20 @@ restart_timer:
 	add_timer(&tp->timer);
 }
 
-static int tg3_request_irq(struct tg3 *tp)
+static int tg3_request_irq(struct tg3 *tp, int irq_num)
 {
 	irq_handler_t fn;
 	unsigned long flags;
-	char *name = tp->dev->name;
+	char *name;
+	struct tg3_napi *tnapi = &tp->napi[irq_num];
+
+	if (tp->irq_cnt == 1)
+		name = tp->dev->name;
+	else {
+		name = &tnapi->irq_lbl[0];
+		snprintf(name, IFNAMSIZ, "%s-%d", tp->dev->name, irq_num);
+		name[IFNAMSIZ-1] = 0;
+	}
 
 	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
 		fn = tg3_msi;
@@ -7762,7 +7778,8 @@ static int tg3_request_irq(struct tg3 *tp)
 			fn = tg3_interrupt_tagged;
 		flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM;
 	}
-	return request_irq(tp->pdev->irq, fn, flags, name, &tp->napi[0]);
+
+	return request_irq(tnapi->irq_vec, fn, flags, name, tnapi);
 }
 
 static int tg3_test_interrupt(struct tg3 *tp)
@@ -7776,9 +7793,9 @@ static int tg3_test_interrupt(struct tg3 *tp)
 
 	tg3_disable_ints(tp);
 
-	free_irq(tp->pdev->irq, tnapi);
+	free_irq(tnapi->irq_vec, tnapi);
 
-	err = request_irq(tp->pdev->irq, tg3_test_isr,
+	err = request_irq(tnapi->irq_vec, tg3_test_isr,
 			  IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi);
 	if (err)
 		return err;
@@ -7806,9 +7823,9 @@ static int tg3_test_interrupt(struct tg3 *tp)
 
 	tg3_disable_ints(tp);
 
-	free_irq(tp->pdev->irq, tnapi);
+	free_irq(tnapi->irq_vec, tnapi);
 
-	err = tg3_request_irq(tp);
+	err = tg3_request_irq(tp, 0);
 
 	if (err)
 		return err;
@@ -7854,13 +7871,13 @@ static int tg3_test_msi(struct tg3 *tp)
 	       "the PCI maintainer and include system chipset information.\n",
 		       tp->dev->name);
 
-	free_irq(tp->pdev->irq, &tp->napi[0]);
+	free_irq(tp->napi[0].irq_vec, &tp->napi[0]);
 
 	pci_disable_msi(tp->pdev);
 
 	tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
 
-	err = tg3_request_irq(tp);
+	err = tg3_request_irq(tp, 0);
 	if (err)
 		return err;
 
@@ -7875,7 +7892,7 @@ static int tg3_test_msi(struct tg3 *tp)
 	tg3_full_unlock(tp);
 
 	if (err)
-		free_irq(tp->pdev->irq, &tp->napi[0]);
+		free_irq(tp->napi[0].irq_vec, &tp->napi[0]);
 
 	return err;
 }
@@ -7928,6 +7945,9 @@ static void tg3_ints_init(struct tg3 *tp)
 			tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
 		}
 	}
+
+	tp->irq_cnt = 1;
+	tp->napi[0].irq_vec = tp->pdev->irq;
 }
 
 static void tg3_ints_fini(struct tg3 *tp)
@@ -7941,7 +7961,7 @@ static void tg3_ints_fini(struct tg3 *tp)
 static int tg3_open(struct net_device *dev)
 {
 	struct tg3 *tp = netdev_priv(dev);
-	int err;
+	int i, err;
 
 	if (tp->fw_needed) {
 		err = tg3_request_firmware(tp);
@@ -7983,7 +8003,15 @@ static int tg3_open(struct net_device *dev)
 
 	napi_enable(&tp->napi[0].napi);
 
-	err = tg3_request_irq(tp);
+	for (i = 0; i < tp->irq_cnt; i++) {
+		struct tg3_napi *tnapi = &tp->napi[i];
+		err = tg3_request_irq(tp, i);
+		if (err) {
+			for (i--; i >= 0; i--)
+				free_irq(tnapi->irq_vec, tnapi);
+			break;
+		}
+	}
 
 	if (err)
 		goto err_out1;
@@ -8054,7 +8082,10 @@ static int tg3_open(struct net_device *dev)
 	return 0;
 
 err_out2:
-	free_irq(tp->pdev->irq, &tp->napi[0]);
+	for (i = tp->irq_cnt - 1; i >= 0; i--) {
+		struct tg3_napi *tnapi = &tp->napi[i];
+		free_irq(tnapi->irq_vec, tnapi);
+	}
 
 err_out1:
 	napi_disable(&tp->napi[0].napi);
@@ -8298,6 +8329,7 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *);
 
 static int tg3_close(struct net_device *dev)
 {
+	int i;
 	struct tg3 *tp = netdev_priv(dev);
 
 	napi_disable(&tp->napi[0].napi);
@@ -8320,7 +8352,10 @@ static int tg3_close(struct net_device *dev)
 
 	tg3_full_unlock(tp);
 
-	free_irq(tp->pdev->irq, &tp->napi[0]);
+	for (i = tp->irq_cnt - 1; i >= 0; i--) {
+		struct tg3_napi *tnapi = &tp->napi[i];
+		free_irq(tnapi->irq_vec, tnapi);
+	}
 
 	tg3_ints_fini(tp);
 
@@ -12151,6 +12186,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 		}
 	}
 
+	tp->irq_max = 1;
+
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
 	     (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
 		tp->tg3_flags |= TG3_FLAG_JUMBO_CAPABLE;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 626b968..a78a0db 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2514,6 +2514,9 @@ struct tg3_napi {
 	dma_addr_t			status_mapping;
 	dma_addr_t			rx_rcb_mapping;
 	dma_addr_t			tx_desc_mapping;
+
+	char				irq_lbl[IFNAMSIZ];
+	unsigned int			irq_vec;
 };
 
 struct tg3 {
@@ -2829,6 +2832,9 @@ struct tg3 {
 
 #define SST_25VF0X0_PAGE_SIZE		4098
 
+	unsigned int			irq_max;
+	unsigned int			irq_cnt;
+
 	struct ethtool_coalesce		coal;
 
 	/* firmware info */
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 02/18] tg3: Add per-int coalesce now member
From: Matt Carlson @ 2009-09-01 22:51 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

Each interrupt vector has its own bit in the host coalescing register to
force that vector's status block to be updated and generate an
interrupt.  This patch adds a member to the per-interrupt structure
that records which bit belongs to that vector.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   16 +++++++++-------
 drivers/net/tg3.h |    2 ++
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 65ff286..ff65ae8 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -631,7 +631,7 @@ static void tg3_enable_ints(struct tg3 *tp)
 	if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
 		tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
 
-	coal_now = HOSTCC_MODE_NOW;
+	coal_now = tnapi->coal_now;
 
 	/* Force an initial interrupt */
 	if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
@@ -682,7 +682,7 @@ static void tg3_int_reenable(struct tg3_napi *tnapi)
 	if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
 	    tg3_has_work(tnapi))
 		tw32(HOSTCC_MODE, tp->coalesce_mode |
-		     (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
+		     HOSTCC_MODE_ENABLE | tnapi->coal_now);
 }
 
 static inline void tg3_netif_stop(struct tg3 *tp)
@@ -7622,7 +7622,7 @@ static void tg3_timer(unsigned long __opaque)
 			     tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
 		} else {
 			tw32(HOSTCC_MODE, tp->coalesce_mode |
-			     (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
+			     HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW);
 		}
 
 		if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
@@ -7765,7 +7765,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
 	tg3_enable_ints(tp);
 
 	tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
-	       HOSTCC_MODE_NOW);
+	       tnapi->coal_now);
 
 	for (i = 0; i < 5; i++) {
 		u32 int_mbox, misc_host_ctrl;
@@ -9840,7 +9840,7 @@ static int tg3_test_memory(struct tg3 *tp)
 static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 {
 	u32 mac_mode, rx_start_idx, rx_idx, tx_idx, opaque_key;
-	u32 desc_idx;
+	u32 desc_idx, coal_now;
 	struct sk_buff *skb, *rx_skb;
 	u8 *tx_data;
 	dma_addr_t map;
@@ -9851,6 +9851,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 
 	tnapi = &tp->napi[0];
 	rnapi = &tp->napi[0];
+	coal_now = tnapi->coal_now | rnapi->coal_now;
 
 	if (loopback_mode == TG3_MAC_LOOPBACK) {
 		/* HW errata - mac loopback fails in some cases on 5780.
@@ -9929,7 +9930,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 	map = pci_map_single(tp->pdev, skb->data, tx_len, PCI_DMA_TODEVICE);
 
 	tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
-	     HOSTCC_MODE_NOW);
+	       rnapi->coal_now);
 
 	udelay(10);
 
@@ -9950,7 +9951,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 	/* 250 usec to allow enough time on some 10/100 Mbps devices.  */
 	for (i = 0; i < 25; i++) {
 		tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
-		       HOSTCC_MODE_NOW);
+		       coal_now);
 
 		udelay(10);
 
@@ -13428,6 +13429,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	tp->napi[0].int_mbox = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
 	tp->napi[0].consmbox = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
 	tp->napi[0].prodmbox = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+	tp->napi[0].coal_now = HOSTCC_MODE_NOW;
 	tp->napi[0].tx_pending = TG3_DEF_TX_RING_PENDING;
 	netif_napi_add(dev, &tp->napi[0].napi, tg3_poll, 64);
 	dev->ethtool_ops = &tg3_ethtool_ops;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index a816b2c..626b968 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1031,6 +1031,7 @@
 #define  HOSTCC_MODE_CLRTICK_TXBD	 0x00000400
 #define  HOSTCC_MODE_NOINT_ON_NOW	 0x00000800
 #define  HOSTCC_MODE_NOINT_ON_FORCE	 0x00001000
+#define  HOSTCC_MODE_COAL_VEC1_NOW	 0x00002000
 #define HOSTCC_STATUS			0x00003c04
 #define  HOSTCC_STATUS_ERROR_ATTN	 0x00000004
 #define HOSTCC_RXCOL_TICKS		0x00003c08
@@ -2497,6 +2498,7 @@ struct tg3_napi {
 	u32				last_tag;
 	u32				last_irq_tag;
 	u32				int_mbox;
+	u32				coal_now;
 	u32				tx_prod;
 	u32				tx_cons;
 	u32				tx_pending;
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 03/18] tg3: Create tg3_rings_reset()
From: Matt Carlson @ 2009-09-01 22:53 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch moves most of the chip ring setup logic into a separate
function.  This will make it easier to verify the multi ring setup
changes.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |  140 ++++++++++++++++++++++++++++++----------------------
 1 files changed, 81 insertions(+), 59 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index ff65ae8..14cead6 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -6818,6 +6818,76 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
 }
 
 /* tp->lock is held. */
+static void tg3_rings_reset(struct tg3 *tp)
+{
+	int i;
+	u32 txrcb, rxrcb, limit;
+	struct tg3_napi *tnapi = &tp->napi[0];
+
+	/* Disable all transmit rings but the first. */
+	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+		limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE * 16;
+	else
+		limit = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE;
+
+	for (txrcb = NIC_SRAM_SEND_RCB + TG3_BDINFO_SIZE;
+	     txrcb < limit; txrcb += TG3_BDINFO_SIZE)
+		tg3_write_mem(tp, txrcb + TG3_BDINFO_MAXLEN_FLAGS,
+			      BDINFO_FLAGS_DISABLED);
+
+
+	/* Disable all receive return rings but the first. */
+	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+		limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16;
+	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+		limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 4;
+	else
+		limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE;
+
+	for (rxrcb = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE;
+	     rxrcb < limit; rxrcb += TG3_BDINFO_SIZE)
+		tg3_write_mem(tp, rxrcb + TG3_BDINFO_MAXLEN_FLAGS,
+			      BDINFO_FLAGS_DISABLED);
+
+	/* Disable interrupts */
+	tw32_mailbox_f(tp->napi[0].int_mbox, 1);
+
+	/* Zero mailbox registers. */
+	tp->napi[0].tx_prod = 0;
+	tp->napi[0].tx_cons = 0;
+	tw32_mailbox(tp->napi[0].prodmbox, 0);
+	tw32_rx_mbox(tp->napi[0].consmbox, 0);
+
+	/* Make sure the NIC-based send BD rings are disabled. */
+	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
+		u32 mbox = MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+		for (i = 0; i < 16; i++)
+			tw32_tx_mbox(mbox + i * 8, 0);
+	}
+
+	txrcb = NIC_SRAM_SEND_RCB;
+	rxrcb = NIC_SRAM_RCV_RET_RCB;
+
+	/* Clear status block in ram. */
+	memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+	/* Set status block DMA address */
+	tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
+	     ((u64) tnapi->status_mapping >> 32));
+	tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
+	     ((u64) tnapi->status_mapping & 0xffffffff));
+
+	tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
+		       (TG3_TX_RING_SIZE <<
+			BDINFO_FLAGS_MAXLEN_SHIFT),
+		       NIC_SRAM_TX_BUFFER_DESC);
+
+	tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
+		       (TG3_RX_RCB_RING_SIZE(tp) <<
+			BDINFO_FLAGS_MAXLEN_SHIFT), 0);
+}
+
+/* tp->lock is held. */
 static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 {
 	u32 val, rdmac_mode;
@@ -7091,48 +7161,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 
 	tw32(RCVDBDI_STD_BD + TG3_BDINFO_MAXLEN_FLAGS, val);
 
-	/* There is only one send ring on 5705/5750, no need to explicitly
-	 * disable the others.
-	 */
-	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
-		/* Clear out send RCB ring in SRAM. */
-		for (i = NIC_SRAM_SEND_RCB; i < NIC_SRAM_RCV_RET_RCB; i += TG3_BDINFO_SIZE)
-			tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS,
-				      BDINFO_FLAGS_DISABLED);
-	}
-
-	tp->napi[0].tx_prod = 0;
-	tp->napi[0].tx_cons = 0;
-	tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
-
-	val = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
-	tw32_mailbox(val, 0);
-
-	tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
-		       tp->napi[0].tx_desc_mapping,
-		       (TG3_TX_RING_SIZE <<
-			BDINFO_FLAGS_MAXLEN_SHIFT),
-		       NIC_SRAM_TX_BUFFER_DESC);
-
-	/* There is only one receive return ring on 5705/5750, no need
-	 * to explicitly disable the others.
-	 */
-	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
-		for (i = NIC_SRAM_RCV_RET_RCB; i < NIC_SRAM_STATS_BLK;
-		     i += TG3_BDINFO_SIZE) {
-			tg3_write_mem(tp, i + TG3_BDINFO_MAXLEN_FLAGS,
-				      BDINFO_FLAGS_DISABLED);
-		}
-	}
-
-	tw32_rx_mbox(tp->napi[0].consmbox, 0);
-
-	tg3_set_bdinfo(tp, NIC_SRAM_RCV_RET_RCB,
-		       tp->napi[0].rx_rcb_mapping,
-		       (TG3_RX_RCB_RING_SIZE(tp) <<
-			BDINFO_FLAGS_MAXLEN_SHIFT),
-		       0);
-
 	tpr->rx_std_ptr = tp->rx_pending;
 	tw32_rx_mbox(MAILBOX_RCV_STD_PROD_IDX + TG3_64BIT_REG_LOW,
 		     tpr->rx_std_ptr);
@@ -7142,6 +7170,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
 		     tpr->rx_jmb_ptr);
 
+	tg3_rings_reset(tp);
+
 	/* Initialize MAC address and backoff seed. */
 	__tg3_set_mac_addr(tp, 0);
 
@@ -7229,12 +7259,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 
 	__tg3_set_coalesce(tp, &tp->coal);
 
-	/* set status block DMA address */
-	tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
-	     ((u64) tp->napi[0].status_mapping >> 32));
-	tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
-	     ((u64) tp->napi[0].status_mapping & 0xffffffff));
-
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
 		/* Status/statistics block address.  See tg3_timer,
 		 * the tg3_periodic_fetch_stats call there, and
@@ -7245,7 +7269,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 		tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
 		     ((u64) tp->stats_mapping & 0xffffffff));
 		tw32(HOSTCC_STATS_BLK_NIC_ADDR, NIC_SRAM_STATS_BLK);
+
 		tw32(HOSTCC_STATUS_BLK_NIC_ADDR, NIC_SRAM_STATUS_BLK);
+
+		/* Clear statistics and status block memory areas */
+		for (i = NIC_SRAM_STATS_BLK;
+		     i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
+		     i += sizeof(u32)) {
+			tg3_write_mem(tp, i, 0);
+			udelay(40);
+		}
 	}
 
 	tw32(HOSTCC_MODE, HOSTCC_MODE_ENABLE | tp->coalesce_mode);
@@ -7255,15 +7288,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
 		tw32(RCVLSC_MODE, RCVLSC_MODE_ENABLE | RCVLSC_MODE_ATTN_ENABLE);
 
-	/* Clear statistics/status block in chip, and status block in ram. */
-	for (i = NIC_SRAM_STATS_BLK;
-	     i < NIC_SRAM_STATUS_BLK + TG3_HW_STATUS_SIZE;
-	     i += sizeof(u32)) {
-		tg3_write_mem(tp, i, 0);
-		udelay(40);
-	}
-	memset(tp->napi[0].hw_status, 0, TG3_HW_STATUS_SIZE);
-
 	if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) {
 		tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT;
 		/* reset to prevent losing 1st rx packet intermittently */
@@ -7315,8 +7339,6 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 	udelay(100);
 
-	tw32_mailbox_f(tp->napi[0].int_mbox, 0);
-
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
 		tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
 		udelay(40);
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 01/18] tg3: inline tg3_cond_int()
From: Matt Carlson @ 2009-09-01 22:47 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch inlines the code of tg3_cond_int() into the function's only
callsite.  This prep work makes the following patch cleaner.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   22 +++++++++++-----------
 1 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 9d5c178..65ff286 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -618,18 +618,9 @@ static void tg3_disable_ints(struct tg3 *tp)
 	tw32_mailbox_f(tp->napi[0].int_mbox, 0x00000001);
 }
 
-static inline void tg3_cond_int(struct tg3 *tp)
-{
-	if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
-	    (tp->napi[0].hw_status->status & SD_STATUS_UPDATED))
-		tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
-	else
-		tw32(HOSTCC_MODE, tp->coalesce_mode |
-		     (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
-}
-
 static void tg3_enable_ints(struct tg3 *tp)
 {
+	u32 coal_now;
 	struct tg3_napi *tnapi = &tp->napi[0];
 	tp->irq_sync = 0;
 	wmb();
@@ -639,7 +630,16 @@ static void tg3_enable_ints(struct tg3 *tp)
 	tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
 	if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
 		tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
-	tg3_cond_int(tp);
+
+	coal_now = HOSTCC_MODE_NOW;
+
+	/* Force an initial interrupt */
+	if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
+	    (tp->napi[0].hw_status->status & SD_STATUS_UPDATED))
+		tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+	else
+		tw32(HOSTCC_MODE, tp->coalesce_mode |
+		     HOSTCC_MODE_ENABLE | coal_now);
 }
 
 static inline unsigned int tg3_has_work(struct tg3_napi *tnapi)
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 06/18] tg3: Add mailbox assignments
From: Matt Carlson @ 2009-09-01 22:58 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

The 5717 assigns mailbox locations to interrupt vectors in a rather
non-intuitive way.  (Much of the complexity stems from legacy
compatibility issues.)  This patch implements the assignment scheme.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   59 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 50 insertions(+), 9 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 12ead83..4d16ce0 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -9219,7 +9219,7 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
 static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 {
 	struct tg3 *tp = netdev_priv(dev);
-	int irq_sync = 0, err = 0;
+	int i, irq_sync = 0, err = 0;
 
 	if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
 	    (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
@@ -9243,7 +9243,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
 	    tp->rx_pending > 63)
 		tp->rx_pending = 63;
 	tp->rx_jumbo_pending = ering->rx_jumbo_pending;
-	tp->napi[0].tx_pending = ering->tx_pending;
+
+	for (i = 0; i < TG3_IRQ_MAX_VECS; i++)
+		tp->napi[i].tx_pending = ering->tx_pending;
 
 	if (netif_running(dev)) {
 		tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
@@ -13443,7 +13445,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	static int tg3_version_printed = 0;
 	struct net_device *dev;
 	struct tg3 *tp;
-	int err, pm_cap;
+	int i, err, pm_cap;
+	u32 sndmbx, rcvmbx, intmbx;
 	char str[40];
 	u64 dma_mask, persist_dma_mask;
 
@@ -13538,12 +13541,50 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 	tp->rx_pending = TG3_DEF_RX_RING_PENDING;
 	tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
 
-	tp->napi[0].tp = tp;
-	tp->napi[0].int_mbox = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
-	tp->napi[0].consmbox = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
-	tp->napi[0].prodmbox = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
-	tp->napi[0].coal_now = HOSTCC_MODE_NOW;
-	tp->napi[0].tx_pending = TG3_DEF_TX_RING_PENDING;
+	intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
+	rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
+	sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
+	for (i = 0; i < TG3_IRQ_MAX_VECS; i++) {
+		struct tg3_napi *tnapi = &tp->napi[i];
+
+		tnapi->tp = tp;
+		tnapi->tx_pending = TG3_DEF_TX_RING_PENDING;
+
+		tnapi->int_mbox = intmbx;
+		if (i < 4)
+			intmbx += 0x8;
+		else
+			intmbx += 0x4;
+
+		tnapi->consmbox = rcvmbx;
+		tnapi->prodmbox = sndmbx;
+
+		if (i)
+			tnapi->coal_now = HOSTCC_MODE_COAL_VEC1_NOW << (i - 1);
+		else
+			tnapi->coal_now = HOSTCC_MODE_NOW;
+
+		if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX))
+			break;
+
+		/*
+		 * If we support MSIX, we'll be using RSS.  If we're using
+		 * RSS, the first vector only handles link interrupts and the
+		 * remaining vectors handle rx and tx interrupts.  Reuse the
+		 * mailbox values for the next iteration.  The values we setup
+		 * above are still useful for the single vectored mode.
+		 */
+		if (!i)
+			continue;
+
+		rcvmbx += 0x8;
+
+		if (sndmbx & 0x4)
+			sndmbx -= 0x4;
+		else
+			sndmbx += 0xc;
+	}
+
 	netif_napi_add(dev, &tp->napi[0].napi, tg3_poll, 64);
 	dev->ethtool_ops = &tg3_ethtool_ops;
 	dev->watchdog_timeo = TG3_TX_TIMEOUT;
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 07/18] tg3: Add tx and rx ring resource tracking
From: Matt Carlson @ 2009-09-01 23:04 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch adds code to assign status block, tx producer ring and rx
return ring resources needed for the other interrupt vectors.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |  242 ++++++++++++++++++++++++++++++++++------------------
 drivers/net/tg3.h |    3 +-
 2 files changed, 160 insertions(+), 85 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 4d16ce0..58a8986 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -5722,28 +5722,31 @@ err_out:
  */
 static void tg3_free_rings(struct tg3 *tp)
 {
-	struct tg3_napi *tnapi = &tp->napi[0];
-	int i;
+	int i, j;
 
-	for (i = 0; i < TG3_TX_RING_SIZE; ) {
-		struct tx_ring_info *txp;
-		struct sk_buff *skb;
+	for (j = 0; j < tp->irq_cnt; j++) {
+		struct tg3_napi *tnapi = &tp->napi[j];
 
-		txp = &tnapi->tx_buffers[i];
-		skb = txp->skb;
+		for (i = 0; i < TG3_TX_RING_SIZE; ) {
+			struct tx_ring_info *txp;
+			struct sk_buff *skb;
 
-		if (skb == NULL) {
-			i++;
-			continue;
-		}
+			txp = &tnapi->tx_buffers[i];
+			skb = txp->skb;
 
-		skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
+			if (skb == NULL) {
+				i++;
+				continue;
+			}
 
-		txp->skb = NULL;
+			skb_dma_unmap(&tp->pdev->dev, skb, DMA_TO_DEVICE);
 
-		i += skb_shinfo(skb)->nr_frags + 1;
+			txp->skb = NULL;
 
-		dev_kfree_skb_any(skb);
+			i += skb_shinfo(skb)->nr_frags + 1;
+
+			dev_kfree_skb_any(skb);
+		}
 	}
 
 	tg3_rx_prodring_free(tp, &tp->prodring[0]);
@@ -5758,16 +5761,27 @@ static void tg3_free_rings(struct tg3 *tp)
  */
 static int tg3_init_rings(struct tg3 *tp)
 {
-	struct tg3_napi *tnapi = &tp->napi[0];
+	int i;
 
 	/* Free up all the SKBs. */
 	tg3_free_rings(tp);
 
-	/* Zero out all descriptors. */
-	memset(tnapi->tx_ring, 0, TG3_TX_RING_BYTES);
+	for (i = 0; i < tp->irq_cnt; i++) {
+		struct tg3_napi *tnapi = &tp->napi[i];
 
-	tnapi->rx_rcb_ptr = 0;
-	memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+		tnapi->last_tag = 0;
+		tnapi->last_irq_tag = 0;
+		tnapi->hw_status->status = 0;
+		tnapi->hw_status->status_tag = 0;
+		memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+		tnapi->tx_prod = 0;
+		tnapi->tx_cons = 0;
+		memset(tnapi->tx_ring, 0, TG3_TX_RING_BYTES);
+
+		tnapi->rx_rcb_ptr = 0;
+		memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+	}
 
 	return tg3_rx_prodring_alloc(tp, &tp->prodring[0]);
 }
@@ -5778,31 +5792,41 @@ static int tg3_init_rings(struct tg3 *tp)
  */
 static void tg3_free_consistent(struct tg3 *tp)
 {
-	struct tg3_napi *tnapi = &tp->napi[0];
+	int i;
 
-	kfree(tnapi->tx_buffers);
-	tnapi->tx_buffers = NULL;
-	if (tnapi->tx_ring) {
-		pci_free_consistent(tp->pdev, TG3_TX_RING_BYTES,
-			tnapi->tx_ring, tnapi->tx_desc_mapping);
-		tnapi->tx_ring = NULL;
-	}
-	if (tnapi->rx_rcb) {
-		pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp),
-				    tnapi->rx_rcb, tnapi->rx_rcb_mapping);
-		tnapi->rx_rcb = NULL;
-	}
-	if (tnapi->hw_status) {
-		pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE,
-				    tnapi->hw_status,
-				    tnapi->status_mapping);
-		tnapi->hw_status = NULL;
+	for (i = 0; i < tp->irq_cnt; i++) {
+		struct tg3_napi *tnapi = &tp->napi[i];
+
+		if (tnapi->tx_ring) {
+			pci_free_consistent(tp->pdev, TG3_TX_RING_BYTES,
+				tnapi->tx_ring, tnapi->tx_desc_mapping);
+			tnapi->tx_ring = NULL;
+		}
+
+		kfree(tnapi->tx_buffers);
+		tnapi->tx_buffers = NULL;
+
+		if (tnapi->rx_rcb) {
+			pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp),
+					    tnapi->rx_rcb,
+					    tnapi->rx_rcb_mapping);
+			tnapi->rx_rcb = NULL;
+		}
+
+		if (tnapi->hw_status) {
+			pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE,
+					    tnapi->hw_status,
+					    tnapi->status_mapping);
+			tnapi->hw_status = NULL;
+		}
 	}
+
 	if (tp->hw_stats) {
 		pci_free_consistent(tp->pdev, sizeof(struct tg3_hw_stats),
 				    tp->hw_stats, tp->stats_mapping);
 		tp->hw_stats = NULL;
 	}
+
 	tg3_rx_prodring_fini(tp, &tp->prodring[0]);
 }
 
@@ -5812,44 +5836,49 @@ static void tg3_free_consistent(struct tg3 *tp)
  */
 static int tg3_alloc_consistent(struct tg3 *tp)
 {
-	struct tg3_napi *tnapi = &tp->napi[0];
+	int i;
 
 	if (tg3_rx_prodring_init(tp, &tp->prodring[0]))
 		return -ENOMEM;
 
-	tnapi->tx_buffers = kzalloc(sizeof(struct tx_ring_info) *
-				    TG3_TX_RING_SIZE, GFP_KERNEL);
-	if (!tnapi->tx_buffers)
+	tp->hw_stats = pci_alloc_consistent(tp->pdev,
+					    sizeof(struct tg3_hw_stats),
+					    &tp->stats_mapping);
+	if (!tp->hw_stats)
 		goto err_out;
 
-	tnapi->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
-					      &tnapi->tx_desc_mapping);
-	if (!tnapi->tx_ring)
-		goto err_out;
+	memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
 
-	tnapi->hw_status = pci_alloc_consistent(tp->pdev,
-						TG3_HW_STATUS_SIZE,
-						&tnapi->status_mapping);
-	if (!tnapi->hw_status)
-		goto err_out;
+	for (i = 0; i < tp->irq_cnt; i++) {
+		struct tg3_napi *tnapi = &tp->napi[i];
 
-	memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+		tnapi->hw_status = pci_alloc_consistent(tp->pdev,
+							TG3_HW_STATUS_SIZE,
+							&tnapi->status_mapping);
+		if (!tnapi->hw_status)
+			goto err_out;
 
-	tnapi->rx_rcb = pci_alloc_consistent(tp->pdev,
-					     TG3_RX_RCB_RING_BYTES(tp),
-					     &tnapi->rx_rcb_mapping);
-	if (!tnapi->rx_rcb)
-		goto err_out;
+		memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
 
-	memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+		tnapi->rx_rcb = pci_alloc_consistent(tp->pdev,
+						     TG3_RX_RCB_RING_BYTES(tp),
+						     &tnapi->rx_rcb_mapping);
+		if (!tnapi->rx_rcb)
+			goto err_out;
 
-	tp->hw_stats = pci_alloc_consistent(tp->pdev,
-					    sizeof(struct tg3_hw_stats),
-					    &tp->stats_mapping);
-	if (!tp->hw_stats)
-		goto err_out;
+		memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
 
-	memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
+		tnapi->tx_buffers = kzalloc(sizeof(struct tx_ring_info) *
+					    TG3_TX_RING_SIZE, GFP_KERNEL);
+		if (!tnapi->tx_buffers)
+			goto err_out;
+
+		tnapi->tx_ring = pci_alloc_consistent(tp->pdev,
+						      TG3_TX_RING_BYTES,
+						      &tnapi->tx_desc_mapping);
+		if (!tnapi->tx_ring)
+			goto err_out;
+	}
 
 	return 0;
 
@@ -5910,7 +5939,6 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int
 static int tg3_abort_hw(struct tg3 *tp, int silent)
 {
 	int i, err;
-	struct tg3_napi *tnapi = &tp->napi[0];
 
 	tg3_disable_ints(tp);
 
@@ -5962,8 +5990,11 @@ static int tg3_abort_hw(struct tg3 *tp, int silent)
 	err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE, silent);
 	err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE, silent);
 
-	if (tnapi->hw_status)
-		memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+	for (i = 0; i < tp->irq_cnt; i++) {
+		struct tg3_napi *tnapi = &tp->napi[i];
+		if (tnapi->hw_status)
+			memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+	}
 	if (tp->hw_stats)
 		memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
 
@@ -6290,12 +6321,15 @@ static int tg3_chip_reset(struct tg3 *tp)
 	 * sharing or irqpoll.
 	 */
 	tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING;
-	if (tp->napi[0].hw_status) {
-		tp->napi[0].hw_status->status = 0;
-		tp->napi[0].hw_status->status_tag = 0;
+	for (i = 0; i < tp->irq_cnt; i++) {
+		struct tg3_napi *tnapi = &tp->napi[i];
+		if (tnapi->hw_status) {
+			tnapi->hw_status->status = 0;
+			tnapi->hw_status->status_tag = 0;
+		}
+		tnapi->last_tag = 0;
+		tnapi->last_irq_tag = 0;
 	}
-	tp->napi[0].last_tag = 0;
-	tp->napi[0].last_irq_tag = 0;
 	smp_mb();
 
 	for (i = 0; i < tp->irq_cnt; i++)
@@ -6829,7 +6863,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
 static void tg3_rings_reset(struct tg3 *tp)
 {
 	int i;
-	u32 txrcb, rxrcb, limit;
+	u32 stblk, txrcb, rxrcb, limit;
 	struct tg3_napi *tnapi = &tp->napi[0];
 
 	/* Disable all transmit rings but the first. */
@@ -6861,10 +6895,20 @@ static void tg3_rings_reset(struct tg3 *tp)
 	tw32_mailbox_f(tp->napi[0].int_mbox, 1);
 
 	/* Zero mailbox registers. */
-	tp->napi[0].tx_prod = 0;
-	tp->napi[0].tx_cons = 0;
-	tw32_mailbox(tp->napi[0].prodmbox, 0);
-	tw32_rx_mbox(tp->napi[0].consmbox, 0);
+	if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) {
+		for (i = 1; i < TG3_IRQ_MAX_VECS; i++) {
+			tp->napi[i].tx_prod = 0;
+			tp->napi[i].tx_cons = 0;
+			tw32_mailbox(tp->napi[i].prodmbox, 0);
+			tw32_rx_mbox(tp->napi[i].consmbox, 0);
+			tw32_mailbox_f(tp->napi[i].int_mbox, 1);
+		}
+	} else {
+		tp->napi[0].tx_prod = 0;
+		tp->napi[0].tx_cons = 0;
+		tw32_mailbox(tp->napi[0].prodmbox, 0);
+		tw32_rx_mbox(tp->napi[0].consmbox, 0);
+	}
 
 	/* Make sure the NIC-based send BD rings are disabled. */
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
@@ -6885,14 +6929,44 @@ static void tg3_rings_reset(struct tg3 *tp)
 	tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
 	     ((u64) tnapi->status_mapping & 0xffffffff));
 
-	tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
-		       (TG3_TX_RING_SIZE <<
-			BDINFO_FLAGS_MAXLEN_SHIFT),
-		       NIC_SRAM_TX_BUFFER_DESC);
+	if (tnapi->tx_ring) {
+		tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
+			       (TG3_TX_RING_SIZE <<
+				BDINFO_FLAGS_MAXLEN_SHIFT),
+			       NIC_SRAM_TX_BUFFER_DESC);
+		txrcb += TG3_BDINFO_SIZE;
+	}
 
-	tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
-		       (TG3_RX_RCB_RING_SIZE(tp) <<
-			BDINFO_FLAGS_MAXLEN_SHIFT), 0);
+	if (tnapi->rx_rcb) {
+		tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
+			       (TG3_RX_RCB_RING_SIZE(tp) <<
+				BDINFO_FLAGS_MAXLEN_SHIFT), 0);
+		rxrcb += TG3_BDINFO_SIZE;
+	}
+
+	stblk = HOSTCC_STATBLCK_RING1;
+
+	for (i = 1, tnapi++; i < tp->irq_cnt; i++, tnapi++) {
+		u64 mapping = (u64)tnapi->status_mapping;
+		tw32(stblk + TG3_64BIT_REG_HIGH, mapping >> 32);
+		tw32(stblk + TG3_64BIT_REG_LOW, mapping & 0xffffffff);
+
+		/* Clear status block in ram. */
+		memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+
+		tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
+			       (TG3_TX_RING_SIZE <<
+				BDINFO_FLAGS_MAXLEN_SHIFT),
+			       NIC_SRAM_TX_BUFFER_DESC);
+
+		tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
+			       (TG3_RX_RCB_RING_SIZE(tp) <<
+				BDINFO_FLAGS_MAXLEN_SHIFT), 0);
+
+		stblk += 8;
+		txrcb += TG3_BDINFO_SIZE;
+		rxrcb += TG3_BDINFO_SIZE;
+	}
 }
 
 /* tp->lock is held. */
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 65bbd77..6452d48 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1117,7 +1117,8 @@
 #define HOSTCC_SND_CON_IDX_13		0x00003cf4
 #define HOSTCC_SND_CON_IDX_14		0x00003cf8
 #define HOSTCC_SND_CON_IDX_15		0x00003cfc
-/* 0x3d00 --> 0x4000 unused */
+#define HOSTCC_STATBLCK_RING1		0x00003d00
+/* 0x3d04 --> 0x4000 unused */
 
 /* Memory arbiter control registers */
 #define MEMARB_MODE			0x00004000
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 11/18] tg3: Add coalesce parameters for msix vectors
From: Matt Carlson @ 2009-09-01 23:12 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch adds code to tune the coalescing parameters for the other
msix vectors.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   57 ++++++++++++++++++++++++++++++++++++++++++++--------
 drivers/net/tg3.h |   10 ++++++++-
 2 files changed, 57 insertions(+), 10 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index ad0fc5d..8e9492b 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -6876,24 +6876,63 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
 static void __tg3_set_rx_mode(struct net_device *);
 static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
 {
-	tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs);
-	tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs);
-	tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames);
-	tw32(HOSTCC_TXMAX_FRAMES, ec->tx_max_coalesced_frames);
-	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
-		tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
-		tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
+	int i;
+
+	if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) {
+		tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs);
+		tw32(HOSTCC_TXMAX_FRAMES, ec->tx_max_coalesced_frames);
+		tw32(HOSTCC_TXCOAL_MAXF_INT, ec->tx_max_coalesced_frames_irq);
+
+		tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs);
+		tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames);
+		tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq);
+	} else {
+		tw32(HOSTCC_TXCOL_TICKS, 0);
+		tw32(HOSTCC_TXMAX_FRAMES, 0);
+		tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
+
+		tw32(HOSTCC_RXCOL_TICKS, 0);
+		tw32(HOSTCC_RXMAX_FRAMES, 0);
+		tw32(HOSTCC_RXCOAL_MAXF_INT, 0);
 	}
-	tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq);
-	tw32(HOSTCC_TXCOAL_MAXF_INT, ec->tx_max_coalesced_frames_irq);
+
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
 		u32 val = ec->stats_block_coalesce_usecs;
 
+		tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
+		tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
+
 		if (!netif_carrier_ok(tp->dev))
 			val = 0;
 
 		tw32(HOSTCC_STAT_COAL_TICKS, val);
 	}
+
+	for (i = 0; i < tp->irq_cnt - 1; i++) {
+		u32 reg;
+
+		reg = HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18;
+		tw32(reg, ec->rx_coalesce_usecs);
+		reg = HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18;
+		tw32(reg, ec->tx_coalesce_usecs);
+		reg = HOSTCC_RXMAX_FRAMES_VEC1 + i * 0x18;
+		tw32(reg, ec->rx_max_coalesced_frames);
+		reg = HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18;
+		tw32(reg, ec->tx_max_coalesced_frames);
+		reg = HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18;
+		tw32(reg, ec->rx_max_coalesced_frames_irq);
+		reg = HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18;
+		tw32(reg, ec->tx_max_coalesced_frames_irq);
+	}
+
+	for (; i < tp->irq_max - 1; i++) {
+		tw32(HOSTCC_RXCOL_TICKS_VEC1 + i * 0x18, 0);
+		tw32(HOSTCC_TXCOL_TICKS_VEC1 + i * 0x18, 0);
+		tw32(HOSTCC_RXMAX_FRAMES_VEC1 + i * 0x18, 0);
+		tw32(HOSTCC_TXMAX_FRAMES_VEC1 + i * 0x18, 0);
+		tw32(HOSTCC_RXCOAL_MAXF_INT_VEC1 + i * 0x18, 0);
+		tw32(HOSTCC_TXCOAL_MAXF_INT_VEC1 + i * 0x18, 0);
+	}
 }
 
 /* tp->lock is held. */
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index d1c7add..978b6d9 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1119,7 +1119,15 @@
 #define HOSTCC_SND_CON_IDX_14		0x00003cf8
 #define HOSTCC_SND_CON_IDX_15		0x00003cfc
 #define HOSTCC_STATBLCK_RING1		0x00003d00
-/* 0x3d04 --> 0x4000 unused */
+/* 0x3d00 --> 0x3d80 unused */
+
+#define HOSTCC_RXCOL_TICKS_VEC1		0x00003d80
+#define HOSTCC_TXCOL_TICKS_VEC1		0x00003d84
+#define HOSTCC_RXMAX_FRAMES_VEC1	0x00003d88
+#define HOSTCC_TXMAX_FRAMES_VEC1	0x00003d8c
+#define HOSTCC_RXCOAL_MAXF_INT_VEC1	0x00003d90
+#define HOSTCC_TXCOAL_MAXF_INT_VEC1	0x00003d94
+/* 0x3d98 --> 0x4000 unused */
 
 /* Memory arbiter control registers */
 #define MEMARB_MODE			0x00004000
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 09/18] tg3: Add TSS support
From: Matt Carlson @ 2009-09-01 23:09 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch exposes the additional transmit rings to the kernel and makes
the necessary modifications to transmit, open, and close paths.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   54 +++++++++++++++++++++++++++++++++++-----------------
 drivers/net/tg3.h |    1 +
 2 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 5389654..2e0f4a5 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -704,11 +704,13 @@ static inline void tg3_netif_stop(struct tg3 *tp)
 static inline void tg3_netif_start(struct tg3 *tp)
 {
 	struct tg3_napi *tnapi = &tp->napi[0];
-	netif_wake_queue(tp->dev);
-	/* NOTE: unconditional netif_wake_queue is only appropriate
-	 * so long as all callers are assured to have free tx slots
-	 * (such as after tg3_init_hw)
+
+	/* NOTE: unconditional netif_tx_wake_all_queues is only
+	 * appropriate so long as all callers are assured to
+	 * have free tx slots (such as after tg3_init_hw)
 	 */
+	netif_tx_wake_all_queues(tp->dev);
+
 	napi_enable(&tnapi->napi);
 	tnapi->hw_status->status |= SD_STATUS_UPDATED;
 	tg3_enable_ints(tp);
@@ -4294,6 +4296,13 @@ static void tg3_tx(struct tg3_napi *tnapi)
 	struct tg3 *tp = tnapi->tp;
 	u32 hw_idx = tnapi->hw_status->idx[0].tx_consumer;
 	u32 sw_idx = tnapi->tx_cons;
+	struct netdev_queue *txq;
+	int index = tnapi - tp->napi;
+
+	if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+		index--;
+
+	txq = netdev_get_tx_queue(tp->dev, index);
 
 	while (sw_idx != hw_idx) {
 		struct tx_ring_info *ri = &tnapi->tx_buffers[sw_idx];
@@ -4335,13 +4344,13 @@ static void tg3_tx(struct tg3_napi *tnapi)
 	 */
 	smp_mb();
 
-	if (unlikely(netif_queue_stopped(tp->dev) &&
+	if (unlikely(netif_tx_queue_stopped(txq) &&
 		     (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)))) {
-		netif_tx_lock(tp->dev);
-		if (netif_queue_stopped(tp->dev) &&
+		__netif_tx_lock(txq, smp_processor_id());
+		if (netif_tx_queue_stopped(txq) &&
 		    (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi)))
-			netif_wake_queue(tp->dev);
-		netif_tx_unlock(tp->dev);
+			netif_tx_wake_queue(txq);
+		__netif_tx_unlock(txq);
 	}
 }
 
@@ -5156,9 +5165,13 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 	u32 len, entry, base_flags, mss;
 	struct skb_shared_info *sp;
 	dma_addr_t mapping;
-	struct tg3_napi *tnapi = &tp->napi[0];
+	struct tg3_napi *tnapi;
+	struct netdev_queue *txq;
 
-	len = skb_headlen(skb);
+	txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
+	tnapi = &tp->napi[skb_get_queue_mapping(skb)];
+	if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+		tnapi++;
 
 	/* We are running in BH disabled context with netif_tx_lock
 	 * and TX reclaim runs via tp->napi.poll inside of a software
@@ -5166,8 +5179,8 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 	 * no IRQ context deadlocks to worry about either.  Rejoice!
 	 */
 	if (unlikely(tg3_tx_avail(tnapi) <= (skb_shinfo(skb)->nr_frags + 1))) {
-		if (!netif_queue_stopped(dev)) {
-			netif_stop_queue(dev);
+		if (!netif_tx_queue_stopped(txq)) {
+			netif_tx_stop_queue(txq);
 
 			/* This is a hard error, log it. */
 			printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
@@ -5226,6 +5239,8 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 
 	tnapi->tx_buffers[entry].skb = skb;
 
+	len = skb_headlen(skb);
+
 	tg3_set_txd(tnapi, entry, mapping, len, base_flags,
 		    (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
 
@@ -5255,9 +5270,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 
 	tnapi->tx_prod = entry;
 	if (unlikely(tg3_tx_avail(tnapi) <= (MAX_SKB_FRAGS + 1))) {
-		netif_stop_queue(dev);
+		netif_tx_stop_queue(txq);
 		if (tg3_tx_avail(tnapi) > TG3_TX_WAKEUP_THRESH(tnapi))
-			netif_wake_queue(tp->dev);
+			netif_tx_wake_queue(txq);
 	}
 
 out_unlock:
@@ -8047,6 +8062,8 @@ static bool tg3_enable_msix(struct tg3 *tp)
 	for (i = 0; i < tp->irq_max; i++)
 		tp->napi[i].irq_vec = msix_ent[i].vector;
 
+	tp->dev->real_num_tx_queues = tp->irq_cnt - 1;
+
 	return true;
 }
 
@@ -8076,6 +8093,7 @@ defcfg:
 	if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) {
 		tp->irq_cnt = 1;
 		tp->napi[0].irq_vec = tp->pdev->irq;
+		tp->dev->real_num_tx_queues = 1;
 	}
 }
 
@@ -8211,7 +8229,7 @@ static int tg3_open(struct net_device *dev)
 
 	tg3_full_unlock(tp);
 
-	netif_start_queue(dev);
+	netif_tx_start_all_queues(dev);
 
 	return 0;
 
@@ -8471,7 +8489,7 @@ static int tg3_close(struct net_device *dev)
 	napi_disable(&tp->napi[0].napi);
 	cancel_work_sync(&tp->reset_task);
 
-	netif_stop_queue(dev);
+	netif_tx_stop_all_queues(dev);
 
 	del_timer_sync(&tp->timer);
 
@@ -13560,7 +13578,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 		goto err_out_free_res;
 	}
 
-	dev = alloc_etherdev(sizeof(*tp));
+	dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS);
 	if (!dev) {
 		printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
 		err = -ENOMEM;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 6452d48..d1c7add 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -822,6 +822,7 @@
 #define  SNDBDI_MODE_RESET		 0x00000001
 #define  SNDBDI_MODE_ENABLE		 0x00000002
 #define  SNDBDI_MODE_ATTN_ENABLE	 0x00000004
+#define  SNDBDI_MODE_MULTI_TXQ_EN	 0x00000020
 #define SNDBDI_STATUS			0x00001804
 #define  SNDBDI_STATUS_ERROR_ATTN	 0x00000004
 #define SNDBDI_IN_PROD_IDX_0		0x00001808
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 08/18] tg3: Update intmbox and coal_now for msix
From: Matt Carlson @ 2009-09-01 23:08 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch fixes up two spots that need attention now that msix support
has been added.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   20 ++++++++++++++------
 1 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 58a8986..5389654 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -614,25 +614,33 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum)
 
 static void tg3_disable_ints(struct tg3 *tp)
 {
+	int i;
+
 	tw32(TG3PCI_MISC_HOST_CTRL,
 	     (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
-	tw32_mailbox_f(tp->napi[0].int_mbox, 0x00000001);
+	for (i = 0; i < tp->irq_max; i++)
+		tw32_mailbox_f(tp->napi[i].int_mbox, 0x00000001);
 }
 
 static void tg3_enable_ints(struct tg3 *tp)
 {
-	u32 coal_now;
-	struct tg3_napi *tnapi = &tp->napi[0];
+	int i;
+	u32 coal_now = 0;
+
 	tp->irq_sync = 0;
 	wmb();
 
 	tw32(TG3PCI_MISC_HOST_CTRL,
 	     (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
-	tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
-	if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
+
+	for (i = 0; i < tp->irq_cnt; i++) {
+		struct tg3_napi *tnapi = &tp->napi[i];
 		tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
+		if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
+			tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
 
-	coal_now = tnapi->coal_now;
+		coal_now |= tnapi->coal_now;
+	}
 
 	/* Force an initial interrupt */
 	if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 05/18] tg3: Add MSI-X support
From: Matt Carlson @ 2009-09-01 22:55 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch adds MSI-X support.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |  108 +++++++++++++++++++++++++++++++++++++++-------------
 drivers/net/tg3.h |    6 +++
 2 files changed, 87 insertions(+), 27 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 7717eae..12ead83 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -160,6 +160,7 @@ MODULE_FIRMWARE(FIRMWARE_TG3);
 MODULE_FIRMWARE(FIRMWARE_TG3TSO);
 MODULE_FIRMWARE(FIRMWARE_TG3TSO5);
 
+#define TG3_RSS_MIN_NUM_MSIX_VECS	2
 
 static int tg3_debug = -1;	/* -1 == use TG3_DEF_MSG_ENABLE as value */
 module_param(tg3_debug, int, 0);
@@ -7767,7 +7768,7 @@ static int tg3_request_irq(struct tg3 *tp, int irq_num)
 		name[IFNAMSIZ-1] = 0;
 	}
 
-	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
+	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) {
 		fn = tg3_msi;
 		if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)
 			fn = tg3_msi_1shot;
@@ -7928,34 +7929,81 @@ static int tg3_request_firmware(struct tg3 *tp)
 	return 0;
 }
 
+static bool tg3_enable_msix(struct tg3 *tp)
+{
+	int i, rc, cpus = num_online_cpus();
+	struct msix_entry msix_ent[tp->irq_max];
+
+	if (cpus == 1)
+		/* Just fallback to the simpler MSI mode. */
+		return false;
+
+	/*
+	 * We want as many rx rings enabled as there are cpus.
+	 * The first MSIX vector only deals with link interrupts, etc,
+	 * so we add one to the number of vectors we are requesting.
+	 */
+	tp->irq_cnt = min_t(unsigned, cpus + 1, tp->irq_max);
+
+	for (i = 0; i < tp->irq_max; i++) {
+		msix_ent[i].entry  = i;
+		msix_ent[i].vector = 0;
+	}
+
+	rc = pci_enable_msix(tp->pdev, msix_ent, tp->irq_cnt);
+	if (rc != 0) {
+		if (rc < TG3_RSS_MIN_NUM_MSIX_VECS)
+			return false;
+		if (pci_enable_msix(tp->pdev, msix_ent, rc))
+			return false;
+		printk(KERN_NOTICE
+		       "%s: Requested %d MSI-X vectors, received %d\n",
+		       tp->dev->name, tp->irq_cnt, rc);
+		tp->irq_cnt = rc;
+	}
+
+	for (i = 0; i < tp->irq_max; i++)
+		tp->napi[i].irq_vec = msix_ent[i].vector;
+
+	return true;
+}
+
 static void tg3_ints_init(struct tg3 *tp)
 {
-	if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) {
+	if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSI_OR_MSIX) &&
+	    !(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
 		/* All MSI supporting chips should support tagged
 		 * status.  Assert that this is the case.
 		 */
-		if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
-			printk(KERN_WARNING PFX "%s: MSI without TAGGED? "
-			       "Not using MSI.\n", tp->dev->name);
-		} else if (pci_enable_msi(tp->pdev) == 0) {
-			u32 msi_mode;
-
-			msi_mode = tr32(MSGINT_MODE);
-			tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
-			tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
-		}
+		printk(KERN_WARNING PFX "%s: MSI without TAGGED? "
+		       "Not using MSI.\n", tp->dev->name);
+		goto defcfg;
 	}
 
-	tp->irq_cnt = 1;
-	tp->napi[0].irq_vec = tp->pdev->irq;
+	if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) && tg3_enable_msix(tp))
+		tp->tg3_flags2 |= TG3_FLG2_USING_MSIX;
+	else if ((tp->tg3_flags & TG3_FLAG_SUPPORT_MSI) &&
+		 pci_enable_msi(tp->pdev) == 0)
+		tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
+
+	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) {
+		u32 msi_mode = tr32(MSGINT_MODE);
+		tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
+	}
+defcfg:
+	if (!(tp->tg3_flags2 & TG3_FLG2_USING_MSIX)) {
+		tp->irq_cnt = 1;
+		tp->napi[0].irq_vec = tp->pdev->irq;
+	}
 }
 
 static void tg3_ints_fini(struct tg3 *tp)
 {
-		if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
-			pci_disable_msi(tp->pdev);
-			tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
-		}
+	if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+		pci_disable_msix(tp->pdev);
+	else if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
+		pci_disable_msi(tp->pdev);
+	tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI_OR_MSIX;
 }
 
 static int tg3_open(struct net_device *dev)
@@ -7992,14 +8040,18 @@ static int tg3_open(struct net_device *dev)
 
 	tg3_full_unlock(tp);
 
+	/*
+	 * Setup interrupts first so we know how
+	 * many NAPI resources to allocate
+	 */
+	tg3_ints_init(tp);
+
 	/* The placement of this call is tied
 	 * to the setup and use of Host TX descriptors.
 	 */
 	err = tg3_alloc_consistent(tp);
 	if (err)
-		return err;
-
-	tg3_ints_init(tp);
+		goto err_out1;
 
 	napi_enable(&tp->napi[0].napi);
 
@@ -8014,7 +8066,7 @@ static int tg3_open(struct net_device *dev)
 	}
 
 	if (err)
-		goto err_out1;
+		goto err_out2;
 
 	tg3_full_lock(tp, 0);
 
@@ -8043,7 +8095,7 @@ static int tg3_open(struct net_device *dev)
 	tg3_full_unlock(tp);
 
 	if (err)
-		goto err_out2;
+		goto err_out3;
 
 	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
 		err = tg3_test_msi(tp);
@@ -8054,7 +8106,7 @@ static int tg3_open(struct net_device *dev)
 			tg3_free_rings(tp);
 			tg3_full_unlock(tp);
 
-			goto err_out1;
+			goto err_out2;
 		}
 
 		if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
@@ -8081,16 +8133,18 @@ static int tg3_open(struct net_device *dev)
 
 	return 0;
 
-err_out2:
+err_out3:
 	for (i = tp->irq_cnt - 1; i >= 0; i--) {
 		struct tg3_napi *tnapi = &tp->napi[i];
 		free_irq(tnapi->irq_vec, tnapi);
 	}
 
-err_out1:
+err_out2:
 	napi_disable(&tp->napi[0].napi);
-	tg3_ints_fini(tp);
 	tg3_free_consistent(tp);
+
+err_out1:
+	tg3_ints_fini(tp);
 	return err;
 }
 
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index a78a0db..65bbd77 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2621,6 +2621,9 @@ struct tg3 {
 #define TG3_FLAG_NVRAM			0x00002000
 #define TG3_FLAG_NVRAM_BUFFERED		0x00004000
 #define TG3_FLAG_SUPPORT_MSI		0x00008000
+#define TG3_FLAG_SUPPORT_MSIX		0x00010000
+#define TG3_FLAG_SUPPORT_MSI_OR_MSIX	(TG3_FLAG_SUPPORT_MSI | \
+					 TG3_FLAG_SUPPORT_MSIX)
 #define TG3_FLAG_PCIX_MODE		0x00020000
 #define TG3_FLAG_PCI_HIGH_SPEED		0x00040000
 #define TG3_FLAG_PCI_32BIT		0x00080000
@@ -2659,6 +2662,9 @@ struct tg3 {
 #define TG3_FLG2_5750_PLUS		0x00080000
 #define TG3_FLG2_PROTECTED_NVRAM	0x00100000
 #define TG3_FLG2_USING_MSI		0x00200000
+#define TG3_FLG2_USING_MSIX		0x00400000
+#define TG3_FLG2_USING_MSI_OR_MSIX	(TG3_FLG2_USING_MSI | \
+					TG3_FLG2_USING_MSIX)
 #define TG3_FLG2_MII_SERDES		0x00800000
 #define TG3_FLG2_ANY_SERDES		(TG3_FLG2_PHY_SERDES |	\
 					TG3_FLG2_MII_SERDES)
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 12/18] tg3: Add RSS support
From: Matt Carlson @ 2009-09-01 23:13 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch adds code needed to enable RSS.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 drivers/net/tg3.h |   25 ++++++++++++++++++++++++-
 2 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 8e9492b..39a8ead 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -102,6 +102,7 @@
 #define TG3_DEF_RX_RING_PENDING		200
 #define TG3_RX_JUMBO_RING_SIZE		256
 #define TG3_DEF_RX_JUMBO_RING_PENDING	100
+#define TG3_RSS_INDIR_TBL_SIZE 128
 
 /* Do not place this n-ring entries value into the tp struct itself,
  * we really want to expose these constants to GCC so that modulo et
@@ -7497,6 +7498,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 	udelay(100);
 
+	if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX) {
+		val = tr32(MSGINT_MODE);
+		val |= MSGINT_MODE_MULTIVEC_EN | MSGINT_MODE_ENABLE;
+		tw32(MSGINT_MODE, val);
+	}
+
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
 		tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
 		udelay(40);
@@ -7565,7 +7572,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE);
 	if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
 		tw32(SNDDATAI_MODE, SNDDATAI_MODE_ENABLE | 0x8);
-	tw32(SNDBDI_MODE, SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE);
+	val = SNDBDI_MODE_ENABLE | SNDBDI_MODE_ATTN_ENABLE;
+	if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+		val |= SNDBDI_MODE_MULTI_TXQ_EN;
+	tw32(SNDBDI_MODE, val);
 	tw32(SNDBDS_MODE, SNDBDS_MODE_ENABLE | SNDBDS_MODE_ATTN_ENABLE);
 
 	if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) {
@@ -7584,10 +7594,46 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	tw32_f(MAC_TX_MODE, tp->tx_mode);
 	udelay(100);
 
+	if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS) {
+		u32 reg = MAC_RSS_INDIR_TBL_0;
+		u8 *ent = (u8 *)&val;
+
+		/* Setup the indirection table */
+		for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) {
+			int idx = i % sizeof(val);
+
+			ent[idx] = i % (tp->irq_cnt - 1);
+			if (idx == sizeof(val) - 1) {
+				tw32(reg, val);
+				reg += 4;
+			}
+		}
+
+		/* Setup the "secret" hash key. */
+		tw32(MAC_RSS_HASH_KEY_0, 0x5f865437);
+		tw32(MAC_RSS_HASH_KEY_1, 0xe4ac62cc);
+		tw32(MAC_RSS_HASH_KEY_2, 0x50103a45);
+		tw32(MAC_RSS_HASH_KEY_3, 0x36621985);
+		tw32(MAC_RSS_HASH_KEY_4, 0xbf14c0e8);
+		tw32(MAC_RSS_HASH_KEY_5, 0x1bc27a1e);
+		tw32(MAC_RSS_HASH_KEY_6, 0x84f4b556);
+		tw32(MAC_RSS_HASH_KEY_7, 0x094ea6fe);
+		tw32(MAC_RSS_HASH_KEY_8, 0x7dda01e7);
+		tw32(MAC_RSS_HASH_KEY_9, 0xc04d7481);
+	}
+
 	tp->rx_mode = RX_MODE_ENABLE;
 	if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
 		tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE;
 
+	if (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS)
+		tp->rx_mode |= RX_MODE_RSS_ENABLE |
+			       RX_MODE_RSS_ITBL_HASH_BITS_7 |
+			       RX_MODE_RSS_IPV6_HASH_EN |
+			       RX_MODE_RSS_TCP_IPV6_HASH_EN |
+			       RX_MODE_RSS_IPV4_HASH_EN |
+			       RX_MODE_RSS_TCP_IPV4_HASH_EN;
+
 	tw32_f(MAC_RX_MODE, tp->rx_mode);
 	udelay(10);
 
@@ -8112,6 +8158,8 @@ static bool tg3_enable_msix(struct tg3 *tp)
 		tp->irq_cnt = rc;
 	}
 
+	tp->tg3_flags3 |= TG3_FLG3_ENABLE_RSS;
+
 	for (i = 0; i < tp->irq_max; i++)
 		tp->napi[i].irq_vec = msix_ent[i].vector;
 
@@ -8140,6 +8188,8 @@ static void tg3_ints_init(struct tg3 *tp)
 
 	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) {
 		u32 msi_mode = tr32(MSGINT_MODE);
+		if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+			msi_mode |= MSGINT_MODE_MULTIVEC_EN;
 		tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
 	}
 defcfg:
@@ -8157,6 +8207,7 @@ static void tg3_ints_fini(struct tg3 *tp)
 	else if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
 		pci_disable_msi(tp->pdev);
 	tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI_OR_MSIX;
+	tp->tg3_flags3 &= ~TG3_FLG3_ENABLE_RSS;
 }
 
 static int tg3_open(struct net_device *dev)
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 978b6d9..348add2 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -446,6 +446,12 @@
 #define  RX_MODE_PROMISC		 0x00000100
 #define  RX_MODE_NO_CRC_CHECK		 0x00000200
 #define  RX_MODE_KEEP_VLAN_TAG		 0x00000400
+#define  RX_MODE_RSS_IPV4_HASH_EN	 0x00010000
+#define  RX_MODE_RSS_TCP_IPV4_HASH_EN	 0x00020000
+#define  RX_MODE_RSS_IPV6_HASH_EN	 0x00040000
+#define  RX_MODE_RSS_TCP_IPV6_HASH_EN	 0x00080000
+#define  RX_MODE_RSS_ITBL_HASH_BITS_7	 0x00700000
+#define  RX_MODE_RSS_ENABLE		 0x00800000
 #define  RX_MODE_IPV6_CSUM_ENABLE	 0x01000000
 #define MAC_RX_STATUS			0x0000046c
 #define  RX_STATUS_REMOTE_TX_XOFFED	 0x00000001
@@ -690,7 +696,22 @@
 /* 0x5b8 --> 0x600 unused */
 #define MAC_TX_MAC_STATE_BASE		0x00000600 /* 16 bytes */
 #define MAC_RX_MAC_STATE_BASE		0x00000610 /* 20 bytes */
-/* 0x624 --> 0x800 unused */
+/* 0x624 --> 0x670 unused */
+
+#define MAC_RSS_INDIR_TBL_0		0x00000630
+
+#define MAC_RSS_HASH_KEY_0		0x00000670
+#define MAC_RSS_HASH_KEY_1		0x00000674
+#define MAC_RSS_HASH_KEY_2		0x00000678
+#define MAC_RSS_HASH_KEY_3		0x0000067c
+#define MAC_RSS_HASH_KEY_4		0x00000680
+#define MAC_RSS_HASH_KEY_5		0x00000684
+#define MAC_RSS_HASH_KEY_6		0x00000688
+#define MAC_RSS_HASH_KEY_7		0x0000068c
+#define MAC_RSS_HASH_KEY_8		0x00000690
+#define MAC_RSS_HASH_KEY_9		0x00000694
+/* 0x698 --> 0x800 unused */
+
 #define MAC_TX_STATS_OCTETS		0x00000800
 #define MAC_TX_STATS_RESV1		0x00000804
 #define MAC_TX_STATS_COLLISIONS		0x00000808
@@ -1465,6 +1486,7 @@
 #define MSGINT_MODE			0x00006000
 #define  MSGINT_MODE_RESET		 0x00000001
 #define  MSGINT_MODE_ENABLE		 0x00000002
+#define  MSGINT_MODE_MULTIVEC_EN	 0x00000080
 #define MSGINT_STATUS			0x00006004
 #define MSGINT_FIFO			0x00006008
 /* 0x600c --> 0x6400 unused */
@@ -2704,6 +2726,7 @@ struct tg3 {
 #define TG3_FLG3_NO_NVRAM		0x00004000
 #define TG3_FLG3_TOGGLE_10_100_L1PLLPD	0x00008000
 #define TG3_FLG3_PHY_IS_FET		0x00010000
+#define TG3_FLG3_ENABLE_RSS		0x00020000
 
 	struct timer_list		timer;
 	u16				timer_counter;
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 16/18] tg3: Add 5717 NVRAM detection routines
From: Matt Carlson @ 2009-09-01 23:20 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch adds NVRAM detection routines for the 5717.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |  154 +++++++++++++++++++++++++++++++++++++----------------
 drivers/net/tg3.h |   23 ++++++++-
 2 files changed, 130 insertions(+), 47 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 2310e56..bc9c13a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -10853,6 +10853,33 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp)
 	}
 }
 
+static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
+{
+	switch (nvmcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
+	case FLASH_5752PAGE_SIZE_256:
+		tp->nvram_pagesize = 256;
+		break;
+	case FLASH_5752PAGE_SIZE_512:
+		tp->nvram_pagesize = 512;
+		break;
+	case FLASH_5752PAGE_SIZE_1K:
+		tp->nvram_pagesize = 1024;
+		break;
+	case FLASH_5752PAGE_SIZE_2K:
+		tp->nvram_pagesize = 2048;
+		break;
+	case FLASH_5752PAGE_SIZE_4K:
+		tp->nvram_pagesize = 4096;
+		break;
+	case FLASH_5752PAGE_SIZE_264:
+		tp->nvram_pagesize = 264;
+		break;
+	case FLASH_5752PAGE_SIZE_528:
+		tp->nvram_pagesize = 528;
+		break;
+	}
+}
+
 static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
 {
 	u32 nvcfg1;
@@ -10884,26 +10911,7 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
 	}
 
 	if (tp->tg3_flags2 & TG3_FLG2_FLASH) {
-		switch (nvcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
-		case FLASH_5752PAGE_SIZE_256:
-			tp->nvram_pagesize = 256;
-			break;
-		case FLASH_5752PAGE_SIZE_512:
-			tp->nvram_pagesize = 512;
-			break;
-		case FLASH_5752PAGE_SIZE_1K:
-			tp->nvram_pagesize = 1024;
-			break;
-		case FLASH_5752PAGE_SIZE_2K:
-			tp->nvram_pagesize = 2048;
-			break;
-		case FLASH_5752PAGE_SIZE_4K:
-			tp->nvram_pagesize = 4096;
-			break;
-		case FLASH_5752PAGE_SIZE_264:
-			tp->nvram_pagesize = 264;
-			break;
-		}
+		tg3_nvram_get_pagesize(tp, nvcfg1);
 	} else {
 		/* For eeprom, set pagesize to maximum eeprom size */
 		tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
@@ -11156,34 +11164,84 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
 		return;
 	}
 
-	switch (nvcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
-	case FLASH_5752PAGE_SIZE_256:
+	tg3_nvram_get_pagesize(tp, nvcfg1);
+	if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528)
 		tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
-		tp->nvram_pagesize = 256;
-		break;
-	case FLASH_5752PAGE_SIZE_512:
-		tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
-		tp->nvram_pagesize = 512;
-		break;
-	case FLASH_5752PAGE_SIZE_1K:
-		tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
-		tp->nvram_pagesize = 1024;
-		break;
-	case FLASH_5752PAGE_SIZE_2K:
-		tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
-		tp->nvram_pagesize = 2048;
-		break;
-	case FLASH_5752PAGE_SIZE_4K:
-		tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
-		tp->nvram_pagesize = 4096;
-		break;
-	case FLASH_5752PAGE_SIZE_264:
-		tp->nvram_pagesize = 264;
+}
+
+
+static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
+{
+	u32 nvcfg1;
+
+	nvcfg1 = tr32(NVRAM_CFG1);
+
+	switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+	case FLASH_5717VENDOR_ATMEL_EEPROM:
+	case FLASH_5717VENDOR_MICRO_EEPROM:
+		tp->nvram_jedecnum = JEDEC_ATMEL;
+		tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+		tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+
+		nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+		tw32(NVRAM_CFG1, nvcfg1);
+		return;
+	case FLASH_5717VENDOR_ATMEL_MDB011D:
+	case FLASH_5717VENDOR_ATMEL_ADB011B:
+	case FLASH_5717VENDOR_ATMEL_ADB011D:
+	case FLASH_5717VENDOR_ATMEL_MDB021D:
+	case FLASH_5717VENDOR_ATMEL_ADB021B:
+	case FLASH_5717VENDOR_ATMEL_ADB021D:
+	case FLASH_5717VENDOR_ATMEL_45USPT:
+		tp->nvram_jedecnum = JEDEC_ATMEL;
+		tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+		tp->tg3_flags2 |= TG3_FLG2_FLASH;
+
+		switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+		case FLASH_5717VENDOR_ATMEL_MDB021D:
+		case FLASH_5717VENDOR_ATMEL_ADB021B:
+		case FLASH_5717VENDOR_ATMEL_ADB021D:
+			tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+			break;
+		default:
+			tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+			break;
+		}
 		break;
-	case FLASH_5752PAGE_SIZE_528:
-		tp->nvram_pagesize = 528;
+	case FLASH_5717VENDOR_ST_M_M25PE10:
+	case FLASH_5717VENDOR_ST_A_M25PE10:
+	case FLASH_5717VENDOR_ST_M_M45PE10:
+	case FLASH_5717VENDOR_ST_A_M45PE10:
+	case FLASH_5717VENDOR_ST_M_M25PE20:
+	case FLASH_5717VENDOR_ST_A_M25PE20:
+	case FLASH_5717VENDOR_ST_M_M45PE20:
+	case FLASH_5717VENDOR_ST_A_M45PE20:
+	case FLASH_5717VENDOR_ST_25USPT:
+	case FLASH_5717VENDOR_ST_45USPT:
+		tp->nvram_jedecnum = JEDEC_ST;
+		tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+		tp->tg3_flags2 |= TG3_FLG2_FLASH;
+
+		switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+		case FLASH_5717VENDOR_ST_M_M25PE20:
+		case FLASH_5717VENDOR_ST_A_M25PE20:
+		case FLASH_5717VENDOR_ST_M_M45PE20:
+		case FLASH_5717VENDOR_ST_A_M45PE20:
+			tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+			break;
+		default:
+			tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+			break;
+		}
 		break;
+	default:
+		tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM;
+		return;
 	}
+
+	tg3_nvram_get_pagesize(tp, nvcfg1);
+	if (tp->nvram_pagesize != 264 && tp->nvram_pagesize != 528)
+		tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
 }
 
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
@@ -11228,6 +11286,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
 			tg3_get_5906_nvram_info(tp);
 		else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
 			tg3_get_57780_nvram_info(tp);
+		else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+			tg3_get_5717_nvram_info(tp);
 		else
 			tg3_get_nvram_info(tp);
 
@@ -13074,8 +13134,10 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 			tw32_f(NVRAM_CMD, NVRAM_CMD_RESET);
 		else
 			tg3_nvram_unlock(tp);
-	}
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+		if (tr32(TG3_CPMU_STATUS) & TG3_CPMU_STATUS_PCIE_FUNC)
+			mac_offset = 0xcc;
+	} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
 		mac_offset = 0x10;
 
 	/* First try to get it from MAC address mailbox. */
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 5994476..ea57a3a 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -1027,8 +1027,10 @@
 #define TG3_CPMU_HST_ACC		0x0000361c
 #define  CPMU_HST_ACC_MACCLK_MASK	 0x001f0000
 #define  CPMU_HST_ACC_MACCLK_6_25	 0x00130000
-/* 0x3620 --> 0x3630 unused */
+/* 0x3620 --> 0x362c unused */
 
+#define TG3_CPMU_STATUS			0x0000362c
+#define  TG3_CPMU_STATUS_PCIE_FUNC	 0x20000000
 #define TG3_CPMU_CLCK_STAT		0x00003630
 #define  CPMU_CLCK_STAT_MAC_CLCK_MASK	 0x001f0000
 #define  CPMU_CLCK_STAT_MAC_CLCK_62_5	 0x00000000
@@ -1692,6 +1694,25 @@
 #define  FLASH_57780VENDOR_ATMEL_AT45DB021B 0x03400002
 #define  FLASH_57780VENDOR_ATMEL_AT45DB041D 0x00400001
 #define  FLASH_57780VENDOR_ATMEL_AT45DB041B 0x03400001
+#define  FLASH_5717VENDOR_ATMEL_EEPROM	 0x02000001
+#define  FLASH_5717VENDOR_MICRO_EEPROM	 0x02000003
+#define  FLASH_5717VENDOR_ATMEL_MDB011D	 0x01000001
+#define  FLASH_5717VENDOR_ATMEL_MDB021D	 0x01000003
+#define  FLASH_5717VENDOR_ST_M_M25PE10	 0x02000000
+#define  FLASH_5717VENDOR_ST_M_M25PE20	 0x02000002
+#define  FLASH_5717VENDOR_ST_M_M45PE10	 0x00000001
+#define  FLASH_5717VENDOR_ST_M_M45PE20	 0x00000003
+#define  FLASH_5717VENDOR_ATMEL_ADB011B	 0x01400000
+#define  FLASH_5717VENDOR_ATMEL_ADB021B	 0x01400002
+#define  FLASH_5717VENDOR_ATMEL_ADB011D	 0x01400001
+#define  FLASH_5717VENDOR_ATMEL_ADB021D	 0x01400003
+#define  FLASH_5717VENDOR_ST_A_M25PE10	 0x02400000
+#define  FLASH_5717VENDOR_ST_A_M25PE20	 0x02400002
+#define  FLASH_5717VENDOR_ST_A_M45PE10	 0x02400001
+#define  FLASH_5717VENDOR_ST_A_M45PE20	 0x02400003
+#define  FLASH_5717VENDOR_ATMEL_45USPT	 0x03400000
+#define  FLASH_5717VENDOR_ST_25USPT	 0x03400002
+#define  FLASH_5717VENDOR_ST_45USPT	 0x03400001
 #define  NVRAM_CFG1_5752PAGE_SIZE_MASK	 0x70000000
 #define  FLASH_5752PAGE_SIZE_256	 0x00000000
 #define  FLASH_5752PAGE_SIZE_512	 0x10000000
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 18/18] tg3: Update version to 3.102
From: Matt Carlson @ 2009-09-01 23:22 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch updates the tg3 version to 3.102.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index a7eb6a0..b669b6f 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -68,8 +68,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.101"
-#define DRV_MODULE_RELDATE	"August 28, 2009"
+#define DRV_MODULE_VERSION	"3.102"
+#define DRV_MODULE_RELDATE	"September 1, 2009"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 10/18] tg3: Enable NAPI instances for other int vectors
From: Matt Carlson @ 2009-09-01 23:10 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch adds code to enable and disable the rest of the NAPI
instances.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   32 +++++++++++++++++++++++---------
 1 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 2e0f4a5..ad0fc5d 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -694,25 +694,39 @@ static void tg3_int_reenable(struct tg3_napi *tnapi)
 		     HOSTCC_MODE_ENABLE | tnapi->coal_now);
 }
 
+static void tg3_napi_disable(struct tg3 *tp)
+{
+	int i;
+
+	for (i = tp->irq_cnt - 1; i >= 0; i--)
+		napi_disable(&tp->napi[i].napi);
+}
+
+static void tg3_napi_enable(struct tg3 *tp)
+{
+	int i;
+
+	for (i = 0; i < tp->irq_cnt; i++)
+		napi_enable(&tp->napi[i].napi);
+}
+
 static inline void tg3_netif_stop(struct tg3 *tp)
 {
 	tp->dev->trans_start = jiffies;	/* prevent tx timeout */
-	napi_disable(&tp->napi[0].napi);
+	tg3_napi_disable(tp);
 	netif_tx_disable(tp->dev);
 }
 
 static inline void tg3_netif_start(struct tg3 *tp)
 {
-	struct tg3_napi *tnapi = &tp->napi[0];
-
 	/* NOTE: unconditional netif_tx_wake_all_queues is only
 	 * appropriate so long as all callers are assured to
 	 * have free tx slots (such as after tg3_init_hw)
 	 */
 	netif_tx_wake_all_queues(tp->dev);
 
-	napi_enable(&tnapi->napi);
-	tnapi->hw_status->status |= SD_STATUS_UPDATED;
+	tg3_napi_enable(tp);
+	tp->napi[0].hw_status->status |= SD_STATUS_UPDATED;
 	tg3_enable_ints(tp);
 }
 
@@ -4958,7 +4972,7 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
 		tg3_full_unlock(tp);
 		del_timer_sync(&tp->timer);
 		tp->irq_sync = 0;
-		napi_enable(&tp->napi[0].napi);
+		tg3_napi_enable(tp);
 		dev_close(tp->dev);
 		tg3_full_lock(tp, 0);
 	}
@@ -8153,7 +8167,7 @@ static int tg3_open(struct net_device *dev)
 	if (err)
 		goto err_out1;
 
-	napi_enable(&tp->napi[0].napi);
+	tg3_napi_enable(tp);
 
 	for (i = 0; i < tp->irq_cnt; i++) {
 		struct tg3_napi *tnapi = &tp->napi[i];
@@ -8240,7 +8254,7 @@ err_out3:
 	}
 
 err_out2:
-	napi_disable(&tp->napi[0].napi);
+	tg3_napi_disable(tp);
 	tg3_free_consistent(tp);
 
 err_out1:
@@ -8486,7 +8500,7 @@ static int tg3_close(struct net_device *dev)
 	int i;
 	struct tg3 *tp = netdev_priv(dev);
 
-	napi_disable(&tp->napi[0].napi);
+	tg3_napi_disable(tp);
 	cancel_work_sync(&tp->reset_task);
 
 	netif_tx_stop_all_queues(dev);
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 17/18] tg3: Add MDIO bus address assignments
From: Matt Carlson @ 2009-09-01 23:21 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

The 5717 is a dual port chip that has a shared MDIO bus design.  While
it is impossible for one function to interface with the wrong phy, that
function still needs to know which MDIO bus address to use when
interfacing with its own phy.  This patch adds code to determine which
MDIO bus address to use.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   23 +++++++++++++++++++----
 drivers/net/tg3.h |    3 +++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index bc9c13a..a7eb6a0 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -782,7 +782,7 @@ static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
 
 	*val = 0x0;
 
-	frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
+	frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
 		      MI_COM_PHY_ADDR_MASK);
 	frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
 		      MI_COM_REG_ADDR_MASK);
@@ -833,7 +833,7 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
 		udelay(80);
 	}
 
-	frame_val  = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
+	frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
 		      MI_COM_PHY_ADDR_MASK);
 	frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
 		      MI_COM_REG_ADDR_MASK);
@@ -1021,6 +1021,21 @@ static void tg3_mdio_start(struct tg3 *tp)
 	tw32_f(MAC_MI_MODE, tp->mi_mode);
 	udelay(80);
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+		u32 funcnum, is_serdes;
+
+		funcnum = tr32(TG3_CPMU_STATUS) & TG3_CPMU_STATUS_PCIE_FUNC;
+		if (funcnum)
+			tp->phy_addr = 2;
+		else
+			tp->phy_addr = 1;
+
+		is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
+		if (is_serdes)
+			tp->phy_addr += 7;
+	} else
+		tp->phy_addr = PHY_ADDR;
+
 	if ((tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) &&
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
 		tg3_mdio_config_5785(tp);
@@ -9266,7 +9281,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 		cmd->speed = tp->link_config.active_speed;
 		cmd->duplex = tp->link_config.active_duplex;
 	}
-	cmd->phy_address = PHY_ADDR;
+	cmd->phy_address = tp->phy_addr;
 	cmd->transceiver = XCVR_INTERNAL;
 	cmd->autoneg = tp->link_config.autoneg;
 	cmd->maxtxpkt = 0;
@@ -10570,7 +10585,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
 	switch(cmd) {
 	case SIOCGMIIPHY:
-		data->phy_id = PHY_ADDR;
+		data->phy_id = tp->phy_addr;
 
 		/* fallthru */
 	case SIOCGMIIREG: {
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index ea57a3a..82b45d8 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -694,6 +694,7 @@
 #define  SG_DIG_PARTNER_FULL_DUPLEX	 0x00020000 /* If !MRADV_CRC16_SELECT */
 #define  SG_DIG_PARTNER_NEXT_PAGE	 0x00010000 /* If !MRADV_CRC16_SELECT */
 #define  SG_DIG_AUTONEG_STATE_MASK	 0x00000ff0
+#define  SG_DIG_IS_SERDES		 0x00000100
 #define  SG_DIG_COMMA_DETECTOR		 0x00000008
 #define  SG_DIG_MAC_ACK_STATUS		 0x00000004
 #define  SG_DIG_AUTONEG_COMPLETE	 0x00000002
@@ -2805,6 +2806,8 @@ struct tg3 {
 	struct mii_bus			*mdio_bus;
 	int				mdio_irq[PHY_MAX_ADDR];
 
+	u8				phy_addr;
+
 	/* PHY info */
 	u32				phy_id;
 #define PHY_ID_MASK			0xfffffff0
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 14/18] tg3: Assign rx ret producer indexes by vector
From: Matt Carlson @ 2009-09-01 23:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

When RSS is enabled, the status block format changes slightly.  The
"rx_jumbo_consumer", "reserved", and "rx_mini_consumer" members get
mapped to the other three rx return ring producer indexes.  This patch
introduces a new per-interrupt member which identifies which location
in the status block a particular vector should look for return ring
updates.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   31 +++++++++++++++++++++++++++----
 drivers/net/tg3.h |    1 +
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 930229b..a2ff202 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -667,7 +667,7 @@ static inline unsigned int tg3_has_work(struct tg3_napi *tnapi)
 	}
 	/* check for RX/TX work to do */
 	if (sblk->idx[0].tx_consumer != tnapi->tx_cons ||
-	    sblk->idx[0].rx_producer != tnapi->rx_rcb_ptr)
+	    *(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr)
 		work_exists = 1;
 
 	return work_exists;
@@ -4518,7 +4518,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
 	int received;
 	struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
 
-	hw_idx = tnapi->hw_status->idx[0].rx_producer;
+	hw_idx = *(tnapi->rx_rcb_prod_idx);
 	/*
 	 * We need to order the read of hw_idx and the read of
 	 * the opaque cookie.
@@ -4649,7 +4649,7 @@ next_pkt_nopost:
 
 		/* Refresh hw_idx to see if there is new work */
 		if (sw_idx == hw_idx) {
-			hw_idx = tnapi->hw_status->idx[0].rx_producer;
+			hw_idx = *(tnapi->rx_rcb_prod_idx);
 			rmb();
 		}
 	}
@@ -4711,7 +4711,7 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
 	 * All RX "locking" is done by ensuring outside
 	 * code synchronizes with tg3->napi.poll()
 	 */
-	if (sblk->idx[0].rx_producer != tnapi->rx_rcb_ptr)
+	if (*(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr)
 		work_done += tg3_rx(tnapi, budget - work_done);
 
 	return work_done;
@@ -5896,6 +5896,7 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 
 	for (i = 0; i < tp->irq_cnt; i++) {
 		struct tg3_napi *tnapi = &tp->napi[i];
+		struct tg3_hw_status *sblk;
 
 		tnapi->hw_status = pci_alloc_consistent(tp->pdev,
 							TG3_HW_STATUS_SIZE,
@@ -5904,6 +5905,28 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 			goto err_out;
 
 		memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
+		sblk = tnapi->hw_status;
+
+		/*
+		 * When RSS is enabled, the status block format changes
+		 * slightly.  The "rx_jumbo_consumer", "reserved",
+		 * and "rx_mini_consumer" members get mapped to the
+		 * other three rx return ring producer indexes.
+		 */
+		switch (i) {
+		default:
+			tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer;
+			break;
+		case 2:
+			tnapi->rx_rcb_prod_idx = &sblk->rx_jumbo_consumer;
+			break;
+		case 3:
+			tnapi->rx_rcb_prod_idx = &sblk->reserved;
+			break;
+		case 4:
+			tnapi->rx_rcb_prod_idx = &sblk->rx_mini_consumer;
+			break;
+		}
 
 		/*
 		 * If multivector RSS is enabled, vector 0 does not handle
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 348add2..685d971 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2538,6 +2538,7 @@ struct tg3_napi {
 
 	u32				consmbox;
 	u32				rx_rcb_ptr;
+	u16				*rx_rcb_prod_idx;
 
 	struct tg3_rx_buffer_desc	*rx_rcb;
 	struct tg3_tx_buffer_desc	*tx_ring;
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 13/18] tg3: Adjust RSS ring allocation strategies
From: Matt Carlson @ 2009-09-01 23:16 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

When multivector RSS is enabled, the first interrupt vector is only used
to report link interrupts and error conditions.  This patch changes the
code so that rx and tx ring resources are not allocated for this vector.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |   31 +++++++++++++++++++++++++------
 1 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 39a8ead..930229b 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4804,7 +4804,8 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id)
 	struct tg3 *tp = tnapi->tp;
 
 	prefetch(tnapi->hw_status);
-	prefetch(&tnapi->rx_rcb[tnapi->rx_rcb_ptr]);
+	if (tnapi->rx_rcb)
+		prefetch(&tnapi->rx_rcb[tnapi->rx_rcb_ptr]);
 
 	if (likely(!tg3_irq_sync(tp)))
 		napi_schedule(&tnapi->napi);
@@ -4822,7 +4823,8 @@ static irqreturn_t tg3_msi(int irq, void *dev_id)
 	struct tg3 *tp = tnapi->tp;
 
 	prefetch(tnapi->hw_status);
-	prefetch(&tnapi->rx_rcb[tnapi->rx_rcb_ptr]);
+	if (tnapi->rx_rcb)
+		prefetch(&tnapi->rx_rcb[tnapi->rx_rcb_ptr]);
 	/*
 	 * Writing any value to intr-mbox-0 clears PCI INTA# and
 	 * chip-internal interrupt pending events.
@@ -5765,6 +5767,9 @@ static void tg3_free_rings(struct tg3 *tp)
 	for (j = 0; j < tp->irq_cnt; j++) {
 		struct tg3_napi *tnapi = &tp->napi[j];
 
+		if (!tnapi->tx_buffers)
+			continue;
+
 		for (i = 0; i < TG3_TX_RING_SIZE; ) {
 			struct tx_ring_info *txp;
 			struct sk_buff *skb;
@@ -5815,10 +5820,12 @@ static int tg3_init_rings(struct tg3 *tp)
 
 		tnapi->tx_prod = 0;
 		tnapi->tx_cons = 0;
-		memset(tnapi->tx_ring, 0, TG3_TX_RING_BYTES);
+		if (tnapi->tx_ring)
+			memset(tnapi->tx_ring, 0, TG3_TX_RING_BYTES);
 
 		tnapi->rx_rcb_ptr = 0;
-		memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
+		if (tnapi->rx_rcb)
+			memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
 	}
 
 	return tg3_rx_prodring_alloc(tp, &tp->prodring[0]);
@@ -5898,6 +5905,13 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 
 		memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
 
+		/*
+		 * If multivector RSS is enabled, vector 0 does not handle
+		 * rx or tx interrupts.  Don't allocate any resources for it.
+		 */
+		if (!i && (tp->tg3_flags3 & TG3_FLG3_ENABLE_RSS))
+			continue;
+
 		tnapi->rx_rcb = pci_alloc_consistent(tp->pdev,
 						     TG3_RX_RCB_RING_BYTES(tp),
 						     &tnapi->rx_rcb_mapping);
@@ -10166,8 +10180,13 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 	struct tg3_napi *tnapi, *rnapi;
 	struct tg3_rx_prodring_set *tpr = &tp->prodring[0];
 
-	tnapi = &tp->napi[0];
-	rnapi = &tp->napi[0];
+	if (tp->irq_cnt > 1) {
+		tnapi = &tp->napi[1];
+		rnapi = &tp->napi[1];
+	} else {
+		tnapi = &tp->napi[0];
+		rnapi = &tp->napi[0];
+	}
 	coal_now = tnapi->coal_now | rnapi->coal_now;
 
 	if (loopback_mode == TG3_MAC_LOOPBACK) {
-- 
1.6.3.3



^ permalink raw reply related

* [PATCH 15/18] tg3: Add 5717 asic rev
From: Matt Carlson @ 2009-09-01 23:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, andy

This patch adds the 5717 asic rev.

Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Benjamin Li <benli@broadcom.com>
---
 drivers/net/tg3.c |  130 +++++++++++++++++++++++++++++++++++++++++------------
 drivers/net/tg3.h |   25 +++++++---
 2 files changed, 119 insertions(+), 36 deletions(-)

diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index a2ff202..2310e56 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -111,7 +111,8 @@
  * replace things like '% foo' with '& (foo - 1)'.
  */
 #define TG3_RX_RCB_RING_SIZE(tp)	\
-	((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ?  512 : 1024)
+	(((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) && \
+	  !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) ? 512 : 1024)
 
 #define TG3_TX_RING_SIZE		512
 #define TG3_DEF_TX_RING_PENDING		(TG3_TX_RING_SIZE - 1)
@@ -733,13 +734,15 @@ static inline void tg3_netif_start(struct tg3 *tp)
 
 static void tg3_switch_clocks(struct tg3 *tp)
 {
-	u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
+	u32 clock_ctrl;
 	u32 orig_clock_ctrl;
 
 	if ((tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) ||
 	    (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
 		return;
 
+	clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
+
 	orig_clock_ctrl = clock_ctrl;
 	clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN |
 		       CLOCK_CTRL_CLKRUN_OENABLE |
@@ -1993,8 +1996,9 @@ static void tg3_frob_aux_power(struct tg3 *tp)
 	if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0)
 		return;
 
-	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714)) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
 		struct net_device *dev_peer;
 
 		dev_peer = pci_get_drvdata(tp->pdev_peer);
@@ -5211,6 +5215,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 	mss = 0;
 	if ((mss = skb_shinfo(skb)->gso_size) != 0) {
 		int tcp_opt_len, ip_tcp_len;
+		u32 hdrlen;
 
 		if (skb_header_cloned(skb) &&
 		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
@@ -5219,7 +5224,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 		}
 
 		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
-			mss |= (skb_headlen(skb) - ETH_HLEN) << 9;
+			hdrlen = skb_headlen(skb) - ETH_HLEN;
 		else {
 			struct iphdr *iph = ip_hdr(skb);
 
@@ -5228,9 +5233,17 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 
 			iph->check = 0;
 			iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
-			mss |= (ip_tcp_len + tcp_opt_len) << 9;
+			hdrlen = ip_tcp_len + tcp_opt_len;
 		}
 
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+			mss |= (hdrlen & 0xc) << 12;
+			if (hdrlen & 0x10)
+				base_flags |= 0x00000010;
+			base_flags |= (hdrlen & 0x3e0) << 5;
+		} else
+			mss |= hdrlen << 9;
+
 		base_flags |= (TXD_FLAG_CPU_PRE_DMA |
 			       TXD_FLAG_CPU_POST_DMA);
 
@@ -5258,6 +5271,10 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb,
 
 	len = skb_headlen(skb);
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+	    !mss && skb->len > ETH_DATA_LEN)
+		base_flags |= TXD_FLAG_JMB_PKT;
+
 	tg3_set_txd(tnapi, entry, mapping, len, base_flags,
 		    (skb_shinfo(skb)->nr_frags == 0) | (mss << 1));
 
@@ -6564,7 +6581,9 @@ static int tg3_chip_reset(struct tg3 *tp)
 	tg3_mdio_start(tp);
 
 	if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) &&
-	    tp->pci_chip_rev_id != CHIPREV_ID_5750_A0) {
+	    tp->pci_chip_rev_id != CHIPREV_ID_5750_A0 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) {
 		val = tr32(0x7c00);
 
 		tw32(0x7c00, val | (1 << 25));
@@ -6993,7 +7012,9 @@ static void tg3_rings_reset(struct tg3 *tp)
 
 
 	/* Disable all receive return rings but the first. */
-	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+		limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 17;
+	else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
 		limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 16;
 	else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
 		limit = NIC_SRAM_RCV_RET_RCB + TG3_BDINFO_SIZE * 4;
@@ -7197,7 +7218,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 		return err;
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) {
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) {
 		/* This value is determined during the probe time DMA
 		 * engine test, tg3_test_dma.
 		 */
@@ -7351,7 +7373,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 			     BDINFO_FLAGS_DISABLED);
 		}
 
-		val = RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT;
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
+			val = (RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT) |
+			      (RX_STD_MAX_SIZE << 2);
+		else
+			val = RX_STD_MAX_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT;
 	} else
 		val = RX_STD_MAX_SIZE_5705 << BDINFO_FLAGS_MAXLEN_SHIFT;
 
@@ -7366,6 +7392,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	tw32_rx_mbox(MAILBOX_RCV_JUMBO_PROD_IDX + TG3_64BIT_REG_LOW,
 		     tpr->rx_jmb_ptr);
 
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+		tw32(STD_REPLENISH_LWM, 32);
+		tw32(JMB_REPLENISH_LWM, 16);
+	}
+
 	tg3_rings_reset(tp);
 
 	/* Initialize MAC address and backoff seed. */
@@ -8021,6 +8052,7 @@ static int tg3_test_interrupt(struct tg3 *tp)
 	struct tg3_napi *tnapi = &tp->napi[0];
 	struct net_device *dev = tp->dev;
 	int err, i, intr_ok = 0;
+	u32 val;
 
 	if (!netif_running(dev))
 		return -ENODEV;
@@ -8029,6 +8061,16 @@ static int tg3_test_interrupt(struct tg3 *tp)
 
 	free_irq(tnapi->irq_vec, tnapi);
 
+	/*
+	 * Turn off MSI one shot mode.  Otherwise this test has no
+	 * observable way to know whether the interrupt was delivered.
+	 */
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+	    (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) {
+		val = tr32(MSGINT_MODE) | MSGINT_MODE_ONE_SHOT_DISABLE;
+		tw32(MSGINT_MODE, val);
+	}
+
 	err = request_irq(tnapi->irq_vec, tg3_test_isr,
 			  IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi);
 	if (err)
@@ -8064,8 +8106,15 @@ static int tg3_test_interrupt(struct tg3 *tp)
 	if (err)
 		return err;
 
-	if (intr_ok)
+	if (intr_ok) {
+		/* Reenable MSI one shot mode. */
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+		    (tp->tg3_flags2 & TG3_FLG2_USING_MSI)) {
+			val = tr32(MSGINT_MODE) & ~MSGINT_MODE_ONE_SHOT_DISABLE;
+			tw32(MSGINT_MODE, val);
+		}
 		return 0;
+	}
 
 	return -EIO;
 }
@@ -8350,13 +8399,13 @@ static int tg3_open(struct net_device *dev)
 			goto err_out2;
 		}
 
-		if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
-			if (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI) {
-				u32 val = tr32(PCIE_TRANSACTION_CFG);
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
+		    (tp->tg3_flags2 & TG3_FLG2_USING_MSI) &&
+		    (tp->tg3_flags2 & TG3_FLG2_1SHOT_MSI)) {
+			u32 val = tr32(PCIE_TRANSACTION_CFG);
 
-				tw32(PCIE_TRANSACTION_CFG,
-				     val | PCIE_TRANS_CFG_1SHOT_MSI);
-			}
+			tw32(PCIE_TRANSACTION_CFG,
+			     val | PCIE_TRANS_CFG_1SHOT_MSI);
 		}
 	}
 
@@ -9392,7 +9441,8 @@ static int tg3_set_tso(struct net_device *dev, u32 value)
 			    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
 			     GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
 			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
-			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+			    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
 				dev->features |= NETIF_F_TSO_ECN;
 		} else
 			dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN);
@@ -12291,8 +12341,17 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
 		u32 prod_id_asic_rev;
 
-		pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
-				      &prod_id_asic_rev);
+		if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717C ||
+		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717S ||
+		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718C ||
+		    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718S)
+			pci_read_config_dword(tp->pdev,
+					      TG3PCI_GEN2_PRODID_ASICREV,
+					      &prod_id_asic_rev);
+		else
+			pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
+					      &prod_id_asic_rev);
+
 		tp->pci_chip_rev_id = prod_id_asic_rev;
 	}
 
@@ -12430,8 +12489,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
 			       tp->misc_host_ctrl);
 
-	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
 		tp->pdev_peer = tg3_find_peer(tp);
 
 	/* Intentionally exclude ASIC_REV_5906 */
@@ -12440,7 +12500,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
 		tp->tg3_flags3 |= TG3_FLG3_5755_PLUS;
 
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
@@ -12490,8 +12551,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 
 	tp->irq_max = 1;
 
+#ifdef TG3_NAPI
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+		tp->tg3_flags |= TG3_FLAG_SUPPORT_MSIX;
+		tp->irq_max = TG3_IRQ_MAX_VECS;
+	}
+#endif
+
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
-	     (tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
+	     (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
 		tp->tg3_flags |= TG3_FLAG_JUMBO_CAPABLE;
 
 	pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
@@ -12625,7 +12694,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 		tp->write32 = tg3_write_flush_reg32;
 	}
 
-
 	if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
 	    (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
 		tp->write32_tx_mbox = tg3_write32_tx_mbox;
@@ -12684,7 +12752,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
 		tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
 
 	/* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
@@ -12762,7 +12831,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
 	    !(tp->tg3_flags3 & TG3_FLG3_PHY_IS_FET) &&
 	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
-	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780) {
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780 &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
@@ -13486,7 +13556,8 @@ static void __devinit tg3_init_link_config(struct tg3 *tp)
 
 static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
 {
-	if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
+	if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717) {
 		tp->bufmgr_config.mbuf_read_dma_low_water =
 			DEFAULT_MB_RDMA_LOW_WATER_5705;
 		tp->bufmgr_config.mbuf_mac_rx_low_water =
@@ -13925,7 +13996,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 		    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
 		     GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
 			GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
-		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 ||
+		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717)
 			dev->features |= NETIF_F_TSO_ECN;
 	}
 
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 685d971..5994476 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -46,6 +46,10 @@
 #define  TG3PCI_DEVICE_TIGON3_57788	 0x1691
 #define  TG3PCI_DEVICE_TIGON3_5785_G	 0x1699 /* GPHY */
 #define  TG3PCI_DEVICE_TIGON3_5785_F	 0x16a0 /* 10/100 only */
+#define  TG3PCI_DEVICE_TIGON3_5717C	 0x1655
+#define  TG3PCI_DEVICE_TIGON3_5717S	 0x1656
+#define  TG3PCI_DEVICE_TIGON3_5718C	 0x1665
+#define  TG3PCI_DEVICE_TIGON3_5718S	 0x1666
 /* 0x04 --> 0x64 unused */
 #define TG3PCI_MSI_DATA			0x00000064
 /* 0x66 --> 0x68 unused */
@@ -117,6 +121,7 @@
 #define   ASIC_REV_5761			 0x5761
 #define   ASIC_REV_5785			 0x5785
 #define   ASIC_REV_57780		 0x57780
+#define   ASIC_REV_5717			 0x5717
 #define  GET_CHIP_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 8)
 #define   CHIPREV_5700_AX		 0x70
 #define   CHIPREV_5700_BX		 0x71
@@ -203,20 +208,20 @@
 #define TG3PCI_MEM_WIN_BASE_ADDR	0x0000007c
 #define TG3PCI_REG_DATA			0x00000080
 #define TG3PCI_MEM_WIN_DATA		0x00000084
-#define TG3PCI_MODE_CTRL		0x00000088
-#define TG3PCI_MISC_CFG			0x0000008c
 #define TG3PCI_MISC_LOCAL_CTRL		0x00000090
 /* 0x94 --> 0x98 unused */
 #define TG3PCI_STD_RING_PROD_IDX	0x00000098 /* 64-bit */
 #define TG3PCI_RCV_RET_RING_CON_IDX	0x000000a0 /* 64-bit */
-#define TG3PCI_SND_PROD_IDX		0x000000a8 /* 64-bit */
-/* 0xb0 --> 0xb8 unused */
+/* 0xa0 --> 0xb8 unused */
 #define TG3PCI_DUAL_MAC_CTRL		0x000000b8
 #define  DUAL_MAC_CTRL_CH_MASK		 0x00000003
 #define  DUAL_MAC_CTRL_ID		 0x00000004
 #define TG3PCI_PRODID_ASICREV		0x000000bc
 #define  PROD_ID_ASIC_REV_MASK		 0x0fffffff
-/* 0xc0 --> 0x110 unused */
+/* 0xc0 --> 0xf4 unused */
+
+#define TG3PCI_GEN2_PRODID_ASICREV	0x000000f4
+/* 0xf8 --> 0x200 unused */
 
 #define TG3_CORR_ERR_STAT		0x00000110
 #define  TG3_CORR_ERR_STAT_CLEAR	0xffffffff
@@ -972,7 +977,11 @@
 #define RCVBDI_MINI_THRESH		0x00002c14
 #define RCVBDI_STD_THRESH		0x00002c18
 #define RCVBDI_JUMBO_THRESH		0x00002c1c
-/* 0x2c20 --> 0x3000 unused */
+/* 0x2c20 --> 0x2d00 unused */
+
+#define STD_REPLENISH_LWM		0x00002d00
+#define JMB_REPLENISH_LWM		0x00002d04
+/* 0x2d08 --> 0x3000 unused */
 
 /* Receive BD Completion Control Registers */
 #define RCVCC_MODE			0x00003000
@@ -1486,6 +1495,7 @@
 #define MSGINT_MODE			0x00006000
 #define  MSGINT_MODE_RESET		 0x00000001
 #define  MSGINT_MODE_ENABLE		 0x00000002
+#define  MSGINT_MODE_ONE_SHOT_DISABLE	 0x00000020
 #define  MSGINT_MODE_MULTIVEC_EN	 0x00000080
 #define MSGINT_STATUS			0x00006004
 #define MSGINT_FIFO			0x00006008
@@ -2124,6 +2134,7 @@ struct tg3_tx_buffer_desc {
 #define TXD_FLAG_IP_CSUM		0x0002
 #define TXD_FLAG_END			0x0004
 #define TXD_FLAG_IP_FRAG		0x0008
+#define TXD_FLAG_JMB_PKT		0x0008
 #define TXD_FLAG_IP_FRAG_END		0x0010
 #define TXD_FLAG_VLAN			0x0040
 #define TXD_FLAG_COAL_NOW		0x0080
@@ -2520,7 +2531,7 @@ struct tg3_rx_prodring_set {
 	dma_addr_t			rx_jmb_mapping;
 };
 
-#define TG3_IRQ_MAX_VECS 1
+#define TG3_IRQ_MAX_VECS 5
 
 struct tg3_napi {
 	struct napi_struct		napi	____cacheline_aligned;
-- 
1.6.3.3



^ permalink raw reply related

* Re: Receive side performance issue with multi-10-GigE and NUMA
From: Bill Fink @ 2009-09-02  5:11 UTC (permalink / raw)
  To: Neil Horman; +Cc: Linux Network Developers, brice, gallatin
In-Reply-To: <20090827175151.GC4762@hmsreliant.think-freely.org>

On Thu, 27 Aug 2009, Neil Horman wrote:

> On Thu, Aug 27, 2009 at 01:44:29PM -0400, Bill Fink wrote:
> > On Wed, 26 Aug 2009, Neil Horman wrote:
> > 
> > > On Wed, Aug 26, 2009 at 07:00:13AM -0400, Neil Horman wrote:
> > > > On Wed, Aug 26, 2009 at 03:10:57AM -0400, Bill Fink wrote:
> > > > 
> > > > > Fortunately, in this specific case, the SuperMicro X8DAH+-F system
> > > > > does have a serial console, and after a fair amount of effort I was
> > > > > able to get it to work as desired, and was able to finally capture
> > > > > a backtrace of the kernel oops.  BTW I believe the reason the
> > > > > kexec/kdump didn't work was probably because it couldn't find
> > > > > a /proc/vmcore file, although I don't know why that would be,
> > > > > and the Fedora 10 /etc/init.d/kdump script will then just boot
> > > > > up normally if it fails to find the /proc/vmcore file (or it's
> > > > > zero size).
> > > > > 
> > > > I take care of kdump for fedora and RHEL.  If you file a bug on this, I'd be
> > > > happy to look into it further.
> > > > 
> > > > > The following shows a simple ping test usage of the skb_sources
> > > > > tracing feature:
> > > > > 
> > > > > [root@xeontest1 tracing]# numactl --membind=1 taskset -c 4 ping -c 5 -s 1472 192.168.1.10
> > > > > PING 192.168.1.10 (192.168.1.10) 1472(1500) bytes of data.
> > > > > 1480 bytes from 192.168.1.10: icmp_seq=1 ttl=64 time=0.139 ms
> > > > > 1480 bytes from 192.168.1.10: icmp_seq=2 ttl=64 time=0.182 ms
> > > > > 1480 bytes from 192.168.1.10: icmp_seq=3 ttl=64 time=0.178 ms
> > > > > 1480 bytes from 192.168.1.10: icmp_seq=4 ttl=64 time=0.188 ms
> > > > > 1480 bytes from 192.168.1.10: icmp_seq=5 ttl=64 time=0.178 ms
> > > > > 
> > > > > --- 192.168.1.10 ping statistics ---
> > > > > 5 packets transmitted, 5 received, 0% packet loss, time 3999ms
> > > > > rtt min/avg/max/mdev = 0.139/0.173/0.188/0.017 ms
> > > > > 
> > > > > [root@xeontest1 tracing]# cat trace
> > > > > # tracer: skb_sources
> > > > > #
> > > > > #       PID     ANID    CNID    IFC     RXQ     CCPU    LEN
> > > > > #        |       |       |       |       |       |       |
> > > > >         4217    1       1       eth2    0       4       1500
> > > > >         4217    1       1       eth2    0       4       1500
> > > > >         4217    1       1       eth2    0       4       1500
> > > > >         4217    1       1       eth2    0       4       1500
> > > > >         4217    1       1       eth2    0       4       1500
> > > > > 
> > > > > All is as was expected.
> > > > > 
> > > > > But if I try an actual nuttcp performance test (even rate limited
> > > > > to 1 Mbps), I get the following kernel oops:
> > > > > 
> > > > thank you, I think I see the problem, I'll have a patch for you in just a bit
> > > > 
> > > > Thanks
> > > > Neil
> > > > 
> > > > > [root@xeontest1 tracing]# numactl --membind=1 nuttcp -In2 -Ri1m -xc4/0 192.168.1.10
> > > > > BUG: unable to handle kernel NULL pointer dereference at 0000000000000038
> > > > > IP: [<ffffffff810b01ab>] probe_skb_dequeue+0xf7/0x152
> > > > > PGD 337d12067 PUD 337d11067 PMD 0
> > > > > Oops: 0000 [#1] SMP
> > > > > last sysfs file: /sys/devices/pci0000:80/0000:80:07.0/0000:8b:00.0/0000:8c:04.0e
> > > > > CPU 4
> > > > > Modules linked in: w83627ehf hwmon_vid coretemp hwmon ipv6 dm_multipath uinput ]
> > > > > Pid: 4222, comm: nuttcp Not tainted 2.6.31-rc6-bf #3 X8DAH
> > > > > RIP: 0010:[<ffffffff810b01ab>]  [<ffffffff810b01ab>] probe_skb_dequeue+0xf7/0x12
> > > > > RSP: 0018:ffff8801a5811a88  EFLAGS: 00010213
> > > > > RAX: 0000000000000000 RBX: ffff88033906d154 RCX: 000000000000000d
> > > > > RDX: 000000000000f88c RSI: 000000000000000b RDI: ffff8803383d3044
> > > > > RBP: ffff8801a5811ab8 R08: 0000000000000001 R09: ffff8801ab311a00
> > > > > R10: 0000000000000005 R11: ffffc9000080e2b0 R12: ffff880337c45400
> > > > > R13: ffff88033906d150 R14: 0000000000000014 R15: ffffffff818bb890
> > > > > FS:  00007fa976d326f0(0000) GS:ffffc90000800000(0000) knlGS:0000000000000000
> > > > > CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
> > > > > CR2: 0000000000000038 CR3: 000000033801e000 CR4: 00000000000006e0
> > > > > DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> > > > > DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> > > > > Process nuttcp (pid: 4222, threadinfo ffff8801a5810000, task ffff8801ab2e5d00)
> > > > > Stack:
> > > > >  ffff8801a5811ab8 ffff8801b35d4ab0 0000000000000014 0000000000000000
> > > > > <0> 0000000000000014 0000000000000014 ffff8801a5811b18 ffffffff81366ae8
> > > > > <0> ffff8801a5811ed8 0000001439084000 ffff880337c45400 00000001001416ef
> > > > > Call Trace:
> > > > >  [<ffffffff81366ae8>] skb_copy_datagram_iovec+0x50/0x1f5
> > > > >  [<ffffffff813ac875>] tcp_rcv_established+0x278/0x6db
> > > > >  [<ffffffff813b3ef5>] tcp_v4_do_rcv+0x1b8/0x366
> > > > >  [<ffffffff8135f99e>] ? release_sock+0xab/0xb4
> > > > >  [<ffffffff8136004d>] ? sk_wait_data+0xc8/0xd6
> > > > >  [<ffffffff813a32d6>] tcp_prequeue_process+0x79/0x8f
> > > > >  [<ffffffff813a455d>] tcp_recvmsg+0x4e8/0xaa0
> > > > >  [<ffffffff8135ec90>] sock_common_recvmsg+0x37/0x4c
> > > > >  [<ffffffff8135cb06>] __sock_recvmsg+0x72/0x7f
> > > > >  [<ffffffff8135cbdd>] sock_aio_read+0xca/0xda
> > > > >  [<ffffffff810d9536>] ? vma_merge+0x2a0/0x318
> > > > >  [<ffffffff810f6d4f>] do_sync_read+0xec/0x132
> > > > >  [<ffffffff81067ddc>] ? autoremove_wake_function+0x0/0x3d
> > > > >  [<ffffffff811b646c>] ? security_file_permission+0x16/0x18
> > > > >  [<ffffffff810f785c>] vfs_read+0xc0/0x107
> > > > >  [<ffffffff810f7971>] sys_read+0x4c/0x75
> > > > >  [<ffffffff81011c82>] system_call_fastpath+0x16/0x1b
> > > > > Code: 44 89 73 30 89 43 14 41 0f b7 84 24 ac 00 00 00 89 43 28 65 8b 04 25 98 e
> > > > > RIP  [<ffffffff810b01ab>] probe_skb_dequeue+0xf7/0x152
> > > > >  RSP <ffff8801a5811a88>
> > > > > CR2: 0000000000000038
> > > 
> > > 
> > > 
> > > Here  you go, I think this will fix your oops.
> > > 
> > > 
> > >     Fix NULL pointer deref in skb sources ftracer
> > >     
> > >     Its possible that skb->sk will be null in this path, so we shouldn't just assume
> > >     we can pass it to sock_net
> > >     
> > >     Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
> > > 
> > >  trace_skb_sources.c |    6 ++++--
> > >  1 file changed, 4 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/kernel/trace/trace_skb_sources.c b/kernel/trace/trace_skb_sources.c
> > > index 40eb071..8bf518f 100644
> > > --- a/kernel/trace/trace_skb_sources.c
> > > +++ b/kernel/trace/trace_skb_sources.c
> > > @@ -29,7 +29,7 @@ static void probe_skb_dequeue(const struct sk_buff *skb, int len)
> > >  	struct ring_buffer_event *event;
> > >  	struct trace_skb_event *entry;
> > >  	struct trace_array *tr = skb_trace;
> > > -	struct net_device *dev;
> > > +	struct net_device *dev = NULL;
> > >  
> > >  	if (!trace_skb_source_enabled)
> > >  		return;
> > > @@ -50,7 +50,9 @@ static void probe_skb_dequeue(const struct sk_buff *skb, int len)
> > >  	entry->event_data.rx_queue = skb->queue_mapping;
> > >  	entry->event_data.ccpu = smp_processor_id();
> > >  
> > > -	dev = dev_get_by_index(sock_net(skb->sk), skb->iif);
> > > +	if (skb->sk)
> > > +		dev = dev_get_by_index(sock_net(skb->sk), skb->iif);
> > > +
> > >  	if (dev) {
> > >  		memcpy(entry->event_data.ifname, dev->name, IFNAMSIZ);
> > >  		dev_put(dev);
> > 
> > 
> > 
> > On the positive side, it did fix the oops.  But the results of the
> > skb_sources tracing was not that useful.
> > 
> > [root@xeontest1 tracing]# numactl --membind=1 nuttcp -In2 -xc4/0 192.168.1.10 & ps ax | grep nuttcp
> >  5521 ttyS0    S      0:00 nuttcp -In2 -xc4/0 192.168.1.10
> > n2: 11819.0786 MB /  10.01 sec = 9905.6427 Mbps 26 %TX 37 %RX 0 retrans 0.18 msRTT
> > 
> > First off, only 10 trace entries were made:
> > 
> > [root@xeontest1 tracing]# wc trace
> > 14 90 334 trace
> > 
> > And here they are:
> > 
> > [root@xeontest1 tracing]# cat trace
> > # tracer: skb_sources
> > #
> > #       PID     ANID    CNID    IFC     RXQ     CCPU    LEN
> > #        |       |       |       |       |       |       |
> >         5521    0       0       Unknown 0       3       888
> >         5521    0       0       Unknown 0       3       896
> >         5521    0       0       Unknown 0       3       20
> >         5521    0       0       Unknown 0       3       888
> >         5521    0       0       Unknown 0       3       896
> >         5521    0       0       Unknown 0       3       20
> >         5521    1       1       Unknown 0       4       20
> >         5521    1       1       Unknown 0       4       11
> >         5521    1       1       Unknown 0       4       540
> >         5521    1       1       Unknown 0       4       0
> > 
> > Even for these 10 entries, why is the IFC Unknown, and the LENs
> > seem to be wrong too.
> > 
> > 						-Bill
> > 
> I'm not sure why you're getting Unknown Interface names.  Nominally that
> indicates that the skb->iif value in the skb was incorrect or otherwise not set,
> which shouldn't be the case.  As for the lengths that just seems wrong.  That
> length value is taken directly from skb->len, so if its not right, it seems like
> its not getting set correctly someplace.
> 
> As you may have seen we're removing the ftrace module, and replacing it with the
> use of raw trace events.  When I have that working, I'll see if I get simmilar
> results.  I never did in my local testing of the ftrace module, but perhaps its
> related to load or something.

IIUC I should keep the first of your original three ftrace patches,
revert all the rest, and then apply your very latest patch that
augments the skb_copy_datagram_iovec TRACE_EVENT.  Do I have that
basically correct?

Then I just need to ask how do I use this new method?

						-Thanks

						-Bill

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox