From 91bc7b69028ff67dab9963b6d06b1235984e1f97 Mon Sep 17 00:00:00 2001 From: David Dillow Date: Fri, 26 Nov 2010 13:02:21 -0500 Subject: [PATCH] --- yaml --- r: 229282 b: refs/heads/master c: f8b6e31e4e46bf514c27fce38783ed5615cca01d h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/infiniband/hw/qib/qib.h | 2 +- trunk/drivers/infiniband/hw/qib/qib_cq.c | 3 +- trunk/drivers/infiniband/hw/qib/qib_driver.c | 155 +------- .../drivers/infiniband/hw/qib/qib_file_ops.c | 10 +- trunk/drivers/infiniband/hw/qib/qib_iba6120.c | 2 +- trunk/drivers/infiniband/hw/qib/qib_iba7220.c | 4 +- trunk/drivers/infiniband/hw/qib/qib_iba7322.c | 373 ++---------------- trunk/drivers/infiniband/hw/qib/qib_init.c | 6 +- trunk/drivers/infiniband/hw/qib/qib_intr.c | 3 +- trunk/drivers/infiniband/hw/qib/qib_keys.c | 80 ++-- trunk/drivers/infiniband/hw/qib/qib_mad.c | 45 +-- trunk/drivers/infiniband/hw/qib/qib_mr.c | 8 +- trunk/drivers/infiniband/hw/qib/qib_qp.c | 32 +- trunk/drivers/infiniband/hw/qib/qib_rc.c | 24 -- trunk/drivers/infiniband/hw/qib/qib_ud.c | 57 +-- .../drivers/infiniband/hw/qib/qib_user_sdma.c | 1 - trunk/drivers/infiniband/hw/qib/qib_verbs.h | 11 +- trunk/drivers/infiniband/ulp/srp/ib_srp.c | 90 ++--- trunk/drivers/infiniband/ulp/srp/ib_srp.h | 10 +- 20 files changed, 196 insertions(+), 722 deletions(-) diff --git a/[refs] b/[refs] index bc63bcf74a92..0a44d1321d37 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 4db62d4786e946e6fc8c2bb1f9201508f7f46c41 +refs/heads/master: f8b6e31e4e46bf514c27fce38783ed5615cca01d diff --git a/trunk/drivers/infiniband/hw/qib/qib.h b/trunk/drivers/infiniband/hw/qib/qib.h index 73225eee3cc6..64c9e7d02d4a 100644 --- a/trunk/drivers/infiniband/hw/qib/qib.h +++ b/trunk/drivers/infiniband/hw/qib/qib.h @@ -766,7 +766,7 @@ struct qib_devdata { void (*f_sdma_hw_start_up)(struct qib_pportdata *); void (*f_sdma_init_early)(struct qib_pportdata *); void (*f_set_cntr_sample)(struct qib_pportdata *, u32, u32); - void (*f_update_usrhead)(struct qib_ctxtdata *, u64, u32, u32, u32); + void (*f_update_usrhead)(struct qib_ctxtdata *, u64, u32, u32); u32 (*f_hdrqempty)(struct qib_ctxtdata *); u64 (*f_portcntr)(struct qib_pportdata *, u32); u32 (*f_read_cntrs)(struct qib_devdata *, loff_t, char **, diff --git a/trunk/drivers/infiniband/hw/qib/qib_cq.c b/trunk/drivers/infiniband/hw/qib/qib_cq.c index 5246aa486bbe..a86cbf880f98 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_cq.c +++ b/trunk/drivers/infiniband/hw/qib/qib_cq.c @@ -100,8 +100,7 @@ void qib_cq_enter(struct qib_cq *cq, struct ib_wc *entry, int solicited) wc->head = next; if (cq->notify == IB_CQ_NEXT_COMP || - (cq->notify == IB_CQ_SOLICITED && - (solicited || entry->status != IB_WC_SUCCESS))) { + (cq->notify == IB_CQ_SOLICITED && solicited)) { cq->notify = IB_CQ_NONE; cq->triggered++; /* diff --git a/trunk/drivers/infiniband/hw/qib/qib_driver.c b/trunk/drivers/infiniband/hw/qib/qib_driver.c index 23e584f4c36c..9cd193603fb1 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_driver.c +++ b/trunk/drivers/infiniband/hw/qib/qib_driver.c @@ -71,11 +71,6 @@ MODULE_DESCRIPTION("QLogic IB driver"); */ #define QIB_PIO_MAXIBHDR 128 -/* - * QIB_MAX_PKT_RCV is the max # if packets processed per receive interrupt. - */ -#define QIB_MAX_PKT_RECV 64 - struct qlogic_ib_stats qib_stats; const char *qib_get_unit_name(int unit) @@ -289,147 +284,14 @@ static inline void *qib_get_egrbuf(const struct qib_ctxtdata *rcd, u32 etail) * Returns 1 if error was a CRC, else 0. * Needed for some chip's synthesized error counters. */ -static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd, - u32 ctxt, u32 eflags, u32 l, u32 etail, - __le32 *rhf_addr, struct qib_message_header *rhdr) +static u32 qib_rcv_hdrerr(struct qib_pportdata *ppd, u32 ctxt, + u32 eflags, u32 l, u32 etail, __le32 *rhf_addr, + struct qib_message_header *hdr) { u32 ret = 0; if (eflags & (QLOGIC_IB_RHF_H_ICRCERR | QLOGIC_IB_RHF_H_VCRCERR)) ret = 1; - else if (eflags == QLOGIC_IB_RHF_H_TIDERR) { - /* For TIDERR and RC QPs premptively schedule a NAK */ - struct qib_ib_header *hdr = (struct qib_ib_header *) rhdr; - struct qib_other_headers *ohdr = NULL; - struct qib_ibport *ibp = &ppd->ibport_data; - struct qib_qp *qp = NULL; - u32 tlen = qib_hdrget_length_in_bytes(rhf_addr); - u16 lid = be16_to_cpu(hdr->lrh[1]); - int lnh = be16_to_cpu(hdr->lrh[0]) & 3; - u32 qp_num; - u32 opcode; - u32 psn; - int diff; - unsigned long flags; - - /* Sanity check packet */ - if (tlen < 24) - goto drop; - - if (lid < QIB_MULTICAST_LID_BASE) { - lid &= ~((1 << ppd->lmc) - 1); - if (unlikely(lid != ppd->lid)) - goto drop; - } - - /* Check for GRH */ - if (lnh == QIB_LRH_BTH) - ohdr = &hdr->u.oth; - else if (lnh == QIB_LRH_GRH) { - u32 vtf; - - ohdr = &hdr->u.l.oth; - if (hdr->u.l.grh.next_hdr != IB_GRH_NEXT_HDR) - goto drop; - vtf = be32_to_cpu(hdr->u.l.grh.version_tclass_flow); - if ((vtf >> IB_GRH_VERSION_SHIFT) != IB_GRH_VERSION) - goto drop; - } else - goto drop; - - /* Get opcode and PSN from packet */ - opcode = be32_to_cpu(ohdr->bth[0]); - opcode >>= 24; - psn = be32_to_cpu(ohdr->bth[2]); - - /* Get the destination QP number. */ - qp_num = be32_to_cpu(ohdr->bth[1]) & QIB_QPN_MASK; - if (qp_num != QIB_MULTICAST_QPN) { - int ruc_res; - qp = qib_lookup_qpn(ibp, qp_num); - if (!qp) - goto drop; - - /* - * Handle only RC QPs - for other QP types drop error - * packet. - */ - spin_lock(&qp->r_lock); - - /* Check for valid receive state. */ - if (!(ib_qib_state_ops[qp->state] & - QIB_PROCESS_RECV_OK)) { - ibp->n_pkt_drops++; - goto unlock; - } - - switch (qp->ibqp.qp_type) { - case IB_QPT_RC: - spin_lock_irqsave(&qp->s_lock, flags); - ruc_res = - qib_ruc_check_hdr( - ibp, hdr, - lnh == QIB_LRH_GRH, - qp, - be32_to_cpu(ohdr->bth[0])); - if (ruc_res) { - spin_unlock_irqrestore(&qp->s_lock, - flags); - goto unlock; - } - spin_unlock_irqrestore(&qp->s_lock, flags); - - /* Only deal with RDMA Writes for now */ - if (opcode < - IB_OPCODE_RC_RDMA_READ_RESPONSE_FIRST) { - diff = qib_cmp24(psn, qp->r_psn); - if (!qp->r_nak_state && diff >= 0) { - ibp->n_rc_seqnak++; - qp->r_nak_state = - IB_NAK_PSN_ERROR; - /* Use the expected PSN. */ - qp->r_ack_psn = qp->r_psn; - /* - * Wait to send the sequence - * NAK until all packets - * in the receive queue have - * been processed. - * Otherwise, we end up - * propagating congestion. - */ - if (list_empty(&qp->rspwait)) { - qp->r_flags |= - QIB_R_RSP_NAK; - atomic_inc( - &qp->refcount); - list_add_tail( - &qp->rspwait, - &rcd->qp_wait_list); - } - } /* Out of sequence NAK */ - } /* QP Request NAKs */ - break; - case IB_QPT_SMI: - case IB_QPT_GSI: - case IB_QPT_UD: - case IB_QPT_UC: - default: - /* For now don't handle any other QP types */ - break; - } - -unlock: - spin_unlock(&qp->r_lock); - /* - * Notify qib_destroy_qp() if it is waiting - * for us to finish. - */ - if (atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); - } /* Unicast QP */ - } /* Valid packet with TIDErr */ - -drop: return ret; } @@ -473,7 +335,7 @@ u32 qib_kreceive(struct qib_ctxtdata *rcd, u32 *llic, u32 *npkts) smp_rmb(); /* prevent speculative reads of dma'ed hdrq */ } - for (last = 0, i = 1; !last; i += !last) { + for (last = 0, i = 1; !last && i <= 64; i += !last) { hdr = dd->f_get_msgheader(dd, rhf_addr); eflags = qib_hdrget_err_flags(rhf_addr); etype = qib_hdrget_rcv_type(rhf_addr); @@ -509,7 +371,7 @@ u32 qib_kreceive(struct qib_ctxtdata *rcd, u32 *llic, u32 *npkts) * packets; only qibhdrerr should be set. */ if (unlikely(eflags)) - crcs += qib_rcv_hdrerr(rcd, ppd, rcd->ctxt, eflags, l, + crcs += qib_rcv_hdrerr(ppd, rcd->ctxt, eflags, l, etail, rhf_addr, hdr); else if (etype == RCVHQ_RCV_TYPE_NON_KD) { qib_ib_rcv(rcd, hdr, ebuf, tlen); @@ -522,9 +384,6 @@ u32 qib_kreceive(struct qib_ctxtdata *rcd, u32 *llic, u32 *npkts) l += rsize; if (l >= maxcnt) l = 0; - if (i == QIB_MAX_PKT_RECV) - last = 1; - rhf_addr = (__le32 *) rcd->rcvhdrq + l + dd->rhf_offset; if (dd->flags & QIB_NODMA_RTAIL) { u32 seq = qib_hdrget_seq(rhf_addr); @@ -543,7 +402,7 @@ u32 qib_kreceive(struct qib_ctxtdata *rcd, u32 *llic, u32 *npkts) */ lval = l; if (!last && !(i & 0xf)) { - dd->f_update_usrhead(rcd, lval, updegr, etail, i); + dd->f_update_usrhead(rcd, lval, updegr, etail); updegr = 0; } } @@ -585,7 +444,7 @@ u32 qib_kreceive(struct qib_ctxtdata *rcd, u32 *llic, u32 *npkts) * if no packets were processed. */ lval = (u64)rcd->head | dd->rhdrhead_intr_off; - dd->f_update_usrhead(rcd, lval, updegr, etail, i); + dd->f_update_usrhead(rcd, lval, updegr, etail); return crcs; } diff --git a/trunk/drivers/infiniband/hw/qib/qib_file_ops.c b/trunk/drivers/infiniband/hw/qib/qib_file_ops.c index 75bfad16c114..79d9971aff1f 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_file_ops.c +++ b/trunk/drivers/infiniband/hw/qib/qib_file_ops.c @@ -1379,17 +1379,17 @@ static int get_a_ctxt(struct file *fp, const struct qib_user_info *uinfo, /* find device (with ACTIVE ports) with fewest ctxts in use */ for (ndev = 0; ndev < devmax; ndev++) { struct qib_devdata *dd = qib_lookup(ndev); - unsigned cused = 0, cfree = 0, pusable = 0; + unsigned cused = 0, cfree = 0; if (!dd) continue; if (port && port <= dd->num_pports && usable(dd->pport + port - 1)) - pusable = 1; + dusable = 1; else for (i = 0; i < dd->num_pports; i++) if (usable(dd->pport + i)) - pusable++; - if (!pusable) + dusable++; + if (!dusable) continue; for (ctxt = dd->first_user_ctxt; ctxt < dd->cfgctxts; ctxt++) @@ -1397,7 +1397,7 @@ static int get_a_ctxt(struct file *fp, const struct qib_user_info *uinfo, cused++; else cfree++; - if (pusable && cfree && cused < inuse) { + if (cfree && cused < inuse) { udd = dd; inuse = cused; } diff --git a/trunk/drivers/infiniband/hw/qib/qib_iba6120.c b/trunk/drivers/infiniband/hw/qib/qib_iba6120.c index 774dea897e9c..a5e29dbb9537 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/trunk/drivers/infiniband/hw/qib/qib_iba6120.c @@ -2074,7 +2074,7 @@ static void qib_6120_config_ctxts(struct qib_devdata *dd) } static void qib_update_6120_usrhead(struct qib_ctxtdata *rcd, u64 hd, - u32 updegr, u32 egrhd, u32 npkts) + u32 updegr, u32 egrhd) { qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); if (updegr) diff --git a/trunk/drivers/infiniband/hw/qib/qib_iba7220.c b/trunk/drivers/infiniband/hw/qib/qib_iba7220.c index 127a0d5069f0..6fd8d74e7392 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/trunk/drivers/infiniband/hw/qib/qib_iba7220.c @@ -2297,7 +2297,7 @@ static void qib_7220_config_ctxts(struct qib_devdata *dd) nchipctxts = qib_read_kreg32(dd, kr_portcnt); dd->cspec->numctxts = nchipctxts; if (qib_n_krcv_queues > 1) { - dd->qpn_mask = 0x3e; + dd->qpn_mask = 0x3f; dd->first_user_ctxt = qib_n_krcv_queues * dd->num_pports; if (dd->first_user_ctxt > nchipctxts) dd->first_user_ctxt = nchipctxts; @@ -2703,7 +2703,7 @@ static int qib_7220_set_loopback(struct qib_pportdata *ppd, const char *what) } static void qib_update_7220_usrhead(struct qib_ctxtdata *rcd, u64 hd, - u32 updegr, u32 egrhd, u32 npkts) + u32 updegr, u32 egrhd) { qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); if (updegr) diff --git a/trunk/drivers/infiniband/hw/qib/qib_iba7322.c b/trunk/drivers/infiniband/hw/qib/qib_iba7322.c index dbbb0e85afe4..584d443b5335 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/trunk/drivers/infiniband/hw/qib/qib_iba7322.c @@ -71,9 +71,6 @@ static void qib_7322_mini_pcs_reset(struct qib_pportdata *); static u32 ahb_mod(struct qib_devdata *, int, int, int, u32, u32); static void ibsd_wr_allchans(struct qib_pportdata *, int, unsigned, unsigned); -static void serdes_7322_los_enable(struct qib_pportdata *, int); -static int serdes_7322_init_old(struct qib_pportdata *); -static int serdes_7322_init_new(struct qib_pportdata *); #define BMASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb)) @@ -114,21 +111,6 @@ static ushort qib_singleport; module_param_named(singleport, qib_singleport, ushort, S_IRUGO); MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space"); -/* - * Receive header queue sizes - */ -static unsigned qib_rcvhdrcnt; -module_param_named(rcvhdrcnt, qib_rcvhdrcnt, uint, S_IRUGO); -MODULE_PARM_DESC(rcvhdrcnt, "receive header count"); - -static unsigned qib_rcvhdrsize; -module_param_named(rcvhdrsize, qib_rcvhdrsize, uint, S_IRUGO); -MODULE_PARM_DESC(rcvhdrsize, "receive header size in 32-bit words"); - -static unsigned qib_rcvhdrentsize; -module_param_named(rcvhdrentsize, qib_rcvhdrentsize, uint, S_IRUGO); -MODULE_PARM_DESC(rcvhdrentsize, "receive header entry size in 32-bit words"); - #define MAX_ATTEN_LEN 64 /* plenty for any real system */ /* for read back, default index is ~5m copper cable */ static char txselect_list[MAX_ATTEN_LEN] = "10"; @@ -562,7 +544,6 @@ static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *); #define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */ #define TXDDS_EXTRA_SZ 13 /* number of extra tx settings entries */ -#define TXDDS_MFG_SZ 2 /* number of mfg tx settings entries */ #define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */ #define H1_FORCE_VAL 8 @@ -623,7 +604,6 @@ struct qib_chippport_specific { u8 ibmalfusesnap; struct qib_qsfp_data qsfp_data; char epmsgbuf[192]; /* for port error interrupt msg buffer */ - u8 bounced; }; static struct { @@ -1697,8 +1677,6 @@ static void handle_serdes_issues(struct qib_pportdata *ppd, u64 ibcst) (ibcst & SYM_MASK(IBCStatusA_0, LinkSpeedQDR))) { force_h1(ppd); ppd->cpspec->qdr_reforce = 1; - if (!ppd->dd->cspec->r1) - serdes_7322_los_enable(ppd, 0); } else if (ppd->cpspec->qdr_reforce && (ibcst & SYM_MASK(IBCStatusA_0, LinkSpeedQDR)) && (ibclt == IB_7322_LT_STATE_CFGENH || @@ -1714,37 +1692,18 @@ static void handle_serdes_issues(struct qib_pportdata *ppd, u64 ibcst) ibclt <= IB_7322_LT_STATE_SLEEPQUIET))) adj_tx_serdes(ppd); - if (ibclt != IB_7322_LT_STATE_LINKUP) { - u8 ltstate = qib_7322_phys_portstate(ibcst); - u8 pibclt = (u8)SYM_FIELD(ppd->lastibcstat, IBCStatusA_0, - LinkTrainingState); - if (!ppd->dd->cspec->r1 && - pibclt == IB_7322_LT_STATE_LINKUP && - ltstate != IB_PHYSPORTSTATE_LINK_ERR_RECOVER && - ltstate != IB_PHYSPORTSTATE_RECOVERY_RETRAIN && - ltstate != IB_PHYSPORTSTATE_RECOVERY_WAITRMT && - ltstate != IB_PHYSPORTSTATE_RECOVERY_IDLE) - /* If the link went down (but no into recovery, - * turn LOS back on */ - serdes_7322_los_enable(ppd, 1); - if (!ppd->cpspec->qdr_dfe_on && - ibclt <= IB_7322_LT_STATE_SLEEPQUIET) { - ppd->cpspec->qdr_dfe_on = 1; - ppd->cpspec->qdr_dfe_time = 0; - /* On link down, reenable QDR adaptation */ - qib_write_kreg_port(ppd, krp_static_adapt_dis(2), - ppd->dd->cspec->r1 ? - QDR_STATIC_ADAPT_DOWN_R1 : - QDR_STATIC_ADAPT_DOWN); - printk(KERN_INFO QIB_DRV_NAME - " IB%u:%u re-enabled QDR adaptation " - "ibclt %x\n", ppd->dd->unit, ppd->port, ibclt); - } + if (!ppd->cpspec->qdr_dfe_on && ibclt != IB_7322_LT_STATE_LINKUP && + ibclt <= IB_7322_LT_STATE_SLEEPQUIET) { + ppd->cpspec->qdr_dfe_on = 1; + ppd->cpspec->qdr_dfe_time = 0; + /* On link down, reenable QDR adaptation */ + qib_write_kreg_port(ppd, krp_static_adapt_dis(2), + ppd->dd->cspec->r1 ? + QDR_STATIC_ADAPT_DOWN_R1 : + QDR_STATIC_ADAPT_DOWN); } } -static int qib_7322_set_ib_cfg(struct qib_pportdata *, int, u32); - /* * This is per-pport error handling. * will likely get it's own MSIx interrupt (one for each port, @@ -1881,23 +1840,7 @@ static noinline void handle_7322_p_errors(struct qib_pportdata *ppd) IB_PHYSPORTSTATE_DISABLED) qib_set_ib_7322_lstate(ppd, 0, QLOGIC_IB_IBCC_LINKINITCMD_DISABLE); - else { - u32 lstate; - /* - * We need the current logical link state before - * lflags are set in handle_e_ibstatuschanged. - */ - lstate = qib_7322_iblink_state(ibcs); - - if (IS_QMH(dd) && !ppd->cpspec->bounced && - ltstate == IB_PHYSPORTSTATE_LINKUP && - (lstate >= IB_PORT_INIT && - lstate <= IB_PORT_ACTIVE)) { - ppd->cpspec->bounced = 1; - qib_7322_set_ib_cfg(ppd, QIB_IB_CFG_LSTATE, - IB_LINKCMD_DOWN | IB_LINKINITCMD_POLL); - } - + else /* * Since going into a recovery state causes the link * state to go down and since recovery is transitory, @@ -1911,7 +1854,6 @@ static noinline void handle_7322_p_errors(struct qib_pportdata *ppd) ltstate != IB_PHYSPORTSTATE_RECOVERY_WAITRMT && ltstate != IB_PHYSPORTSTATE_RECOVERY_IDLE) qib_handle_e_ibstatuschanged(ppd, ibcs); - } } if (*msg && iserr) qib_dev_porterr(dd, ppd->port, "%s error\n", msg); @@ -2843,6 +2785,7 @@ static irqreturn_t qib_7322intr(int irq, void *data) ctxtrbits &= ~rmask; if (dd->rcd[i]) { qib_kreceive(dd->rcd[i], NULL, &npkts); + adjust_rcv_timeout(dd->rcd[i], npkts); } } rmask <<= 1; @@ -2892,6 +2835,7 @@ static irqreturn_t qib_7322pintr(int irq, void *data) (1ULL << QIB_I_RCVURG_LSB)) << rcd->ctxt); qib_kreceive(rcd, NULL, &npkts); + adjust_rcv_timeout(rcd, npkts); return IRQ_HANDLED; } @@ -3213,10 +3157,6 @@ static unsigned qib_7322_boardname(struct qib_devdata *dd) case BOARD_QME7342: n = "InfiniPath_QME7342"; break; - case 8: - n = "InfiniPath_QME7362"; - dd->flags |= QIB_HAS_QSFP; - break; case 15: n = "InfiniPath_QLE7342_TEST"; dd->flags |= QIB_HAS_QSFP; @@ -3535,6 +3475,11 @@ static void qib_7322_config_ctxts(struct qib_devdata *dd) nchipctxts = qib_read_kreg32(dd, kr_contextcnt); dd->cspec->numctxts = nchipctxts; if (qib_n_krcv_queues > 1 && dd->num_pports) { + /* + * Set the mask for which bits from the QPN are used + * to select a context number. + */ + dd->qpn_mask = 0x3f; dd->first_user_ctxt = NUM_IB_PORTS + (qib_n_krcv_queues - 1) * dd->num_pports; if (dd->first_user_ctxt > nchipctxts) @@ -3585,11 +3530,8 @@ static void qib_7322_config_ctxts(struct qib_devdata *dd) /* kr_rcvegrcnt changes based on the number of contexts enabled */ dd->cspec->rcvegrcnt = qib_read_kreg32(dd, kr_rcvegrcnt); - if (qib_rcvhdrcnt) - dd->rcvhdrcnt = max(dd->cspec->rcvegrcnt, qib_rcvhdrcnt); - else - dd->rcvhdrcnt = max(dd->cspec->rcvegrcnt, - dd->num_pports > 1 ? 1024U : 2048U); + dd->rcvhdrcnt = max(dd->cspec->rcvegrcnt, + dd->num_pports > 1 ? 1024U : 2048U); } static int qib_7322_get_ib_cfg(struct qib_pportdata *ppd, int which) @@ -4060,14 +4002,8 @@ static int qib_7322_set_ib_table(struct qib_pportdata *ppd, int which, void *t) } static void qib_update_7322_usrhead(struct qib_ctxtdata *rcd, u64 hd, - u32 updegr, u32 egrhd, u32 npkts) + u32 updegr, u32 egrhd) { - /* - * Need to write timeout register before updating rcvhdrhead to ensure - * that the timer is enabled on reception of a packet. - */ - if (hd >> IBA7322_HDRHEAD_PKTINT_SHIFT) - adjust_rcv_timeout(rcd, npkts); qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); if (updegr) @@ -5586,7 +5522,7 @@ static void qsfp_7322_event(struct work_struct *work) u64 now = get_jiffies_64(); if (time_after64(now, pwrup)) break; - msleep(20); + msleep(1); } ret = qib_refresh_qsfp_cache(ppd, &qd->cache); /* @@ -5643,7 +5579,6 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change) u32 pidx, unit, port, deflt, h1; unsigned long val; int any = 0, seth1; - int txdds_size; str = txselect_list; @@ -5652,10 +5587,6 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change) for (pidx = 0; pidx < dd->num_pports; ++pidx) dd->pport[pidx].cpspec->no_eep = deflt; - txdds_size = TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ; - if (IS_QME(dd) || IS_QMH(dd)) - txdds_size += TXDDS_MFG_SZ; - while (*nxt && nxt[1]) { str = ++nxt; unit = simple_strtoul(str, &nxt, 0); @@ -5678,7 +5609,7 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change) ; continue; } - if (val >= txdds_size) + if (val >= TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ) continue; seth1 = 0; h1 = 0; /* gcc thinks it might be used uninitted */ @@ -5730,11 +5661,10 @@ static int setup_txselect(const char *str, struct kernel_param *kp) return -ENOSPC; } val = simple_strtoul(str, &n, 0); - if (n == str || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ + - TXDDS_MFG_SZ)) { + if (n == str || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)) { printk(KERN_INFO QIB_DRV_NAME "txselect_values must start with a number < %d\n", - TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ + TXDDS_MFG_SZ); + TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ); return -EINVAL; } strcpy(txselect_list, str); @@ -5880,8 +5810,7 @@ static void write_7322_initregs(struct qib_devdata *dd) unsigned n, regno; unsigned long flags; - if (dd->n_krcv_queues < 2 || - !dd->pport[pidx].link_speed_supported) + if (!dd->qpn_mask || !dd->pport[pidx].link_speed_supported) continue; ppd = &dd->pport[pidx]; @@ -6168,10 +6097,8 @@ static int qib_init_7322_variables(struct qib_devdata *dd) ppd++; } - dd->rcvhdrentsize = qib_rcvhdrentsize ? - qib_rcvhdrentsize : QIB_RCVHDR_ENTSIZE; - dd->rcvhdrsize = qib_rcvhdrsize ? - qib_rcvhdrsize : QIB_DFLT_RCVHDRSIZE; + dd->rcvhdrentsize = QIB_RCVHDR_ENTSIZE; + dd->rcvhdrsize = QIB_DFLT_RCVHDRSIZE; dd->rhf_offset = dd->rcvhdrentsize - sizeof(u64) / sizeof(u32); /* we always allocate at least 2048 bytes for eager buffers */ @@ -6568,7 +6495,7 @@ static void qib_7322_txchk_change(struct qib_devdata *dd, u32 start, /* make sure we see an updated copy next time around */ sendctrl_7322_mod(dd->pport, QIB_SENDCTRL_AVAIL_BLIP); sleeps++; - msleep(20); + msleep(1); } switch (which) { @@ -7066,12 +6993,6 @@ static const struct txdds_ent txdds_extra_qdr[TXDDS_EXTRA_SZ] = { { 0, 1, 0, 12 }, /* QMH7342 backplane settings */ }; -static const struct txdds_ent txdds_extra_mfg[TXDDS_MFG_SZ] = { - /* amp, pre, main, post */ - { 0, 0, 0, 0 }, /* QME7342 mfg settings */ - { 0, 0, 0, 6 }, /* QME7342 P2 mfg settings */ -}; - static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds, unsigned atten) { @@ -7145,16 +7066,6 @@ static void find_best_ent(struct qib_pportdata *ppd, *sdr_dds = &txdds_extra_sdr[idx]; *ddr_dds = &txdds_extra_ddr[idx]; *qdr_dds = &txdds_extra_qdr[idx]; - } else if ((IS_QME(ppd->dd) || IS_QMH(ppd->dd)) && - ppd->cpspec->no_eep < (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ + - TXDDS_MFG_SZ)) { - idx = ppd->cpspec->no_eep - (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ); - printk(KERN_INFO QIB_DRV_NAME - " IB%u:%u use idx %u into txdds_mfg\n", - ppd->dd->unit, ppd->port, idx); - *sdr_dds = &txdds_extra_mfg[idx]; - *ddr_dds = &txdds_extra_mfg[idx]; - *qdr_dds = &txdds_extra_mfg[idx]; } else { /* this shouldn't happen, it's range checked */ *sdr_dds = txdds_sdr + qib_long_atten; @@ -7299,30 +7210,9 @@ static void ibsd_wr_allchans(struct qib_pportdata *ppd, int addr, unsigned data, } } -static void serdes_7322_los_enable(struct qib_pportdata *ppd, int enable) -{ - u64 data = qib_read_kreg_port(ppd, krp_serdesctrl); - printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS %s\n", - ppd->dd->unit, ppd->port, (enable ? "on" : "off")); - if (enable) - data |= SYM_MASK(IBSerdesCtrl_0, RXLOSEN); - else - data &= ~SYM_MASK(IBSerdesCtrl_0, RXLOSEN); - qib_write_kreg_port(ppd, krp_serdesctrl, data); -} - static int serdes_7322_init(struct qib_pportdata *ppd) { - int ret = 0; - if (ppd->dd->cspec->r1) - ret = serdes_7322_init_old(ppd); - else - ret = serdes_7322_init_new(ppd); - return ret; -} - -static int serdes_7322_init_old(struct qib_pportdata *ppd) -{ + u64 data; u32 le_val; /* @@ -7380,7 +7270,11 @@ static int serdes_7322_init_old(struct qib_pportdata *ppd) ibsd_wr_allchans(ppd, 20, (2 << 10), BMASK(12, 10)); /* DDR */ ibsd_wr_allchans(ppd, 20, (4 << 13), BMASK(15, 13)); /* SDR */ - serdes_7322_los_enable(ppd, 1); + data = qib_read_kreg_port(ppd, krp_serdesctrl); + /* Turn off IB latency mode */ + data &= ~SYM_MASK(IBSerdesCtrl_0, IB_LAT_MODE); + qib_write_kreg_port(ppd, krp_serdesctrl, data | + SYM_MASK(IBSerdesCtrl_0, RXLOSEN)); /* rxbistena; set 0 to avoid effects of it switch later */ ibsd_wr_allchans(ppd, 9, 0 << 15, 1 << 15); @@ -7420,205 +7314,6 @@ static int serdes_7322_init_old(struct qib_pportdata *ppd) return 0; } -static int serdes_7322_init_new(struct qib_pportdata *ppd) -{ - u64 tstart; - u32 le_val, rxcaldone; - int chan, chan_done = (1 << SERDES_CHANS) - 1; - - /* - * Initialize the Tx DDS tables. Also done every QSFP event, - * for adapters with QSFP - */ - init_txdds_table(ppd, 0); - - /* Clear cmode-override, may be set from older driver */ - ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 0 << 14, 1 << 14); - - /* ensure no tx overrides from earlier driver loads */ - qib_write_kreg_port(ppd, krp_tx_deemph_override, - SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, - reset_tx_deemphasis_override)); - - /* START OF LSI SUGGESTED SERDES BRINGUP */ - /* Reset - Calibration Setup */ - /* Stop DFE adaptaion */ - ibsd_wr_allchans(ppd, 1, 0, BMASK(9, 1)); - /* Disable LE1 */ - ibsd_wr_allchans(ppd, 13, 0, BMASK(5, 5)); - /* Disable autoadapt for LE1 */ - ibsd_wr_allchans(ppd, 1, 0, BMASK(15, 15)); - /* Disable LE2 */ - ibsd_wr_allchans(ppd, 13, 0, BMASK(6, 6)); - /* Disable VGA */ - ibsd_wr_allchans(ppd, 5, 0, BMASK(0, 0)); - /* Disable AFE Offset Cancel */ - ibsd_wr_allchans(ppd, 12, 0, BMASK(12, 12)); - /* Disable Timing Loop */ - ibsd_wr_allchans(ppd, 2, 0, BMASK(3, 3)); - /* Disable Frequency Loop */ - ibsd_wr_allchans(ppd, 2, 0, BMASK(4, 4)); - /* Disable Baseline Wander Correction */ - ibsd_wr_allchans(ppd, 13, 0, BMASK(13, 13)); - /* Disable RX Calibration */ - ibsd_wr_allchans(ppd, 4, 0, BMASK(10, 10)); - /* Disable RX Offset Calibration */ - ibsd_wr_allchans(ppd, 12, 0, BMASK(4, 4)); - /* Select BB CDR */ - ibsd_wr_allchans(ppd, 2, (1 << 15), BMASK(15, 15)); - /* CDR Step Size */ - ibsd_wr_allchans(ppd, 5, 0, BMASK(9, 8)); - /* Enable phase Calibration */ - ibsd_wr_allchans(ppd, 12, (1 << 5), BMASK(5, 5)); - /* DFE Bandwidth [2:14-12] */ - ibsd_wr_allchans(ppd, 2, (4 << 12), BMASK(14, 12)); - /* DFE Config (4 taps only) */ - ibsd_wr_allchans(ppd, 16, 0, BMASK(1, 0)); - /* Gain Loop Bandwidth */ - if (!ppd->dd->cspec->r1) { - ibsd_wr_allchans(ppd, 12, 1 << 12, BMASK(12, 12)); - ibsd_wr_allchans(ppd, 12, 2 << 8, BMASK(11, 8)); - } else { - ibsd_wr_allchans(ppd, 19, (3 << 11), BMASK(13, 11)); - } - /* Baseline Wander Correction Gain [13:4-0] (leave as default) */ - /* Baseline Wander Correction Gain [3:7-5] (leave as default) */ - /* Data Rate Select [5:7-6] (leave as default) */ - /* RX Parralel Word Width [3:10-8] (leave as default) */ - - /* RX REST */ - /* Single- or Multi-channel reset */ - /* RX Analog reset */ - /* RX Digital reset */ - ibsd_wr_allchans(ppd, 0, 0, BMASK(15, 13)); - msleep(20); - /* RX Analog reset */ - ibsd_wr_allchans(ppd, 0, (1 << 14), BMASK(14, 14)); - msleep(20); - /* RX Digital reset */ - ibsd_wr_allchans(ppd, 0, (1 << 13), BMASK(13, 13)); - msleep(20); - - /* setup LoS params; these are subsystem, so chan == 5 */ - /* LoS filter threshold_count on, ch 0-3, set to 8 */ - ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 5, 8 << 11, BMASK(14, 11)); - ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 7, 8 << 4, BMASK(7, 4)); - ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 8, 8 << 11, BMASK(14, 11)); - ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 8 << 4, BMASK(7, 4)); - - /* LoS filter threshold_count off, ch 0-3, set to 4 */ - ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 6, 4 << 0, BMASK(3, 0)); - ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 7, 4 << 8, BMASK(11, 8)); - ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 9, 4 << 0, BMASK(3, 0)); - ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 10, 4 << 8, BMASK(11, 8)); - - /* LoS filter select enabled */ - ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), 5, 9, 1 << 15, 1 << 15); - - /* LoS target data: SDR=4, DDR=2, QDR=1 */ - ibsd_wr_allchans(ppd, 14, (1 << 3), BMASK(5, 3)); /* QDR */ - ibsd_wr_allchans(ppd, 20, (2 << 10), BMASK(12, 10)); /* DDR */ - ibsd_wr_allchans(ppd, 20, (4 << 13), BMASK(15, 13)); /* SDR */ - - /* Turn on LOS on initial SERDES init */ - serdes_7322_los_enable(ppd, 1); - /* FLoop LOS gate: PPM filter enabled */ - ibsd_wr_allchans(ppd, 38, 0 << 10, 1 << 10); - - /* RX LATCH CALIBRATION */ - /* Enable Eyefinder Phase Calibration latch */ - ibsd_wr_allchans(ppd, 15, 1, BMASK(0, 0)); - /* Enable RX Offset Calibration latch */ - ibsd_wr_allchans(ppd, 12, (1 << 4), BMASK(4, 4)); - msleep(20); - /* Start Calibration */ - ibsd_wr_allchans(ppd, 4, (1 << 10), BMASK(10, 10)); - tstart = get_jiffies_64(); - while (chan_done && - !time_after64(tstart, tstart + msecs_to_jiffies(500))) { - msleep(20); - for (chan = 0; chan < SERDES_CHANS; ++chan) { - rxcaldone = ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), - (chan + (chan >> 1)), - 25, 0, 0); - if ((~rxcaldone & (u32)BMASK(9, 9)) == 0 && - (~chan_done & (1 << chan)) == 0) - chan_done &= ~(1 << chan); - } - } - if (chan_done) { - printk(KERN_INFO QIB_DRV_NAME - " Serdes %d calibration not done after .5 sec: 0x%x\n", - IBSD(ppd->hw_pidx), chan_done); - } else { - for (chan = 0; chan < SERDES_CHANS; ++chan) { - rxcaldone = ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), - (chan + (chan >> 1)), - 25, 0, 0); - if ((~rxcaldone & (u32)BMASK(10, 10)) == 0) - printk(KERN_INFO QIB_DRV_NAME - " Serdes %d chan %d calibration " - "failed\n", IBSD(ppd->hw_pidx), chan); - } - } - - /* Turn off Calibration */ - ibsd_wr_allchans(ppd, 4, 0, BMASK(10, 10)); - msleep(20); - - /* BRING RX UP */ - /* Set LE2 value (May be overridden in qsfp_7322_event) */ - le_val = IS_QME(ppd->dd) ? LE2_QME : LE2_DEFAULT; - ibsd_wr_allchans(ppd, 13, (le_val << 7), BMASK(9, 7)); - /* Set LE2 Loop bandwidth */ - ibsd_wr_allchans(ppd, 3, (7 << 5), BMASK(7, 5)); - /* Enable LE2 */ - ibsd_wr_allchans(ppd, 13, (1 << 6), BMASK(6, 6)); - msleep(20); - /* Enable H0 only */ - ibsd_wr_allchans(ppd, 1, 1, BMASK(9, 1)); - /* gain hi stop 32 (22) (6:1) lo stop 7 (10:7) target 22 (13) (15:11) */ - le_val = (ppd->dd->cspec->r1 || IS_QME(ppd->dd)) ? 0xb6c0 : 0x6bac; - ibsd_wr_allchans(ppd, 21, le_val, 0xfffe); - /* Enable VGA */ - ibsd_wr_allchans(ppd, 5, 0, BMASK(0, 0)); - msleep(20); - /* Set Frequency Loop Bandwidth */ - ibsd_wr_allchans(ppd, 2, (7 << 5), BMASK(8, 5)); - /* Enable Frequency Loop */ - ibsd_wr_allchans(ppd, 2, (1 << 4), BMASK(4, 4)); - /* Set Timing Loop Bandwidth */ - ibsd_wr_allchans(ppd, 2, 0, BMASK(11, 9)); - /* Enable Timing Loop */ - ibsd_wr_allchans(ppd, 2, (1 << 3), BMASK(3, 3)); - msleep(50); - /* Enable DFE - * Set receive adaptation mode. SDR and DDR adaptation are - * always on, and QDR is initially enabled; later disabled. - */ - qib_write_kreg_port(ppd, krp_static_adapt_dis(0), 0ULL); - qib_write_kreg_port(ppd, krp_static_adapt_dis(1), 0ULL); - qib_write_kreg_port(ppd, krp_static_adapt_dis(2), - ppd->dd->cspec->r1 ? - QDR_STATIC_ADAPT_DOWN_R1 : QDR_STATIC_ADAPT_DOWN); - ppd->cpspec->qdr_dfe_on = 1; - /* Disable LE1 */ - ibsd_wr_allchans(ppd, 13, (0 << 5), (1 << 5)); - /* Disable auto adapt for LE1 */ - ibsd_wr_allchans(ppd, 1, (0 << 15), BMASK(15, 15)); - msleep(20); - /* Enable AFE Offset Cancel */ - ibsd_wr_allchans(ppd, 12, (1 << 12), BMASK(12, 12)); - /* Enable Baseline Wander Correction */ - ibsd_wr_allchans(ppd, 12, (1 << 13), BMASK(13, 13)); - /* Termination: rxtermctrl_r2d addr 11 bits [12:11] = 1 */ - ibsd_wr_allchans(ppd, 11, (1 << 11), BMASK(12, 11)); - /* VGA output common mode */ - ibsd_wr_allchans(ppd, 12, (3 << 2), BMASK(3, 2)); - - return 0; -} - /* start adjust QMH serdes parameters */ static void set_man_code(struct qib_pportdata *ppd, int chan, int code) diff --git a/trunk/drivers/infiniband/hw/qib/qib_init.c b/trunk/drivers/infiniband/hw/qib/qib_init.c index 7896afbb9ce8..f3b503936043 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_init.c +++ b/trunk/drivers/infiniband/hw/qib/qib_init.c @@ -92,11 +92,9 @@ unsigned long *qib_cpulist; /* set number of contexts we'll actually use */ void qib_set_ctxtcnt(struct qib_devdata *dd) { - if (!qib_cfgctxts) { + if (!qib_cfgctxts) dd->cfgctxts = dd->first_user_ctxt + num_online_cpus(); - if (dd->cfgctxts > dd->ctxtcnt) - dd->cfgctxts = dd->ctxtcnt; - } else if (qib_cfgctxts < dd->num_pports) + else if (qib_cfgctxts < dd->num_pports) dd->cfgctxts = dd->ctxtcnt; else if (qib_cfgctxts <= dd->ctxtcnt) dd->cfgctxts = qib_cfgctxts; diff --git a/trunk/drivers/infiniband/hw/qib/qib_intr.c b/trunk/drivers/infiniband/hw/qib/qib_intr.c index a693c56ec8a6..54a40828a106 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_intr.c +++ b/trunk/drivers/infiniband/hw/qib/qib_intr.c @@ -131,8 +131,7 @@ void qib_handle_e_ibstatuschanged(struct qib_pportdata *ppd, u64 ibcs) /* start a 75msec timer to clear symbol errors */ mod_timer(&ppd->symerr_clear_timer, msecs_to_jiffies(75)); - } else if (ltstate == IB_PHYSPORTSTATE_LINKUP && - !(ppd->lflags & QIBL_LINKACTIVE)) { + } else if (ltstate == IB_PHYSPORTSTATE_LINKUP) { /* active, but not active defered */ qib_hol_up(ppd); /* useful only for 6120 now */ *ppd->statusp |= diff --git a/trunk/drivers/infiniband/hw/qib/qib_keys.c b/trunk/drivers/infiniband/hw/qib/qib_keys.c index 8fd19a47df0c..4b80eb153d57 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_keys.c +++ b/trunk/drivers/infiniband/hw/qib/qib_keys.c @@ -136,6 +136,7 @@ int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd, struct qib_mregion *mr; unsigned n, m; size_t off; + int ret = 0; unsigned long flags; /* @@ -151,8 +152,6 @@ int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd, if (!dev->dma_mr) goto bail; atomic_inc(&dev->dma_mr->refcount); - spin_unlock_irqrestore(&rkt->lock, flags); - isge->mr = dev->dma_mr; isge->vaddr = (void *) sge->addr; isge->length = sge->length; @@ -171,34 +170,19 @@ int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd, off + sge->length > mr->length || (mr->access_flags & acc) != acc)) goto bail; - atomic_inc(&mr->refcount); - spin_unlock_irqrestore(&rkt->lock, flags); off += mr->offset; - if (mr->page_shift) { - /* - page sizes are uniform power of 2 so no loop is necessary - entries_spanned_by_off is the number of times the loop below - would have executed. - */ - size_t entries_spanned_by_off; - - entries_spanned_by_off = off >> mr->page_shift; - off -= (entries_spanned_by_off << mr->page_shift); - m = entries_spanned_by_off/QIB_SEGSZ; - n = entries_spanned_by_off%QIB_SEGSZ; - } else { - m = 0; - n = 0; - while (off >= mr->map[m]->segs[n].length) { - off -= mr->map[m]->segs[n].length; - n++; - if (n >= QIB_SEGSZ) { - m++; - n = 0; - } + m = 0; + n = 0; + while (off >= mr->map[m]->segs[n].length) { + off -= mr->map[m]->segs[n].length; + n++; + if (n >= QIB_SEGSZ) { + m++; + n = 0; } } + atomic_inc(&mr->refcount); isge->mr = mr; isge->vaddr = mr->map[m]->segs[n].vaddr + off; isge->length = mr->map[m]->segs[n].length - off; @@ -206,10 +190,10 @@ int qib_lkey_ok(struct qib_lkey_table *rkt, struct qib_pd *pd, isge->m = m; isge->n = n; ok: - return 1; + ret = 1; bail: spin_unlock_irqrestore(&rkt->lock, flags); - return 0; + return ret; } /** @@ -230,6 +214,7 @@ int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge, struct qib_mregion *mr; unsigned n, m; size_t off; + int ret = 0; unsigned long flags; /* @@ -246,8 +231,6 @@ int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge, if (!dev->dma_mr) goto bail; atomic_inc(&dev->dma_mr->refcount); - spin_unlock_irqrestore(&rkt->lock, flags); - sge->mr = dev->dma_mr; sge->vaddr = (void *) vaddr; sge->length = len; @@ -265,34 +248,19 @@ int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge, if (unlikely(vaddr < mr->iova || off + len > mr->length || (mr->access_flags & acc) == 0)) goto bail; - atomic_inc(&mr->refcount); - spin_unlock_irqrestore(&rkt->lock, flags); off += mr->offset; - if (mr->page_shift) { - /* - page sizes are uniform power of 2 so no loop is necessary - entries_spanned_by_off is the number of times the loop below - would have executed. - */ - size_t entries_spanned_by_off; - - entries_spanned_by_off = off >> mr->page_shift; - off -= (entries_spanned_by_off << mr->page_shift); - m = entries_spanned_by_off/QIB_SEGSZ; - n = entries_spanned_by_off%QIB_SEGSZ; - } else { - m = 0; - n = 0; - while (off >= mr->map[m]->segs[n].length) { - off -= mr->map[m]->segs[n].length; - n++; - if (n >= QIB_SEGSZ) { - m++; - n = 0; - } + m = 0; + n = 0; + while (off >= mr->map[m]->segs[n].length) { + off -= mr->map[m]->segs[n].length; + n++; + if (n >= QIB_SEGSZ) { + m++; + n = 0; } } + atomic_inc(&mr->refcount); sge->mr = mr; sge->vaddr = mr->map[m]->segs[n].vaddr + off; sge->length = mr->map[m]->segs[n].length - off; @@ -300,10 +268,10 @@ int qib_rkey_ok(struct qib_qp *qp, struct qib_sge *sge, sge->m = m; sge->n = n; ok: - return 1; + ret = 1; bail: spin_unlock_irqrestore(&rkt->lock, flags); - return 0; + return ret; } /* diff --git a/trunk/drivers/infiniband/hw/qib/qib_mad.c b/trunk/drivers/infiniband/hw/qib/qib_mad.c index 5ad224e4a38b..94b0d1f3a8f0 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_mad.c +++ b/trunk/drivers/infiniband/hw/qib/qib_mad.c @@ -668,8 +668,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, lid = be16_to_cpu(pip->lid); /* Must be a valid unicast LID address. */ if (lid == 0 || lid >= QIB_MULTICAST_LID_BASE) - smp->status |= IB_SMP_INVALID_FIELD; - else if (ppd->lid != lid || ppd->lmc != (pip->mkeyprot_resv_lmc & 7)) { + goto err; + if (ppd->lid != lid || ppd->lmc != (pip->mkeyprot_resv_lmc & 7)) { if (ppd->lid != lid) qib_set_uevent_bits(ppd, _QIB_EVENT_LID_CHANGE_BIT); if (ppd->lmc != (pip->mkeyprot_resv_lmc & 7)) @@ -683,8 +683,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, msl = pip->neighbormtu_mastersmsl & 0xF; /* Must be a valid unicast LID address. */ if (smlid == 0 || smlid >= QIB_MULTICAST_LID_BASE) - smp->status |= IB_SMP_INVALID_FIELD; - else if (smlid != ibp->sm_lid || msl != ibp->sm_sl) { + goto err; + if (smlid != ibp->sm_lid || msl != ibp->sm_sl) { spin_lock_irqsave(&ibp->lock, flags); if (ibp->sm_ah) { if (smlid != ibp->sm_lid) @@ -707,9 +707,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, if (lwe == 0xFF) lwe = ppd->link_width_supported; else if (lwe >= 16 || (lwe & ~ppd->link_width_supported)) - smp->status |= IB_SMP_INVALID_FIELD; - else if (lwe != ppd->link_width_enabled) - set_link_width_enabled(ppd, lwe); + goto err; + set_link_width_enabled(ppd, lwe); } lse = pip->linkspeedactive_enabled & 0xF; @@ -722,9 +721,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, if (lse == 15) lse = ppd->link_speed_supported; else if (lse >= 8 || (lse & ~ppd->link_speed_supported)) - smp->status |= IB_SMP_INVALID_FIELD; - else if (lse != ppd->link_speed_enabled) - set_link_speed_enabled(ppd, lse); + goto err; + set_link_speed_enabled(ppd, lse); } /* Set link down default state. */ @@ -740,7 +738,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, IB_LINKINITCMD_POLL); break; default: - smp->status |= IB_SMP_INVALID_FIELD; + goto err; } ibp->mkeyprot = pip->mkeyprot_resv_lmc >> 6; @@ -750,17 +748,15 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, mtu = ib_mtu_enum_to_int((pip->neighbormtu_mastersmsl >> 4) & 0xF); if (mtu == -1) - smp->status |= IB_SMP_INVALID_FIELD; - else - qib_set_mtu(ppd, mtu); + goto err; + qib_set_mtu(ppd, mtu); /* Set operational VLs */ vls = (pip->operationalvl_pei_peo_fpi_fpo >> 4) & 0xF; if (vls) { if (vls > ppd->vls_supported) - smp->status |= IB_SMP_INVALID_FIELD; - else - (void) dd->f_set_ib_cfg(ppd, QIB_IB_CFG_OP_VLS, vls); + goto err; + (void) dd->f_set_ib_cfg(ppd, QIB_IB_CFG_OP_VLS, vls); } if (pip->mkey_violations == 0) @@ -774,10 +770,10 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, ore = pip->localphyerrors_overrunerrors; if (set_phyerrthreshold(ppd, (ore >> 4) & 0xF)) - smp->status |= IB_SMP_INVALID_FIELD; + goto err; if (set_overrunthreshold(ppd, (ore & 0xF))) - smp->status |= IB_SMP_INVALID_FIELD; + goto err; ibp->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F; @@ -796,7 +792,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, state = pip->linkspeed_portstate & 0xF; lstate = (pip->portphysstate_linkdown >> 4) & 0xF; if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP)) - smp->status |= IB_SMP_INVALID_FIELD; + goto err; /* * Only state changes of DOWN, ARM, and ACTIVE are valid @@ -816,10 +812,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, lstate = QIB_IB_LINKDOWN; else if (lstate == 3) lstate = QIB_IB_LINKDOWN_DISABLE; - else { - smp->status |= IB_SMP_INVALID_FIELD; - break; - } + else + goto err; spin_lock_irqsave(&ppd->lflags_lock, flags); ppd->lflags &= ~QIBL_LINKV; spin_unlock_irqrestore(&ppd->lflags_lock, flags); @@ -841,7 +835,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, qib_set_linkstate(ppd, QIB_IB_LINKACTIVE); break; default: - smp->status |= IB_SMP_INVALID_FIELD; + /* XXX We have already partially updated our state! */ + goto err; } ret = subn_get_portinfo(smp, ibdev, port); diff --git a/trunk/drivers/infiniband/hw/qib/qib_mr.c b/trunk/drivers/infiniband/hw/qib/qib_mr.c index 08944e2ee334..5f95f0f6385d 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_mr.c +++ b/trunk/drivers/infiniband/hw/qib/qib_mr.c @@ -39,6 +39,7 @@ /* Fast memory region */ struct qib_fmr { struct ib_fmr ibfmr; + u8 page_shift; struct qib_mregion mr; /* must be last */ }; @@ -106,7 +107,6 @@ static struct qib_mr *alloc_mr(int count, struct qib_lkey_table *lk_table) goto bail; } mr->mr.mapsz = m; - mr->mr.page_shift = 0; mr->mr.max_segs = count; /* @@ -231,8 +231,6 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, mr->mr.access_flags = mr_access_flags; mr->umem = umem; - if (is_power_of_2(umem->page_size)) - mr->mr.page_shift = ilog2(umem->page_size); m = 0; n = 0; list_for_each_entry(chunk, &umem->chunk_list, list) { @@ -392,7 +390,7 @@ struct ib_fmr *qib_alloc_fmr(struct ib_pd *pd, int mr_access_flags, fmr->mr.offset = 0; fmr->mr.access_flags = mr_access_flags; fmr->mr.max_segs = fmr_attr->max_pages; - fmr->mr.page_shift = fmr_attr->page_shift; + fmr->page_shift = fmr_attr->page_shift; atomic_set(&fmr->mr.refcount, 0); ret = &fmr->ibfmr; @@ -439,7 +437,7 @@ int qib_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, spin_lock_irqsave(&rkt->lock, flags); fmr->mr.user_base = iova; fmr->mr.iova = iova; - ps = 1 << fmr->mr.page_shift; + ps = 1 << fmr->page_shift; fmr->mr.length = list_len * ps; m = 0; n = 0; diff --git a/trunk/drivers/infiniband/hw/qib/qib_qp.c b/trunk/drivers/infiniband/hw/qib/qib_qp.c index e16751f8639e..6c39851d2ded 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_qp.c +++ b/trunk/drivers/infiniband/hw/qib/qib_qp.c @@ -48,12 +48,13 @@ static inline unsigned mk_qpn(struct qib_qpn_table *qpt, static inline unsigned find_next_offset(struct qib_qpn_table *qpt, struct qpn_map *map, unsigned off, - unsigned n) + unsigned r) { if (qpt->mask) { off++; - if (((off & qpt->mask) >> 1) >= n) - off = (off | qpt->mask) + 2; + if ((off & qpt->mask) >> 1 != r) + off = ((off & qpt->mask) ? + (off | qpt->mask) + 1 : off) | (r << 1); } else off = find_next_zero_bit(map->page, BITS_PER_PAGE, off); return off; @@ -122,6 +123,7 @@ static int alloc_qpn(struct qib_devdata *dd, struct qib_qpn_table *qpt, u32 i, offset, max_scan, qpn; struct qpn_map *map; u32 ret; + int r; if (type == IB_QPT_SMI || type == IB_QPT_GSI) { unsigned n; @@ -137,11 +139,15 @@ static int alloc_qpn(struct qib_devdata *dd, struct qib_qpn_table *qpt, goto bail; } - qpn = qpt->last + 2; + r = smp_processor_id(); + if (r >= dd->n_krcv_queues) + r %= dd->n_krcv_queues; + qpn = qpt->last + 1; if (qpn >= QPN_MAX) qpn = 2; - if (qpt->mask && ((qpn & qpt->mask) >> 1) >= dd->n_krcv_queues) - qpn = (qpn | qpt->mask) + 2; + if (qpt->mask && ((qpn & qpt->mask) >> 1) != r) + qpn = ((qpn & qpt->mask) ? (qpn | qpt->mask) + 1 : qpn) | + (r << 1); offset = qpn & BITS_PER_PAGE_MASK; map = &qpt->map[qpn / BITS_PER_PAGE]; max_scan = qpt->nmaps - !offset; @@ -157,8 +163,7 @@ static int alloc_qpn(struct qib_devdata *dd, struct qib_qpn_table *qpt, ret = qpn; goto bail; } - offset = find_next_offset(qpt, map, offset, - dd->n_krcv_queues); + offset = find_next_offset(qpt, map, offset, r); qpn = mk_qpn(qpt, map, offset); /* * This test differs from alloc_pidmap(). @@ -178,13 +183,13 @@ static int alloc_qpn(struct qib_devdata *dd, struct qib_qpn_table *qpt, if (qpt->nmaps == QPNMAP_ENTRIES) break; map = &qpt->map[qpt->nmaps++]; - offset = 0; + offset = qpt->mask ? (r << 1) : 0; } else if (map < &qpt->map[qpt->nmaps]) { ++map; - offset = 0; + offset = qpt->mask ? (r << 1) : 0; } else { map = &qpt->map[0]; - offset = 2; + offset = qpt->mask ? (r << 1) : 2; } qpn = mk_qpn(qpt, map, offset); } @@ -463,10 +468,6 @@ int qib_error_qp(struct qib_qp *qp, enum ib_wc_status err) qp->s_flags &= ~(QIB_S_TIMER | QIB_S_WAIT_RNR); del_timer(&qp->s_timer); } - - if (qp->s_flags & QIB_S_ANY_WAIT_SEND) - qp->s_flags &= ~QIB_S_ANY_WAIT_SEND; - spin_lock(&dev->pending_lock); if (!list_empty(&qp->iowait) && !(qp->s_flags & QIB_S_BUSY)) { qp->s_flags &= ~QIB_S_ANY_WAIT_IO; @@ -1060,6 +1061,7 @@ struct ib_qp *qib_create_qp(struct ib_pd *ibpd, } qp->ibqp.qp_num = err; qp->port_num = init_attr->port_num; + qp->processor_id = smp_processor_id(); qib_reset_qp(qp, init_attr->qp_type); break; diff --git a/trunk/drivers/infiniband/hw/qib/qib_rc.c b/trunk/drivers/infiniband/hw/qib/qib_rc.c index 8245237b67ce..955fb7157793 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_rc.c +++ b/trunk/drivers/infiniband/hw/qib/qib_rc.c @@ -1407,7 +1407,6 @@ static void qib_rc_rcv_resp(struct qib_ibport *ibp, struct qib_ctxtdata *rcd) { struct qib_swqe *wqe; - struct qib_pportdata *ppd = ppd_from_ibp(ibp); enum ib_wc_status status; unsigned long flags; int diff; @@ -1415,29 +1414,6 @@ static void qib_rc_rcv_resp(struct qib_ibport *ibp, u32 aeth; u64 val; - if (opcode != OP(RDMA_READ_RESPONSE_MIDDLE)) { - /* - * If ACK'd PSN on SDMA busy list try to make progress to - * reclaim SDMA credits. - */ - if ((qib_cmp24(psn, qp->s_sending_psn) >= 0) && - (qib_cmp24(qp->s_sending_psn, qp->s_sending_hpsn) <= 0)) { - - /* - * If send tasklet not running attempt to progress - * SDMA queue. - */ - if (!(qp->s_flags & QIB_S_BUSY)) { - /* Acquire SDMA Lock */ - spin_lock_irqsave(&ppd->sdma_lock, flags); - /* Invoke sdma make progress */ - qib_sdma_make_progress(ppd); - /* Release SDMA Lock */ - spin_unlock_irqrestore(&ppd->sdma_lock, flags); - } - } - } - spin_lock_irqsave(&qp->s_lock, flags); /* Ignore invalid responses. */ diff --git a/trunk/drivers/infiniband/hw/qib/qib_ud.c b/trunk/drivers/infiniband/hw/qib/qib_ud.c index 4a51fd1e9cb7..e1b3da2a1f85 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_ud.c +++ b/trunk/drivers/infiniband/hw/qib/qib_ud.c @@ -445,14 +445,13 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr, qkey = be32_to_cpu(ohdr->u.ud.deth[0]); src_qp = be32_to_cpu(ohdr->u.ud.deth[1]) & QIB_QPN_MASK; - /* - * Get the number of bytes the message was padded by - * and drop incomplete packets. - */ + /* Get the number of bytes the message was padded by. */ pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3; - if (unlikely(tlen < (hdrsize + pad + 4))) - goto drop; - + if (unlikely(tlen < (hdrsize + pad + 4))) { + /* Drop incomplete packets. */ + ibp->n_pkt_drops++; + goto bail; + } tlen -= hdrsize + pad + 4; /* @@ -461,8 +460,10 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr, */ if (qp->ibqp.qp_num) { if (unlikely(hdr->lrh[1] == IB_LID_PERMISSIVE || - hdr->lrh[3] == IB_LID_PERMISSIVE)) - goto drop; + hdr->lrh[3] == IB_LID_PERMISSIVE)) { + ibp->n_pkt_drops++; + goto bail; + } if (qp->ibqp.qp_num > 1) { u16 pkey1, pkey2; @@ -475,7 +476,7 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr, 0xF, src_qp, qp->ibqp.qp_num, hdr->lrh[3], hdr->lrh[1]); - return; + goto bail; } } if (unlikely(qkey != qp->qkey)) { @@ -483,24 +484,30 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr, (be16_to_cpu(hdr->lrh[0]) >> 4) & 0xF, src_qp, qp->ibqp.qp_num, hdr->lrh[3], hdr->lrh[1]); - return; + goto bail; } /* Drop invalid MAD packets (see 13.5.3.1). */ if (unlikely(qp->ibqp.qp_num == 1 && (tlen != 256 || - (be16_to_cpu(hdr->lrh[0]) >> 12) == 15))) - goto drop; + (be16_to_cpu(hdr->lrh[0]) >> 12) == 15))) { + ibp->n_pkt_drops++; + goto bail; + } } else { struct ib_smp *smp; /* Drop invalid MAD packets (see 13.5.3.1). */ - if (tlen != 256 || (be16_to_cpu(hdr->lrh[0]) >> 12) != 15) - goto drop; + if (tlen != 256 || (be16_to_cpu(hdr->lrh[0]) >> 12) != 15) { + ibp->n_pkt_drops++; + goto bail; + } smp = (struct ib_smp *) data; if ((hdr->lrh[1] == IB_LID_PERMISSIVE || hdr->lrh[3] == IB_LID_PERMISSIVE) && - smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) - goto drop; + smp->mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) { + ibp->n_pkt_drops++; + goto bail; + } } /* @@ -512,12 +519,14 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr, opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) { wc.ex.imm_data = ohdr->u.ud.imm_data; wc.wc_flags = IB_WC_WITH_IMM; - tlen -= sizeof(u32); + hdrsize += sizeof(u32); } else if (opcode == IB_OPCODE_UD_SEND_ONLY) { wc.ex.imm_data = 0; wc.wc_flags = 0; - } else - goto drop; + } else { + ibp->n_pkt_drops++; + goto bail; + } /* * A GRH is expected to preceed the data even if not @@ -547,7 +556,8 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr, /* Silently drop packets which are too big. */ if (unlikely(wc.byte_len > qp->r_len)) { qp->r_flags |= QIB_R_REUSE_SGE; - goto drop; + ibp->n_pkt_drops++; + return; } if (has_grh) { qib_copy_sge(&qp->r_sge, &hdr->u.l.grh, @@ -584,8 +594,5 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct qib_ib_header *hdr, qib_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, (ohdr->bth[0] & cpu_to_be32(IB_BTH_SOLICITED)) != 0); - return; - -drop: - ibp->n_pkt_drops++; +bail:; } diff --git a/trunk/drivers/infiniband/hw/qib/qib_user_sdma.c b/trunk/drivers/infiniband/hw/qib/qib_user_sdma.c index 66208bcd7c13..4c19e06b5e85 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_user_sdma.c +++ b/trunk/drivers/infiniband/hw/qib/qib_user_sdma.c @@ -382,7 +382,6 @@ static void qib_user_sdma_free_pkt_list(struct device *dev, kmem_cache_free(pq->pkt_slab, pkt); } - INIT_LIST_HEAD(list); } /* diff --git a/trunk/drivers/infiniband/hw/qib/qib_verbs.h b/trunk/drivers/infiniband/hw/qib/qib_verbs.h index 63b22a9a7feb..bd57c1273225 100644 --- a/trunk/drivers/infiniband/hw/qib/qib_verbs.h +++ b/trunk/drivers/infiniband/hw/qib/qib_verbs.h @@ -301,7 +301,6 @@ struct qib_mregion { int access_flags; u32 max_segs; /* number of qib_segs in all the arrays */ u32 mapsz; /* size of the map array */ - u8 page_shift; /* 0 - non unform/non powerof2 sizes */ atomic_t refcount; struct qib_segarray *map[0]; /* the segments */ }; @@ -436,6 +435,7 @@ struct qib_qp { spinlock_t r_lock; /* used for APM */ spinlock_t s_lock; atomic_t s_dma_busy; + unsigned processor_id; /* Processor ID QP is bound to */ u32 s_flags; u32 s_cur_size; /* size of send packet in bytes */ u32 s_len; /* total length of s_sge */ @@ -813,8 +813,13 @@ extern struct workqueue_struct *qib_cq_wq; */ static inline void qib_schedule_send(struct qib_qp *qp) { - if (qib_send_ok(qp)) - queue_work(qib_wq, &qp->s_work); + if (qib_send_ok(qp)) { + if (qp->processor_id == smp_processor_id()) + queue_work(qib_wq, &qp->s_work); + else + queue_work_on(qp->processor_id, + qib_wq, &qp->s_work); + } } static inline int qib_pkey_ok(u16 pkey1, u16 pkey2) diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.c b/trunk/drivers/infiniband/ulp/srp/ib_srp.c index 1e1e347a7715..29429a13fd90 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.c +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.c @@ -542,6 +542,7 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, static void srp_remove_req(struct srp_target_port *target, struct srp_request *req) { srp_unmap_data(req->scmnd, target, req); + req->scmnd = NULL; list_move_tail(&req->list, &target->free_reqs); } @@ -925,15 +926,13 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) target->req_lim += delta; - req = &target->req_ring[rsp->tag & ~SRP_TAG_TSK_MGMT]; - if (unlikely(rsp->tag & SRP_TAG_TSK_MGMT)) { - if (be32_to_cpu(rsp->resp_data_len) < 4) - req->tsk_status = -1; - else - req->tsk_status = rsp->data[3]; - complete(&req->done); + target->tsk_mgmt_status = -1; + if (be32_to_cpu(rsp->resp_data_len) >= 4) + target->tsk_mgmt_status = rsp->data[3]; + complete(&target->tsk_mgmt_done); } else { + req = &target->req_ring[rsp->tag]; scmnd = req->scmnd; if (!scmnd) shost_printk(KERN_ERR, target->scsi_host, @@ -953,13 +952,9 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER)) scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt)); - if (!req->tsk_mgmt) { - scmnd->host_scribble = (void *) -1L; - scmnd->scsi_done(scmnd); - - srp_remove_req(target, req); - } else - req->cmd_done = 1; + scmnd->host_scribble = NULL; + scmnd->scsi_done(scmnd); + srp_remove_req(target, req); } spin_unlock_irqrestore(target->scsi_host->host_lock, flags); @@ -1155,7 +1150,7 @@ static int srp_queuecommand_lck(struct scsi_cmnd *scmnd, scmnd->scsi_done = done; scmnd->result = 0; - scmnd->host_scribble = (void *) (long) req->index; + scmnd->host_scribble = (void *) req; cmd = iu->buf; memset(cmd, 0, sizeof *cmd); @@ -1167,8 +1162,6 @@ static int srp_queuecommand_lck(struct scsi_cmnd *scmnd, req->scmnd = scmnd; req->cmd = iu; - req->cmd_done = 0; - req->tsk_mgmt = NULL; len = srp_map_data(scmnd, target, req); if (len < 0) { @@ -1442,7 +1435,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) } static int srp_send_tsk_mgmt(struct srp_target_port *target, - struct srp_request *req, u8 func) + u64 req_tag, unsigned int lun, u8 func) { struct ib_device *dev = target->srp_host->srp_dev->dev; struct srp_iu *iu; @@ -1451,12 +1444,10 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target, spin_lock_irq(target->scsi_host->host_lock); if (target->state == SRP_TARGET_DEAD || - target->state == SRP_TARGET_REMOVED) { - req->scmnd->result = DID_BAD_TARGET << 16; + target->state == SRP_TARGET_REMOVED) goto out; - } - init_completion(&req->done); + init_completion(&target->tsk_mgmt_done); iu = __srp_get_tx_iu(target, SRP_IU_TSK_MGMT); if (!iu) @@ -1468,21 +1459,19 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target, memset(tsk_mgmt, 0, sizeof *tsk_mgmt); tsk_mgmt->opcode = SRP_TSK_MGMT; - tsk_mgmt->lun = cpu_to_be64((u64) req->scmnd->device->lun << 48); - tsk_mgmt->tag = req->index | SRP_TAG_TSK_MGMT; + tsk_mgmt->lun = cpu_to_be64((u64) lun << 48); + tsk_mgmt->tag = req_tag | SRP_TAG_TSK_MGMT; tsk_mgmt->tsk_mgmt_func = func; - tsk_mgmt->task_tag = req->index; + tsk_mgmt->task_tag = req_tag; ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt, DMA_TO_DEVICE); if (__srp_post_send(target, iu, sizeof *tsk_mgmt)) goto out; - req->tsk_mgmt = iu; - spin_unlock_irq(target->scsi_host->host_lock); - if (!wait_for_completion_timeout(&req->done, + if (!wait_for_completion_timeout(&target->tsk_mgmt_done, msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS))) return -1; @@ -1493,43 +1482,29 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target, return -1; } -static int srp_find_req(struct srp_target_port *target, - struct scsi_cmnd *scmnd, - struct srp_request **req) -{ - if (scmnd->host_scribble == (void *) -1L) - return -1; - - *req = &target->req_ring[(long) scmnd->host_scribble]; - - return 0; -} - static int srp_abort(struct scsi_cmnd *scmnd) { struct srp_target_port *target = host_to_target(scmnd->device->host); - struct srp_request *req; + struct srp_request *req = (struct srp_request *) scmnd->host_scribble; int ret = SUCCESS; shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); - if (target->qp_in_error) - return FAILED; - if (srp_find_req(target, scmnd, &req)) + if (!req || target->qp_in_error) return FAILED; - if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK)) + if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, + SRP_TSK_ABORT_TASK)) return FAILED; spin_lock_irq(target->scsi_host->host_lock); - if (req->cmd_done) { - srp_remove_req(target, req); - scmnd->scsi_done(scmnd); - } else if (!req->tsk_status) { - srp_remove_req(target, req); - scmnd->result = DID_ABORT << 16; - } else - ret = FAILED; + if (req->scmnd) { + if (!target->tsk_mgmt_status) { + srp_remove_req(target, req); + scmnd->result = DID_ABORT << 16; + } else + ret = FAILED; + } spin_unlock_irq(target->scsi_host->host_lock); @@ -1545,17 +1520,16 @@ static int srp_reset_device(struct scsi_cmnd *scmnd) if (target->qp_in_error) return FAILED; - if (srp_find_req(target, scmnd, &req)) - return FAILED; - if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET)) + if (srp_send_tsk_mgmt(target, SRP_TAG_NO_REQ, scmnd->device->lun, + SRP_TSK_LUN_RESET)) return FAILED; - if (req->tsk_status) + if (target->tsk_mgmt_status) return FAILED; spin_lock_irq(target->scsi_host->host_lock); list_for_each_entry_safe(req, tmp, &target->req_queue, list) - if (req->scmnd->device == scmnd->device) + if (req->scmnd && req->scmnd->device == scmnd->device) srp_reset_req(target, req); spin_unlock_irq(target->scsi_host->host_lock); diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.h b/trunk/drivers/infiniband/ulp/srp/ib_srp.h index ed0dce9e479f..f8b689a644b7 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.h +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.h @@ -68,7 +68,8 @@ enum { SRP_TSK_MGMT_SQ_SIZE = 1, SRP_CMD_SQ_SIZE = SRP_REQ_SQ_SIZE - SRP_TSK_MGMT_SQ_SIZE, - SRP_TAG_TSK_MGMT = 1 << (SRP_RQ_SHIFT + 1), + SRP_TAG_NO_REQ = ~0U, + SRP_TAG_TSK_MGMT = 1U << 31, SRP_FMR_SIZE = 256, SRP_FMR_POOL_SIZE = 1024, @@ -113,12 +114,8 @@ struct srp_request { struct list_head list; struct scsi_cmnd *scmnd; struct srp_iu *cmd; - struct srp_iu *tsk_mgmt; struct ib_pool_fmr *fmr; - struct completion done; short index; - u8 cmd_done; - u8 tsk_status; }; struct srp_target_port { @@ -165,6 +162,9 @@ struct srp_target_port { int status; enum srp_target_state state; int qp_in_error; + + struct completion tsk_mgmt_done; + u8 tsk_mgmt_status; }; struct srp_iu {