xscore-y := xscore_impl.o xs_ud.o xscore_api.o xsmp.o \
xscore_stats.o xscore_uadm.o
-ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8035\"
+ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8037\"
ccflags-y += -DRDMA_PORT_LINK_LAYER_CHANGES -DHAS_SKB_ACCESS_FUNCTIONS
ccflags-y += -DSCSI_STRUCT_CHANGES -DSCSI_TIMEOUT_CHANGES -DLLE
ccflags-y += -DXG_FRAG_SIZE_PRESENT -DXG_FRAG_PAGE_PRESENT
vhba_attr.o vhba_wq.o vhba_proc.o vhba_stats.o vhba_ib.o \
vhba_scsi_intf.o vhba_align.o
-ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8035\"
+ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8037\"
ccflags-y += -DRDMA_PORT_LINK_LAYER_CHANGES -DHAS_SKB_ACCESS_FUNCTIONS
ccflags-y += -DSCSI_STRUCT_CHANGES -DSCSI_TIMEOUT_CHANGES -DLLE
ccflags-y += -DXG_FRAG_SIZE_PRESENT -DXG_FRAG_PAGE_PRESENT
obj-$(CONFIG_INFINIBAND_XSVNIC) := xsvnic.o
xsvnic-y := xsvnic_main.o xsvnic_stats.o
-ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8035\"
+ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8037\"
ccflags-y += -DRDMA_PORT_LINK_LAYER_CHANGES -DHAS_SKB_ACCESS_FUNCTIONS
ccflags-y += -DSCSI_STRUCT_CHANGES -DSCSI_TIMEOUT_CHANGES -DLLE
ccflags-y += -DXG_FRAG_SIZE_PRESENT -DXG_FRAG_PAGE_PRESENT
xve-y := xve_main.o xve_verbs.o xve_multicast.o xve_ib.o xve_tables.o \
xve_ethtool.o xve_cm.o xve_stats.o
-ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8035\"
+ccflags-y += -DXSIGO_LOCAL_VERSION=\"6.0.r8037\"
ccflags-y += -DRDMA_PORT_LINK_LAYER_CHANGES -DHAS_SKB_ACCESS_FUNCTIONS
ccflags-y += -DSCSI_STRUCT_CHANGES -DSCSI_TIMEOUT_CHANGES -DLLE
ccflags-y += -DXG_FRAG_SIZE_PRESENT -DXG_FRAG_PAGE_PRESENT
XVE_FLAG_IB_EVENT = 14,
XVE_FLAG_DONT_DETACH_MCAST = 15,
XVE_MAX_BACKOFF_SECONDS = 16,
+ XVE_DRAIN_IN_PROGRESS = 17,
};
enum xve_advert_types {
XVE_TX_RC_COUNTER,
XVE_RC_RXCOMPL_COUNTER,
XVE_RC_TXCOMPL_COUNTER,
+ XVE_RC_RXCOMPL_ERR_COUNTER,
+ XVE_RC_TXCOMPL_ERR_COUNTER,
XVE_TX_MCAST_PKT,
XVE_TX_BCAST_PKT,
XVE_TX_MCAST_ARP_QUERY,
extern struct workqueue_struct *xve_taskqueue;
extern struct workqueue_struct *xve_workqueue;
extern int xve_mc_sendonly_timeout;
+extern int xve_wait_txcompl;
extern void xve_remove_procfs_root_entries(void);
extern int xve_create_procfs_root_entries(void);
u32 rx_rate;
u32 tx_bytes;
u32 rx_bytes;
+ u32 tx_compl_err;
};
module_param_named(rnr_retry_count, rnr_retry_count, int, 0644);
MODULE_PARM_DESC(rnr_retry_count, "Max number rnr retries");
+int xve_wait_txcompl = 10;
+module_param_named(xve_wait_txcompl, xve_wait_txcompl, int, 0644);
+
+static int xve_modify_qp = 1;
+module_param_named(xve_modify_qp, xve_modify_qp, int, 0644);
+
#define XVE_CM_IETF_ID 0x1000000000000000ULL
#define XVE_CM_RX_UPDATE_TIME (256 * HZ)
wc->qp->qp_num, wc->status, wr_id,
wc->vendor_err);
INC_RX_DROP_STATS(priv, dev);
+ priv->counters[XVE_RC_RXCOMPL_ERR_COUNTER]++;
goto repost;
}
}
static void xve_cm_tx_buf_free(struct xve_dev_priv *priv,
- struct xve_cm_buf *tx_req)
+ struct xve_cm_buf *tx_req,
+ struct xve_cm_ctx *tx,
+ uint32_t wr_id, uint32_t qp_num)
{
- if ((tx_req->skb == NULL) || (tx_req->mapping[0] == 0))
- xve_debug(DEBUG_DATA_INFO, priv,
- "%s Contents of tx_req %p are NULL skb %p mapping %lld\n",
- __func__, tx_req, tx_req->skb, tx_req->mapping[0]);
- else
- ib_dma_unmap_single(priv->ca, tx_req->mapping[0],
- tx_req->skb->len, DMA_TO_DEVICE);
+ BUG_ON(tx_req == NULL || tx_req->skb == NULL);
+ ib_dma_unmap_single(priv->ca, tx_req->mapping[0],
+ tx_req->skb->len, DMA_TO_DEVICE);
xve_dev_kfree_skb_any(priv, tx_req->skb, 1);
memset(tx_req, 0, sizeof(struct xve_cm_buf));
}
xve_warn(priv, "QP[%d] post_send failed wr_id:%d ctx:%p",
tx->qp->qp_num, wr_id, tx);
INC_TX_ERROR_STATS(priv, dev);
- xve_cm_tx_buf_free(priv, tx_req);
+ xve_cm_tx_buf_free(priv, tx_req, tx, 0, tx->qp->qp_num);
} else {
dev->trans_start = jiffies;
++tx->tx_head;
}
tx_req = &tx->tx_ring[wr_id];
- xve_cm_tx_buf_free(priv, tx_req);
+ xve_cm_tx_buf_free(priv, tx_req, tx, wr_id, wc->qp->qp_num);
netif_tx_lock(dev);
++tx->tx_tail;
}
if (wc->status != IB_WC_SUCCESS && wc->status != IB_WC_WR_FLUSH_ERR) {
+ priv->counters[XVE_RC_TXCOMPL_ERR_COUNTER]++;
+ tx->stats.tx_compl_err++;
if (wc->status != IB_WC_RNR_RETRY_EXC_ERR)
xve_warn(priv, "QP[%x] failed cm send event status:%d wrid:%d vend_err:%x",
wc->qp->qp_num, wc->status, wr_id,
return ret;
}
+static int wait_for_txcmcompletions(struct xve_cm_ctx *p, u8 modify)
+{
+ struct xve_dev_priv *priv = netdev_priv(p->netdev);
+ unsigned long begin;
+ uint32_t qpnum = p->qp ? p->qp->qp_num : 0;
+
+
+ if (p->tx_ring) {
+ int num_loops = 0;
+
+ begin = jiffies;
+
+ while ((int)p->tx_tail - (int)p->tx_head < 0) {
+ if (!num_loops && xve_modify_qp && modify) {
+ ib_modify_qp(p->qp, &xve_cm_err_attr,
+ IB_QP_STATE);
+ xve_debug(DEBUG_CM_INFO, priv,
+ "M%d QP[%x] TX completions pending[%d]",
+ modify, qpnum, p->tx_head - p->tx_tail);
+ }
+
+ /* If Oper State is down poll for completions */
+ if (!test_bit(XVE_OPER_UP, &priv->state))
+ xve_drain_cq(priv->netdev);
+
+ if (time_after(jiffies,
+ begin + xve_wait_txcompl * HZ)) {
+ xve_warn(priv,
+ "M%d QP[%x] Tx Completions Pending[%d], Waited[%d:%d] state%d",
+ modify, qpnum, p->tx_head - p->tx_tail,
+ num_loops, xve_wait_txcompl,
+ test_bit(XVE_OPER_UP, &priv->state));
+ return -EINVAL;
+ }
+ num_loops++;
+ msleep(20);
+ }
+ if (num_loops != 0)
+ xve_debug(DEBUG_CM_INFO, priv, "M%d QP%x Overall Wait[%d:%d]",
+ modify, qpnum, num_loops,
+ jiffies_to_msecs(jiffies - begin));
+ }
+
+ return 0;
+}
+
static void xve_cm_tx_destroy(struct xve_cm_ctx *p)
{
struct xve_dev_priv *priv = netdev_priv(p->netdev);
struct xve_cm_buf *tx_req;
- unsigned long begin;
unsigned long flags = 0;
uint32_t qp_num = p->qp ? p->qp->qp_num : 0;
if (p->id)
ib_destroy_cm_id(p->id);
- if (p->tx_ring) {
- /* Wait for all sends to complete */
- if (!netif_carrier_ok(priv->netdev)
- && unlikely(priv->tx_outstanding > MAX_SEND_CQE))
- while (poll_tx(priv))
- ; /* nothing */
+ wait_for_txcmcompletions(p, 1);
- begin = jiffies;
- while ((int)p->tx_tail - (int)p->tx_head < 0) {
- if (time_after(jiffies, begin + 5 * HZ)) {
- xve_warn(priv,
- "timing out; %d sends not completed\n",
- p->tx_head - p->tx_tail);
- goto timeout;
- }
+ /* Destroy QP and Wait for any pending completions */
+ if (p->qp)
+ ib_destroy_qp(p->qp);
- msleep(20);
- }
- }
+ pr_info("%s QP[%x] ctx:%p Destroyed head[0x%x] tail[0x%x]\n",
+ priv->xve_name, qp_num, p, p->tx_head, p->tx_tail);
-timeout:
+ wait_for_txcmcompletions(p, 0);
spin_lock_irqsave(&priv->lock, flags);
while ((int)p->tx_tail - (int)p->tx_head < 0) {
- tx_req = &p->tx_ring[p->tx_tail & (priv->xve_sendq_size - 1)];
+ uint32_t wr_id = p->tx_tail & (priv->xve_sendq_size - 1);
+
+ tx_req = &p->tx_ring[wr_id];
++p->tx_tail;
spin_unlock_irqrestore(&priv->lock, flags);
- xve_cm_tx_buf_free(priv, tx_req);
+ xve_cm_tx_buf_free(priv, tx_req, p, 0, 0);
netif_tx_lock_bh(p->netdev);
if (unlikely(--priv->tx_outstanding ==
(priv->xve_sendq_size >> 1))
}
spin_unlock_irqrestore(&priv->lock, flags);
- xve_warn(priv, "QP[%x] Destroyed, head[0x%x] tail[0x%x]",
- qp_num, p->tx_head, p->tx_tail);
- if (p->qp)
- ib_destroy_qp(p->qp);
if (p->tx_ring)
vfree(p->tx_ring);
if (p != NULL)
}
tx_req = &priv->tx_ring[wr_id];
- if ((tx_req == NULL) || (tx_req->ah == NULL)) {
- xve_debug(DEBUG_DATA_INFO, priv,
- "%s [ca %p] wr_id%d content NULL\n",
- __func__, priv->ca, wr_id);
- return;
- }
+
+ BUG_ON(tx_req == NULL || tx_req->ah == NULL);
xve_put_ah_refcnt(tx_req->ah);
xve_free_txbuf_memory(priv, tx_req);
int poll_tx(struct xve_dev_priv *priv)
{
- int n, i, tot = 0;
+ int n, i;
- do {
- n = ib_poll_cq(priv->send_cq, MAX_SEND_CQE, priv->send_wc);
- /* handle multiple WC's in one call */
- for (i = 0; i < n; ++i)
- xve_ib_handle_tx_wc(priv->netdev,
- priv->send_wc + i);
- if (n < 0) {
- xve_warn(priv, "%s ib_poll_cq() failed, rc %d\n",
- __func__, n);
- }
- tot += n;
- } while (n == MAX_SEND_CQE);
+ n = ib_poll_cq(priv->send_cq, MAX_SEND_CQE, priv->send_wc);
+ /* handle multiple WC's in one call */
+ for (i = 0; i < n; ++i)
+ xve_ib_handle_tx_wc(priv->netdev,
+ priv->send_wc + i);
+ if (n < 0) {
+ xve_warn(priv, "%s ib_poll_cq() failed, rc %d\n",
+ __func__, n);
+ }
- return tot;
+ return n == MAX_SEND_CQE;
}
static int poll_rx(struct xve_dev_priv *priv, int num_polls, int *done,
spin_lock_irqsave(&priv->lock, flags);
if (test_bit(XVE_OPER_UP, &priv->state) &&
!test_bit(XVE_DELETING, &priv->state)) {
- poll_tx(priv);
+ while (poll_tx(priv))
+ ; /* nothing */
}
spin_unlock_irqrestore(&priv->lock, flags);
if (netif_queue_stopped(dev))
int id;
id = priv->tx_head & (priv->xve_sendq_size - 1);
+
+ /*
+ * Gateway broadcast packet's can come as that packets are not
+ * controlled by network layer
+ */
+ if (priv->tx_outstanding >= priv->xve_sendq_size) {
+ xve_warn(priv, "TX QUEUE FULL %d head%d tail%d out%d type%d",
+ id, priv->tx_head, priv->tx_tail,
+ priv->tx_outstanding, type);
+ goto drop_pkt;
+ }
+
if (skb_is_gso(skb)) {
hlen = skb_transport_offset(skb) + tcp_hdrlen(skb);
phead = skb->data;
}
priv->send_hbeat_flag = 0;
- if (unlikely(priv->tx_outstanding > SENDQ_LOW_WMARK)) {
- priv->counters[XVE_TX_WMARK_REACH_COUNTER]++;
- poll_tx(priv);
- }
if (packet_sent)
priv->counters[XVE_TX_COUNTER]++;
{
struct xve_dev_priv *priv = netdev_priv(dev);
int n, done = 0;
+ unsigned long flags = 0;
+ if (test_and_set_bit(XVE_DRAIN_IN_PROGRESS, &priv->flags)) {
+ xve_info(priv, "Drain in progress[%d:%d:%d] state[%lx:%lx]",
+ priv->tx_outstanding, priv->tx_head,
+ priv->tx_tail, priv->flags, priv->state);
+ return;
+ }
/*
* We call completion handling routines that expect to be
* called from the BH-disabled NAPI poll context, so disable
n = poll_rx(priv, XVE_NUM_WC, &done, 1);
} while (n == XVE_NUM_WC);
- poll_tx(priv);
local_bh_enable();
+
+ /* Poll UD completions */
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (priv->tx_outstanding)
+ while (poll_tx(priv))
+ ; /* nothing */
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
+
+ clear_bit(XVE_DRAIN_IN_PROGRESS, &priv->flags);
}
int xve_ib_dev_open(struct net_device *dev)
begin = jiffies;
while (priv->tx_head != priv->tx_tail || recvs_pending(dev)) {
- if (time_after(jiffies, begin + 5 * HZ)) {
+ /* Wait for xve_wait_txcompl seconds */
+ if (time_after(jiffies, begin + xve_wait_txcompl * HZ)) {
xve_warn(priv,
"%s timing out; %d sends %d receives not completed\n",
__func__, priv->tx_head - priv->tx_tail,
skb->dev = dev;
xve_get_ah_refcnt(path->ah);
priv->counters[XVE_PATHREC_GW_COUNTER]++;
- /* Sending the queued GATEWAY Packet */
+ /* Send G/W packet */
+ netif_tx_lock_bh(dev);
+ spin_lock_irqsave(&priv->lock, flags);
+
ret = xve_send(dev, skb, path->ah, priv->gw.t_data_qp, 2);
if (ret == NETDEV_TX_BUSY) {
xve_warn(priv, "send queue full full, dropping packet for %s\n",
priv->xve_name);
- }
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ netif_tx_unlock_bh(dev);
+
}
}
int ret = NETDEV_TX_OK;
path = xve_get_gw_path(dev);
- if (!path)
+ if (!path) {
+ dev_kfree_skb_any(skb);
return NETDEV_TX_BUSY;
+ }
if (path->ah) {
xve_dbg_data(priv, "Sending unicast copy to gw ah:%p dqpn:%u\n",
dev_kfree_skb_any(skb);
spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (unlikely(priv->tx_outstanding > SENDQ_LOW_WMARK)) {
+ priv->counters[XVE_TX_WMARK_REACH_COUNTER]++;
+ mod_timer(&priv->poll_timer, jiffies);
+
+ }
+
return ret;
}
{
if (state) {
priv->jiffies = jiffies;
- priv->counters[XVE_TX_WAKE_UP_COUNTER]++;
netif_carrier_on(priv->netdev);
- netif_wake_queue(priv->netdev);
+ if (netif_queue_stopped(priv->netdev)) {
+ netif_wake_queue(priv->netdev);
+ priv->counters[XVE_TX_WAKE_UP_COUNTER]++;
+ }
/* careful we are holding lock (priv->lock)inside this */
xve_data_recv_handler(priv);
} else {
__func__, xmsgp->xve_name);
return;
}
+ xve_info(priv, "Start Deleting interface");
spin_lock_irqsave(&priv->lock, flags);
set_bit(XVE_DELETING, &priv->state);
+ /*Set OperState to down*/
+ clear_bit(XVE_OPER_UP, &priv->state);
spin_unlock_irqrestore(&priv->lock, flags);
}
if (xsmp_sessions_match(&priv->xsmp_info, xsmp_hndl)) {
spin_lock_irqsave(&priv->lock, flags);
set_bit(XVE_DELETING, &priv->state);
+ /*Set OperState to down*/
+ clear_bit(XVE_OPER_UP, &priv->state);
spin_unlock_irqrestore(&priv->lock, flags);
}
}
list_for_each_entry(priv, &xve_dev_list, list) {
spin_lock_irqsave(&priv->lock, flags);
set_bit(XVE_DELETING, &priv->state);
+ /*Set OperState to down*/
+ clear_bit(XVE_OPER_UP, &priv->state);
set_bit(XVE_SHUTDOWN, &priv->state);
spin_unlock_irqrestore(&priv->lock, flags);
}
"mcast detach count:\t\t",
"tx ud count:\t\t\t",
"tx rc count:\t\t\t",
- "rc tx compl count:\t\t\t",
"rc rx compl count:\t\t\t",
+ "rc tx compl count:\t\t\t",
+ "rc rx compl error count:\t\t",
+ "rc tx compl error count:\t\t",
"tx mcast count:\t\t\t",
"tx broadcast count:\t\t\t",
"tx arp count:\t\t\t",