cxgb3 - Add dual licensing
[linux-3.10.git] / drivers / net / cxgb3 / sge.c
index 6c77f4bab62fdc93e04d3d79ae1e665663f03550..3f2cf8a07c613a78ffe951a68b48571aec921820 100644 (file)
@@ -1,14 +1,34 @@
 /*
 /*
- * This file is part of the Chelsio T3 Ethernet driver.
- *
- * Copyright (C) 2005-2006 Chelsio Communications.  All rights reserved.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the LICENSE file included in this
- * release for licensing terms and conditions.
+ * Copyright (c) 2005-2007 Chelsio, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
  */
  */
-
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -1198,6 +1218,14 @@ static void restart_ctrlq(unsigned long data)
                     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
 }
 
                     F_SELEGRCNTX | V_EGRCNTX(q->cntxt_id));
 }
 
+/*
+ * Send a management message through control queue 0
+ */
+int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb)
+{
+       return ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb);
+}
+
 /**
  *     write_ofld_wr - write an offload work request
  *     @adap: the adapter
 /**
  *     write_ofld_wr - write an offload work request
  *     @adap: the adapter
@@ -1541,33 +1569,6 @@ static inline int rx_offload(struct t3cdev *tdev, struct sge_rspq *rq,
        return gather_idx;
 }
 
        return gather_idx;
 }
 
-/**
- *     update_tx_completed - update the number of processed Tx descriptors
- *     @qs: the queue set to update
- *     @idx: which Tx queue within the set to update
- *     @credits: number of new processed descriptors
- *     @tx_completed: accumulates credits for the queues
- *
- *     Updates the number of completed Tx descriptors for a queue set's Tx
- *     queue.  On UP systems we updated the information immediately but on
- *     MP we accumulate the credits locally and update the Tx queue when we
- *     reach a threshold to avoid cache-line bouncing.
- */
-static inline void update_tx_completed(struct sge_qset *qs, int idx,
-                                      unsigned int credits,
-                                      unsigned int tx_completed[])
-{
-#ifdef CONFIG_SMP
-       tx_completed[idx] += credits;
-       if (tx_completed[idx] > 32) {
-               qs->txq[idx].processed += tx_completed[idx];
-               tx_completed[idx] = 0;
-       }
-#else
-       qs->txq[idx].processed += credits;
-#endif
-}
-
 /**
  *     restart_tx - check whether to restart suspended Tx queues
  *     @qs: the queue set to resume
 /**
  *     restart_tx - check whether to restart suspended Tx queues
  *     @qs: the queue set to resume
@@ -1648,13 +1649,12 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
  *     handle_rsp_cntrl_info - handles control information in a response
  *     @qs: the queue set corresponding to the response
  *     @flags: the response control flags
  *     handle_rsp_cntrl_info - handles control information in a response
  *     @qs: the queue set corresponding to the response
  *     @flags: the response control flags
- *     @tx_completed: accumulates completion credits for the Tx queues
  *
  *     Handles the control information of an SGE response, such as GTS
  *     indications and completion credits for the queue set's Tx queues.
  *
  *     Handles the control information of an SGE response, such as GTS
  *     indications and completion credits for the queue set's Tx queues.
+ *     HW coalesces credits, we don't do any extra SW coalescing.
  */
  */
-static inline void handle_rsp_cntrl_info(struct sge_qset *qs, u32 flags,
-                                        unsigned int tx_completed[])
+static inline void handle_rsp_cntrl_info(struct sge_qset *qs, u32 flags)
 {
        unsigned int credits;
 
 {
        unsigned int credits;
 
@@ -1663,37 +1663,21 @@ static inline void handle_rsp_cntrl_info(struct sge_qset *qs, u32 flags,
                clear_bit(TXQ_RUNNING, &qs->txq[TXQ_ETH].flags);
 #endif
 
                clear_bit(TXQ_RUNNING, &qs->txq[TXQ_ETH].flags);
 #endif
 
-       /* ETH credits are already coalesced, return them immediately. */
        credits = G_RSPD_TXQ0_CR(flags);
        if (credits)
                qs->txq[TXQ_ETH].processed += credits;
 
        credits = G_RSPD_TXQ0_CR(flags);
        if (credits)
                qs->txq[TXQ_ETH].processed += credits;
 
+       credits = G_RSPD_TXQ2_CR(flags);
+       if (credits)
+               qs->txq[TXQ_CTRL].processed += credits;
+
 # if USE_GTS
        if (flags & F_RSPD_TXQ1_GTS)
                clear_bit(TXQ_RUNNING, &qs->txq[TXQ_OFLD].flags);
 # endif
 # if USE_GTS
        if (flags & F_RSPD_TXQ1_GTS)
                clear_bit(TXQ_RUNNING, &qs->txq[TXQ_OFLD].flags);
 # endif
-       update_tx_completed(qs, TXQ_OFLD, G_RSPD_TXQ1_CR(flags), tx_completed);
-       update_tx_completed(qs, TXQ_CTRL, G_RSPD_TXQ2_CR(flags), tx_completed);
-}
-
-/**
- *     flush_tx_completed - returns accumulated Tx completions to Tx queues
- *     @qs: the queue set to update
- *     @tx_completed: pending completion credits to return to Tx queues
- *
- *     Updates the number of completed Tx descriptors for a queue set's Tx
- *     queues with the credits pending in @tx_completed.  This does something
- *     only on MP systems as on UP systems we return the credits immediately.
- */
-static inline void flush_tx_completed(struct sge_qset *qs,
-                                     unsigned int tx_completed[])
-{
-#if defined(CONFIG_SMP)
-       if (tx_completed[TXQ_OFLD])
-               qs->txq[TXQ_OFLD].processed += tx_completed[TXQ_OFLD];
-       if (tx_completed[TXQ_CTRL])
-               qs->txq[TXQ_CTRL].processed += tx_completed[TXQ_CTRL];
-#endif
+       credits = G_RSPD_TXQ1_CR(flags);
+       if (credits)
+               qs->txq[TXQ_OFLD].processed += credits;
 }
 
 /**
 }
 
 /**
@@ -1776,7 +1760,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
        struct sge_rspq *q = &qs->rspq;
        struct rsp_desc *r = &q->desc[q->cidx];
        int budget_left = budget;
        struct sge_rspq *q = &qs->rspq;
        struct rsp_desc *r = &q->desc[q->cidx];
        int budget_left = budget;
-       unsigned int sleeping = 0, tx_completed[3] = { 0, 0, 0 };
+       unsigned int sleeping = 0;
        struct sk_buff *offload_skbs[RX_BUNDLE_SIZE];
        int ngathered = 0;
 
        struct sk_buff *offload_skbs[RX_BUNDLE_SIZE];
        int ngathered = 0;
 
@@ -1829,7 +1813,7 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
 
                if (flags & RSPD_CTRL_MASK) {
                        sleeping |= flags & RSPD_GTS_MASK;
 
                if (flags & RSPD_CTRL_MASK) {
                        sleeping |= flags & RSPD_GTS_MASK;
-                       handle_rsp_cntrl_info(qs, flags, tx_completed);
+                       handle_rsp_cntrl_info(qs, flags);
                }
 
                r++;
                }
 
                r++;
@@ -1860,7 +1844,6 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs,
                --budget_left;
        }
 
                --budget_left;
        }
 
-       flush_tx_completed(qs, tx_completed);
        deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered);
        if (sleeping)
                check_ring_db(adap, qs, sleeping);
        deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered);
        if (sleeping)
                check_ring_db(adap, qs, sleeping);
@@ -1945,7 +1928,7 @@ static int process_pure_responses(struct adapter *adap, struct sge_qset *qs,
                                  struct rsp_desc *r)
 {
        struct sge_rspq *q = &qs->rspq;
                                  struct rsp_desc *r)
 {
        struct sge_rspq *q = &qs->rspq;
-       unsigned int sleeping = 0, tx_completed[3] = { 0, 0, 0 };
+       unsigned int sleeping = 0;
 
        do {
                u32 flags = ntohl(r->flags);
 
        do {
                u32 flags = ntohl(r->flags);
@@ -1960,7 +1943,7 @@ static int process_pure_responses(struct adapter *adap, struct sge_qset *qs,
 
                if (flags & RSPD_CTRL_MASK) {
                        sleeping |= flags & RSPD_GTS_MASK;
 
                if (flags & RSPD_CTRL_MASK) {
                        sleeping |= flags & RSPD_GTS_MASK;
-                       handle_rsp_cntrl_info(qs, flags, tx_completed);
+                       handle_rsp_cntrl_info(qs, flags);
                }
 
                q->pure_rsps++;
                }
 
                q->pure_rsps++;
@@ -1970,8 +1953,6 @@ static int process_pure_responses(struct adapter *adap, struct sge_qset *qs,
                }
        } while (is_new_response(r, q) && is_pure_response(r));
 
                }
        } while (is_new_response(r, q) && is_pure_response(r));
 
-       flush_tx_completed(qs, tx_completed);
-
        if (sleeping)
                check_ring_db(adap, qs, sleeping);
 
        if (sleeping)
                check_ring_db(adap, qs, sleeping);
 
@@ -2238,14 +2219,12 @@ static irqreturn_t t3b_intr_napi(int irq, void *cookie)
        if (likely(map & 1)) {
                dev = adap->sge.qs[0].netdev;
 
        if (likely(map & 1)) {
                dev = adap->sge.qs[0].netdev;
 
-               BUG_ON(napi_is_scheduled(dev));
                if (likely(__netif_rx_schedule_prep(dev)))
                        __netif_rx_schedule(dev);
        }
        if (map & 2) {
                dev = adap->sge.qs[1].netdev;
 
                if (likely(__netif_rx_schedule_prep(dev)))
                        __netif_rx_schedule(dev);
        }
        if (map & 2) {
                dev = adap->sge.qs[1].netdev;
 
-               BUG_ON(napi_is_scheduled(dev));
                if (likely(__netif_rx_schedule_prep(dev)))
                        __netif_rx_schedule(dev);
        }
                if (likely(__netif_rx_schedule_prep(dev)))
                        __netif_rx_schedule(dev);
        }
@@ -2622,7 +2601,7 @@ void t3_sge_init(struct adapter *adap, struct sge_params *p)
                     V_LORCQDRBTHRSH(512));
        t3_write_reg(adap, A_SG_TIMER_TICK, core_ticks_per_usec(adap) / 10);
        t3_write_reg(adap, A_SG_CMDQ_CREDIT_TH, V_THRESHOLD(32) |
                     V_LORCQDRBTHRSH(512));
        t3_write_reg(adap, A_SG_TIMER_TICK, core_ticks_per_usec(adap) / 10);
        t3_write_reg(adap, A_SG_CMDQ_CREDIT_TH, V_THRESHOLD(32) |
-                    V_TIMEOUT(100 * core_ticks_per_usec(adap)));
+                    V_TIMEOUT(200 * core_ticks_per_usec(adap)));
        t3_write_reg(adap, A_SG_HI_DRB_HI_THRSH, 1000);
        t3_write_reg(adap, A_SG_HI_DRB_LO_THRSH, 256);
        t3_write_reg(adap, A_SG_LO_DRB_HI_THRSH, 1000);
        t3_write_reg(adap, A_SG_HI_DRB_HI_THRSH, 1000);
        t3_write_reg(adap, A_SG_HI_DRB_LO_THRSH, 256);
        t3_write_reg(adap, A_SG_LO_DRB_HI_THRSH, 1000);