From e214a0fe2b382fa302c036ecd6e6ffe99e3b9875 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Tue, 3 Jan 2012 20:36:48 -0800 Subject: IB/uverbs: Protect QP multicast list Userspace verbs multicast attach/detach operations on a QP are done while holding the rwsem of the QP for reading. That's not sufficient since a reader lock allows more than one reader to acquire the lock. However, multicast attach/detach does list manipulation that can corrupt the list if multiple threads run in parallel. Fix this by acquiring the rwsem as a writer to serialize attach/detach operations. Add idr_write_qp() and put_qp_write() to encapsulate this. This fixes oops seen when running applications that perform multicast joins/leaves. Reported by: Mike Dubman Signed-off-by: Eli Cohen Cc: Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 254f164..e3db8ef 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -241,11 +241,24 @@ static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context) return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0); } +static struct ib_qp *idr_write_qp(int qp_handle, struct ib_ucontext *context) +{ + struct ib_uobject *uobj; + + uobj = idr_write_uobj(&ib_uverbs_qp_idr, qp_handle, context); + return uobj ? uobj->object : NULL; +} + static void put_qp_read(struct ib_qp *qp) { put_uobj_read(qp->uobject); } +static void put_qp_write(struct ib_qp *qp) +{ + put_uobj_write(qp->uobject); +} + static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context) { return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0); @@ -2375,7 +2388,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - qp = idr_read_qp(cmd.qp_handle, file->ucontext); + qp = idr_write_qp(cmd.qp_handle, file->ucontext); if (!qp) return -EINVAL; @@ -2404,7 +2417,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, kfree(mcast); out_put: - put_qp_read(qp); + put_qp_write(qp); return ret ? ret : in_len; } @@ -2422,7 +2435,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - qp = idr_read_qp(cmd.qp_handle, file->ucontext); + qp = idr_write_qp(cmd.qp_handle, file->ucontext); if (!qp) return -EINVAL; @@ -2441,7 +2454,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, } out_put: - put_qp_read(qp); + put_qp_write(qp); return ret ? ret : in_len; } -- cgit v0.10.2 From 865b64be86ed6e3e6137ce6506f31051097bf9cb Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Wed, 9 Nov 2011 13:35:55 -0500 Subject: IB/qib: Fix style issues More style issues revealed with checkpatch.pl -f. Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/qib/qib_driver.c b/drivers/infiniband/hw/qib/qib_driver.c index c90a55f..6fc9365 100644 --- a/drivers/infiniband/hw/qib/qib_driver.c +++ b/drivers/infiniband/hw/qib/qib_driver.c @@ -371,9 +371,8 @@ static u32 qib_rcv_hdrerr(struct qib_ctxtdata *rcd, struct qib_pportdata *ppd, lnh == QIB_LRH_GRH, qp, be32_to_cpu(ohdr->bth[0])); - if (ruc_res) { + if (ruc_res) goto unlock; - } /* Only deal with RDMA Writes for now */ if (opcode < diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 58b0f8a..cf0cd30 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -1015,7 +1015,7 @@ static int __devinit qib_init_one(struct pci_dev *, #define DRIVER_LOAD_MSG "QLogic " QIB_DRV_NAME " loaded: " #define PFX QIB_DRV_NAME ": " -static const struct pci_device_id qib_pci_tbl[] = { +static DEFINE_PCI_DEVICE_TABLE(qib_pci_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_QLOGIC_IB_6120) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_IB_7220) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_IB_7322) }, diff --git a/drivers/infiniband/hw/qib/qib_sd7220.c b/drivers/infiniband/hw/qib/qib_sd7220.c index de1a4b2..ac065dd 100644 --- a/drivers/infiniband/hw/qib/qib_sd7220.c +++ b/drivers/infiniband/hw/qib/qib_sd7220.c @@ -300,7 +300,7 @@ bail: } static void qib_sd_trimdone_monitor(struct qib_devdata *dd, - const char *where) + const char *where) { int ret, chn, baduns; u64 val; diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c index 78fbd56..dae5160 100644 --- a/drivers/infiniband/hw/qib/qib_sysfs.c +++ b/drivers/infiniband/hw/qib/qib_sysfs.c @@ -150,7 +150,7 @@ static ssize_t show_status(struct qib_pportdata *ppd, char *buf) * For userland compatibility, these offsets must remain fixed. * They are strings for QIB_STATUS_* */ -static const char *qib_status_str[] = { +static const char * const qib_status_str[] = { "Initted", "", "", -- cgit v0.10.2 From 8482d5d1bc18c17429a89ad37f8b74d5a16de239 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Wed, 9 Nov 2011 13:36:08 -0500 Subject: IB/qib: Eliminate 64-bit jiffies use The qib driver makes use of the the 64-bit jiffies API. Code inspection reveals that that version of the API is not really required. This patch converts to use the "normal" jiffies. Reviewed-by: Ram Vepa Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/qib/qib_7220.h b/drivers/infiniband/hw/qib/qib_7220.h index 21f374a..a5356cb 100644 --- a/drivers/infiniband/hw/qib/qib_7220.h +++ b/drivers/infiniband/hw/qib/qib_7220.h @@ -97,7 +97,7 @@ struct qib_chippport_specific { u64 iblnkerrsnap; u64 ibcctrl; /* kr_ibcctrl shadow */ u64 ibcddrctrl; /* kr_ibcddrctrl shadow */ - u64 chase_end; + unsigned long chase_end; u32 last_delay_mult; }; diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index 439d3c5..9dd886c 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -1051,7 +1051,7 @@ static void reenable_7220_chase(unsigned long opaque) static void handle_7220_chase(struct qib_pportdata *ppd, u64 ibcst) { u8 ibclt; - u64 tnow; + unsigned long tnow; ibclt = (u8)SYM_FIELD(ibcst, IBCStatus, LinkTrainingState); @@ -1066,9 +1066,9 @@ static void handle_7220_chase(struct qib_pportdata *ppd, u64 ibcst) case IB_7220_LT_STATE_CFGWAITRMT: case IB_7220_LT_STATE_TXREVLANES: case IB_7220_LT_STATE_CFGENH: - tnow = get_jiffies_64(); + tnow = jiffies; if (ppd->cpspec->chase_end && - time_after64(tnow, ppd->cpspec->chase_end)) { + time_after(tnow, ppd->cpspec->chase_end)) { ppd->cpspec->chase_end = 0; qib_set_ib_7220_lstate(ppd, QLOGIC_IB_IBCC_LINKCMD_DOWN, diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 1d58959..abd218d 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -615,8 +615,8 @@ struct qib_chippport_specific { u64 ibmalfsnap; u64 ibcctrl_a; /* krp_ibcctrl_a shadow */ u64 ibcctrl_b; /* krp_ibcctrl_b shadow */ - u64 qdr_dfe_time; - u64 chase_end; + unsigned long qdr_dfe_time; + unsigned long chase_end; u32 autoneg_tries; u32 recovery_init; u32 qdr_dfe_on; @@ -1672,7 +1672,8 @@ static void reenable_chase(unsigned long opaque) QLOGIC_IB_IBCC_LINKINITCMD_POLL); } -static void disable_chase(struct qib_pportdata *ppd, u64 tnow, u8 ibclt) +static void disable_chase(struct qib_pportdata *ppd, unsigned long tnow, + u8 ibclt) { ppd->cpspec->chase_end = 0; @@ -1688,7 +1689,7 @@ static void disable_chase(struct qib_pportdata *ppd, u64 tnow, u8 ibclt) static void handle_serdes_issues(struct qib_pportdata *ppd, u64 ibcst) { u8 ibclt; - u64 tnow; + unsigned long tnow; ibclt = (u8)SYM_FIELD(ibcst, IBCStatusA_0, LinkTrainingState); @@ -1703,9 +1704,9 @@ static void handle_serdes_issues(struct qib_pportdata *ppd, u64 ibcst) case IB_7322_LT_STATE_CFGWAITRMT: case IB_7322_LT_STATE_TXREVLANES: case IB_7322_LT_STATE_CFGENH: - tnow = get_jiffies_64(); + tnow = jiffies; if (ppd->cpspec->chase_end && - time_after64(tnow, ppd->cpspec->chase_end)) + time_after(tnow, ppd->cpspec->chase_end)) disable_chase(ppd, tnow, ibclt); else if (!ppd->cpspec->chase_end) ppd->cpspec->chase_end = tnow + QIB_CHASE_TIME; @@ -2714,7 +2715,7 @@ static noinline void unknown_7322_gpio_intr(struct qib_devdata *dd) pins >>= SYM_LSB(EXTStatus, GPIOIn); if (!(pins & mask)) { ++handled; - qd->t_insert = get_jiffies_64(); + qd->t_insert = jiffies; queue_work(ib_wq, &qd->work); } } @@ -4794,7 +4795,7 @@ static void qib_get_7322_faststats(unsigned long opaque) (ppd->lflags & (QIBL_LINKINIT | QIBL_LINKARMED | QIBL_LINKACTIVE)) && ppd->cpspec->qdr_dfe_time && - time_after64(get_jiffies_64(), ppd->cpspec->qdr_dfe_time)) { + time_is_before_jiffies(ppd->cpspec->qdr_dfe_time)) { ppd->cpspec->qdr_dfe_on = 0; qib_write_kreg_port(ppd, krp_static_adapt_dis(2), @@ -5240,7 +5241,7 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs) /* schedule the qsfp refresh which should turn the link off */ if (ppd->dd->flags & QIB_HAS_QSFP) { - qd->t_insert = get_jiffies_64(); + qd->t_insert = jiffies; queue_work(ib_wq, &qd->work); } spin_lock_irqsave(&ppd->sdma_lock, flags); @@ -5592,7 +5593,7 @@ static void qsfp_7322_event(struct work_struct *work) { struct qib_qsfp_data *qd; struct qib_pportdata *ppd; - u64 pwrup; + unsigned long pwrup; unsigned long flags; int ret; u32 le2; @@ -5620,8 +5621,7 @@ static void qsfp_7322_event(struct work_struct *work) * to insertion. */ while (1) { - u64 now = get_jiffies_64(); - if (time_after64(now, pwrup)) + if (time_is_before_jiffies(pwrup)) break; msleep(20); } @@ -7506,7 +7506,7 @@ static int serdes_7322_init_old(struct qib_pportdata *ppd) static int serdes_7322_init_new(struct qib_pportdata *ppd) { - u64 tstart; + unsigned long tend; u32 le_val, rxcaldone; int chan, chan_done = (1 << SERDES_CHANS) - 1; @@ -7611,10 +7611,8 @@ static int serdes_7322_init_new(struct qib_pportdata *ppd) msleep(20); /* Start Calibration */ ibsd_wr_allchans(ppd, 4, (1 << 10), BMASK(10, 10)); - tstart = get_jiffies_64(); - while (chan_done && - !time_after64(get_jiffies_64(), - tstart + msecs_to_jiffies(500))) { + tend = jiffies + msecs_to_jiffies(500); + while (chan_done && !time_is_before_jiffies(tend)) { msleep(20); for (chan = 0; chan < SERDES_CHANS; ++chan) { rxcaldone = ahb_mod(ppd->dd, IBSD(ppd->hw_pidx), diff --git a/drivers/infiniband/hw/qib/qib_qsfp.h b/drivers/infiniband/hw/qib/qib_qsfp.h index 46002a9..91908f5 100644 --- a/drivers/infiniband/hw/qib/qib_qsfp.h +++ b/drivers/infiniband/hw/qib/qib_qsfp.h @@ -177,7 +177,7 @@ struct qib_qsfp_data { struct qib_pportdata *ppd; struct work_struct work; struct qib_qsfp_cache cache; - u64 t_insert; + unsigned long t_insert; u8 modpresent; }; -- cgit v0.10.2 From eddfb675256f49d14e8c5763098afe3eb2c93701 Mon Sep 17 00:00:00 2001 From: Ram Vepa Date: Fri, 23 Dec 2011 08:01:43 -0500 Subject: IB/qib: Fix a possible data corruption when receiving packets Prevent a receive data corruption by ensuring that the write to update the rcvhdrheadn register to generate an interrupt is at the very end of the receive processing. Signed-off-by: Ramkrishna Vepa Signed-off-by: Mike Marciniszyn Cc: Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 781a802..4f18e2d 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -2076,9 +2076,11 @@ 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) { - qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); if (updegr) qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt); + mmiowb(); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + mmiowb(); } static u32 qib_6120_hdrqempty(struct qib_ctxtdata *rcd) diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index 9dd886c..3c722f7 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -2725,9 +2725,11 @@ 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) { - qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); if (updegr) qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt); + mmiowb(); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + mmiowb(); } static u32 qib_7220_hdrqempty(struct qib_ctxtdata *rcd) diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index abd218d..e227354 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -4083,10 +4083,12 @@ static void qib_update_7322_usrhead(struct qib_ctxtdata *rcd, u64 hd, */ 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) qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt); + mmiowb(); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + mmiowb(); } static u32 qib_7322_hdrqempty(struct qib_ctxtdata *rcd) -- cgit v0.10.2 From 489471095170ed1c6d0341739a243461638b0e06 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 23 Dec 2011 08:03:41 -0500 Subject: IB/qib: Optimize locking for get_txreq() The current code locks the QP s_lock, followed by the pending_lock, I guess to to protect against the allocate failing. This patch only locks the pending_lock, assuming that the empty case is an exeception, in which case the pending_lock is dropped, and the original code is executed. This will save a lock of s_lock in the normal case. The observation is that the sdma descriptors will deplete at twice the rate of txreq's, so this should be rare. Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index a894762..7b6c3bf 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c @@ -913,8 +913,8 @@ static void copy_io(u32 __iomem *piobuf, struct qib_sge_state *ss, __raw_writel(last, piobuf); } -static struct qib_verbs_txreq *get_txreq(struct qib_ibdev *dev, - struct qib_qp *qp, int *retp) +static noinline struct qib_verbs_txreq *__get_txreq(struct qib_ibdev *dev, + struct qib_qp *qp) { struct qib_verbs_txreq *tx; unsigned long flags; @@ -926,8 +926,9 @@ static struct qib_verbs_txreq *get_txreq(struct qib_ibdev *dev, struct list_head *l = dev->txreq_free.next; list_del(l); + spin_unlock(&dev->pending_lock); + spin_unlock_irqrestore(&qp->s_lock, flags); tx = list_entry(l, struct qib_verbs_txreq, txreq.list); - *retp = 0; } else { if (ib_qib_state_ops[qp->state] & QIB_PROCESS_RECV_OK && list_empty(&qp->iowait)) { @@ -935,14 +936,33 @@ static struct qib_verbs_txreq *get_txreq(struct qib_ibdev *dev, qp->s_flags |= QIB_S_WAIT_TX; list_add_tail(&qp->iowait, &dev->txwait); } - tx = NULL; qp->s_flags &= ~QIB_S_BUSY; - *retp = -EBUSY; + spin_unlock(&dev->pending_lock); + spin_unlock_irqrestore(&qp->s_lock, flags); + tx = ERR_PTR(-EBUSY); } + return tx; +} - spin_unlock(&dev->pending_lock); - spin_unlock_irqrestore(&qp->s_lock, flags); +static inline struct qib_verbs_txreq *get_txreq(struct qib_ibdev *dev, + struct qib_qp *qp) +{ + struct qib_verbs_txreq *tx; + unsigned long flags; + spin_lock_irqsave(&dev->pending_lock, flags); + /* assume the list non empty */ + if (likely(!list_empty(&dev->txreq_free))) { + struct list_head *l = dev->txreq_free.next; + + list_del(l); + spin_unlock_irqrestore(&dev->pending_lock, flags); + tx = list_entry(l, struct qib_verbs_txreq, txreq.list); + } else { + /* call slow path to get the extra lock */ + spin_unlock_irqrestore(&dev->pending_lock, flags); + tx = __get_txreq(dev, qp); + } return tx; } @@ -1122,9 +1142,9 @@ static int qib_verbs_send_dma(struct qib_qp *qp, struct qib_ib_header *hdr, goto bail; } - tx = get_txreq(dev, qp, &ret); - if (!tx) - goto bail; + tx = get_txreq(dev, qp); + if (IS_ERR(tx)) + goto bail_tx; control = dd->f_setpbc_control(ppd, plen, qp->s_srate, be16_to_cpu(hdr->lrh[0]) >> 12); @@ -1195,6 +1215,9 @@ unaligned: ibp->n_unaligned++; bail: return ret; +bail_tx: + ret = PTR_ERR(tx); + goto bail; } /* -- cgit v0.10.2 From 8d4548f2b7407f7212f71831bb7b457ceb752709 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Fri, 23 Dec 2011 11:12:10 -0500 Subject: IB/qib: Default some module parameters optimally Minimize the need for users to have to set module parameters to get good performance. The following two parameters are changed: - rcvhdrcnt to twice the rcvegrcnt - pcie_caps=0x51 The rcvhdrcnt at twice the egrcount allows the preemptive NAK code during reception to function in 100% of the cases rather than a sender jiffies-based timeout. The pcie_caps default of 0x51 will set the proposed MaxPayload and MaxReceiveReqest to 256 and 4096 respectively. The capabilities on the root complex will be used to limit those values. Reviewed-by: Ram Vepa Signed-off-by: Mike Marciniszyn Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index e227354..41e9208 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -3603,7 +3603,7 @@ static void qib_7322_config_ctxts(struct qib_devdata *dd) if (qib_rcvhdrcnt) dd->rcvhdrcnt = max(dd->cspec->rcvegrcnt, qib_rcvhdrcnt); else - dd->rcvhdrcnt = max(dd->cspec->rcvegrcnt, + dd->rcvhdrcnt = 2 * max(dd->cspec->rcvegrcnt, dd->num_pports > 1 ? 1024U : 2048U); } diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index 97a8bdf..f695061 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -560,9 +560,9 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd) * BIOS may not set PCIe bus-utilization parameters for best performance. * Check and optionally adjust them to maximize our throughput. */ -static int qib_pcie_caps; +static int qib_pcie_caps = 0x51; module_param_named(pcie_caps, qib_pcie_caps, int, S_IRUGO); -MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (4lsb), ReadReq (D4..7)"); +MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (0..3), ReadReq (4..7)"); static int qib_tune_pcie_caps(struct qib_devdata *dd) { -- cgit v0.10.2 From 9106c410697427363517ca6b4f463698aebc5f25 Mon Sep 17 00:00:00 2001 From: Or Gerlitz Date: Sun, 11 Dec 2011 16:40:05 +0200 Subject: IB/mlx4: Fix SL to 802.1Q priority-bits mapping for IBoE For IBoE, SLs 0-7 are mapped to Ethernet 802.1Q user priority bits (pbits) which are part of the VLAN tag, SLs 8-15 are reserved. Under Ethernet, the ConnectX firmware treats (decode/encode) the four bit SL field in various constructs such as QPC / UD WQE / CQE as PPP0 and not as 0PPP. This correlates well to the fact that within the vlan tag the pbits are located in bits 15-13 and not 12-14. The current code wasn't consistent around that area - the encoding was correct for the IBoE QPC.path.schedule_queue field, but was wrong for IBoE CQEs and when MLX header was built. These inconsistencies resulted in wrong SL <--> wire 802.1Q pbits mapping, which is fixed by using SL <--> PPP0 all around the place. Signed-off-by: Oren Duer Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c index 4b8f9c4..a251bec 100644 --- a/drivers/infiniband/hw/mlx4/ah.c +++ b/drivers/infiniband/hw/mlx4/ah.c @@ -126,7 +126,7 @@ static struct ib_ah *create_iboe_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr ah->av.ib.dlid = cpu_to_be16(0xc000); memcpy(ah->av.eth.dgid, ah_attr->grh.dgid.raw, 16); - ah->av.eth.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28); + ah->av.eth.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 29); return &ah->ibah; } diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index e8df155..5ecf38d 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c @@ -715,13 +715,17 @@ repoll: } wc->slid = be16_to_cpu(cqe->rlid); - wc->sl = be16_to_cpu(cqe->sl_vid) >> 12; g_mlpath_rqpn = be32_to_cpu(cqe->g_mlpath_rqpn); wc->src_qp = g_mlpath_rqpn & 0xffffff; wc->dlid_path_bits = (g_mlpath_rqpn >> 24) & 0x7f; wc->wc_flags |= g_mlpath_rqpn & 0x80000000 ? IB_WC_GRH : 0; wc->pkey_index = be32_to_cpu(cqe->immed_rss_invalid) & 0x7f; wc->csum_ok = mlx4_ib_ipoib_csum_ok(cqe->status, cqe->checksum); + if (rdma_port_get_link_layer(wc->qp->device, + (*cur_qp)->port) == IB_LINK_LAYER_ETHERNET) + wc->sl = be16_to_cpu(cqe->sl_vid) >> 13; + else + wc->sl = be16_to_cpu(cqe->sl_vid) >> 12; } return 0; diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index a16f0c8..aa2aefa 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -962,7 +962,7 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah, if (is_eth) { path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | - ((port - 1) << 6) | ((ah->sl & 7) << 3) | ((ah->sl & 8) >> 1); + ((port - 1) << 6) | ((ah->sl & 7) << 3); if (!(ah->ah_flags & IB_AH_GRH)) return -1; @@ -1437,7 +1437,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, u16 pcp; sqp->ud_header.vlan.type = cpu_to_be16(MLX4_IB_IBOE_ETHERTYPE); - pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 27 & 3) << 13; + pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 29) << 13; sqp->ud_header.vlan.tag = cpu_to_be16(vlan | pcp); } } else { -- cgit v0.10.2 From 6f233d300d301b08b4627fbcf29dfc4eda16e4d8 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Mon, 19 Dec 2011 21:46:53 +0200 Subject: IB/cm: Fix layout of APR message Add a missing 16-bit reserved field between ap_status and info fields. Signed-off-by: Eli Cohen Acked-by: Sean Hefty Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/core/cm_msgs.h b/drivers/infiniband/core/cm_msgs.h index 505db2a..7da9b21 100644 --- a/drivers/infiniband/core/cm_msgs.h +++ b/drivers/infiniband/core/cm_msgs.h @@ -799,6 +799,7 @@ struct cm_apr_msg { u8 info_length; u8 ap_status; + __be16 rsvd; u8 info[IB_CM_APR_INFO_LENGTH]; u8 private_data[IB_CM_APR_PRIVATE_DATA_SIZE]; -- cgit v0.10.2 From 30b7e117af450850b0fe813e1ee0780934bdcad3 Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Wed, 7 Dec 2011 16:24:06 -0600 Subject: RDMA/nes: Change MDIO bus clock to 2.5MHz Change the PHY clock divisor to make the MDIO clock 2.5MHz, instead of 3.5MHz (which is out of spec). Signed-off-by: Tatyana Nikolova Signed-off-by: Faisal Latif Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 7c0ff19..6ee570b 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -1529,7 +1529,7 @@ int nes_init_phy(struct nes_device *nesdev) } else { /* setup 10G MDIO operation */ tx_config &= 0xFFFFFFE3; - tx_config |= 0x15; + tx_config |= 0x1D; } nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config); -- cgit v0.10.2 From b0fda90f2a8eeac269833e7ef9e32d199747072b Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Wed, 7 Dec 2011 16:04:27 -0600 Subject: RDMA/nes: Make unnecessarily global nes_set_pau() static Warned about by sparse. Signed-off-by: Tatyana Nikolova Signed-off-by: Faisal Latif Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c index cd10968..8b4c2ff 100644 --- a/drivers/infiniband/hw/nes/nes_utils.c +++ b/drivers/infiniband/hw/nes/nes_utils.c @@ -56,7 +56,7 @@ static u16 nes_read16_eeprom(void __iomem *addr, u16 offset); u32 mh_detected; u32 mh_pauses_sent; -u32 nes_set_pau(struct nes_device *nesdev) +static u32 nes_set_pau(struct nes_device *nesdev) { u32 ret = 0; u32 counter; -- cgit v0.10.2 From 196f40c8464799d185ee7417d2ee532468b374e6 Mon Sep 17 00:00:00 2001 From: Tatyana Nikolova Date: Mon, 5 Dec 2011 11:39:12 -0600 Subject: RDMA/nes: Fix terminate during AE Fix for reset which happens right after sending a terminate message. Terminate timer is not deleted when the connection is closed. Signed-off-by: Tatyana Nikolova Signed-off-by: Faisal Latif Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 0a52d72..db0831d 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -2838,6 +2838,7 @@ static int nes_cm_disconn_true(struct nes_qp *nesqp) issue_disconn = 1; issue_close = 1; nesqp->cm_id = NULL; + del_timer(&nesqp->terminate_timer); if (nesqp->flush_issued == 0) { nesqp->flush_issued = 1; issue_flush = 1; diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 6ee570b..055f4b5 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -3619,10 +3619,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, } break; case NES_AEQE_AEID_LLP_CLOSE_COMPLETE: - if (nesqp->term_flags) { - nes_terminate_done(nesqp, 0); - return; - } spin_lock_irqsave(&nesqp->lock, flags); nesqp->hw_iwarp_state = iwarp_state; nesqp->hw_tcp_state = tcp_state; -- cgit v0.10.2 From 46ea5061c750fc6b088b9566234287115fb70f98 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Tue, 6 Dec 2011 21:15:18 +0000 Subject: RDMA/cma: Fix endianness bugs Fix endianness bugs reported by sparse in the RDMA core stack. Note that these are real bugs, but don't affect any existing code to the best of my knowledge. The mlid issue would only affect kernel users of rdma_join_multicast which have the rdma_cm attach/detach its QP. There are no current in tree users that do this. (rdma_join_multicast may be used called by user space applications, which does not have this issue.) And the pkey setting is simply returned as informational. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index d0d4aa9..fdd8ef8 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1110,7 +1110,7 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id, if (cma_any_addr((struct sockaddr *) &rt->addr.src_addr)) { rt->addr.dev_addr.dev_type = ARPHRD_INFINIBAND; rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid); - ib_addr_set_pkey(&rt->addr.dev_addr, rt->path_rec[0].pkey); + ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey)); } else { ret = rdma_translate_ip((struct sockaddr *) &rt->addr.src_addr, &rt->addr.dev_addr); @@ -2926,7 +2926,7 @@ static int cma_ib_mc_handler(int status, struct ib_sa_multicast *multicast) mutex_lock(&id_priv->qp_mutex); if (!status && id_priv->id.qp) status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid, - multicast->rec.mlid); + be16_to_cpu(multicast->rec.mlid)); mutex_unlock(&id_priv->qp_mutex); memset(&event, 0, sizeof event); @@ -3187,7 +3187,7 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr) if (id->qp) ib_detach_mcast(id->qp, &mc->multicast.ib->rec.mgid, - mc->multicast.ib->rec.mlid); + be16_to_cpu(mc->multicast.ib->rec.mlid)); if (rdma_node_get_transport(id_priv->cma_dev->device->node_type) == RDMA_TRANSPORT_IB) { switch (rdma_port_get_link_layer(id->device, id->port_num)) { case IB_LINK_LAYER_INFINIBAND: -- cgit v0.10.2 From c89d1bedf8b130d5b20f56a484989a19a2c2842a Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Tue, 6 Dec 2011 21:13:10 +0000 Subject: rdma/core: Fix sparse warnings Clean up sparse warnings in the rdma core layer. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index b8a0b4a..06f0871 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c @@ -106,9 +106,6 @@ enum { IB_UCM_MAX_DEVICES = 32 }; -/* ib_cm and ib_user_cm modules share /sys/class/infiniband_cm */ -extern struct class cm_class; - #define IB_UCM_BASE_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_BASE_MINOR) static void ib_ucm_add_one(struct ib_device *device); diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 254f164..e26193f 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -2446,9 +2446,9 @@ out_put: return ret ? ret : in_len; } -int __uverbs_create_xsrq(struct ib_uverbs_file *file, - struct ib_uverbs_create_xsrq *cmd, - struct ib_udata *udata) +static int __uverbs_create_xsrq(struct ib_uverbs_file *file, + struct ib_uverbs_create_xsrq *cmd, + struct ib_udata *udata) { struct ib_uverbs_create_srq_resp resp; struct ib_usrq_object *obj; diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h index 639a449..9996539 100644 --- a/include/rdma/ib_addr.h +++ b/include/rdma/ib_addr.h @@ -281,7 +281,7 @@ static inline u16 rdma_get_vlan_id(union ib_gid *dgid) static inline struct net_device *rdma_vlan_dev_real_dev(const struct net_device *dev) { return dev->priv_flags & IFF_802_1Q_VLAN ? - vlan_dev_real_dev(dev) : 0; + vlan_dev_real_dev(dev) : NULL; } #endif /* IB_ADDR_H */ diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h index c8f94e8..83f77ac 100644 --- a/include/rdma/ib_cm.h +++ b/include/rdma/ib_cm.h @@ -38,6 +38,9 @@ #include #include +/* ib_cm and ib_user_cm modules share /sys/class/infiniband_cm */ +extern struct class cm_class; + enum ib_cm_state { IB_CM_IDLE, IB_CM_LISTEN, -- cgit v0.10.2