+++ /dev/null
-From 881806bc155c0d5d78196c8bfae0ea2e76ae7386 Mon Sep 17 00:00:00 2001
-From: Vipul Pandya <vipul@chelsio.com>
-Date: Fri, 18 May 2012 15:29:24 +0530
-Subject: [PATCH 04/13] cxgb4: Detect DB FULL events and notify RDMA ULD
-
-Signed-off-by: Vipul Pandya <vipul@chelsio.com>
-Signed-off-by: Steve Wise <swise@opengridcomputing.com>
-Signed-off-by: Roland Dreier <roland@purestorage.com>
----
- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 4 +
- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 77 +++++++++++++++++++++++
- drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 7 ++
- drivers/net/ethernet/chelsio/cxgb4/sge.c | 6 ++
- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 9 +++
- 5 files changed, 103 insertions(+), 0 deletions(-)
-
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
-index 0fe1885..f91b259 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
-+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
-@@ -504,6 +504,8 @@ struct adapter {
- void **tid_release_head;
- spinlock_t tid_release_lock;
- struct work_struct tid_release_task;
-+ struct work_struct db_full_task;
-+ struct work_struct db_drop_task;
- bool tid_release_task_busy;
-
- struct dentry *debugfs_root;
-@@ -719,4 +721,6 @@ int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
- int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
- unsigned int vf, unsigned int eqid);
- int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
-+void t4_db_full(struct adapter *adapter);
-+void t4_db_dropped(struct adapter *adapter);
- #endif /* __CXGB4_H__ */
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
-index b126b98..c243f93 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
-+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
-@@ -2366,6 +2366,16 @@ unsigned int cxgb4_port_chan(const struct net_device *dev)
- }
- EXPORT_SYMBOL(cxgb4_port_chan);
-
-+unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo)
-+{
-+ struct adapter *adap = netdev2adap(dev);
-+ u32 v;
-+
-+ v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
-+ return lpfifo ? G_LP_COUNT(v) : G_HP_COUNT(v);
-+}
-+EXPORT_SYMBOL(cxgb4_dbfifo_count);
-+
- /**
- * cxgb4_port_viid - get the VI id of a port
- * @dev: the net device for the port
-@@ -2446,6 +2456,69 @@ static struct notifier_block cxgb4_netevent_nb = {
- .notifier_call = netevent_cb
- };
-
-+static void notify_rdma_uld(struct adapter *adap, enum cxgb4_control cmd)
-+{
-+ mutex_lock(&uld_mutex);
-+ if (adap->uld_handle[CXGB4_ULD_RDMA])
-+ ulds[CXGB4_ULD_RDMA].control(adap->uld_handle[CXGB4_ULD_RDMA],
-+ cmd);
-+ mutex_unlock(&uld_mutex);
-+}
-+
-+static void process_db_full(struct work_struct *work)
-+{
-+ struct adapter *adap;
-+ static int delay = 1000;
-+ u32 v;
-+
-+ adap = container_of(work, struct adapter, db_full_task);
-+
-+
-+ /* stop LLD queues */
-+
-+ notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL);
-+ do {
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(usecs_to_jiffies(delay));
-+ v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
-+ if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0)
-+ break;
-+ } while (1);
-+ notify_rdma_uld(adap, CXGB4_CONTROL_DB_EMPTY);
-+
-+
-+ /*
-+ * The more we get db full interrupts, the more we'll delay
-+ * in re-enabling db rings on queues, capped off at 200ms.
-+ */
-+ delay = min(delay << 1, 200000);
-+
-+ /* resume LLD queues */
-+}
-+
-+static void process_db_drop(struct work_struct *work)
-+{
-+ struct adapter *adap;
-+ adap = container_of(work, struct adapter, db_drop_task);
-+
-+
-+ /*
-+ * sync the PIDX values in HW and SW for LLD queues.
-+ */
-+
-+ notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
-+}
-+
-+void t4_db_full(struct adapter *adap)
-+{
-+ schedule_work(&adap->db_full_task);
-+}
-+
-+void t4_db_dropped(struct adapter *adap)
-+{
-+ schedule_work(&adap->db_drop_task);
-+}
-+
- static void uld_attach(struct adapter *adap, unsigned int uld)
- {
- void *handle;
-@@ -2649,6 +2722,8 @@ static void cxgb_down(struct adapter *adapter)
- {
- t4_intr_disable(adapter);
- cancel_work_sync(&adapter->tid_release_task);
-+ cancel_work_sync(&adapter->db_full_task);
-+ cancel_work_sync(&adapter->db_drop_task);
- adapter->tid_release_task_busy = false;
- adapter->tid_release_head = NULL;
-
-@@ -3601,6 +3676,8 @@ static int __devinit init_one(struct pci_dev *pdev,
- spin_lock_init(&adapter->tid_release_lock);
-
- INIT_WORK(&adapter->tid_release_task, process_tid_release_list);
-+ INIT_WORK(&adapter->db_full_task, process_db_full);
-+ INIT_WORK(&adapter->db_drop_task, process_db_drop);
-
- err = t4_prep_adapter(adapter);
- if (err)
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
-index b1d39b8..5cc2f27 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
-+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
-@@ -163,6 +163,12 @@ enum cxgb4_state {
- CXGB4_STATE_DETACH
- };
-
-+enum cxgb4_control {
-+ CXGB4_CONTROL_DB_FULL,
-+ CXGB4_CONTROL_DB_EMPTY,
-+ CXGB4_CONTROL_DB_DROP,
-+};
-+
- struct pci_dev;
- struct l2t_data;
- struct net_device;
-@@ -225,6 +231,7 @@ struct cxgb4_uld_info {
- int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
- int cxgb4_unregister_uld(enum cxgb4_uld type);
- int cxgb4_ofld_send(struct net_device *dev, struct sk_buff *skb);
-+unsigned int cxgb4_dbfifo_count(const struct net_device *dev, int lpfifo);
- unsigned int cxgb4_port_chan(const struct net_device *dev);
- unsigned int cxgb4_port_viid(const struct net_device *dev);
- unsigned int cxgb4_port_idx(const struct net_device *dev);
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
-index 2dae795..234c157 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
-+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
-@@ -2415,6 +2415,12 @@ void t4_sge_init(struct adapter *adap)
- RXPKTCPLMODE |
- (STAT_LEN == 128 ? EGRSTATUSPAGESIZE : 0));
-
-+ t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
-+ V_HP_INT_THRESH(5) | V_LP_INT_THRESH(5),
-+ V_HP_INT_THRESH(5) | V_LP_INT_THRESH(5));
-+ t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_ENABLE_DROP,
-+ F_ENABLE_DROP);
-+
- for (i = v = 0; i < 32; i += 4)
- v |= (PAGE_SHIFT - 10) << i;
- t4_write_reg(adap, SGE_HOST_PAGE_SIZE, v);
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
-index d1ec111..13609bf 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
-+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
-@@ -1013,6 +1013,8 @@ static void sge_intr_handler(struct adapter *adapter)
- { ERR_INVALID_CIDX_INC,
- "SGE GTS CIDX increment too large", -1, 0 },
- { ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
-+ { F_DBFIFO_LP_INT, NULL, -1, 0 },
-+ { F_DBFIFO_HP_INT, NULL, -1, 0 },
- { ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 },
- { ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0,
- "SGE IQID > 1023 received CPL for FL", -1, 0 },
-@@ -1042,6 +1044,12 @@ static void sge_intr_handler(struct adapter *adapter)
- t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32);
- }
-
-+ err = t4_read_reg(adapter, A_SGE_INT_CAUSE3);
-+ if (err & (F_DBFIFO_HP_INT|F_DBFIFO_LP_INT))
-+ t4_db_full(adapter);
-+ if (err & F_ERR_DROPPED_DB)
-+ t4_db_dropped(adapter);
-+
- if (t4_handle_intr_status(adapter, SGE_INT_CAUSE3, sge_intr_info) ||
- v != 0)
- t4_fatal_err(adapter);
-@@ -1513,6 +1521,7 @@ void t4_intr_enable(struct adapter *adapter)
- ERR_BAD_DB_PIDX2 | ERR_BAD_DB_PIDX1 |
- ERR_BAD_DB_PIDX0 | ERR_ING_CTXT_PRIO |
- ERR_EGR_CTXT_PRIO | INGRESS_SIZE_ERR |
-+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT |
- EGRESS_SIZE_ERR);
- t4_write_reg(adapter, MYPF_REG(PL_PF_INT_ENABLE), PF_INTR_MASK);
- t4_set_reg_field(adapter, PL_INT_MAP0, 0, 1 << pf);
---
-1.7.1
-
+++ /dev/null
-From 8caa1e8446948afefdb4dd2050a465f6da777652 Mon Sep 17 00:00:00 2001
-From: Vipul Pandya <vipul@chelsio.com>
-Date: Fri, 18 May 2012 15:29:25 +0530
-Subject: [PATCH 05/13] cxgb4: Common platform specific changes for DB Drop Recovery
-
-Add platform-specific callback functions for interrupts. This is
-needed to do a single read-clear of the CAUSE register and then call
-out to platform specific functions for DB threshold interrupts and DB
-drop interrupts.
-
-Add t4_mem_win_read_len() - mem-window reads for arbitrary lengths.
-This is used to read the CIDX/PIDX values from EC contexts during DB
-drop recovery.
-
-Add t4_fwaddrspace_write() - sends addrspace write cmds to the fw.
-Needed to flush the sge eq context cache.
-
-Signed-off-by: Vipul Pandya <vipul@chelsio.com>
-Signed-off-by: Steve Wise <swise@opengridcomputing.com>
-Signed-off-by: Roland Dreier <roland@purestorage.com>
----
- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 3 +
- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 69 +++++++++++++++++++++++----
- 2 files changed, 61 insertions(+), 11 deletions(-)
-
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
-index f91b259..5f3c0a7 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
-+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
-@@ -723,4 +723,7 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
- int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
- void t4_db_full(struct adapter *adapter);
- void t4_db_dropped(struct adapter *adapter);
-+int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len);
-+int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
-+ u32 addr, u32 val);
- #endif /* __CXGB4_H__ */
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
-index 13609bf..32e1dd5 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
-+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
-@@ -868,11 +868,14 @@ int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port)
- return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
- }
-
-+typedef void (*int_handler_t)(struct adapter *adap);
-+
- struct intr_info {
- unsigned int mask; /* bits to check in interrupt status */
- const char *msg; /* message to print or NULL */
- short stat_idx; /* stat counter to increment or -1 */
- unsigned short fatal; /* whether the condition reported is fatal */
-+ int_handler_t int_handler; /* platform-specific int handler */
- };
-
- /**
-@@ -905,6 +908,8 @@ static int t4_handle_intr_status(struct adapter *adapter, unsigned int reg,
- } else if (acts->msg && printk_ratelimit())
- dev_warn(adapter->pdev_dev, "%s (0x%x)\n", acts->msg,
- status & acts->mask);
-+ if (acts->int_handler)
-+ acts->int_handler(adapter);
- mask |= acts->mask;
- }
- status &= mask;
-@@ -1013,9 +1018,9 @@ static void sge_intr_handler(struct adapter *adapter)
- { ERR_INVALID_CIDX_INC,
- "SGE GTS CIDX increment too large", -1, 0 },
- { ERR_CPL_OPCODE_0, "SGE received 0-length CPL", -1, 0 },
-- { F_DBFIFO_LP_INT, NULL, -1, 0 },
-- { F_DBFIFO_HP_INT, NULL, -1, 0 },
-- { ERR_DROPPED_DB, "SGE doorbell dropped", -1, 0 },
-+ { F_DBFIFO_LP_INT, NULL, -1, 0, t4_db_full },
-+ { F_DBFIFO_HP_INT, NULL, -1, 0, t4_db_full },
-+ { F_ERR_DROPPED_DB, NULL, -1, 0, t4_db_dropped },
- { ERR_DATA_CPL_ON_HIGH_QID1 | ERR_DATA_CPL_ON_HIGH_QID0,
- "SGE IQID > 1023 received CPL for FL", -1, 0 },
- { ERR_BAD_DB_PIDX3, "SGE DBP 3 pidx increment too large", -1,
-@@ -1036,20 +1041,14 @@ static void sge_intr_handler(struct adapter *adapter)
- };
-
- v = (u64)t4_read_reg(adapter, SGE_INT_CAUSE1) |
-- ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32);
-+ ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2) << 32);
- if (v) {
- dev_alert(adapter->pdev_dev, "SGE parity error (%#llx)\n",
-- (unsigned long long)v);
-+ (unsigned long long)v);
- t4_write_reg(adapter, SGE_INT_CAUSE1, v);
- t4_write_reg(adapter, SGE_INT_CAUSE2, v >> 32);
- }
-
-- err = t4_read_reg(adapter, A_SGE_INT_CAUSE3);
-- if (err & (F_DBFIFO_HP_INT|F_DBFIFO_LP_INT))
-- t4_db_full(adapter);
-- if (err & F_ERR_DROPPED_DB)
-- t4_db_dropped(adapter);
--
- if (t4_handle_intr_status(adapter, SGE_INT_CAUSE3, sge_intr_info) ||
- v != 0)
- t4_fatal_err(adapter);
-@@ -1995,6 +1994,54 @@ int t4_wol_pat_enable(struct adapter *adap, unsigned int port, unsigned int map,
- (var).retval_len16 = htonl(FW_LEN16(var)); \
- } while (0)
-
-+int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
-+ u32 addr, u32 val)
-+{
-+ struct fw_ldst_cmd c;
-+
-+ memset(&c, 0, sizeof(c));
-+ c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST |
-+ F_FW_CMD_WRITE |
-+ V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE));
-+ c.cycles_to_len16 = htonl(FW_LEN16(c));
-+ c.u.addrval.addr = htonl(addr);
-+ c.u.addrval.val = htonl(val);
-+
-+ return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
-+}
-+
-+/*
-+ * t4_mem_win_read_len - read memory through PCIE memory window
-+ * @adap: the adapter
-+ * @addr: address of first byte requested aligned on 32b.
-+ * @data: len bytes to hold the data read
-+ * @len: amount of data to read from window. Must be <=
-+ * MEMWIN0_APERATURE after adjusting for 16B alignment
-+ * requirements of the the memory window.
-+ *
-+ * Read len bytes of data from MC starting at @addr.
-+ */
-+int t4_mem_win_read_len(struct adapter *adap, u32 addr, __be32 *data, int len)
-+{
-+ int i;
-+ int off;
-+
-+ /*
-+ * Align on a 16B boundary.
-+ */
-+ off = addr & 15;
-+ if ((addr & 3) || (len + off) > MEMWIN0_APERTURE)
-+ return -EINVAL;
-+
-+ t4_write_reg(adap, A_PCIE_MEM_ACCESS_OFFSET, addr & ~15);
-+ t4_read_reg(adap, A_PCIE_MEM_ACCESS_OFFSET);
-+
-+ for (i = 0; i < len; i += 4)
-+ *data++ = t4_read_reg(adap, (MEMWIN0_BASE + off + i));
-+
-+ return 0;
-+}
-+
- /**
- * t4_mdio_rd - read a PHY register through MDIO
- * @adap: the adapter
---
-1.7.1
-
+++ /dev/null
-From 3069ee9bc451d90a2fa8c3c7ef2774744d9d3bb0 Mon Sep 17 00:00:00 2001
-From: Vipul Pandya <vipul@chelsio.com>
-Date: Fri, 18 May 2012 15:29:26 +0530
-Subject: [PATCH 06/13] cxgb4: DB Drop Recovery for RDMA and LLD queues
-
-recover LLD EQs for DB drop interrupts. This includes adding a new
-db_lock, a spin lock disabling BH too, used by the recovery thread and
-the ring_tx_db() paths to allow db drop recovery.
-
-Clean up initial DB avoidance code.
-
-Add read_eq_indices() - this allows the LLD to use the PCIe mw to
-efficiently read hw eq contexts.
-
-Add cxgb4_sync_txq_pidx() - called by iw_cxgb4 to sync up the sw/hw
-pidx value.
-
-Add flush_eq_cache() and cxgb4_flush_eq_cache(). This allows iw_cxgb4
-to flush the sge eq context cache before beginning db drop recovery.
-
-Add module parameter, dbfoifo_int_thresh, to allow tuning the db
-interrupt threshold value.
-
-Add dbfifo_int_thresh to cxgb4_lld_info so iw_cxgb4 knows the threshold.
-
-Add module parameter, dbfoifo_drain_delay, to allow tuning the amount
-of time delay between DB FULL and EMPTY upcalls to iw_cxgb4.
-
-Signed-off-by: Vipul Pandya <vipul@chelsio.com>
-Signed-off-by: Steve Wise <swise@opengridcomputing.com>
-Signed-off-by: Roland Dreier <roland@purestorage.com>
----
- drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 16 ++
- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 214 +++++++++++++++++++----
- drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 4 +
- drivers/net/ethernet/chelsio/cxgb4/sge.c | 20 ++-
- drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 53 ++++++
- drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 15 ++
- 6 files changed, 280 insertions(+), 42 deletions(-)
-
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
-index 5f3c0a7..ec2dafe 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
-+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
-@@ -51,6 +51,8 @@
- #define FW_VERSION_MINOR 1
- #define FW_VERSION_MICRO 0
-
-+#define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
-+
- enum {
- MAX_NPORTS = 4, /* max # of ports */
- SERNUM_LEN = 24, /* Serial # length */
-@@ -64,6 +66,15 @@ enum {
- MEM_MC
- };
-
-+enum {
-+ MEMWIN0_APERTURE = 65536,
-+ MEMWIN0_BASE = 0x30000,
-+ MEMWIN1_APERTURE = 32768,
-+ MEMWIN1_BASE = 0x28000,
-+ MEMWIN2_APERTURE = 2048,
-+ MEMWIN2_BASE = 0x1b800,
-+};
-+
- enum dev_master {
- MASTER_CANT,
- MASTER_MAY,
-@@ -403,6 +414,9 @@ struct sge_txq {
- struct tx_sw_desc *sdesc; /* address of SW Tx descriptor ring */
- struct sge_qstat *stat; /* queue status entry */
- dma_addr_t phys_addr; /* physical address of the ring */
-+ spinlock_t db_lock;
-+ int db_disabled;
-+ unsigned short db_pidx;
- };
-
- struct sge_eth_txq { /* state for an SGE Ethernet Tx queue */
-@@ -475,6 +489,7 @@ struct adapter {
- void __iomem *regs;
- struct pci_dev *pdev;
- struct device *pdev_dev;
-+ unsigned int mbox;
- unsigned int fn;
- unsigned int flags;
-
-@@ -607,6 +622,7 @@ irqreturn_t t4_sge_intr_msix(int irq, void *cookie);
- void t4_sge_init(struct adapter *adap);
- void t4_sge_start(struct adapter *adap);
- void t4_sge_stop(struct adapter *adap);
-+extern int dbfifo_int_thresh;
-
- #define for_each_port(adapter, iter) \
- for (iter = 0; iter < (adapter)->params.nports; ++iter)
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
-index c243f93..e1f96fb 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
-+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
-@@ -149,15 +149,6 @@ static unsigned int pfvfres_pmask(struct adapter *adapter,
- #endif
-
- enum {
-- MEMWIN0_APERTURE = 65536,
-- MEMWIN0_BASE = 0x30000,
-- MEMWIN1_APERTURE = 32768,
-- MEMWIN1_BASE = 0x28000,
-- MEMWIN2_APERTURE = 2048,
-- MEMWIN2_BASE = 0x1b800,
--};
--
--enum {
- MAX_TXQ_ENTRIES = 16384,
- MAX_CTRL_TXQ_ENTRIES = 1024,
- MAX_RSPQ_ENTRIES = 16384,
-@@ -371,6 +362,15 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
- uhash | mhash, sleep);
- }
-
-+int dbfifo_int_thresh = 10; /* 10 == 640 entry threshold */
-+module_param(dbfifo_int_thresh, int, 0644);
-+MODULE_PARM_DESC(dbfifo_int_thresh, "doorbell fifo interrupt threshold");
-+
-+int dbfifo_drain_delay = 1000; /* usecs to sleep while draining the dbfifo */
-+module_param(dbfifo_drain_delay, int, 0644);
-+MODULE_PARM_DESC(dbfifo_drain_delay,
-+ "usecs to sleep while draining the dbfifo");
-+
- /*
- * Set Rx properties of a port, such as promiscruity, address filters, and MTU.
- * If @mtu is -1 it is left unchanged.
-@@ -389,6 +389,8 @@ static int set_rxmode(struct net_device *dev, int mtu, bool sleep_ok)
- return ret;
- }
-
-+static struct workqueue_struct *workq;
-+
- /**
- * link_start - enable a port
- * @dev: the port to enable
-@@ -2196,7 +2198,7 @@ static void cxgb4_queue_tid_release(struct tid_info *t, unsigned int chan,
- adap->tid_release_head = (void **)((uintptr_t)p | chan);
- if (!adap->tid_release_task_busy) {
- adap->tid_release_task_busy = true;
-- schedule_work(&adap->tid_release_task);
-+ queue_work(workq, &adap->tid_release_task);
- }
- spin_unlock_bh(&adap->tid_release_lock);
- }
-@@ -2423,6 +2425,59 @@ void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask,
- }
- EXPORT_SYMBOL(cxgb4_iscsi_init);
-
-+int cxgb4_flush_eq_cache(struct net_device *dev)
-+{
-+ struct adapter *adap = netdev2adap(dev);
-+ int ret;
-+
-+ ret = t4_fwaddrspace_write(adap, adap->mbox,
-+ 0xe1000000 + A_SGE_CTXT_CMD, 0x20000000);
-+ return ret;
-+}
-+EXPORT_SYMBOL(cxgb4_flush_eq_cache);
-+
-+static int read_eq_indices(struct adapter *adap, u16 qid, u16 *pidx, u16 *cidx)
-+{
-+ u32 addr = t4_read_reg(adap, A_SGE_DBQ_CTXT_BADDR) + 24 * qid + 8;
-+ __be64 indices;
-+ int ret;
-+
-+ ret = t4_mem_win_read_len(adap, addr, (__be32 *)&indices, 8);
-+ if (!ret) {
-+ indices = be64_to_cpu(indices);
-+ *cidx = (indices >> 25) & 0xffff;
-+ *pidx = (indices >> 9) & 0xffff;
-+ }
-+ return ret;
-+}
-+
-+int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx,
-+ u16 size)
-+{
-+ struct adapter *adap = netdev2adap(dev);
-+ u16 hw_pidx, hw_cidx;
-+ int ret;
-+
-+ ret = read_eq_indices(adap, qid, &hw_pidx, &hw_cidx);
-+ if (ret)
-+ goto out;
-+
-+ if (pidx != hw_pidx) {
-+ u16 delta;
-+
-+ if (pidx >= hw_pidx)
-+ delta = pidx - hw_pidx;
-+ else
-+ delta = size - hw_pidx + pidx;
-+ wmb();
-+ t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL),
-+ V_QID(qid) | V_PIDX(delta));
-+ }
-+out:
-+ return ret;
-+}
-+EXPORT_SYMBOL(cxgb4_sync_txq_pidx);
-+
- static struct pci_driver cxgb4_driver;
-
- static void check_neigh_update(struct neighbour *neigh)
-@@ -2456,6 +2511,95 @@ static struct notifier_block cxgb4_netevent_nb = {
- .notifier_call = netevent_cb
- };
-
-+static void drain_db_fifo(struct adapter *adap, int usecs)
-+{
-+ u32 v;
-+
-+ do {
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(usecs_to_jiffies(usecs));
-+ v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
-+ if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0)
-+ break;
-+ } while (1);
-+}
-+
-+static void disable_txq_db(struct sge_txq *q)
-+{
-+ spin_lock_irq(&q->db_lock);
-+ q->db_disabled = 1;
-+ spin_unlock_irq(&q->db_lock);
-+}
-+
-+static void enable_txq_db(struct sge_txq *q)
-+{
-+ spin_lock_irq(&q->db_lock);
-+ q->db_disabled = 0;
-+ spin_unlock_irq(&q->db_lock);
-+}
-+
-+static void disable_dbs(struct adapter *adap)
-+{
-+ int i;
-+
-+ for_each_ethrxq(&adap->sge, i)
-+ disable_txq_db(&adap->sge.ethtxq[i].q);
-+ for_each_ofldrxq(&adap->sge, i)
-+ disable_txq_db(&adap->sge.ofldtxq[i].q);
-+ for_each_port(adap, i)
-+ disable_txq_db(&adap->sge.ctrlq[i].q);
-+}
-+
-+static void enable_dbs(struct adapter *adap)
-+{
-+ int i;
-+
-+ for_each_ethrxq(&adap->sge, i)
-+ enable_txq_db(&adap->sge.ethtxq[i].q);
-+ for_each_ofldrxq(&adap->sge, i)
-+ enable_txq_db(&adap->sge.ofldtxq[i].q);
-+ for_each_port(adap, i)
-+ enable_txq_db(&adap->sge.ctrlq[i].q);
-+}
-+
-+static void sync_txq_pidx(struct adapter *adap, struct sge_txq *q)
-+{
-+ u16 hw_pidx, hw_cidx;
-+ int ret;
-+
-+ spin_lock_bh(&q->db_lock);
-+ ret = read_eq_indices(adap, (u16)q->cntxt_id, &hw_pidx, &hw_cidx);
-+ if (ret)
-+ goto out;
-+ if (q->db_pidx != hw_pidx) {
-+ u16 delta;
-+
-+ if (q->db_pidx >= hw_pidx)
-+ delta = q->db_pidx - hw_pidx;
-+ else
-+ delta = q->size - hw_pidx + q->db_pidx;
-+ wmb();
-+ t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL),
-+ V_QID(q->cntxt_id) | V_PIDX(delta));
-+ }
-+out:
-+ q->db_disabled = 0;
-+ spin_unlock_bh(&q->db_lock);
-+ if (ret)
-+ CH_WARN(adap, "DB drop recovery failed.\n");
-+}
-+static void recover_all_queues(struct adapter *adap)
-+{
-+ int i;
-+
-+ for_each_ethrxq(&adap->sge, i)
-+ sync_txq_pidx(adap, &adap->sge.ethtxq[i].q);
-+ for_each_ofldrxq(&adap->sge, i)
-+ sync_txq_pidx(adap, &adap->sge.ofldtxq[i].q);
-+ for_each_port(adap, i)
-+ sync_txq_pidx(adap, &adap->sge.ctrlq[i].q);
-+}
-+
- static void notify_rdma_uld(struct adapter *adap, enum cxgb4_control cmd)
- {
- mutex_lock(&uld_mutex);
-@@ -2468,55 +2612,41 @@ static void notify_rdma_uld(struct adapter *adap, enum cxgb4_control cmd)
- static void process_db_full(struct work_struct *work)
- {
- struct adapter *adap;
-- static int delay = 1000;
-- u32 v;
-
- adap = container_of(work, struct adapter, db_full_task);
-
--
-- /* stop LLD queues */
--
- notify_rdma_uld(adap, CXGB4_CONTROL_DB_FULL);
-- do {
-- set_current_state(TASK_UNINTERRUPTIBLE);
-- schedule_timeout(usecs_to_jiffies(delay));
-- v = t4_read_reg(adap, A_SGE_DBFIFO_STATUS);
-- if (G_LP_COUNT(v) == 0 && G_HP_COUNT(v) == 0)
-- break;
-- } while (1);
-+ drain_db_fifo(adap, dbfifo_drain_delay);
-+ t4_set_reg_field(adap, A_SGE_INT_ENABLE3,
-+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT,
-+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT);
- notify_rdma_uld(adap, CXGB4_CONTROL_DB_EMPTY);
--
--
-- /*
-- * The more we get db full interrupts, the more we'll delay
-- * in re-enabling db rings on queues, capped off at 200ms.
-- */
-- delay = min(delay << 1, 200000);
--
-- /* resume LLD queues */
- }
-
- static void process_db_drop(struct work_struct *work)
- {
- struct adapter *adap;
-- adap = container_of(work, struct adapter, db_drop_task);
-
-+ adap = container_of(work, struct adapter, db_drop_task);
-
-- /*
-- * sync the PIDX values in HW and SW for LLD queues.
-- */
--
-+ t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_DROPPED_DB, 0);
-+ disable_dbs(adap);
- notify_rdma_uld(adap, CXGB4_CONTROL_DB_DROP);
-+ drain_db_fifo(adap, 1);
-+ recover_all_queues(adap);
-+ enable_dbs(adap);
- }
-
- void t4_db_full(struct adapter *adap)
- {
-- schedule_work(&adap->db_full_task);
-+ t4_set_reg_field(adap, A_SGE_INT_ENABLE3,
-+ F_DBFIFO_HP_INT | F_DBFIFO_LP_INT, 0);
-+ queue_work(workq, &adap->db_full_task);
- }
-
- void t4_db_dropped(struct adapter *adap)
- {
-- schedule_work(&adap->db_drop_task);
-+ queue_work(workq, &adap->db_drop_task);
- }
-
- static void uld_attach(struct adapter *adap, unsigned int uld)
-@@ -2552,6 +2682,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
- lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS);
- lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL);
- lli.fw_vers = adap->params.fw_vers;
-+ lli.dbfifo_int_thresh = dbfifo_int_thresh;
-
- handle = ulds[uld].add(&lli);
- if (IS_ERR(handle)) {
-@@ -3668,6 +3799,7 @@ static int __devinit init_one(struct pci_dev *pdev,
-
- adapter->pdev = pdev;
- adapter->pdev_dev = &pdev->dev;
-+ adapter->mbox = func;
- adapter->fn = func;
- adapter->msg_enable = dflt_msg_enable;
- memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map));
-@@ -3865,6 +3997,10 @@ static int __init cxgb4_init_module(void)
- {
- int ret;
-
-+ workq = create_singlethread_workqueue("cxgb4");
-+ if (!workq)
-+ return -ENOMEM;
-+
- /* Debugfs support is optional, just warn if this fails */
- cxgb4_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
- if (!cxgb4_debugfs_root)
-@@ -3880,6 +4016,8 @@ static void __exit cxgb4_cleanup_module(void)
- {
- pci_unregister_driver(&cxgb4_driver);
- debugfs_remove(cxgb4_debugfs_root); /* NULL ok */
-+ flush_workqueue(workq);
-+ destroy_workqueue(workq);
- }
-
- module_init(cxgb4_init_module);
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
-index 5cc2f27..d79980c 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
-+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
-@@ -218,6 +218,7 @@ struct cxgb4_lld_info {
- unsigned short ucq_density; /* # of user CQs/page */
- void __iomem *gts_reg; /* address of GTS register */
- void __iomem *db_reg; /* address of kernel doorbell */
-+ int dbfifo_int_thresh; /* doorbell fifo int threshold */
- };
-
- struct cxgb4_uld_info {
-@@ -226,6 +227,7 @@ struct cxgb4_uld_info {
- int (*rx_handler)(void *handle, const __be64 *rsp,
- const struct pkt_gl *gl);
- int (*state_change)(void *handle, enum cxgb4_state new_state);
-+ int (*control)(void *handle, enum cxgb4_control control, ...);
- };
-
- int cxgb4_register_uld(enum cxgb4_uld type, const struct cxgb4_uld_info *p);
-@@ -243,4 +245,6 @@ void cxgb4_iscsi_init(struct net_device *dev, unsigned int tag_mask,
- const unsigned int *pgsz_order);
- struct sk_buff *cxgb4_pktgl_to_skb(const struct pkt_gl *gl,
- unsigned int skb_len, unsigned int pull_len);
-+int cxgb4_sync_txq_pidx(struct net_device *dev, u16 qid, u16 pidx, u16 size);
-+int cxgb4_flush_eq_cache(struct net_device *dev);
- #endif /* !__CXGB4_OFLD_H */
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
-index 234c157..e111d97 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
-+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
-@@ -767,8 +767,13 @@ static void write_sgl(const struct sk_buff *skb, struct sge_txq *q,
- static inline void ring_tx_db(struct adapter *adap, struct sge_txq *q, int n)
- {
- wmb(); /* write descriptors before telling HW */
-- t4_write_reg(adap, MYPF_REG(SGE_PF_KDOORBELL),
-- QID(q->cntxt_id) | PIDX(n));
-+ spin_lock(&q->db_lock);
-+ if (!q->db_disabled) {
-+ t4_write_reg(adap, MYPF_REG(A_SGE_PF_KDOORBELL),
-+ V_QID(q->cntxt_id) | V_PIDX(n));
-+ }
-+ q->db_pidx = q->pidx;
-+ spin_unlock(&q->db_lock);
- }
-
- /**
-@@ -2081,6 +2086,7 @@ static void init_txq(struct adapter *adap, struct sge_txq *q, unsigned int id)
- q->stops = q->restarts = 0;
- q->stat = (void *)&q->desc[q->size];
- q->cntxt_id = id;
-+ spin_lock_init(&q->db_lock);
- adap->sge.egr_map[id - adap->sge.egr_start] = q;
- }
-
-@@ -2415,9 +2421,15 @@ void t4_sge_init(struct adapter *adap)
- RXPKTCPLMODE |
- (STAT_LEN == 128 ? EGRSTATUSPAGESIZE : 0));
-
-+ /*
-+ * Set up to drop DOORBELL writes when the DOORBELL FIFO overflows
-+ * and generate an interrupt when this occurs so we can recover.
-+ */
- t4_set_reg_field(adap, A_SGE_DBFIFO_STATUS,
-- V_HP_INT_THRESH(5) | V_LP_INT_THRESH(5),
-- V_HP_INT_THRESH(5) | V_LP_INT_THRESH(5));
-+ V_HP_INT_THRESH(M_HP_INT_THRESH) |
-+ V_LP_INT_THRESH(M_LP_INT_THRESH),
-+ V_HP_INT_THRESH(dbfifo_int_thresh) |
-+ V_LP_INT_THRESH(dbfifo_int_thresh));
- t4_set_reg_field(adap, A_SGE_DOORBELL_CONTROL, F_ENABLE_DROP,
- F_ENABLE_DROP);
-
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
-index 0adc5bc..111fc32 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
-+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
-@@ -190,6 +190,59 @@
- #define SGE_DEBUG_DATA_LOW 0x10d4
- #define SGE_INGRESS_QUEUES_PER_PAGE_PF 0x10f4
-
-+#define S_LP_INT_THRESH 12
-+#define V_LP_INT_THRESH(x) ((x) << S_LP_INT_THRESH)
-+#define S_HP_INT_THRESH 28
-+#define V_HP_INT_THRESH(x) ((x) << S_HP_INT_THRESH)
-+#define A_SGE_DBFIFO_STATUS 0x10a4
-+
-+#define S_ENABLE_DROP 13
-+#define V_ENABLE_DROP(x) ((x) << S_ENABLE_DROP)
-+#define F_ENABLE_DROP V_ENABLE_DROP(1U)
-+#define A_SGE_DOORBELL_CONTROL 0x10a8
-+
-+#define A_SGE_CTXT_CMD 0x11fc
-+#define A_SGE_DBQ_CTXT_BADDR 0x1084
-+
-+#define A_SGE_PF_KDOORBELL 0x0
-+
-+#define S_QID 15
-+#define V_QID(x) ((x) << S_QID)
-+
-+#define S_PIDX 0
-+#define V_PIDX(x) ((x) << S_PIDX)
-+
-+#define M_LP_COUNT 0x7ffU
-+#define S_LP_COUNT 0
-+#define G_LP_COUNT(x) (((x) >> S_LP_COUNT) & M_LP_COUNT)
-+
-+#define M_HP_COUNT 0x7ffU
-+#define S_HP_COUNT 16
-+#define G_HP_COUNT(x) (((x) >> S_HP_COUNT) & M_HP_COUNT)
-+
-+#define A_SGE_INT_ENABLE3 0x1040
-+
-+#define S_DBFIFO_HP_INT 8
-+#define V_DBFIFO_HP_INT(x) ((x) << S_DBFIFO_HP_INT)
-+#define F_DBFIFO_HP_INT V_DBFIFO_HP_INT(1U)
-+
-+#define S_DBFIFO_LP_INT 7
-+#define V_DBFIFO_LP_INT(x) ((x) << S_DBFIFO_LP_INT)
-+#define F_DBFIFO_LP_INT V_DBFIFO_LP_INT(1U)
-+
-+#define S_DROPPED_DB 0
-+#define V_DROPPED_DB(x) ((x) << S_DROPPED_DB)
-+#define F_DROPPED_DB V_DROPPED_DB(1U)
-+
-+#define S_ERR_DROPPED_DB 18
-+#define V_ERR_DROPPED_DB(x) ((x) << S_ERR_DROPPED_DB)
-+#define F_ERR_DROPPED_DB V_ERR_DROPPED_DB(1U)
-+
-+#define A_PCIE_MEM_ACCESS_OFFSET 0x306c
-+
-+#define M_HP_INT_THRESH 0xfU
-+#define M_LP_INT_THRESH 0xfU
-+
- #define PCIE_PF_CLI 0x44
- #define PCIE_INT_CAUSE 0x3004
- #define UNXSPLCPLERR 0x20000000U
-diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
-index edcfd7e..ad53f79 100644
---- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
-+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
-@@ -1620,4 +1620,19 @@ struct fw_hdr {
- #define FW_HDR_FW_VER_MINOR_GET(x) (((x) >> 16) & 0xff)
- #define FW_HDR_FW_VER_MICRO_GET(x) (((x) >> 8) & 0xff)
- #define FW_HDR_FW_VER_BUILD_GET(x) (((x) >> 0) & 0xff)
-+
-+#define S_FW_CMD_OP 24
-+#define V_FW_CMD_OP(x) ((x) << S_FW_CMD_OP)
-+
-+#define S_FW_CMD_REQUEST 23
-+#define V_FW_CMD_REQUEST(x) ((x) << S_FW_CMD_REQUEST)
-+#define F_FW_CMD_REQUEST V_FW_CMD_REQUEST(1U)
-+
-+#define S_FW_CMD_WRITE 21
-+#define V_FW_CMD_WRITE(x) ((x) << S_FW_CMD_WRITE)
-+#define F_FW_CMD_WRITE V_FW_CMD_WRITE(1U)
-+
-+#define S_FW_LDST_CMD_ADDRSPACE 0
-+#define V_FW_LDST_CMD_ADDRSPACE(x) ((x) << S_FW_LDST_CMD_ADDRSPACE)
-+
- #endif /* _T4FW_INTERFACE_H_ */
---
-1.7.1
-
+++ /dev/null
-From 8d81ef34b249109084b2f3c4bb826d0417ef5814 Mon Sep 17 00:00:00 2001
-From: Vipul Pandya <vipul@chelsio.com>
-Date: Fri, 18 May 2012 15:29:27 +0530
-Subject: [PATCH 07/13] RDMA/cxgb4: Add debugfs RDMA memory stats
-
-Signed-off-by: Vipul Pandya <vipul@chelsio.com>
-Signed-off-by: Steve Wise <swise@opengridcomputing.com>
-Signed-off-by: Roland Dreier <roland@purestorage.com>
----
- drivers/infiniband/hw/cxgb4/device.c | 78 +++++++++++++++++++++++++++++++-
- drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 17 +++++++
- drivers/infiniband/hw/cxgb4/mem.c | 11 ++++-
- drivers/infiniband/hw/cxgb4/provider.c | 8 +++
- drivers/infiniband/hw/cxgb4/resource.c | 44 ++++++++++++++++++
- 5 files changed, 155 insertions(+), 3 deletions(-)
-
-diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
-index 6d0df6e..8483111 100644
---- a/drivers/infiniband/hw/cxgb4/device.c
-+++ b/drivers/infiniband/hw/cxgb4/device.c
-@@ -240,6 +240,62 @@ static const struct file_operations stag_debugfs_fops = {
- .llseek = default_llseek,
- };
-
-+static int stats_show(struct seq_file *seq, void *v)
-+{
-+ struct c4iw_dev *dev = seq->private;
-+
-+ seq_printf(seq, " Object: %10s %10s %10s\n", "Total", "Current", "Max");
-+ seq_printf(seq, " PDID: %10llu %10llu %10llu\n",
-+ dev->rdev.stats.pd.total, dev->rdev.stats.pd.cur,
-+ dev->rdev.stats.pd.max);
-+ seq_printf(seq, " QID: %10llu %10llu %10llu\n",
-+ dev->rdev.stats.qid.total, dev->rdev.stats.qid.cur,
-+ dev->rdev.stats.qid.max);
-+ seq_printf(seq, " TPTMEM: %10llu %10llu %10llu\n",
-+ dev->rdev.stats.stag.total, dev->rdev.stats.stag.cur,
-+ dev->rdev.stats.stag.max);
-+ seq_printf(seq, " PBLMEM: %10llu %10llu %10llu\n",
-+ dev->rdev.stats.pbl.total, dev->rdev.stats.pbl.cur,
-+ dev->rdev.stats.pbl.max);
-+ seq_printf(seq, " RQTMEM: %10llu %10llu %10llu\n",
-+ dev->rdev.stats.rqt.total, dev->rdev.stats.rqt.cur,
-+ dev->rdev.stats.rqt.max);
-+ seq_printf(seq, " OCQPMEM: %10llu %10llu %10llu\n",
-+ dev->rdev.stats.ocqp.total, dev->rdev.stats.ocqp.cur,
-+ dev->rdev.stats.ocqp.max);
-+ return 0;
-+}
-+
-+static int stats_open(struct inode *inode, struct file *file)
-+{
-+ return single_open(file, stats_show, inode->i_private);
-+}
-+
-+static ssize_t stats_clear(struct file *file, const char __user *buf,
-+ size_t count, loff_t *pos)
-+{
-+ struct c4iw_dev *dev = ((struct seq_file *)file->private_data)->private;
-+
-+ mutex_lock(&dev->rdev.stats.lock);
-+ dev->rdev.stats.pd.max = 0;
-+ dev->rdev.stats.qid.max = 0;
-+ dev->rdev.stats.stag.max = 0;
-+ dev->rdev.stats.pbl.max = 0;
-+ dev->rdev.stats.rqt.max = 0;
-+ dev->rdev.stats.ocqp.max = 0;
-+ mutex_unlock(&dev->rdev.stats.lock);
-+ return count;
-+}
-+
-+static const struct file_operations stats_debugfs_fops = {
-+ .owner = THIS_MODULE,
-+ .open = stats_open,
-+ .release = single_release,
-+ .read = seq_read,
-+ .llseek = seq_lseek,
-+ .write = stats_clear,
-+};
-+
- static int setup_debugfs(struct c4iw_dev *devp)
- {
- struct dentry *de;
-@@ -256,6 +312,12 @@ static int setup_debugfs(struct c4iw_dev *devp)
- (void *)devp, &stag_debugfs_fops);
- if (de && de->d_inode)
- de->d_inode->i_size = 4096;
-+
-+ de = debugfs_create_file("stats", S_IWUSR, devp->debugfs_root,
-+ (void *)devp, &stats_debugfs_fops);
-+ if (de && de->d_inode)
-+ de->d_inode->i_size = 4096;
-+
- return 0;
- }
-
-@@ -269,9 +331,13 @@ void c4iw_release_dev_ucontext(struct c4iw_rdev *rdev,
- list_for_each_safe(pos, nxt, &uctx->qpids) {
- entry = list_entry(pos, struct c4iw_qid_list, entry);
- list_del_init(&entry->entry);
-- if (!(entry->qid & rdev->qpmask))
-+ if (!(entry->qid & rdev->qpmask)) {
- c4iw_put_resource(&rdev->resource.qid_fifo, entry->qid,
-- &rdev->resource.qid_fifo_lock);
-+ &rdev->resource.qid_fifo_lock);
-+ mutex_lock(&rdev->stats.lock);
-+ rdev->stats.qid.cur -= rdev->qpmask + 1;
-+ mutex_unlock(&rdev->stats.lock);
-+ }
- kfree(entry);
- }
-
-@@ -332,6 +398,13 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
- goto err1;
- }
-
-+ rdev->stats.pd.total = T4_MAX_NUM_PD;
-+ rdev->stats.stag.total = rdev->lldi.vr->stag.size;
-+ rdev->stats.pbl.total = rdev->lldi.vr->pbl.size;
-+ rdev->stats.rqt.total = rdev->lldi.vr->rq.size;
-+ rdev->stats.ocqp.total = rdev->lldi.vr->ocq.size;
-+ rdev->stats.qid.total = rdev->lldi.vr->qp.size;
-+
- err = c4iw_init_resource(rdev, c4iw_num_stags(rdev), T4_MAX_NUM_PD);
- if (err) {
- printk(KERN_ERR MOD "error %d initializing resources\n", err);
-@@ -440,6 +513,7 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
- idr_init(&devp->qpidr);
- idr_init(&devp->mmidr);
- spin_lock_init(&devp->lock);
-+ mutex_init(&devp->rdev.stats.lock);
-
- if (c4iw_debugfs_root) {
- devp->debugfs_root = debugfs_create_dir(
-diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-index 1357c5b..a849074 100644
---- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-@@ -103,6 +103,22 @@ enum c4iw_rdev_flags {
- T4_FATAL_ERROR = (1<<0),
- };
-
-+struct c4iw_stat {
-+ u64 total;
-+ u64 cur;
-+ u64 max;
-+};
-+
-+struct c4iw_stats {
-+ struct mutex lock;
-+ struct c4iw_stat qid;
-+ struct c4iw_stat pd;
-+ struct c4iw_stat stag;
-+ struct c4iw_stat pbl;
-+ struct c4iw_stat rqt;
-+ struct c4iw_stat ocqp;
-+};
-+
- struct c4iw_rdev {
- struct c4iw_resource resource;
- unsigned long qpshift;
-@@ -117,6 +133,7 @@ struct c4iw_rdev {
- struct cxgb4_lld_info lldi;
- unsigned long oc_mw_pa;
- void __iomem *oc_mw_kva;
-+ struct c4iw_stats stats;
- };
-
- static inline int c4iw_fatal_error(struct c4iw_rdev *rdev)
-diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
-index 40c8353..2a87379 100644
---- a/drivers/infiniband/hw/cxgb4/mem.c
-+++ b/drivers/infiniband/hw/cxgb4/mem.c
-@@ -135,6 +135,11 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
- &rdev->resource.tpt_fifo_lock);
- if (!stag_idx)
- return -ENOMEM;
-+ mutex_lock(&rdev->stats.lock);
-+ rdev->stats.stag.cur += 32;
-+ if (rdev->stats.stag.cur > rdev->stats.stag.max)
-+ rdev->stats.stag.max = rdev->stats.stag.cur;
-+ mutex_unlock(&rdev->stats.lock);
- *stag = (stag_idx << 8) | (atomic_inc_return(&key) & 0xff);
- }
- PDBG("%s stag_state 0x%0x type 0x%0x pdid 0x%0x, stag_idx 0x%x\n",
-@@ -165,9 +170,13 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
- (rdev->lldi.vr->stag.start >> 5),
- sizeof(tpt), &tpt);
-
-- if (reset_tpt_entry)
-+ if (reset_tpt_entry) {
- c4iw_put_resource(&rdev->resource.tpt_fifo, stag_idx,
- &rdev->resource.tpt_fifo_lock);
-+ mutex_lock(&rdev->stats.lock);
-+ rdev->stats.stag.cur -= 32;
-+ mutex_unlock(&rdev->stats.lock);
-+ }
- return err;
- }
-
-diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
-index be1c18f..8d58736 100644
---- a/drivers/infiniband/hw/cxgb4/provider.c
-+++ b/drivers/infiniband/hw/cxgb4/provider.c
-@@ -190,6 +190,9 @@ static int c4iw_deallocate_pd(struct ib_pd *pd)
- PDBG("%s ibpd %p pdid 0x%x\n", __func__, pd, php->pdid);
- c4iw_put_resource(&rhp->rdev.resource.pdid_fifo, php->pdid,
- &rhp->rdev.resource.pdid_fifo_lock);
-+ mutex_lock(&rhp->rdev.stats.lock);
-+ rhp->rdev.stats.pd.cur--;
-+ mutex_unlock(&rhp->rdev.stats.lock);
- kfree(php);
- return 0;
- }
-@@ -222,6 +225,11 @@ static struct ib_pd *c4iw_allocate_pd(struct ib_device *ibdev,
- return ERR_PTR(-EFAULT);
- }
- }
-+ mutex_lock(&rhp->rdev.stats.lock);
-+ rhp->rdev.stats.pd.cur++;
-+ if (rhp->rdev.stats.pd.cur > rhp->rdev.stats.pd.max)
-+ rhp->rdev.stats.pd.max = rhp->rdev.stats.pd.cur;
-+ mutex_unlock(&rhp->rdev.stats.lock);
- PDBG("%s pdid 0x%0x ptr 0x%p\n", __func__, pdid, php);
- return &php->ibpd;
- }
-diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c
-index 407ff39..1b948d1 100644
---- a/drivers/infiniband/hw/cxgb4/resource.c
-+++ b/drivers/infiniband/hw/cxgb4/resource.c
-@@ -185,6 +185,9 @@ u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
- &rdev->resource.qid_fifo_lock);
- if (!qid)
- goto out;
-+ mutex_lock(&rdev->stats.lock);
-+ rdev->stats.qid.cur += rdev->qpmask + 1;
-+ mutex_unlock(&rdev->stats.lock);
- for (i = qid+1; i & rdev->qpmask; i++) {
- entry = kmalloc(sizeof *entry, GFP_KERNEL);
- if (!entry)
-@@ -213,6 +216,10 @@ u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
- out:
- mutex_unlock(&uctx->lock);
- PDBG("%s qid 0x%x\n", __func__, qid);
-+ mutex_lock(&rdev->stats.lock);
-+ if (rdev->stats.qid.cur > rdev->stats.qid.max)
-+ rdev->stats.qid.max = rdev->stats.qid.cur;
-+ mutex_unlock(&rdev->stats.lock);
- return qid;
- }
-
-@@ -249,6 +256,9 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
- &rdev->resource.qid_fifo_lock);
- if (!qid)
- goto out;
-+ mutex_lock(&rdev->stats.lock);
-+ rdev->stats.qid.cur += rdev->qpmask + 1;
-+ mutex_unlock(&rdev->stats.lock);
- for (i = qid+1; i & rdev->qpmask; i++) {
- entry = kmalloc(sizeof *entry, GFP_KERNEL);
- if (!entry)
-@@ -277,6 +287,10 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
- out:
- mutex_unlock(&uctx->lock);
- PDBG("%s qid 0x%x\n", __func__, qid);
-+ mutex_lock(&rdev->stats.lock);
-+ if (rdev->stats.qid.cur > rdev->stats.qid.max)
-+ rdev->stats.qid.max = rdev->stats.qid.cur;
-+ mutex_unlock(&rdev->stats.lock);
- return qid;
- }
-
-@@ -315,12 +329,22 @@ u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size)
- if (!addr)
- printk_ratelimited(KERN_WARNING MOD "%s: Out of PBL memory\n",
- pci_name(rdev->lldi.pdev));
-+ if (addr) {
-+ mutex_lock(&rdev->stats.lock);
-+ rdev->stats.pbl.cur += roundup(size, 1 << MIN_PBL_SHIFT);
-+ if (rdev->stats.pbl.cur > rdev->stats.pbl.max)
-+ rdev->stats.pbl.max = rdev->stats.pbl.cur;
-+ mutex_unlock(&rdev->stats.lock);
-+ }
- return (u32)addr;
- }
-
- void c4iw_pblpool_free(struct c4iw_rdev *rdev, u32 addr, int size)
- {
- PDBG("%s addr 0x%x size %d\n", __func__, addr, size);
-+ mutex_lock(&rdev->stats.lock);
-+ rdev->stats.pbl.cur -= roundup(size, 1 << MIN_PBL_SHIFT);
-+ mutex_unlock(&rdev->stats.lock);
- gen_pool_free(rdev->pbl_pool, (unsigned long)addr, size);
- }
-
-@@ -377,12 +401,22 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
- if (!addr)
- printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n",
- pci_name(rdev->lldi.pdev));
-+ if (addr) {
-+ mutex_lock(&rdev->stats.lock);
-+ rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT);
-+ if (rdev->stats.rqt.cur > rdev->stats.rqt.max)
-+ rdev->stats.rqt.max = rdev->stats.rqt.cur;
-+ mutex_unlock(&rdev->stats.lock);
-+ }
- return (u32)addr;
- }
-
- void c4iw_rqtpool_free(struct c4iw_rdev *rdev, u32 addr, int size)
- {
- PDBG("%s addr 0x%x size %d\n", __func__, addr, size << 6);
-+ mutex_lock(&rdev->stats.lock);
-+ rdev->stats.rqt.cur -= roundup(size << 6, 1 << MIN_RQT_SHIFT);
-+ mutex_unlock(&rdev->stats.lock);
- gen_pool_free(rdev->rqt_pool, (unsigned long)addr, size << 6);
- }
-
-@@ -433,12 +467,22 @@ u32 c4iw_ocqp_pool_alloc(struct c4iw_rdev *rdev, int size)
- {
- unsigned long addr = gen_pool_alloc(rdev->ocqp_pool, size);
- PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
-+ if (addr) {
-+ mutex_lock(&rdev->stats.lock);
-+ rdev->stats.ocqp.cur += roundup(size, 1 << MIN_OCQP_SHIFT);
-+ if (rdev->stats.ocqp.cur > rdev->stats.ocqp.max)
-+ rdev->stats.ocqp.max = rdev->stats.ocqp.cur;
-+ mutex_unlock(&rdev->stats.lock);
-+ }
- return (u32)addr;
- }
-
- void c4iw_ocqp_pool_free(struct c4iw_rdev *rdev, u32 addr, int size)
- {
- PDBG("%s addr 0x%x size %d\n", __func__, addr, size);
-+ mutex_lock(&rdev->stats.lock);
-+ rdev->stats.ocqp.cur -= roundup(size, 1 << MIN_OCQP_SHIFT);
-+ mutex_unlock(&rdev->stats.lock);
- gen_pool_free(rdev->ocqp_pool, (unsigned long)addr, size);
- }
-
---
-1.7.1
-
+++ /dev/null
-From 2c97478106880a5fb241a473252e61845a69386e Mon Sep 17 00:00:00 2001
-From: Vipul Pandya <vipul@chelsio.com>
-Date: Fri, 18 May 2012 15:29:28 +0530
-Subject: [PATCH 08/13] RDMA/cxgb4: Add DB Overflow Avoidance
-
-Get FULL/EMPTY/DROP events from LLD. On FULL event, disable normal
-user mode DB rings.
-
-Add modify_qp semantics to allow user processes to call into the
-kernel to ring doobells without overflowing.
-
-Add DB Full/Empty/Drop stats.
-
-Mark queues when created indicating the doorbell state.
-
-If we're in the middle of db overflow avoidance, then newly created
-queues should start out in this mode.
-
-Bump the C4IW_UVERBS_ABI_VERSION to 2 so the user mode library can
-know if the driver supports the kernel mode db ringing.
-
-Signed-off-by: Vipul Pandya <vipul@chelsio.com>
-Signed-off-by: Steve Wise <swise@opengridcomputing.com>
-Signed-off-by: Roland Dreier <roland@purestorage.com>
----
- drivers/infiniband/hw/cxgb4/device.c | 84 +++++++++++++++++++++++++++++--
- drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 37 ++++++++++++--
- drivers/infiniband/hw/cxgb4/qp.c | 51 +++++++++++++++++++-
- drivers/infiniband/hw/cxgb4/user.h | 2 +-
- 4 files changed, 162 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
-index 8483111..9062ed9 100644
---- a/drivers/infiniband/hw/cxgb4/device.c
-+++ b/drivers/infiniband/hw/cxgb4/device.c
-@@ -44,6 +44,12 @@ MODULE_DESCRIPTION("Chelsio T4 RDMA Driver");
- MODULE_LICENSE("Dual BSD/GPL");
- MODULE_VERSION(DRV_VERSION);
-
-+struct uld_ctx {
-+ struct list_head entry;
-+ struct cxgb4_lld_info lldi;
-+ struct c4iw_dev *dev;
-+};
-+
- static LIST_HEAD(uld_ctx_list);
- static DEFINE_MUTEX(dev_mutex);
-
-@@ -263,6 +269,9 @@ static int stats_show(struct seq_file *seq, void *v)
- seq_printf(seq, " OCQPMEM: %10llu %10llu %10llu\n",
- dev->rdev.stats.ocqp.total, dev->rdev.stats.ocqp.cur,
- dev->rdev.stats.ocqp.max);
-+ seq_printf(seq, " DB FULL: %10llu\n", dev->rdev.stats.db_full);
-+ seq_printf(seq, " DB EMPTY: %10llu\n", dev->rdev.stats.db_empty);
-+ seq_printf(seq, " DB DROP: %10llu\n", dev->rdev.stats.db_drop);
- return 0;
- }
-
-@@ -283,6 +292,9 @@ static ssize_t stats_clear(struct file *file, const char __user *buf,
- dev->rdev.stats.pbl.max = 0;
- dev->rdev.stats.rqt.max = 0;
- dev->rdev.stats.ocqp.max = 0;
-+ dev->rdev.stats.db_full = 0;
-+ dev->rdev.stats.db_empty = 0;
-+ dev->rdev.stats.db_drop = 0;
- mutex_unlock(&dev->rdev.stats.lock);
- return count;
- }
-@@ -443,12 +455,6 @@ static void c4iw_rdev_close(struct c4iw_rdev *rdev)
- c4iw_destroy_resource(&rdev->resource);
- }
-
--struct uld_ctx {
-- struct list_head entry;
-- struct cxgb4_lld_info lldi;
-- struct c4iw_dev *dev;
--};
--
- static void c4iw_dealloc(struct uld_ctx *ctx)
- {
- c4iw_rdev_close(&ctx->dev->rdev);
-@@ -514,6 +520,7 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
- idr_init(&devp->mmidr);
- spin_lock_init(&devp->lock);
- mutex_init(&devp->rdev.stats.lock);
-+ mutex_init(&devp->db_mutex);
-
- if (c4iw_debugfs_root) {
- devp->debugfs_root = debugfs_create_dir(
-@@ -659,11 +666,76 @@ static int c4iw_uld_state_change(void *handle, enum cxgb4_state new_state)
- return 0;
- }
-
-+static int disable_qp_db(int id, void *p, void *data)
-+{
-+ struct c4iw_qp *qp = p;
-+
-+ t4_disable_wq_db(&qp->wq);
-+ return 0;
-+}
-+
-+static void stop_queues(struct uld_ctx *ctx)
-+{
-+ spin_lock_irq(&ctx->dev->lock);
-+ ctx->dev->db_state = FLOW_CONTROL;
-+ idr_for_each(&ctx->dev->qpidr, disable_qp_db, NULL);
-+ spin_unlock_irq(&ctx->dev->lock);
-+}
-+
-+static int enable_qp_db(int id, void *p, void *data)
-+{
-+ struct c4iw_qp *qp = p;
-+
-+ t4_enable_wq_db(&qp->wq);
-+ return 0;
-+}
-+
-+static void resume_queues(struct uld_ctx *ctx)
-+{
-+ spin_lock_irq(&ctx->dev->lock);
-+ ctx->dev->db_state = NORMAL;
-+ idr_for_each(&ctx->dev->qpidr, enable_qp_db, NULL);
-+ spin_unlock_irq(&ctx->dev->lock);
-+}
-+
-+static int c4iw_uld_control(void *handle, enum cxgb4_control control, ...)
-+{
-+ struct uld_ctx *ctx = handle;
-+
-+ switch (control) {
-+ case CXGB4_CONTROL_DB_FULL:
-+ stop_queues(ctx);
-+ mutex_lock(&ctx->dev->rdev.stats.lock);
-+ ctx->dev->rdev.stats.db_full++;
-+ mutex_unlock(&ctx->dev->rdev.stats.lock);
-+ break;
-+ case CXGB4_CONTROL_DB_EMPTY:
-+ resume_queues(ctx);
-+ mutex_lock(&ctx->dev->rdev.stats.lock);
-+ ctx->dev->rdev.stats.db_empty++;
-+ mutex_unlock(&ctx->dev->rdev.stats.lock);
-+ break;
-+ case CXGB4_CONTROL_DB_DROP:
-+ printk(KERN_WARNING MOD "%s: Fatal DB DROP\n",
-+ pci_name(ctx->lldi.pdev));
-+ mutex_lock(&ctx->dev->rdev.stats.lock);
-+ ctx->dev->rdev.stats.db_drop++;
-+ mutex_unlock(&ctx->dev->rdev.stats.lock);
-+ break;
-+ default:
-+ printk(KERN_WARNING MOD "%s: unknown control cmd %u\n",
-+ pci_name(ctx->lldi.pdev), control);
-+ break;
-+ }
-+ return 0;
-+}
-+
- static struct cxgb4_uld_info c4iw_uld_info = {
- .name = DRV_NAME,
- .add = c4iw_uld_add,
- .rx_handler = c4iw_uld_rx_handler,
- .state_change = c4iw_uld_state_change,
-+ .control = c4iw_uld_control,
- };
-
- static int __init c4iw_init_module(void)
-diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-index a849074..a11ed5c 100644
---- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-@@ -117,6 +117,9 @@ struct c4iw_stats {
- struct c4iw_stat pbl;
- struct c4iw_stat rqt;
- struct c4iw_stat ocqp;
-+ u64 db_full;
-+ u64 db_empty;
-+ u64 db_drop;
- };
-
- struct c4iw_rdev {
-@@ -192,6 +195,12 @@ static inline int c4iw_wait_for_reply(struct c4iw_rdev *rdev,
- return wr_waitp->ret;
- }
-
-+enum db_state {
-+ NORMAL = 0,
-+ FLOW_CONTROL = 1,
-+ RECOVERY = 2
-+};
-+
- struct c4iw_dev {
- struct ib_device ibdev;
- struct c4iw_rdev rdev;
-@@ -200,7 +209,9 @@ struct c4iw_dev {
- struct idr qpidr;
- struct idr mmidr;
- spinlock_t lock;
-+ struct mutex db_mutex;
- struct dentry *debugfs_root;
-+ enum db_state db_state;
- };
-
- static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev)
-@@ -228,8 +239,8 @@ static inline struct c4iw_mr *get_mhp(struct c4iw_dev *rhp, u32 mmid)
- return idr_find(&rhp->mmidr, mmid);
- }
-
--static inline int insert_handle(struct c4iw_dev *rhp, struct idr *idr,
-- void *handle, u32 id)
-+static inline int _insert_handle(struct c4iw_dev *rhp, struct idr *idr,
-+ void *handle, u32 id, int lock)
- {
- int ret;
- int newid;
-@@ -237,15 +248,29 @@ static inline int insert_handle(struct c4iw_dev *rhp, struct idr *idr,
- do {
- if (!idr_pre_get(idr, GFP_KERNEL))
- return -ENOMEM;
-- spin_lock_irq(&rhp->lock);
-+ if (lock)
-+ spin_lock_irq(&rhp->lock);
- ret = idr_get_new_above(idr, handle, id, &newid);
- BUG_ON(newid != id);
-- spin_unlock_irq(&rhp->lock);
-+ if (lock)
-+ spin_unlock_irq(&rhp->lock);
- } while (ret == -EAGAIN);
-
- return ret;
- }
-
-+static inline int insert_handle(struct c4iw_dev *rhp, struct idr *idr,
-+ void *handle, u32 id)
-+{
-+ return _insert_handle(rhp, idr, handle, id, 1);
-+}
-+
-+static inline int insert_handle_nolock(struct c4iw_dev *rhp, struct idr *idr,
-+ void *handle, u32 id)
-+{
-+ return _insert_handle(rhp, idr, handle, id, 0);
-+}
-+
- static inline void remove_handle(struct c4iw_dev *rhp, struct idr *idr, u32 id)
- {
- spin_lock_irq(&rhp->lock);
-@@ -370,6 +395,8 @@ struct c4iw_qp_attributes {
- struct c4iw_ep *llp_stream_handle;
- u8 layer_etype;
- u8 ecode;
-+ u16 sq_db_inc;
-+ u16 rq_db_inc;
- };
-
- struct c4iw_qp {
-@@ -444,6 +471,8 @@ static inline void insert_mmap(struct c4iw_ucontext *ucontext,
-
- enum c4iw_qp_attr_mask {
- C4IW_QP_ATTR_NEXT_STATE = 1 << 0,
-+ C4IW_QP_ATTR_SQ_DB = 1<<1,
-+ C4IW_QP_ATTR_RQ_DB = 1<<2,
- C4IW_QP_ATTR_ENABLE_RDMA_READ = 1 << 7,
- C4IW_QP_ATTR_ENABLE_RDMA_WRITE = 1 << 8,
- C4IW_QP_ATTR_ENABLE_RDMA_BIND = 1 << 9,
-diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
-index 5f940ae..beec667 100644
---- a/drivers/infiniband/hw/cxgb4/qp.c
-+++ b/drivers/infiniband/hw/cxgb4/qp.c
-@@ -34,6 +34,10 @@
-
- #include "iw_cxgb4.h"
-
-+static int db_delay_usecs = 1;
-+module_param(db_delay_usecs, int, 0644);
-+MODULE_PARM_DESC(db_delay_usecs, "Usecs to delay awaiting db fifo to drain");
-+
- static int ocqp_support = 1;
- module_param(ocqp_support, int, 0644);
- MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=1)");
-@@ -1128,6 +1132,29 @@ out:
- return ret;
- }
-
-+/*
-+ * Called by the library when the qp has user dbs disabled due to
-+ * a DB_FULL condition. This function will single-thread all user
-+ * DB rings to avoid overflowing the hw db-fifo.
-+ */
-+static int ring_kernel_db(struct c4iw_qp *qhp, u32 qid, u16 inc)
-+{
-+ int delay = db_delay_usecs;
-+
-+ mutex_lock(&qhp->rhp->db_mutex);
-+ do {
-+ if (cxgb4_dbfifo_count(qhp->rhp->rdev.lldi.ports[0], 1) < 768) {
-+ writel(V_QID(qid) | V_PIDX(inc), qhp->wq.db);
-+ break;
-+ }
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(usecs_to_jiffies(delay));
-+ delay = min(delay << 1, 200000);
-+ } while (1);
-+ mutex_unlock(&qhp->rhp->db_mutex);
-+ return 0;
-+}
-+
- int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
- enum c4iw_qp_attr_mask mask,
- struct c4iw_qp_attributes *attrs,
-@@ -1176,6 +1203,15 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
- qhp->attr = newattr;
- }
-
-+ if (mask & C4IW_QP_ATTR_SQ_DB) {
-+ ret = ring_kernel_db(qhp, qhp->wq.sq.qid, attrs->sq_db_inc);
-+ goto out;
-+ }
-+ if (mask & C4IW_QP_ATTR_RQ_DB) {
-+ ret = ring_kernel_db(qhp, qhp->wq.rq.qid, attrs->rq_db_inc);
-+ goto out;
-+ }
-+
- if (!(mask & C4IW_QP_ATTR_NEXT_STATE))
- goto out;
- if (qhp->attr.state == attrs->next_state)
-@@ -1469,7 +1505,11 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
- init_waitqueue_head(&qhp->wait);
- atomic_set(&qhp->refcnt, 1);
-
-- ret = insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
-+ spin_lock_irq(&rhp->lock);
-+ if (rhp->db_state != NORMAL)
-+ t4_disable_wq_db(&qhp->wq);
-+ ret = insert_handle_nolock(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
-+ spin_unlock_irq(&rhp->lock);
- if (ret)
- goto err2;
-
-@@ -1613,6 +1653,15 @@ int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
- C4IW_QP_ATTR_ENABLE_RDMA_WRITE |
- C4IW_QP_ATTR_ENABLE_RDMA_BIND) : 0;
-
-+ /*
-+ * Use SQ_PSN and RQ_PSN to pass in IDX_INC values for
-+ * ringing the queue db when we're in DB_FULL mode.
-+ */
-+ attrs.sq_db_inc = attr->sq_psn;
-+ attrs.rq_db_inc = attr->rq_psn;
-+ mask |= (attr_mask & IB_QP_SQ_PSN) ? C4IW_QP_ATTR_SQ_DB : 0;
-+ mask |= (attr_mask & IB_QP_RQ_PSN) ? C4IW_QP_ATTR_RQ_DB : 0;
-+
- return c4iw_modify_qp(rhp, qhp, mask, &attrs, 0);
- }
-
-diff --git a/drivers/infiniband/hw/cxgb4/user.h b/drivers/infiniband/hw/cxgb4/user.h
-index e6669d5..32b754c 100644
---- a/drivers/infiniband/hw/cxgb4/user.h
-+++ b/drivers/infiniband/hw/cxgb4/user.h
-@@ -32,7 +32,7 @@
- #ifndef __C4IW_USER_H__
- #define __C4IW_USER_H__
-
--#define C4IW_UVERBS_ABI_VERSION 1
-+#define C4IW_UVERBS_ABI_VERSION 2
-
- /*
- * Make sure that all structs defined in this file remain laid out so
---
-1.7.1
-
+++ /dev/null
-From 4984037bef54253d4d010d3e57f175ab694bee26 Mon Sep 17 00:00:00 2001
-From: Vipul Pandya <vipul@chelsio.com>
-Date: Fri, 18 May 2012 15:29:29 +0530
-Subject: [PATCH 09/13] RDMA/cxgb4: Disable interrupts in c4iw_ev_dispatch()
-
-Use GFP_ATOMIC in _insert_handle() if ints are disabled.
-
-Don't panic if we get an abort with no endpoint found. Just log a
-warning.
-
-Signed-off-by: Vipul Pandya <vipul@chelsio.com>
-Signed-off-by: Steve Wise <swise@opengridcomputing.com>
-Signed-off-by: Roland Dreier <roland@purestorage.com>
----
- drivers/infiniband/hw/cxgb4/cm.c | 5 ++++-
- drivers/infiniband/hw/cxgb4/ev.c | 8 ++++----
- drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 2 +-
- 3 files changed, 9 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
-index 4c7c62f..6ce401a 100644
---- a/drivers/infiniband/hw/cxgb4/cm.c
-+++ b/drivers/infiniband/hw/cxgb4/cm.c
-@@ -1362,7 +1362,10 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
-
- ep = lookup_tid(t, tid);
- PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
-- BUG_ON(!ep);
-+ if (!ep) {
-+ printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n");
-+ return 0;
-+ }
- mutex_lock(&ep->com.mutex);
- switch (ep->com.state) {
- case ABORTING:
-diff --git a/drivers/infiniband/hw/cxgb4/ev.c b/drivers/infiniband/hw/cxgb4/ev.c
-index 397cb36..cf2f6b4 100644
---- a/drivers/infiniband/hw/cxgb4/ev.c
-+++ b/drivers/infiniband/hw/cxgb4/ev.c
-@@ -84,7 +84,7 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
- struct c4iw_qp *qhp;
- u32 cqid;
-
-- spin_lock(&dev->lock);
-+ spin_lock_irq(&dev->lock);
- qhp = get_qhp(dev, CQE_QPID(err_cqe));
- if (!qhp) {
- printk(KERN_ERR MOD "BAD AE qpid 0x%x opcode %d "
-@@ -93,7 +93,7 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
- CQE_OPCODE(err_cqe), CQE_STATUS(err_cqe),
- CQE_TYPE(err_cqe), CQE_WRID_HI(err_cqe),
- CQE_WRID_LOW(err_cqe));
-- spin_unlock(&dev->lock);
-+ spin_unlock_irq(&dev->lock);
- goto out;
- }
-
-@@ -109,13 +109,13 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
- CQE_OPCODE(err_cqe), CQE_STATUS(err_cqe),
- CQE_TYPE(err_cqe), CQE_WRID_HI(err_cqe),
- CQE_WRID_LOW(err_cqe));
-- spin_unlock(&dev->lock);
-+ spin_unlock_irq(&dev->lock);
- goto out;
- }
-
- c4iw_qp_add_ref(&qhp->ibqp);
- atomic_inc(&chp->refcnt);
-- spin_unlock(&dev->lock);
-+ spin_unlock_irq(&dev->lock);
-
- /* Bad incoming write */
- if (RQ_TYPE(err_cqe) &&
-diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-index a11ed5c..e8b88a0 100644
---- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-@@ -246,7 +246,7 @@ static inline int _insert_handle(struct c4iw_dev *rhp, struct idr *idr,
- int newid;
-
- do {
-- if (!idr_pre_get(idr, GFP_KERNEL))
-+ if (!idr_pre_get(idr, lock ? GFP_KERNEL : GFP_ATOMIC))
- return -ENOMEM;
- if (lock)
- spin_lock_irq(&rhp->lock);
---
-1.7.1
-
+++ /dev/null
-From 422eea0a8cf658bc9564726d74e8384b89a8f4fa Mon Sep 17 00:00:00 2001
-From: Vipul Pandya <vipul@chelsio.com>
-Date: Fri, 18 May 2012 15:29:30 +0530
-Subject: [PATCH 10/13] RDMA/cxgb4: DB Drop Recovery for RDMA and LLD queues
-
-Add module option db_fc_threshold which is the count of active QPs
-that trigger automatic db flow control mode. Automatically transition
-to/from flow control mode when the active qp count crosses
-db_fc_theshold.
-
-Add more db debugfs stats
-
-On DB DROP event from the LLD, recover all the iwarp queues.
-
-Signed-off-by: Vipul Pandya <vipul@chelsio.com>
-Signed-off-by: Steve Wise <swise@opengridcomputing.com>
-Signed-off-by: Roland Dreier <roland@purestorage.com>
----
- drivers/infiniband/hw/cxgb4/device.c | 176 ++++++++++++++++++++++++++++++-
- drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 24 ++++-
- drivers/infiniband/hw/cxgb4/qp.c | 47 ++++++++-
- drivers/infiniband/hw/cxgb4/t4.h | 24 +++++
- 4 files changed, 259 insertions(+), 12 deletions(-)
-
-diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
-index 9062ed9..bdb398f 100644
---- a/drivers/infiniband/hw/cxgb4/device.c
-+++ b/drivers/infiniband/hw/cxgb4/device.c
-@@ -246,6 +246,8 @@ static const struct file_operations stag_debugfs_fops = {
- .llseek = default_llseek,
- };
-
-+static char *db_state_str[] = {"NORMAL", "FLOW_CONTROL", "RECOVERY"};
-+
- static int stats_show(struct seq_file *seq, void *v)
- {
- struct c4iw_dev *dev = seq->private;
-@@ -272,6 +274,9 @@ static int stats_show(struct seq_file *seq, void *v)
- seq_printf(seq, " DB FULL: %10llu\n", dev->rdev.stats.db_full);
- seq_printf(seq, " DB EMPTY: %10llu\n", dev->rdev.stats.db_empty);
- seq_printf(seq, " DB DROP: %10llu\n", dev->rdev.stats.db_drop);
-+ seq_printf(seq, " DB State: %s Transitions %llu\n",
-+ db_state_str[dev->db_state],
-+ dev->rdev.stats.db_state_transitions);
- return 0;
- }
-
-@@ -295,6 +300,7 @@ static ssize_t stats_clear(struct file *file, const char __user *buf,
- dev->rdev.stats.db_full = 0;
- dev->rdev.stats.db_empty = 0;
- dev->rdev.stats.db_drop = 0;
-+ dev->rdev.stats.db_state_transitions = 0;
- mutex_unlock(&dev->rdev.stats.lock);
- return count;
- }
-@@ -677,8 +683,11 @@ static int disable_qp_db(int id, void *p, void *data)
- static void stop_queues(struct uld_ctx *ctx)
- {
- spin_lock_irq(&ctx->dev->lock);
-- ctx->dev->db_state = FLOW_CONTROL;
-- idr_for_each(&ctx->dev->qpidr, disable_qp_db, NULL);
-+ if (ctx->dev->db_state == NORMAL) {
-+ ctx->dev->rdev.stats.db_state_transitions++;
-+ ctx->dev->db_state = FLOW_CONTROL;
-+ idr_for_each(&ctx->dev->qpidr, disable_qp_db, NULL);
-+ }
- spin_unlock_irq(&ctx->dev->lock);
- }
-
-@@ -693,9 +702,165 @@ static int enable_qp_db(int id, void *p, void *data)
- static void resume_queues(struct uld_ctx *ctx)
- {
- spin_lock_irq(&ctx->dev->lock);
-- ctx->dev->db_state = NORMAL;
-- idr_for_each(&ctx->dev->qpidr, enable_qp_db, NULL);
-+ if (ctx->dev->qpcnt <= db_fc_threshold &&
-+ ctx->dev->db_state == FLOW_CONTROL) {
-+ ctx->dev->db_state = NORMAL;
-+ ctx->dev->rdev.stats.db_state_transitions++;
-+ idr_for_each(&ctx->dev->qpidr, enable_qp_db, NULL);
-+ }
-+ spin_unlock_irq(&ctx->dev->lock);
-+}
-+
-+struct qp_list {
-+ unsigned idx;
-+ struct c4iw_qp **qps;
-+};
-+
-+static int add_and_ref_qp(int id, void *p, void *data)
-+{
-+ struct qp_list *qp_listp = data;
-+ struct c4iw_qp *qp = p;
-+
-+ c4iw_qp_add_ref(&qp->ibqp);
-+ qp_listp->qps[qp_listp->idx++] = qp;
-+ return 0;
-+}
-+
-+static int count_qps(int id, void *p, void *data)
-+{
-+ unsigned *countp = data;
-+ (*countp)++;
-+ return 0;
-+}
-+
-+static void deref_qps(struct qp_list qp_list)
-+{
-+ int idx;
-+
-+ for (idx = 0; idx < qp_list.idx; idx++)
-+ c4iw_qp_rem_ref(&qp_list.qps[idx]->ibqp);
-+}
-+
-+static void recover_lost_dbs(struct uld_ctx *ctx, struct qp_list *qp_list)
-+{
-+ int idx;
-+ int ret;
-+
-+ for (idx = 0; idx < qp_list->idx; idx++) {
-+ struct c4iw_qp *qp = qp_list->qps[idx];
-+
-+ ret = cxgb4_sync_txq_pidx(qp->rhp->rdev.lldi.ports[0],
-+ qp->wq.sq.qid,
-+ t4_sq_host_wq_pidx(&qp->wq),
-+ t4_sq_wq_size(&qp->wq));
-+ if (ret) {
-+ printk(KERN_ERR MOD "%s: Fatal error - "
-+ "DB overflow recovery failed - "
-+ "error syncing SQ qid %u\n",
-+ pci_name(ctx->lldi.pdev), qp->wq.sq.qid);
-+ return;
-+ }
-+
-+ ret = cxgb4_sync_txq_pidx(qp->rhp->rdev.lldi.ports[0],
-+ qp->wq.rq.qid,
-+ t4_rq_host_wq_pidx(&qp->wq),
-+ t4_rq_wq_size(&qp->wq));
-+
-+ if (ret) {
-+ printk(KERN_ERR MOD "%s: Fatal error - "
-+ "DB overflow recovery failed - "
-+ "error syncing RQ qid %u\n",
-+ pci_name(ctx->lldi.pdev), qp->wq.rq.qid);
-+ return;
-+ }
-+
-+ /* Wait for the dbfifo to drain */
-+ while (cxgb4_dbfifo_count(qp->rhp->rdev.lldi.ports[0], 1) > 0) {
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(usecs_to_jiffies(10));
-+ }
-+ }
-+}
-+
-+static void recover_queues(struct uld_ctx *ctx)
-+{
-+ int count = 0;
-+ struct qp_list qp_list;
-+ int ret;
-+
-+ /* lock out kernel db ringers */
-+ mutex_lock(&ctx->dev->db_mutex);
-+
-+ /* put all queues in to recovery mode */
-+ spin_lock_irq(&ctx->dev->lock);
-+ ctx->dev->db_state = RECOVERY;
-+ ctx->dev->rdev.stats.db_state_transitions++;
-+ idr_for_each(&ctx->dev->qpidr, disable_qp_db, NULL);
-+ spin_unlock_irq(&ctx->dev->lock);
-+
-+ /* slow everybody down */
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(usecs_to_jiffies(1000));
-+
-+ /* Wait for the dbfifo to completely drain. */
-+ while (cxgb4_dbfifo_count(ctx->dev->rdev.lldi.ports[0], 1) > 0) {
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(usecs_to_jiffies(10));
-+ }
-+
-+ /* flush the SGE contexts */
-+ ret = cxgb4_flush_eq_cache(ctx->dev->rdev.lldi.ports[0]);
-+ if (ret) {
-+ printk(KERN_ERR MOD "%s: Fatal error - DB overflow recovery failed\n",
-+ pci_name(ctx->lldi.pdev));
-+ goto out;
-+ }
-+
-+ /* Count active queues so we can build a list of queues to recover */
-+ spin_lock_irq(&ctx->dev->lock);
-+ idr_for_each(&ctx->dev->qpidr, count_qps, &count);
-+
-+ qp_list.qps = kzalloc(count * sizeof *qp_list.qps, GFP_ATOMIC);
-+ if (!qp_list.qps) {
-+ printk(KERN_ERR MOD "%s: Fatal error - DB overflow recovery failed\n",
-+ pci_name(ctx->lldi.pdev));
-+ spin_unlock_irq(&ctx->dev->lock);
-+ goto out;
-+ }
-+ qp_list.idx = 0;
-+
-+ /* add and ref each qp so it doesn't get freed */
-+ idr_for_each(&ctx->dev->qpidr, add_and_ref_qp, &qp_list);
-+
- spin_unlock_irq(&ctx->dev->lock);
-+
-+ /* now traverse the list in a safe context to recover the db state*/
-+ recover_lost_dbs(ctx, &qp_list);
-+
-+ /* we're almost done! deref the qps and clean up */
-+ deref_qps(qp_list);
-+ kfree(qp_list.qps);
-+
-+ /* Wait for the dbfifo to completely drain again */
-+ while (cxgb4_dbfifo_count(ctx->dev->rdev.lldi.ports[0], 1) > 0) {
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout(usecs_to_jiffies(10));
-+ }
-+
-+ /* resume the queues */
-+ spin_lock_irq(&ctx->dev->lock);
-+ if (ctx->dev->qpcnt > db_fc_threshold)
-+ ctx->dev->db_state = FLOW_CONTROL;
-+ else {
-+ ctx->dev->db_state = NORMAL;
-+ idr_for_each(&ctx->dev->qpidr, enable_qp_db, NULL);
-+ }
-+ ctx->dev->rdev.stats.db_state_transitions++;
-+ spin_unlock_irq(&ctx->dev->lock);
-+
-+out:
-+ /* start up kernel db ringers again */
-+ mutex_unlock(&ctx->dev->db_mutex);
- }
-
- static int c4iw_uld_control(void *handle, enum cxgb4_control control, ...)
-@@ -716,8 +881,7 @@ static int c4iw_uld_control(void *handle, enum cxgb4_control control, ...)
- mutex_unlock(&ctx->dev->rdev.stats.lock);
- break;
- case CXGB4_CONTROL_DB_DROP:
-- printk(KERN_WARNING MOD "%s: Fatal DB DROP\n",
-- pci_name(ctx->lldi.pdev));
-+ recover_queues(ctx);
- mutex_lock(&ctx->dev->rdev.stats.lock);
- ctx->dev->rdev.stats.db_drop++;
- mutex_unlock(&ctx->dev->rdev.stats.lock);
-diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-index e8b88a0..6818659 100644
---- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-@@ -120,6 +120,7 @@ struct c4iw_stats {
- u64 db_full;
- u64 db_empty;
- u64 db_drop;
-+ u64 db_state_transitions;
- };
-
- struct c4iw_rdev {
-@@ -212,6 +213,7 @@ struct c4iw_dev {
- struct mutex db_mutex;
- struct dentry *debugfs_root;
- enum db_state db_state;
-+ int qpcnt;
- };
-
- static inline struct c4iw_dev *to_c4iw_dev(struct ib_device *ibdev)
-@@ -271,11 +273,25 @@ static inline int insert_handle_nolock(struct c4iw_dev *rhp, struct idr *idr,
- return _insert_handle(rhp, idr, handle, id, 0);
- }
-
--static inline void remove_handle(struct c4iw_dev *rhp, struct idr *idr, u32 id)
-+static inline void _remove_handle(struct c4iw_dev *rhp, struct idr *idr,
-+ u32 id, int lock)
- {
-- spin_lock_irq(&rhp->lock);
-+ if (lock)
-+ spin_lock_irq(&rhp->lock);
- idr_remove(idr, id);
-- spin_unlock_irq(&rhp->lock);
-+ if (lock)
-+ spin_unlock_irq(&rhp->lock);
-+}
-+
-+static inline void remove_handle(struct c4iw_dev *rhp, struct idr *idr, u32 id)
-+{
-+ _remove_handle(rhp, idr, id, 1);
-+}
-+
-+static inline void remove_handle_nolock(struct c4iw_dev *rhp,
-+ struct idr *idr, u32 id)
-+{
-+ _remove_handle(rhp, idr, id, 0);
- }
-
- struct c4iw_pd {
-@@ -843,5 +859,7 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe);
- extern struct cxgb4_client t4c_client;
- extern c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS];
- extern int c4iw_max_read_depth;
-+extern int db_fc_threshold;
-+
-
- #endif
-diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
-index beec667..ba1343e 100644
---- a/drivers/infiniband/hw/cxgb4/qp.c
-+++ b/drivers/infiniband/hw/cxgb4/qp.c
-@@ -42,6 +42,11 @@ static int ocqp_support = 1;
- module_param(ocqp_support, int, 0644);
- MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=1)");
-
-+int db_fc_threshold = 2000;
-+module_param(db_fc_threshold, int, 0644);
-+MODULE_PARM_DESC(db_fc_threshold, "QP count/threshold that triggers automatic "
-+ "db flow control mode (default = 2000)");
-+
- static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)
- {
- unsigned long flag;
-@@ -1143,13 +1148,19 @@ static int ring_kernel_db(struct c4iw_qp *qhp, u32 qid, u16 inc)
-
- mutex_lock(&qhp->rhp->db_mutex);
- do {
-- if (cxgb4_dbfifo_count(qhp->rhp->rdev.lldi.ports[0], 1) < 768) {
-+
-+ /*
-+ * The interrupt threshold is dbfifo_int_thresh << 6. So
-+ * make sure we don't cross that and generate an interrupt.
-+ */
-+ if (cxgb4_dbfifo_count(qhp->rhp->rdev.lldi.ports[0], 1) <
-+ (qhp->rhp->rdev.lldi.dbfifo_int_thresh << 5)) {
- writel(V_QID(qid) | V_PIDX(inc), qhp->wq.db);
- break;
- }
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(usecs_to_jiffies(delay));
-- delay = min(delay << 1, 200000);
-+ delay = min(delay << 1, 2000);
- } while (1);
- mutex_unlock(&qhp->rhp->db_mutex);
- return 0;
-@@ -1388,6 +1399,14 @@ out:
- return ret;
- }
-
-+static int enable_qp_db(int id, void *p, void *data)
-+{
-+ struct c4iw_qp *qp = p;
-+
-+ t4_enable_wq_db(&qp->wq);
-+ return 0;
-+}
-+
- int c4iw_destroy_qp(struct ib_qp *ib_qp)
- {
- struct c4iw_dev *rhp;
-@@ -1405,7 +1424,16 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
- c4iw_modify_qp(rhp, qhp, C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
- wait_event(qhp->wait, !qhp->ep);
-
-- remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid);
-+ spin_lock_irq(&rhp->lock);
-+ remove_handle_nolock(rhp, &rhp->qpidr, qhp->wq.sq.qid);
-+ rhp->qpcnt--;
-+ BUG_ON(rhp->qpcnt < 0);
-+ if (rhp->qpcnt <= db_fc_threshold && rhp->db_state == FLOW_CONTROL) {
-+ rhp->rdev.stats.db_state_transitions++;
-+ rhp->db_state = NORMAL;
-+ idr_for_each(&rhp->qpidr, enable_qp_db, NULL);
-+ }
-+ spin_unlock_irq(&rhp->lock);
- atomic_dec(&qhp->refcnt);
- wait_event(qhp->wait, !atomic_read(&qhp->refcnt));
-
-@@ -1419,6 +1447,14 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
- return 0;
- }
-
-+static int disable_qp_db(int id, void *p, void *data)
-+{
-+ struct c4iw_qp *qp = p;
-+
-+ t4_disable_wq_db(&qp->wq);
-+ return 0;
-+}
-+
- struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
- struct ib_udata *udata)
- {
-@@ -1508,6 +1544,11 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
- spin_lock_irq(&rhp->lock);
- if (rhp->db_state != NORMAL)
- t4_disable_wq_db(&qhp->wq);
-+ if (++rhp->qpcnt > db_fc_threshold && rhp->db_state == NORMAL) {
-+ rhp->rdev.stats.db_state_transitions++;
-+ rhp->db_state = FLOW_CONTROL;
-+ idr_for_each(&rhp->qpidr, disable_qp_db, NULL);
-+ }
- ret = insert_handle_nolock(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
- spin_unlock_irq(&rhp->lock);
- if (ret)
-diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
-index c0221ee..16f26ab 100644
---- a/drivers/infiniband/hw/cxgb4/t4.h
-+++ b/drivers/infiniband/hw/cxgb4/t4.h
-@@ -62,6 +62,10 @@ struct t4_status_page {
- __be16 pidx;
- u8 qp_err; /* flit 1 - sw owns */
- u8 db_off;
-+ u8 pad;
-+ u16 host_wq_pidx;
-+ u16 host_cidx;
-+ u16 host_pidx;
- };
-
- #define T4_EQ_ENTRY_SIZE 64
-@@ -375,6 +379,16 @@ static inline void t4_rq_consume(struct t4_wq *wq)
- wq->rq.cidx = 0;
- }
-
-+static inline u16 t4_rq_host_wq_pidx(struct t4_wq *wq)
-+{
-+ return wq->rq.queue[wq->rq.size].status.host_wq_pidx;
-+}
-+
-+static inline u16 t4_rq_wq_size(struct t4_wq *wq)
-+{
-+ return wq->rq.size * T4_RQ_NUM_SLOTS;
-+}
-+
- static inline int t4_sq_onchip(struct t4_sq *sq)
- {
- return sq->flags & T4_SQ_ONCHIP;
-@@ -412,6 +426,16 @@ static inline void t4_sq_consume(struct t4_wq *wq)
- wq->sq.cidx = 0;
- }
-
-+static inline u16 t4_sq_host_wq_pidx(struct t4_wq *wq)
-+{
-+ return wq->sq.queue[wq->sq.size].status.host_wq_pidx;
-+}
-+
-+static inline u16 t4_sq_wq_size(struct t4_wq *wq)
-+{
-+ return wq->sq.size * T4_SQ_NUM_SLOTS;
-+}
-+
- static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc)
- {
- wmb();
---
-1.7.1
-
+++ /dev/null
-From d716a2a014ad199362a59004b5ab932030a213ff Mon Sep 17 00:00:00 2001
-From: Vipul Pandya <vipul@chelsio.com>
-Date: Fri, 18 May 2012 15:29:31 +0530
-Subject: [PATCH 11/13] RDMA/cxgb4: Use vmalloc() for debugfs QP dump
-
-This allows dumping thousands of QPs. Log active open failures of
-interest.
-
-Signed-off-by: Vipul Pandya <vipul@chelsio.com>
-Signed-off-by: Steve Wise <swise@opengridcomputing.com>
-Signed-off-by: Roland Dreier <roland@purestorage.com>
----
- drivers/infiniband/hw/cxgb4/cm.c | 18 ++++++++++++++++++
- drivers/infiniband/hw/cxgb4/device.c | 4 ++--
- 2 files changed, 20 insertions(+), 2 deletions(-)
-
-diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
-index 6ce401a..55ab284 100644
---- a/drivers/infiniband/hw/cxgb4/cm.c
-+++ b/drivers/infiniband/hw/cxgb4/cm.c
-@@ -1413,6 +1413,24 @@ static int act_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
- return 0;
- }
-
-+ /*
-+ * Log interesting failures.
-+ */
-+ switch (status) {
-+ case CPL_ERR_CONN_RESET:
-+ case CPL_ERR_CONN_TIMEDOUT:
-+ break;
-+ default:
-+ printk(KERN_INFO MOD "Active open failure - "
-+ "atid %u status %u errno %d %pI4:%u->%pI4:%u\n",
-+ atid, status, status2errno(status),
-+ &ep->com.local_addr.sin_addr.s_addr,
-+ ntohs(ep->com.local_addr.sin_port),
-+ &ep->com.remote_addr.sin_addr.s_addr,
-+ ntohs(ep->com.remote_addr.sin_port));
-+ break;
-+ }
-+
- connect_reply_upcall(ep, status2errno(status));
- state_set(&ep->com, DEAD);
-
-diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
-index bdb398f..8545629 100644
---- a/drivers/infiniband/hw/cxgb4/device.c
-+++ b/drivers/infiniband/hw/cxgb4/device.c
-@@ -121,7 +121,7 @@ static int qp_release(struct inode *inode, struct file *file)
- printk(KERN_INFO "%s null qpd?\n", __func__);
- return 0;
- }
-- kfree(qpd->buf);
-+ vfree(qpd->buf);
- kfree(qpd);
- return 0;
- }
-@@ -145,7 +145,7 @@ static int qp_open(struct inode *inode, struct file *file)
- spin_unlock_irq(&qpd->devp->lock);
-
- qpd->bufsize = count * 128;
-- qpd->buf = kmalloc(qpd->bufsize, GFP_KERNEL);
-+ qpd->buf = vmalloc(qpd->bufsize);
- if (!qpd->buf) {
- ret = -ENOMEM;
- goto err1;
---
-1.7.1
-
+++ /dev/null
-From ec3eead217181d7360a11317a888ceb30807867c Mon Sep 17 00:00:00 2001
-From: Vipul Pandya <vipul@chelsio.com>
-Date: Fri, 18 May 2012 15:29:32 +0530
-Subject: [PATCH 12/13] RDMA/cxgb4: Remove kfifo usage
-
-Using kfifos for ID management was limiting the number of QPs and
-preventing NP384 MPI jobs. So replace it with a simple bitmap
-allocator.
-
-Remove IDs from the IDR tables before deallocating them. This bug was
-causing the BUG_ON() in insert_handle() to fire because the ID was
-getting reused before being removed from the IDR table.
-
-Signed-off-by: Vipul Pandya <vipul@chelsio.com>
-Signed-off-by: Steve Wise <swise@opengridcomputing.com>
-Signed-off-by: Roland Dreier <roland@purestorage.com>
----
- drivers/infiniband/hw/cxgb4/Makefile | 2 +-
- drivers/infiniband/hw/cxgb4/device.c | 37 +++++---
- drivers/infiniband/hw/cxgb4/id_table.c | 112 ++++++++++++++++++++++++
- drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 35 ++++++--
- drivers/infiniband/hw/cxgb4/mem.c | 10 +--
- drivers/infiniband/hw/cxgb4/provider.c | 9 +--
- drivers/infiniband/hw/cxgb4/resource.c | 148 ++++++++------------------------
- 7 files changed, 203 insertions(+), 150 deletions(-)
- create mode 100644 drivers/infiniband/hw/cxgb4/id_table.c
-
-diff --git a/drivers/infiniband/hw/cxgb4/Makefile b/drivers/infiniband/hw/cxgb4/Makefile
-index 46b878c..e11cf72 100644
---- a/drivers/infiniband/hw/cxgb4/Makefile
-+++ b/drivers/infiniband/hw/cxgb4/Makefile
-@@ -2,4 +2,4 @@ ccflags-y := -Idrivers/net/ethernet/chelsio/cxgb4
-
- obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
-
--iw_cxgb4-y := device.o cm.o provider.o mem.o cq.o qp.o resource.o ev.o
-+iw_cxgb4-y := device.o cm.o provider.o mem.o cq.o qp.o resource.o ev.o id_table.o
-diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
-index 8545629..c8fd1d8 100644
---- a/drivers/infiniband/hw/cxgb4/device.c
-+++ b/drivers/infiniband/hw/cxgb4/device.c
-@@ -252,25 +252,26 @@ static int stats_show(struct seq_file *seq, void *v)
- {
- struct c4iw_dev *dev = seq->private;
-
-- seq_printf(seq, " Object: %10s %10s %10s\n", "Total", "Current", "Max");
-- seq_printf(seq, " PDID: %10llu %10llu %10llu\n",
-+ seq_printf(seq, " Object: %10s %10s %10s %10s\n", "Total", "Current",
-+ "Max", "Fail");
-+ seq_printf(seq, " PDID: %10llu %10llu %10llu %10llu\n",
- dev->rdev.stats.pd.total, dev->rdev.stats.pd.cur,
-- dev->rdev.stats.pd.max);
-- seq_printf(seq, " QID: %10llu %10llu %10llu\n",
-+ dev->rdev.stats.pd.max, dev->rdev.stats.pd.fail);
-+ seq_printf(seq, " QID: %10llu %10llu %10llu %10llu\n",
- dev->rdev.stats.qid.total, dev->rdev.stats.qid.cur,
-- dev->rdev.stats.qid.max);
-- seq_printf(seq, " TPTMEM: %10llu %10llu %10llu\n",
-+ dev->rdev.stats.qid.max, dev->rdev.stats.qid.fail);
-+ seq_printf(seq, " TPTMEM: %10llu %10llu %10llu %10llu\n",
- dev->rdev.stats.stag.total, dev->rdev.stats.stag.cur,
-- dev->rdev.stats.stag.max);
-- seq_printf(seq, " PBLMEM: %10llu %10llu %10llu\n",
-+ dev->rdev.stats.stag.max, dev->rdev.stats.stag.fail);
-+ seq_printf(seq, " PBLMEM: %10llu %10llu %10llu %10llu\n",
- dev->rdev.stats.pbl.total, dev->rdev.stats.pbl.cur,
-- dev->rdev.stats.pbl.max);
-- seq_printf(seq, " RQTMEM: %10llu %10llu %10llu\n",
-+ dev->rdev.stats.pbl.max, dev->rdev.stats.pbl.fail);
-+ seq_printf(seq, " RQTMEM: %10llu %10llu %10llu %10llu\n",
- dev->rdev.stats.rqt.total, dev->rdev.stats.rqt.cur,
-- dev->rdev.stats.rqt.max);
-- seq_printf(seq, " OCQPMEM: %10llu %10llu %10llu\n",
-+ dev->rdev.stats.rqt.max, dev->rdev.stats.rqt.fail);
-+ seq_printf(seq, " OCQPMEM: %10llu %10llu %10llu %10llu\n",
- dev->rdev.stats.ocqp.total, dev->rdev.stats.ocqp.cur,
-- dev->rdev.stats.ocqp.max);
-+ dev->rdev.stats.ocqp.max, dev->rdev.stats.ocqp.fail);
- seq_printf(seq, " DB FULL: %10llu\n", dev->rdev.stats.db_full);
- seq_printf(seq, " DB EMPTY: %10llu\n", dev->rdev.stats.db_empty);
- seq_printf(seq, " DB DROP: %10llu\n", dev->rdev.stats.db_drop);
-@@ -292,11 +293,17 @@ static ssize_t stats_clear(struct file *file, const char __user *buf,
-
- mutex_lock(&dev->rdev.stats.lock);
- dev->rdev.stats.pd.max = 0;
-+ dev->rdev.stats.pd.fail = 0;
- dev->rdev.stats.qid.max = 0;
-+ dev->rdev.stats.qid.fail = 0;
- dev->rdev.stats.stag.max = 0;
-+ dev->rdev.stats.stag.fail = 0;
- dev->rdev.stats.pbl.max = 0;
-+ dev->rdev.stats.pbl.fail = 0;
- dev->rdev.stats.rqt.max = 0;
-+ dev->rdev.stats.rqt.fail = 0;
- dev->rdev.stats.ocqp.max = 0;
-+ dev->rdev.stats.ocqp.fail = 0;
- dev->rdev.stats.db_full = 0;
- dev->rdev.stats.db_empty = 0;
- dev->rdev.stats.db_drop = 0;
-@@ -350,8 +357,8 @@ void c4iw_release_dev_ucontext(struct c4iw_rdev *rdev,
- entry = list_entry(pos, struct c4iw_qid_list, entry);
- list_del_init(&entry->entry);
- if (!(entry->qid & rdev->qpmask)) {
-- c4iw_put_resource(&rdev->resource.qid_fifo, entry->qid,
-- &rdev->resource.qid_fifo_lock);
-+ c4iw_put_resource(&rdev->resource.qid_table,
-+ entry->qid);
- mutex_lock(&rdev->stats.lock);
- rdev->stats.qid.cur -= rdev->qpmask + 1;
- mutex_unlock(&rdev->stats.lock);
-diff --git a/drivers/infiniband/hw/cxgb4/id_table.c b/drivers/infiniband/hw/cxgb4/id_table.c
-new file mode 100644
-index 0000000..f95e5df
---- /dev/null
-+++ b/drivers/infiniband/hw/cxgb4/id_table.c
-@@ -0,0 +1,112 @@
-+/*
-+ * Copyright (c) 2011 Chelsio Communications. 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/kernel.h>
-+#include <linux/random.h>
-+#include "iw_cxgb4.h"
-+
-+#define RANDOM_SKIP 16
-+
-+/*
-+ * Trivial bitmap-based allocator. If the random flag is set, the
-+ * allocator is designed to:
-+ * - pseudo-randomize the id returned such that it is not trivially predictable.
-+ * - avoid reuse of recently used id (at the expense of predictability)
-+ */
-+u32 c4iw_id_alloc(struct c4iw_id_table *alloc)
-+{
-+ unsigned long flags;
-+ u32 obj;
-+
-+ spin_lock_irqsave(&alloc->lock, flags);
-+
-+ obj = find_next_zero_bit(alloc->table, alloc->max, alloc->last);
-+ if (obj >= alloc->max)
-+ obj = find_first_zero_bit(alloc->table, alloc->max);
-+
-+ if (obj < alloc->max) {
-+ if (alloc->flags & C4IW_ID_TABLE_F_RANDOM)
-+ alloc->last += random32() % RANDOM_SKIP;
-+ else
-+ alloc->last = obj + 1;
-+ if (alloc->last >= alloc->max)
-+ alloc->last = 0;
-+ set_bit(obj, alloc->table);
-+ obj += alloc->start;
-+ } else
-+ obj = -1;
-+
-+ spin_unlock_irqrestore(&alloc->lock, flags);
-+ return obj;
-+}
-+
-+void c4iw_id_free(struct c4iw_id_table *alloc, u32 obj)
-+{
-+ unsigned long flags;
-+
-+ obj -= alloc->start;
-+ BUG_ON((int)obj < 0);
-+
-+ spin_lock_irqsave(&alloc->lock, flags);
-+ clear_bit(obj, alloc->table);
-+ spin_unlock_irqrestore(&alloc->lock, flags);
-+}
-+
-+int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num,
-+ u32 reserved, u32 flags)
-+{
-+ int i;
-+
-+ alloc->start = start;
-+ alloc->flags = flags;
-+ if (flags & C4IW_ID_TABLE_F_RANDOM)
-+ alloc->last = random32() % RANDOM_SKIP;
-+ else
-+ alloc->last = 0;
-+ alloc->max = num;
-+ spin_lock_init(&alloc->lock);
-+ alloc->table = kmalloc(BITS_TO_LONGS(num) * sizeof(long),
-+ GFP_KERNEL);
-+ if (!alloc->table)
-+ return -ENOMEM;
-+
-+ bitmap_zero(alloc->table, num);
-+ if (!(alloc->flags & C4IW_ID_TABLE_F_EMPTY))
-+ for (i = 0; i < reserved; ++i)
-+ set_bit(i, alloc->table);
-+
-+ return 0;
-+}
-+
-+void c4iw_id_table_free(struct c4iw_id_table *alloc)
-+{
-+ kfree(alloc->table);
-+}
-diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-index 6818659..2d5b06b 100644
---- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-@@ -45,7 +45,6 @@
- #include <linux/kref.h>
- #include <linux/timer.h>
- #include <linux/io.h>
--#include <linux/kfifo.h>
-
- #include <asm/byteorder.h>
-
-@@ -79,13 +78,22 @@ static inline void *cplhdr(struct sk_buff *skb)
- return skb->data;
- }
-
-+#define C4IW_ID_TABLE_F_RANDOM 1 /* Pseudo-randomize the id's returned */
-+#define C4IW_ID_TABLE_F_EMPTY 2 /* Table is initially empty */
-+
-+struct c4iw_id_table {
-+ u32 flags;
-+ u32 start; /* logical minimal id */
-+ u32 last; /* hint for find */
-+ u32 max;
-+ spinlock_t lock;
-+ unsigned long *table;
-+};
-+
- struct c4iw_resource {
-- struct kfifo tpt_fifo;
-- spinlock_t tpt_fifo_lock;
-- struct kfifo qid_fifo;
-- spinlock_t qid_fifo_lock;
-- struct kfifo pdid_fifo;
-- spinlock_t pdid_fifo_lock;
-+ struct c4iw_id_table tpt_table;
-+ struct c4iw_id_table qid_table;
-+ struct c4iw_id_table pdid_table;
- };
-
- struct c4iw_qid_list {
-@@ -107,6 +115,7 @@ struct c4iw_stat {
- u64 total;
- u64 cur;
- u64 max;
-+ u64 fail;
- };
-
- struct c4iw_stats {
-@@ -253,7 +262,7 @@ static inline int _insert_handle(struct c4iw_dev *rhp, struct idr *idr,
- if (lock)
- spin_lock_irq(&rhp->lock);
- ret = idr_get_new_above(idr, handle, id, &newid);
-- BUG_ON(newid != id);
-+ BUG_ON(!ret && newid != id);
- if (lock)
- spin_unlock_irq(&rhp->lock);
- } while (ret == -EAGAIN);
-@@ -755,14 +764,20 @@ static inline int compute_wscale(int win)
- return wscale;
- }
-
-+u32 c4iw_id_alloc(struct c4iw_id_table *alloc);
-+void c4iw_id_free(struct c4iw_id_table *alloc, u32 obj);
-+int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num,
-+ u32 reserved, u32 flags);
-+void c4iw_id_table_free(struct c4iw_id_table *alloc);
-+
- typedef int (*c4iw_handler_func)(struct c4iw_dev *dev, struct sk_buff *skb);
-
- int c4iw_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new,
- struct l2t_entry *l2t);
- void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qpid,
- struct c4iw_dev_ucontext *uctx);
--u32 c4iw_get_resource(struct kfifo *fifo, spinlock_t *lock);
--void c4iw_put_resource(struct kfifo *fifo, u32 entry, spinlock_t *lock);
-+u32 c4iw_get_resource(struct c4iw_id_table *id_table);
-+void c4iw_put_resource(struct c4iw_id_table *id_table, u32 entry);
- int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid);
- int c4iw_init_ctrl_qp(struct c4iw_rdev *rdev);
- int c4iw_pblpool_create(struct c4iw_rdev *rdev);
-diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c
-index 2a87379..57e07c6 100644
---- a/drivers/infiniband/hw/cxgb4/mem.c
-+++ b/drivers/infiniband/hw/cxgb4/mem.c
-@@ -131,8 +131,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
- stag_idx = (*stag) >> 8;
-
- if ((!reset_tpt_entry) && (*stag == T4_STAG_UNSET)) {
-- stag_idx = c4iw_get_resource(&rdev->resource.tpt_fifo,
-- &rdev->resource.tpt_fifo_lock);
-+ stag_idx = c4iw_get_resource(&rdev->resource.tpt_table);
- if (!stag_idx)
- return -ENOMEM;
- mutex_lock(&rdev->stats.lock);
-@@ -171,8 +170,7 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
- sizeof(tpt), &tpt);
-
- if (reset_tpt_entry) {
-- c4iw_put_resource(&rdev->resource.tpt_fifo, stag_idx,
-- &rdev->resource.tpt_fifo_lock);
-+ c4iw_put_resource(&rdev->resource.tpt_table, stag_idx);
- mutex_lock(&rdev->stats.lock);
- rdev->stats.stag.cur -= 32;
- mutex_unlock(&rdev->stats.lock);
-@@ -695,8 +693,8 @@ int c4iw_dealloc_mw(struct ib_mw *mw)
- mhp = to_c4iw_mw(mw);
- rhp = mhp->rhp;
- mmid = (mw->rkey) >> 8;
-- deallocate_window(&rhp->rdev, mhp->attr.stag);
- remove_handle(rhp, &rhp->mmidr, mmid);
-+ deallocate_window(&rhp->rdev, mhp->attr.stag);
- kfree(mhp);
- PDBG("%s ib_mw %p mmid 0x%x ptr %p\n", __func__, mw, mmid, mhp);
- return 0;
-@@ -798,12 +796,12 @@ int c4iw_dereg_mr(struct ib_mr *ib_mr)
- mhp = to_c4iw_mr(ib_mr);
- rhp = mhp->rhp;
- mmid = mhp->attr.stag >> 8;
-+ remove_handle(rhp, &rhp->mmidr, mmid);
- dereg_mem(&rhp->rdev, mhp->attr.stag, mhp->attr.pbl_size,
- mhp->attr.pbl_addr);
- if (mhp->attr.pbl_size)
- c4iw_pblpool_free(&mhp->rhp->rdev, mhp->attr.pbl_addr,
- mhp->attr.pbl_size << 3);
-- remove_handle(rhp, &rhp->mmidr, mmid);
- if (mhp->kva)
- kfree((void *) (unsigned long) mhp->kva);
- if (mhp->umem)
-diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
-index 8d58736..fe98a0a 100644
---- a/drivers/infiniband/hw/cxgb4/provider.c
-+++ b/drivers/infiniband/hw/cxgb4/provider.c
-@@ -188,8 +188,7 @@ static int c4iw_deallocate_pd(struct ib_pd *pd)
- php = to_c4iw_pd(pd);
- rhp = php->rhp;
- PDBG("%s ibpd %p pdid 0x%x\n", __func__, pd, php->pdid);
-- c4iw_put_resource(&rhp->rdev.resource.pdid_fifo, php->pdid,
-- &rhp->rdev.resource.pdid_fifo_lock);
-+ c4iw_put_resource(&rhp->rdev.resource.pdid_table, php->pdid);
- mutex_lock(&rhp->rdev.stats.lock);
- rhp->rdev.stats.pd.cur--;
- mutex_unlock(&rhp->rdev.stats.lock);
-@@ -207,14 +206,12 @@ static struct ib_pd *c4iw_allocate_pd(struct ib_device *ibdev,
-
- PDBG("%s ibdev %p\n", __func__, ibdev);
- rhp = (struct c4iw_dev *) ibdev;
-- pdid = c4iw_get_resource(&rhp->rdev.resource.pdid_fifo,
-- &rhp->rdev.resource.pdid_fifo_lock);
-+ pdid = c4iw_get_resource(&rhp->rdev.resource.pdid_table);
- if (!pdid)
- return ERR_PTR(-EINVAL);
- php = kzalloc(sizeof(*php), GFP_KERNEL);
- if (!php) {
-- c4iw_put_resource(&rhp->rdev.resource.pdid_fifo, pdid,
-- &rhp->rdev.resource.pdid_fifo_lock);
-+ c4iw_put_resource(&rhp->rdev.resource.pdid_table, pdid);
- return ERR_PTR(-ENOMEM);
- }
- php->pdid = pdid;
-diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c
-index 1b948d1..cdef4d7 100644
---- a/drivers/infiniband/hw/cxgb4/resource.c
-+++ b/drivers/infiniband/hw/cxgb4/resource.c
-@@ -30,96 +30,25 @@
- * SOFTWARE.
- */
- /* Crude resource management */
--#include <linux/kernel.h>
--#include <linux/random.h>
--#include <linux/slab.h>
--#include <linux/kfifo.h>
- #include <linux/spinlock.h>
--#include <linux/errno.h>
- #include <linux/genalloc.h>
- #include <linux/ratelimit.h>
- #include "iw_cxgb4.h"
-
--#define RANDOM_SIZE 16
--
--static int __c4iw_init_resource_fifo(struct kfifo *fifo,
-- spinlock_t *fifo_lock,
-- u32 nr, u32 skip_low,
-- u32 skip_high,
-- int random)
--{
-- u32 i, j, entry = 0, idx;
-- u32 random_bytes;
-- u32 rarray[16];
-- spin_lock_init(fifo_lock);
--
-- if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL))
-- return -ENOMEM;
--
-- for (i = 0; i < skip_low + skip_high; i++)
-- kfifo_in(fifo, (unsigned char *) &entry, sizeof(u32));
-- if (random) {
-- j = 0;
-- random_bytes = random32();
-- for (i = 0; i < RANDOM_SIZE; i++)
-- rarray[i] = i + skip_low;
-- for (i = skip_low + RANDOM_SIZE; i < nr - skip_high; i++) {
-- if (j >= RANDOM_SIZE) {
-- j = 0;
-- random_bytes = random32();
-- }
-- idx = (random_bytes >> (j * 2)) & 0xF;
-- kfifo_in(fifo,
-- (unsigned char *) &rarray[idx],
-- sizeof(u32));
-- rarray[idx] = i;
-- j++;
-- }
-- for (i = 0; i < RANDOM_SIZE; i++)
-- kfifo_in(fifo,
-- (unsigned char *) &rarray[i],
-- sizeof(u32));
-- } else
-- for (i = skip_low; i < nr - skip_high; i++)
-- kfifo_in(fifo, (unsigned char *) &i, sizeof(u32));
--
-- for (i = 0; i < skip_low + skip_high; i++)
-- if (kfifo_out_locked(fifo, (unsigned char *) &entry,
-- sizeof(u32), fifo_lock))
-- break;
-- return 0;
--}
--
--static int c4iw_init_resource_fifo(struct kfifo *fifo, spinlock_t * fifo_lock,
-- u32 nr, u32 skip_low, u32 skip_high)
--{
-- return __c4iw_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
-- skip_high, 0);
--}
--
--static int c4iw_init_resource_fifo_random(struct kfifo *fifo,
-- spinlock_t *fifo_lock,
-- u32 nr, u32 skip_low, u32 skip_high)
--{
-- return __c4iw_init_resource_fifo(fifo, fifo_lock, nr, skip_low,
-- skip_high, 1);
--}
--
--static int c4iw_init_qid_fifo(struct c4iw_rdev *rdev)
-+static int c4iw_init_qid_table(struct c4iw_rdev *rdev)
- {
- u32 i;
-
-- spin_lock_init(&rdev->resource.qid_fifo_lock);
--
-- if (kfifo_alloc(&rdev->resource.qid_fifo, rdev->lldi.vr->qp.size *
-- sizeof(u32), GFP_KERNEL))
-+ if (c4iw_id_table_alloc(&rdev->resource.qid_table,
-+ rdev->lldi.vr->qp.start,
-+ rdev->lldi.vr->qp.size,
-+ rdev->lldi.vr->qp.size, 0))
- return -ENOMEM;
-
- for (i = rdev->lldi.vr->qp.start;
-- i < rdev->lldi.vr->qp.start + rdev->lldi.vr->qp.size; i++)
-+ i < rdev->lldi.vr->qp.start + rdev->lldi.vr->qp.size; i++)
- if (!(i & rdev->qpmask))
-- kfifo_in(&rdev->resource.qid_fifo,
-- (unsigned char *) &i, sizeof(u32));
-+ c4iw_id_free(&rdev->resource.qid_table, i);
- return 0;
- }
-
-@@ -127,44 +56,42 @@ static int c4iw_init_qid_fifo(struct c4iw_rdev *rdev)
- int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid)
- {
- int err = 0;
-- err = c4iw_init_resource_fifo_random(&rdev->resource.tpt_fifo,
-- &rdev->resource.tpt_fifo_lock,
-- nr_tpt, 1, 0);
-+ err = c4iw_id_table_alloc(&rdev->resource.tpt_table, 0, nr_tpt, 1,
-+ C4IW_ID_TABLE_F_RANDOM);
- if (err)
- goto tpt_err;
-- err = c4iw_init_qid_fifo(rdev);
-+ err = c4iw_init_qid_table(rdev);
- if (err)
- goto qid_err;
-- err = c4iw_init_resource_fifo(&rdev->resource.pdid_fifo,
-- &rdev->resource.pdid_fifo_lock,
-- nr_pdid, 1, 0);
-+ err = c4iw_id_table_alloc(&rdev->resource.pdid_table, 0,
-+ nr_pdid, 1, 0);
- if (err)
- goto pdid_err;
- return 0;
--pdid_err:
-- kfifo_free(&rdev->resource.qid_fifo);
--qid_err:
-- kfifo_free(&rdev->resource.tpt_fifo);
--tpt_err:
-+ pdid_err:
-+ c4iw_id_table_free(&rdev->resource.qid_table);
-+ qid_err:
-+ c4iw_id_table_free(&rdev->resource.tpt_table);
-+ tpt_err:
- return -ENOMEM;
- }
-
- /*
- * returns 0 if no resource available
- */
--u32 c4iw_get_resource(struct kfifo *fifo, spinlock_t *lock)
-+u32 c4iw_get_resource(struct c4iw_id_table *id_table)
- {
- u32 entry;
-- if (kfifo_out_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock))
-- return entry;
-- else
-+ entry = c4iw_id_alloc(id_table);
-+ if (entry == (u32)(-1))
- return 0;
-+ return entry;
- }
-
--void c4iw_put_resource(struct kfifo *fifo, u32 entry, spinlock_t *lock)
-+void c4iw_put_resource(struct c4iw_id_table *id_table, u32 entry)
- {
- PDBG("%s entry 0x%x\n", __func__, entry);
-- kfifo_in_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock);
-+ c4iw_id_free(id_table, entry);
- }
-
- u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
-@@ -181,8 +108,7 @@ u32 c4iw_get_cqid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
- qid = entry->qid;
- kfree(entry);
- } else {
-- qid = c4iw_get_resource(&rdev->resource.qid_fifo,
-- &rdev->resource.qid_fifo_lock);
-+ qid = c4iw_get_resource(&rdev->resource.qid_table);
- if (!qid)
- goto out;
- mutex_lock(&rdev->stats.lock);
-@@ -252,8 +178,7 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx)
- qid = entry->qid;
- kfree(entry);
- } else {
-- qid = c4iw_get_resource(&rdev->resource.qid_fifo,
-- &rdev->resource.qid_fifo_lock);
-+ qid = c4iw_get_resource(&rdev->resource.qid_table);
- if (!qid)
- goto out;
- mutex_lock(&rdev->stats.lock);
-@@ -311,9 +236,9 @@ void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qid,
-
- void c4iw_destroy_resource(struct c4iw_resource *rscp)
- {
-- kfifo_free(&rscp->tpt_fifo);
-- kfifo_free(&rscp->qid_fifo);
-- kfifo_free(&rscp->pdid_fifo);
-+ c4iw_id_table_free(&rscp->tpt_table);
-+ c4iw_id_table_free(&rscp->qid_table);
-+ c4iw_id_table_free(&rscp->pdid_table);
- }
-
- /*
-@@ -326,16 +251,14 @@ u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size)
- {
- unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size);
- PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
-- if (!addr)
-- printk_ratelimited(KERN_WARNING MOD "%s: Out of PBL memory\n",
-- pci_name(rdev->lldi.pdev));
-+ mutex_lock(&rdev->stats.lock);
- if (addr) {
-- mutex_lock(&rdev->stats.lock);
- rdev->stats.pbl.cur += roundup(size, 1 << MIN_PBL_SHIFT);
- if (rdev->stats.pbl.cur > rdev->stats.pbl.max)
- rdev->stats.pbl.max = rdev->stats.pbl.cur;
-- mutex_unlock(&rdev->stats.lock);
-- }
-+ } else
-+ rdev->stats.pbl.fail++;
-+ mutex_unlock(&rdev->stats.lock);
- return (u32)addr;
- }
-
-@@ -401,13 +324,14 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
- if (!addr)
- printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n",
- pci_name(rdev->lldi.pdev));
-+ mutex_lock(&rdev->stats.lock);
- if (addr) {
-- mutex_lock(&rdev->stats.lock);
- rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT);
- if (rdev->stats.rqt.cur > rdev->stats.rqt.max)
- rdev->stats.rqt.max = rdev->stats.rqt.cur;
-- mutex_unlock(&rdev->stats.lock);
-- }
-+ } else
-+ rdev->stats.rqt.fail++;
-+ mutex_unlock(&rdev->stats.lock);
- return (u32)addr;
- }
-
---
-1.7.1
-
+++ /dev/null
-From 67bbc05512d8a609e9a2d284dbfda9d2c50f0bf6 Mon Sep 17 00:00:00 2001
-From: Vipul Pandya <vipul@chelsio.com>
-Date: Fri, 18 May 2012 15:29:33 +0530
-Subject: [PATCH 13/13] RDMA/cxgb4: Add query_qp support
-
-This allows querying the QP state before flushing.
-
-Signed-off-by: Vipul Pandya <vipul@chelsio.com>
-Signed-off-by: Steve Wise <swise@opengridcomputing.com>
-Signed-off-by: Roland Dreier <roland@purestorage.com>
----
- drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 19 +++++++++++++++++++
- drivers/infiniband/hw/cxgb4/provider.c | 2 ++
- drivers/infiniband/hw/cxgb4/qp.c | 11 +++++++++++
- 3 files changed, 32 insertions(+), 0 deletions(-)
-
-diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-index 2d5b06b..9beb3a9 100644
---- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
-@@ -551,6 +551,23 @@ static inline int c4iw_convert_state(enum ib_qp_state ib_state)
- }
- }
-
-+static inline int to_ib_qp_state(int c4iw_qp_state)
-+{
-+ switch (c4iw_qp_state) {
-+ case C4IW_QP_STATE_IDLE:
-+ return IB_QPS_INIT;
-+ case C4IW_QP_STATE_RTS:
-+ return IB_QPS_RTS;
-+ case C4IW_QP_STATE_CLOSING:
-+ return IB_QPS_SQD;
-+ case C4IW_QP_STATE_TERMINATE:
-+ return IB_QPS_SQE;
-+ case C4IW_QP_STATE_ERROR:
-+ return IB_QPS_ERR;
-+ }
-+ return IB_QPS_ERR;
-+}
-+
- static inline u32 c4iw_ib_to_tpt_access(int a)
- {
- return (a & IB_ACCESS_REMOTE_WRITE ? FW_RI_MEM_ACCESS_REM_WRITE : 0) |
-@@ -846,6 +863,8 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd,
- struct ib_udata *udata);
- int c4iw_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
- int attr_mask, struct ib_udata *udata);
-+int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
-+ int attr_mask, struct ib_qp_init_attr *init_attr);
- struct ib_qp *c4iw_get_qp(struct ib_device *dev, int qpn);
- u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size);
- void c4iw_rqtpool_free(struct c4iw_rdev *rdev, u32 addr, int size);
-diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c
-index fe98a0a..e084fdc 100644
---- a/drivers/infiniband/hw/cxgb4/provider.c
-+++ b/drivers/infiniband/hw/cxgb4/provider.c
-@@ -443,6 +443,7 @@ int c4iw_register_device(struct c4iw_dev *dev)
- (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) |
- (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
- (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
-+ (1ull << IB_USER_VERBS_CMD_QUERY_QP) |
- (1ull << IB_USER_VERBS_CMD_POLL_CQ) |
- (1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
- (1ull << IB_USER_VERBS_CMD_POST_SEND) |
-@@ -465,6 +466,7 @@ int c4iw_register_device(struct c4iw_dev *dev)
- dev->ibdev.destroy_ah = c4iw_ah_destroy;
- dev->ibdev.create_qp = c4iw_create_qp;
- dev->ibdev.modify_qp = c4iw_ib_modify_qp;
-+ dev->ibdev.query_qp = c4iw_ib_query_qp;
- dev->ibdev.destroy_qp = c4iw_destroy_qp;
- dev->ibdev.create_cq = c4iw_create_cq;
- dev->ibdev.destroy_cq = c4iw_destroy_cq;
-diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
-index ba1343e..45aedf1 100644
---- a/drivers/infiniband/hw/cxgb4/qp.c
-+++ b/drivers/infiniband/hw/cxgb4/qp.c
-@@ -1711,3 +1711,14 @@ struct ib_qp *c4iw_get_qp(struct ib_device *dev, int qpn)
- PDBG("%s ib_dev %p qpn 0x%x\n", __func__, dev, qpn);
- return (struct ib_qp *)get_qhp(to_c4iw_dev(dev), qpn);
- }
-+
-+int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
-+ int attr_mask, struct ib_qp_init_attr *init_attr)
-+{
-+ struct c4iw_qp *qhp = to_c4iw_qp(ibqp);
-+
-+ memset(attr, 0, sizeof *attr);
-+ memset(init_attr, 0, sizeof *init_attr);
-+ attr->qp_state = to_ib_qp_state(qhp->attr.state);
-+ return 0;
-+}
---
-1.7.1
-
+++ /dev/null
-From a6f7feae6d19e84253918d88b04153af09d3a243 Mon Sep 17 00:00:00 2001
-From: Jack Morgenstein <jackm@mellanox.com>
-Date: Thu, 26 Jan 2012 16:41:33 +0200
-Subject: [PATCH] IB/mlx4: pass SMP vendor-specific attribute MADs to firmware
-
-In the current code, vendor-specific MADs (e.g with the FDR-10
-attribute) are silently dropped by the driver, resulting in timeouts
-at the sending side and inability to query/configure the relevant
-feature. However, the ConnectX firmware is able to handle such MADs.
-For unsupported attributes, the firmware returns a GET_RESPONSE MAD
-containing an error status.
-
-For example, for a FDR-10 node with LID 11:
-
- # ibstat mlx4_0 1
-
- CA: 'mlx4_0'
- Port 1:
- State: Active
- Physical state: LinkUp
- Rate: 40 (FDR10)
- Base lid: 11
- LMC: 0
- SM lid: 24
- Capability mask: 0x02514868
- Port GUID: 0x0002c903002e65d1
- Link layer: InfiniBand
-
-Extended Port Query (EPI) vendor mad timeouts before the patch:
-
- # smpquery MEPI 11 -d
-
- ibwarn: [4196] smp_query_via: attr 0xff90 mod 0x0 route Lid 11
- ibwarn: [4196] _do_madrpc: retry 1 (timeout 1000 ms)
- ibwarn: [4196] _do_madrpc: retry 2 (timeout 1000 ms)
- ibwarn: [4196] _do_madrpc: timeout after 3 retries, 3000 ms
- ibwarn: [4196] mad_rpc: _do_madrpc failed; dport (Lid 11)
- smpquery: iberror: [pid 4196] main: failed: operation EPI: ext port info query failed
-
-EPI query works OK with the patch:
-
- # smpquery MEPI 11 -d
-
- ibwarn: [6548] smp_query_via: attr 0xff90 mod 0x0 route Lid 11
- ibwarn: [6548] mad_rpc: data offs 64 sz 64
- mad data
- 0000 0000 0000 0001 0000 0001 0000 0001
- 0000 0000 0000 0000 0000 0000 0000 0000
- 0000 0000 0000 0000 0000 0000 0000 0000
- 0000 0000 0000 0000 0000 0000 0000 0000
- # Ext Port info: Lid 11 port 0
- StateChangeEnable:...............0x00
- LinkSpeedSupported:..............0x01
- LinkSpeedEnabled:................0x01
- LinkSpeedActive:.................0x01
-
-Signed-off-by: Jack Morgenstein <jackm@mellanox.com>
-Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
-Acked-by: Ira Weiny <weiny2@llnl.gov>
-Cc: <stable@vger.kernel.org>
-Signed-off-by: Roland Dreier <roland@purestorage.com>
----
- drivers/infiniband/hw/mlx4/mad.c | 7 ++-----
- 1 files changed, 2 insertions(+), 5 deletions(-)
-
-diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
-index 95c94d8..259b067 100644
---- a/drivers/infiniband/hw/mlx4/mad.c
-+++ b/drivers/infiniband/hw/mlx4/mad.c
-@@ -257,12 +257,9 @@ static int ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
- return IB_MAD_RESULT_SUCCESS;
-
- /*
-- * Don't process SMInfo queries or vendor-specific
-- * MADs -- the SMA can't handle them.
-+ * Don't process SMInfo queries -- the SMA can't handle them.
- */
-- if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO ||
-- ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) ==
-- IB_SMP_ATTR_VENDOR_MASK))
-+ if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
- return IB_MAD_RESULT_SUCCESS;
- } else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||
- in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1 ||
---
-1.7.0.4
-