Set of ipath patches for 2.6.22
PATCH 1/1 IB/ipath - Fix CQ flushing when QP is modified to error state
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994465 25200
# Node ID aaee8124e3bc44ec423b5e1c46ef90ede9f21483 # Parent 84a9691cf7ff54ce76de402d2353a451ba9c555b IB/ipath - Fix CQ flushing when QP is modified to error state
If a receive work request has been removed from the queue but has not had a CQ entry generated for it and the QP is modified to the error state, the completion entry generated is incorrect. This patch fixes the problem.
drivers/infiniband/hw/ipath/ipath_qp.c +1 -1
@@ -519,7 +519,7 @@ int ipath_modify_qp(struct ib_qp *ibqp,break ;case IB_QPS_ERR : -ipath_error_qp (qp,IB_WC_GENERAL_ERR ); +ipath_error_qp (qp,IB_WC_WR_FLUSH_ERR );break ;default :
drivers/infiniband/hw/ipath/ipath_ud.c +1 -0
@@ -647,6 +647,7 @@ void ipath_ud_rcv(struct ipath_ibdev *deipath_skip_sge (&qp->r_sge,sizeof (struct ib_grh ));ipath_copy_sge (&qp->r_sge, data, wc.byte_len -sizeof (struct ib_grh )); + qp->r_wrid_valid =0 ; wc.wr_id = qp->r_wr_id; wc.status =IB_WC_SUCCESS ; wc.opcode =IB_WC_RECV ;
PATCH 1/1 IB/ipath - remove unused register read routine ipath_read_kreg64_port()
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994465 25200
# Node ID a023ffe32d9df8cba7d8b15c24e7918eeb236a2c
# Parent 4d22cec2265b606cecee72d5abca4436bb1e6cb7
IB/ipath - remove unused register read routine ipath_read_kreg64_port()
drivers/infiniband/hw/ipath/ipath_driver.c +0 -23
@@ -1804,29 +1804,6 @@ int ipath_set_lid(struct ipath_devdata *return 0 ; } -/** -* ipath_read_kreg64_port - read a device's per-port 64-bit kernel register -* @dd: the infinipath device -* @regno: the register number to read -* @port: the port containing the register -* -* Registers that vary with the chip implementation constants (port) -* use this routine. -*/ -u64 ipath_read_kreg64_port (const struct ipath_devdata *dd,ipath_kreg regno, -unsigned port) -{ -u16 where; - -if (port < dd->ipath_portcnt && - (regno == dd->ipath_kregs->kr_rcvhdraddr || - regno == dd->ipath_kregs->kr_rcvhdrtailaddr)) - where = regno + port; -else - where =-1 ; - -return ipath_read_kreg64 (dd, where); -}/** * ipath_write_kreg_port - write a device's per-port 64-bit kernel register
drivers/infiniband/hw/ipath/ipath_iba6110.c +2 -2
@@ -208,8 +208,8 @@ static const struct ipath_kregs ipath_ht .kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus), .kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig),/* -* These should not be used directly via ipath_read_kreg64(), -* use them with ipath_read_kreg64_port(), +* These should not be used directly via ipath_write_kreg64(), +* use them with ipath_write_kreg64_port(), */ .kr_rcvhdraddr =IPATH_KREG_OFFSET (RcvHdrAddr0), .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0)
drivers/infiniband/hw/ipath/ipath_iba6120.c +2 -2
@@ -207,8 +207,8 @@ static const struct ipath_kregs ipath_pe .kr_ibpllcfg = IPATH_KREG_OFFSET(IBPLLCfg),/* -* These should not be used directly via ipath_read_kreg64(), -* use them with ipath_read_kreg64_port() +* These should not be used directly via ipath_write_kreg64(), +* use them with ipath_write_kreg64_port(), */ .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0), .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0),
drivers/infiniband/hw/ipath/ipath_kernel.h +0 -2
@@ -756,8 +756,6 @@ int ipath_eeprom_write(struct ipath_devd/* these are used for the registers that vary with port */ void ipath_write_kreg_port (const struct ipath_devdata *,ipath_kreg ,unsigned ,u64 ); -u64 ipath_read_kreg64_port (const struct ipath_devdata *,ipath_kreg , -unsigned );/* * We could have a single register get/put routine, that takes a group type,
PATCH 1/1 IB/ipath - fix unit selection due to all cpu affinity bits set
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994465 25200
# Node ID 8c4f730dbde3eed6e066ead5be4746d58840f24f
# Parent b436c73d4fe312c3cba092d5f642de5c0ff6aa91 IB/ipath - fix unit selection due to all cpu affinity bits set
At some point things changed so that all the affinity bits can be set, but cpus_full() macro is not true. This caused problems with the unit selection logic on multi-unit (board) configurations.
drivers/infiniband/hw/ipath/ipath_file_ops.c +5 -4
@@ -1592,15 +1592,16 @@ static int find_best_unit(struct file *f*/ if (!cpus_empty (current->cpus_allowed) && !cpus_full (current->cpus_allowed)) { -int ncpus =num_online_cpus (), curcpu =-1 ; +int ncpus =num_online_cpus (), curcpu =-1 , nset =0 ;for (i =0 ; i < ncpus; i++)if (cpu_isset (i, current->cpus_allowed)) {ipath_cdbg (PROC ,"%s[%u] affinity set for " -"cpu %d\n" , current->comm, - current->pid, i); +"cpu %d/%d\n" , current->comm, + current->pid, i, ncpus); curcpu = i; + nset++; } -if (curcpu !=-1 ) { +if (curcpu !=-1 && nset != ncpus) {if (npresent) { prefunit = curcpu / (ncpus / npresent); ipath_cdbg(PROC,"%s[%u] %d chips, %d cpus, "
PATCH 1/1 IB/ipath - print better error messages if kernel is misconfigured
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994465 25200
# Node ID fe719d50378ce70909f96bd5e7bc8e4f28a5031b
# Parent 68302e9dbd8803f937af9f02ca26a63ff43e9afa IB/ipath - print better error messages if kernel is misconfigured
drivers/infiniband/hw/ipath/ipath_driver.c +10 -2
@@ -390,15 +390,23 @@ static int __devinit ipath_init_one(stru/* setup the chip-specific functions, as early as possible. */ switch (ent->device) { +case PCI_DEVICE_ID_INFINIPATH_HT :#ifdef CONFIG_HT_IRQ -case PCI_DEVICE_ID_INFINIPATH_HT :ipath_init_iba6110_funcs (dd);break ; +#else +ipath_dev_err (dd,"QLogic HT device 0x%x cannot work if " +"CONFIG_HT_IRQ is not enabled\n" , ent->device); +return -ENODEV ;#endif +case PCI_DEVICE_ID_INFINIPATH_PE800 :#ifdef CONFIG_PCI_MSI -case PCI_DEVICE_ID_INFINIPATH_PE800 :ipath_init_iba6120_funcs (dd);break ; +#else +ipath_dev_err (dd,"QLogic PCIE device 0x%x cannot work if " +"CONFIG_PCI_MSI is not enabled\n" , ent->device); +return -ENODEV ;#endif default : ipath_dev_err(dd, "Found unknown QLogic deviceid 0x%x, "
PATCH 1/1 IB/ipath - don't initialize port memory for subports
In reply to Bryan O'Sullivan# HG changeset patch
# User Ralph Campbell <[email protected]> # Date 1173994464 25200
# Node ID d90faa722f120e0896aff3643a623b1e0c0c69d0 # Parent e2eec96f356a7269b46a68f29fc5e711d2f5a7a4 IB/ipath - don't initialize port memory for subports
A recent change was made to allocate memory for a port after CPU affinity is set. That change didn't account for subports and was trying to allocate memory for the port twice.
drivers/infiniband/hw/ipath/ipath_file_ops.c +15 -4
@@ -178,8 +178,7 @@ static int ipath_get_base_info(struct fi kinfo->spi_rcvhdr_base = ((u64 ) pd->subport_rcvhdr_base + pd->port_rcvhdrq_size * slave) &MMAP64_MASK ; - kinfo->spi_rcvhdr_tailaddr = - (u64 ) pd->port_rcvhdrqtailaddr_phys &MMAP64_MASK ; + kinfo->spi_rcvhdr_tailaddr =0 ; kinfo->spi_rcv_egrbufs = ((u64 ) pd->subport_rcvegrbuf + dd->ipath_rcvegrcnt * dd->ipath_rcvegrbufsize * slave) &MMAP64_MASK ;
@@ -1443,6 +1442,7 @@ static int init_subports(struct ipath_de pd->port_subport_cnt = uinfo->spu_subport_cnt; pd->port_subport_id = uinfo->spu_subport_id; pd->active_slaves =1 ; +set_bit (IPATH_PORT_MASTER_UNINIT , &pd->port_flag); goto bail; bail_rhdr:
@@ -1764,11 +1764,17 @@ static int ipath_do_user_init(struct fil const struct ipath_user_info *uinfo) {int ret; -struct ipath_portdata *pd; +struct ipath_portdata *pd =port_fp (fp);struct ipath_devdata *dd;u32 head32; - pd =port_fp (fp); +/* Subports don't need to initialize anything since master did it. */ +if (subport_fp (fp)) { + ret =wait_event_interruptible (pd->port_wait, + !test_bit (IPATH_PORT_MASTER_UNINIT , &pd->port_flag)); + goto done; + } + dd = pd->port_dd;if (uinfo->spu_rcvhdrsize) {
@@ -1826,6 +1832,11 @@ static int ipath_do_user_init(struct fil dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD);ipath_write_kreg (dd, dd->ipath_kregs->kr_rcvctrl, dd->ipath_rcvctrl); +/* Notify any waiting slaves */ +if (pd->port_subport_cnt) { +clear_bit (IPATH_PORT_MASTER_UNINIT , &pd->port_flag); +wake_up (&pd->port_wait); + } done:return ret; }
drivers/infiniband/hw/ipath/ipath_kernel.h +2 -0
@@ -701,6 +701,8 @@ int ipath_set_rx_pol_inv(struct ipath_de#define IPATH_PORT_WAITING_RCV 2/* waiting for a PIO buffer to be available */ #define IPATH_PORT_WAITING_PIO 3 +/* master has not finished initializing */ +#define IPATH_PORT_MASTER_UNINIT 4/* free up any allocated data at closes */ void ipath_free_data (struct ipath_portdata *dd);
PATCH 1/1 IB/ipath - fix case where SRQ limit event causes CQ entry to be dropped
In reply to Bryan O'Sullivan# HG changeset patch
# User Ralph Campbell <[email protected]>
# Date 1173994464 25200
# Node ID fa38a027a0853a80c4f7dfc50345c89f195bc85b
# Parent d90faa722f120e0896aff3643a623b1e0c0c69d0
IB/ipath - fix case where SRQ limit event causes CQ entry to be dropped
A silly programming error causes a CQ entry to not be generated if a SRQ limit event is generated.
drivers/infiniband/hw/ipath/ipath_ruc.c +1 -1
@@ -202,6 +202,7 @@ int ipath_get_rwqe(struct ipath_qp *qp, wq->tail = tail; ret =1 ; + qp->r_wrid_valid =1 ;if (handler) {u32 n;
@@ -229,7 +230,6 @@ int ipath_get_rwqe(struct ipath_qp *qp, } }spin_unlock_irqrestore (&rq->lock, flags); - qp->r_wrid_valid =1 ; bail:return ret;
PATCH 1/1 IB/ipath - fix drift between WCs in user and kernel space
In reply to Bryan O'Sullivan# HG changeset patch
# User Robert Walsh <[email protected]>
# Date 1173994466 25200
# Node ID e61b0123190cfbc01cc34d1c648d1752a89f8f3d # Parent c3b5b279bc90e5758da2ac382cbff4ee0245e84b IB/ipath - fix drift between WCs in user and kernel space
The kernel ib_wc structure now uses a QP pointer, but the user space equivalent uses a QP number instead. This means we can no longer use a simple structure copy to copy stuff into user space.
drivers/infiniband/hw/ipath/ipath_cq.c +36 -2
@@ -76,7 +76,20 @@ void ipath_cq_enter(struct ipath_cq *cq, }return ; } - wc->queue[head] = *entry; + wc->queue[head].wr_id = entry->wr_id; + wc->queue[head].status = entry->status; + wc->queue[head].opcode = entry->opcode; + wc->queue[head].vendor_err = entry->vendor_err; + wc->queue[head].byte_len = entry->byte_len; + wc->queue[head].imm_data = (__u32 __force )entry->imm_data; + wc->queue[head].qp_num = entry->qp->qp_num; + wc->queue[head].src_qp = entry->src_qp; + wc->queue[head].wc_flags = entry->wc_flags; + wc->queue[head].pkey_index = entry->pkey_index; + wc->queue[head].slid = entry->slid; + wc->queue[head].sl = entry->sl; + wc->queue[head].dlid_path_bits = entry->dlid_path_bits; + wc->queue[head].port_num = entry->port_num; wc->head = next; if (cq->notify == IB_CQ_NEXT_COMP ||
@@ -122,9 +135,30 @@ int ipath_poll_cq(struct ib_cq *ibcq, inif (tail > (u32 ) cq->ibcq.cqe) tail = (u32 ) cq->ibcq.cqe;for (npolled =0 ; npolled < num_entries; ++npolled, ++entry) { +struct ipath_qp *qp; +if (tail == wc->head)break ; - *entry = wc->queue[tail]; + + qp =ipath_lookup_qpn (&to_idev (cq->ibcq.device)->qp_table, + wc->queue[tail].qp_num); + entry->qp = &qp->ibqp; +if (atomic_dec_and_test (&qp->refcount)) +wake_up (&qp->wait); + + entry->wr_id = wc->queue[tail].wr_id; + entry->status = wc->queue[tail].status; + entry->opcode = wc->queue[tail].opcode; + entry->vendor_err = wc->queue[tail].vendor_err; + entry->byte_len = wc->queue[tail].byte_len; + entry->imm_data = wc->queue[tail].imm_data; + entry->src_qp = wc->queue[tail].src_qp; + entry->wc_flags = wc->queue[tail].wc_flags; + entry->pkey_index = wc->queue[tail].pkey_index; + entry->slid = wc->queue[tail].slid; + entry->sl = wc->queue[tail].sl; + entry->dlid_path_bits = wc->queue[tail].dlid_path_bits; + entry->port_num = wc->queue[tail].port_num;if (tail >= cq->ibcq.cqe) tail =0 ;else
drivers/infiniband/hw/ipath/ipath_verbs.h +2 -1
@@ -40,6 +40,7 @@#include <linux/interrupt.h> #include <linux/kref.h> #include <rdma/ib_pack.h> +#include <rdma/ib_user_verbs.h> #include "ipath_layer.h"
@@ -188,7 +189,7 @@ struct ipath_cq_wc {struct ipath_cq_wc {u32 head;/* index of next entry to fill */ u32 tail;/* index of next ib_poll_cq() entry */ -struct ib_wc queue[1 ];/* this is actually size ibcq.cqe + 1 */ +struct ib_uverbs_wc queue[1 ];/* this is actually size ibcq.cqe + 1 */ };/*
PATCH 1/1 IB/ipath - check reserved keys
In reply to Bryan O'Sullivan# HG changeset patch
# User Robert Walsh <[email protected]> # Date 1173994465 25200
# Node ID bf280d5f83d59788b58c17ff206bc3f54271a790 # Parent 8c4f730dbde3eed6e066ead5be4746d58840f24f IB/ipath - check reserved keys
Don't let userspace use the direct-physical-map L-key or R-key.
drivers/infiniband/hw/ipath/ipath_keys.c +12 -0
@@ -133,6 +133,12 @@ int ipath_lkey_ok(struct ipath_qp *qp, s* being reversible by calling bus_to_virt(). */ if (sge->lkey ==0 ) { +struct ipath_pd *pd =to_ipd (qp->ibqp.pd); + +if (pd->user) { + ret =0 ; + goto bail; + } isge->mr =NULL ; isge->vaddr = (void *) sge->addr; isge->length = sge->length;
@@ -206,6 +212,12 @@ int ipath_rkey_ok(struct ipath_qp *qp, s* (see ipath_get_dma_mr and ipath_dma.c). */ if (rkey ==0 ) { +struct ipath_pd *pd =to_ipd (qp->ibqp.pd); + +if (pd->user) { + ret =0 ; + goto bail; + } sge->mr =NULL ; sge->vaddr = (void *) vaddr; sge->length = len;
PATCH 1/1 IB/ipath - remove duplicate stuff from ipath_verbs.h
In reply to Bryan O'Sullivan# HG changeset patch
# User Robert Walsh <[email protected]> # Date 1173994465 25200
# Node ID 9f6468cddf59f26e087d100980a11ee9f1af4f56 # Parent bf280d5f83d59788b58c17ff206bc3f54271a790 IB/ipath - remove duplicate stuff from ipath_verbs.h
ipath_verbs.h has some duplicate stuff.
drivers/infiniband/hw/ipath/ipath_verbs.h +0 -2
@@ -731,8 +731,6 @@ int ipath_query_srq(struct ib_srq *ibsrqint ipath_destroy_srq (struct ib_srq *ibsrq); -void ipath_cq_enter (struct ipath_cq *cq,struct ib_wc *entry,int sig); -int ipath_poll_cq (struct ib_cq *ibcq,int num_entries,struct ib_wc *entry); struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries,
PATCH 1/1 IB/ipath - check that a UD work request's address handle is valid
In reply to Bryan O'Sullivan# HG changeset patch
# User Robert Walsh <[email protected]>
# Date 1173994466 25200
# Node ID c3b5b279bc90e5758da2ac382cbff4ee0245e84b
# Parent 9f6468cddf59f26e087d100980a11ee9f1af4f56 IB/ipath - check that a UD work request's address handle is valid
drivers/infiniband/hw/ipath/ipath_ud.c +5 -0
@@ -305,6 +305,11 @@ int ipath_post_ud_send(struct ipath_qp *if (!(ib_ipath_state_ops[qp->state] &IPATH_PROCESS_SEND_OK )) { ret =0 ; + goto bail; + } + +if (wr->wr.ud.ah->pd != qp->ibqp.pd) { + ret = -EPERM ; goto bail; }
PATCH 1/1 IB/ipath - fix port sharing on powerpc
In reply to Bryan O'Sullivan# HG changeset patch
# User Ralph Campbell <[email protected]> # Date 1173994465 25200
# Node ID 62da2fb770b66310ac06ba0190bf2bed2a5a764f # Parent aaee8124e3bc44ec423b5e1c46ef90ede9f21483 IB/ipath - fix port sharing on powerpc
The port sharing feature mixed kernel virtual addresses as well as physical addresses for the offset used to describe the mmap address to map the InfiniPath hardware into user space. This had a conflict on powerpc. The new scheme converts it to a physical address so it doesn't conflict with chip addresses and yet still fits in 40/44 bits so it isn't truncated by 32-bit applications calling mmap64().
drivers/infiniband/hw/ipath/ipath_file_ops.c +49 -45
@@ -41,12 +41,6 @@#include "ipath_kernel.h" #include "ipath_common.h" -/* -* mmap64 doesn't allow all 64 bits for 32-bit applications -* so only use the low 43 bits. -*/ -#define MMAP64_MASK 0x7FFFFFFFFFFUL -static int ipath_open (struct inode *,struct file *);static int ipath_close (struct inode *,struct file *); static ssize_t ipath_write(struct file *, const char __user *, size_t,
@@ -62,6 +56,24 @@ static const struct file_operations ipat .poll = ipath_poll, .mmap = ipath_mmap }; + +/* +* Convert kernel virtual addresses to physical addresses so they don't +* potentially conflict with the chip addresses used as mmap offsets. +* It doesn't really matter what mmap offset we use as long as we can +* interpret it correctly. +*/ +static u64 cvt_kvaddr (void *p) +{ +struct page *page; +u64 paddr =0 ; + + page =vmalloc_to_page (p); +if (page) + paddr =page_to_pfn (page) <<PAGE_SHIFT ; + +return paddr; +}static int ipath_get_base_info (struct file *fp,void __user *ubase,size_t ubase_size)
@@ -173,15 +185,14 @@ static int ipath_get_base_info(struct fi kinfo->spi_piocnt = dd->ipath_pbufsport / subport_cnt; kinfo->spi_piobufbase = (u64 ) pd->port_piobufs + dd->ipath_palign * kinfo->spi_piocnt * slave; - kinfo->__spi_uregbase = ((u64 ) pd->subport_uregbase + -PAGE_SIZE * slave) &MMAP64_MASK ; - - kinfo->spi_rcvhdr_base = ((u64 ) pd->subport_rcvhdr_base + - pd->port_rcvhdrq_size * slave) &MMAP64_MASK ; + kinfo->__spi_uregbase =cvt_kvaddr (pd->subport_uregbase + +PAGE_SIZE * slave); + + kinfo->spi_rcvhdr_base =cvt_kvaddr (pd->subport_rcvhdr_base + + pd->port_rcvhdrq_size * slave); kinfo->spi_rcvhdr_tailaddr =0 ; - kinfo->spi_rcv_egrbufs = ((u64 ) pd->subport_rcvegrbuf + - dd->ipath_rcvegrcnt * dd->ipath_rcvegrbufsize * slave) & -MMAP64_MASK ; + kinfo->spi_rcv_egrbufs =cvt_kvaddr (pd->subport_rcvegrbuf + + dd->ipath_rcvegrcnt * dd->ipath_rcvegrbufsize * slave); } kinfo->spi_pioindex = (kinfo->spi_piobufbase - dd->ipath_piobufbase) /
@@ -199,11 +210,11 @@ static int ipath_get_base_info(struct fiif (master) { kinfo->spi_runtime_flags |=IPATH_RUNTIME_MASTER ; kinfo->spi_subport_uregbase = - (u64 ) pd->subport_uregbase &MMAP64_MASK ; +cvt_kvaddr (pd->subport_uregbase); kinfo->spi_subport_rcvegrbuf = - (u64 ) pd->subport_rcvegrbuf &MMAP64_MASK ; +cvt_kvaddr (pd->subport_rcvegrbuf); kinfo->spi_subport_rcvhdr_base = - (u64 ) pd->subport_rcvhdr_base &MMAP64_MASK ; +cvt_kvaddr (pd->subport_rcvhdr_base); ipath_cdbg(PROC, "port %u flags %x %llx %llx %llx\n", kinfo->spi_port, kinfo->spi_runtime_flags, (unsigned long long) kinfo->spi_subport_uregbase,
@@ -1131,13 +1142,11 @@ static int mmap_kvaddr(struct vm_area_ststruct ipath_devdata *dd;void *addr;size_t size; -int ret; +int ret =0 ;/* If the port is not shared, all addresses should be physical */ -if (!pd->port_subport_cnt) { - ret = -EINVAL ; - goto bail; - } +if (!pd->port_subport_cnt) + goto bail; dd = pd->port_dd; size = pd->port_rcvegrbuf_chunks * pd->port_rcvegrbuf_size;
@@ -1149,33 +1158,28 @@ static int mmap_kvaddr(struct vm_area_stif (subport ==0 ) {unsigned num_slaves = pd->port_subport_cnt -1 ; -if (pgaddr == ((u64 ) pd->subport_uregbase &MMAP64_MASK )) { +if (pgaddr ==cvt_kvaddr (pd->subport_uregbase)) { addr = pd->subport_uregbase; size =PAGE_SIZE * num_slaves; - }else if (pgaddr == ((u64 ) pd->subport_rcvhdr_base & -MMAP64_MASK )) { + }else if (pgaddr ==cvt_kvaddr (pd->subport_rcvhdr_base)) { addr = pd->subport_rcvhdr_base; size = pd->port_rcvhdrq_size * num_slaves; - }else if (pgaddr == ((u64 ) pd->subport_rcvegrbuf & -MMAP64_MASK )) { + }else if (pgaddr ==cvt_kvaddr (pd->subport_rcvegrbuf)) { addr = pd->subport_rcvegrbuf; size *= num_slaves; - }else { - ret = -EINVAL ; + }else goto bail; - } - }else if (pgaddr == (((u64 ) pd->subport_uregbase + -PAGE_SIZE * (subport -1 )) &MMAP64_MASK )) { + }else if (pgaddr ==cvt_kvaddr (pd->subport_uregbase + +PAGE_SIZE * (subport -1 ))) { addr = pd->subport_uregbase +PAGE_SIZE * (subport -1 ); size =PAGE_SIZE ; - }else if (pgaddr == (((u64 ) pd->subport_rcvhdr_base + - pd->port_rcvhdrq_size * (subport -1 )) & -MMAP64_MASK )) { + }else if (pgaddr ==cvt_kvaddr (pd->subport_rcvhdr_base + + pd->port_rcvhdrq_size * (subport -1 ))) { addr = pd->subport_rcvhdr_base + pd->port_rcvhdrq_size * (subport -1 ); size = pd->port_rcvhdrq_size; - }else if (pgaddr == (((u64 ) pd->subport_rcvegrbuf + - size * (subport -1 )) &MMAP64_MASK )) { + }else if (pgaddr ==cvt_kvaddr (pd->subport_rcvegrbuf + + size * (subport -1 ))) { addr = pd->subport_rcvegrbuf + size * (subport -1 );/* rcvegrbufs are read-only on the slave */ if (vma->vm_flags &VM_WRITE ) {
@@ -1190,10 +1194,8 @@ static int mmap_kvaddr(struct vm_area_st* with mprotect. */ vma->vm_flags &= ~VM_MAYWRITE ; - }else { - ret = -EINVAL ; - goto bail; - } + }else + goto bail; len = vma->vm_end - vma->vm_start;if (len > size) {ipath_cdbg (MM ,"FAIL: reqlen %lx > %zx\n" , len, size);
@@ -1204,7 +1206,7 @@ static int mmap_kvaddr(struct vm_area_st vma->vm_pgoff = (unsigned long ) addr >>PAGE_SHIFT ; vma->vm_ops = &ipath_file_vm_ops; vma->vm_flags |=VM_RESERVED |VM_DONTEXPAND ; - ret =0 ; + ret =1 ; bail:return ret;
@@ -1264,8 +1266,10 @@ static int ipath_mmap(struct file *fp, s* Check for kernel virtual addresses first, anything else must * match a HW or memory address. */ -if (pgaddr >= (1ULL <<40 )) { - ret =mmap_kvaddr (vma, pgaddr, pd,subport_fp (fp)); + ret =mmap_kvaddr (vma, pgaddr, pd,subport_fp (fp)); +if (ret) { +if (ret >0 ) + ret =0 ; goto bail; }
@@ -1411,7 +1415,7 @@ static int init_subports(struct ipath_de*/ if (uinfo->spu_subport_cnt <=1 ) goto bail; -if (uinfo->spu_subport_cnt >4 ) { +if (uinfo->spu_subport_cnt >INFINIPATH_MAX_SUBPORT ) { ret = -EINVAL ; goto bail; }
PATCH 1/1 IB/ipath - fix RDMA reads of length zero and error handling
In reply to Bryan O'Sullivan# HG changeset patch
# User Ralph Campbell <[email protected]> # Date 1173994465 25200
# Node ID 4d22cec2265b606cecee72d5abca4436bb1e6cb7 # Parent 5ff8f23d0e61169f598ab1d93aa6324d88c17921 IB/ipath - fix RDMA reads of length zero and error handling
Fix RDMA read response length checking for RDMA_READ_RESPONSE_ONLY to allow a zero length response.
RDMA read responses which don't match the expected length or occur in response to some other operation should generate a completion queue error (see table 56, ch. 9.9.2.3).
drivers/infiniband/hw/ipath/ipath_rc.c +44 -19
@@ -1136,7 +1136,7 @@ static inline void ipath_rc_rcv_resp(str goto ack_done; hdrsize +=4 ;if (unlikely (wqe->wr.opcode !=IB_WR_RDMA_READ )) - goto ack_done; + goto ack_op_err;/* * If this is a response to a resent RDMA read, we * have to be careful to copy the data to the right
@@ -1154,12 +1154,12 @@ static inline void ipath_rc_rcv_resp(str goto ack_done; }if (unlikely (wqe->wr.opcode !=IB_WR_RDMA_READ )) - goto ack_done; + goto ack_op_err; read_middle:if (unlikely (tlen != (hdrsize + pmtu +4 ))) - goto ack_done; + goto ack_len_err;if (unlikely (pmtu >= qp->s_rdma_read_len)) - goto ack_done; + goto ack_len_err;/* We got a response so update the timeout. */ spin_lock (&dev->pending_lock);
@@ -1184,12 +1184,20 @@ static inline void ipath_rc_rcv_resp(str goto ack_done; }if (unlikely (wqe->wr.opcode !=IB_WR_RDMA_READ )) - goto ack_done; + goto ack_op_err; +/* Get the number of bytes the message was padded by. */ + pad = (be32_to_cpu (ohdr->bth[0 ]) >>20 ) &3 ; +/* +* Check that the data size is >= 0 && <= pmtu. +* Remember to account for the AETH header (4) and +* ICRC (4). +*/ +if (unlikely (tlen < (hdrsize + pad +8 ))) + goto ack_len_err;/* * If this is a response to a resent RDMA read, we * have to be careful to copy the data to the right * location. -* XXX should check PSN and wqe opcode first. */ qp->s_rdma_read_len =restart_sge (&qp->s_rdma_read_sge, wqe, psn, pmtu);
@@ -1203,26 +1211,20 @@ static inline void ipath_rc_rcv_resp(str goto ack_done; }if (unlikely (wqe->wr.opcode !=IB_WR_RDMA_READ )) - goto ack_done; - read_last: -/* -* Get the number of bytes the message was padded by. -*/ + goto ack_op_err; +/* Get the number of bytes the message was padded by. */ pad = (be32_to_cpu (ohdr->bth[0 ]) >>20 ) &3 ;/* * Check that the data size is >= 1 && <= pmtu. * Remember to account for the AETH header (4) and * ICRC (4). */ -if (unlikely (tlen <= (hdrsize + pad +8 ))) { -/* XXX Need to generate an error CQ entry. */ - goto ack_done; - } +if (unlikely (tlen <= (hdrsize + pad +8 ))) + goto ack_len_err; + read_last: tlen -= hdrsize + pad +8 ; -if (unlikely (tlen != qp->s_rdma_read_len)) { -/* XXX Need to generate an error CQ entry. */ - goto ack_done; - } +if (unlikely (tlen != qp->s_rdma_read_len)) + goto ack_len_err;if (!header_in_data) aeth =be32_to_cpu (ohdr->u.aeth);else {
@@ -1236,6 +1238,29 @@ static inline void ipath_rc_rcv_resp(str ack_done:spin_unlock_irqrestore (&qp->s_lock, flags); + goto bail; + +ack_op_err: + wc.status =IB_WC_LOC_QP_OP_ERR ; + goto ack_err; + +ack_len_err: + wc.status =IB_WC_LOC_LEN_ERR ; +ack_err: + wc.wr_id = wqe->wr.wr_id; + wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; + wc.vendor_err =0 ; + wc.byte_len =0 ; + wc.imm_data =0 ; + wc.qp = &qp->ibqp; + wc.src_qp = qp->remote_qpn; + wc.wc_flags =0 ; + wc.pkey_index =0 ; + wc.slid = qp->remote_ah_attr.dlid; + wc.sl = qp->remote_ah_attr.sl; + wc.dlid_path_bits =0 ; + wc.port_num =0 ; +ipath_sqerror_qp (qp, &wc); bail:return ; }
PATCH 1/1 IB/ipath - Change packet problems vs chip errors handling and reporting
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994464 25200
# Node ID c793dc8a526564b73018924a707bcb21052f8f36
# Parent 4050989280f08d81d06642e3d6cf5c3ea4397107
IB/ipath - Change packet problems vs chip errors handling and reporting
Some types of packet errors are moderately common with longer IB cables and large clusters, and are not reported with prints by other IB HCA drivers. This suppresses those messages unless the new __IPATH_ERRPKTDBG bit is set in ipath_debug. Reporting of temporarily disabled frequent error interrupts was also made clearer
We also distinguish between chip errors, and bad packets sent or received in the wording of the messages.
drivers/infiniband/hw/ipath/ipath_debug.h +1 -0
@@ -57,6 +57,7 @@#define __IPATH_PROCDBG 0x100/* print mmap/nopage stuff, not using VDBG any more */ #define __IPATH_MMDBG 0x200 +#define __IPATH_ERRPKTDBG 0x400#define __IPATH_USER_SEND 0x1000/* use user mode send */ #define __IPATH_KERNEL_SEND 0x2000/* use kernel mode send */ #define __IPATH_EPKTDBG 0x4000/* print ethernet packet data */
drivers/infiniband/hw/ipath/ipath_driver.c +39 -16
98 lines not on this page · raw message
drivers/infiniband/hw/ipath/ipath_intr.c +40 -17
110 lines not on this page · raw message
drivers/infiniband/hw/ipath/ipath_kernel.h +1 -1
@@ -611,7 +611,7 @@ extern int ipath_diag_inuse;extern int ipath_diag_inuse;irqreturn_t ipath_intr (int irq,void *devid); -void ipath_decode_err (char *buf,size_t blen,ipath_err_t err); +int ipath_decode_err (char *buf,size_t blen,ipath_err_t err);#if __IPATH_INFO || __IPATH_DBGextern const char *ipath_ibcstatus_str[];#endif
drivers/infiniband/hw/ipath/ipath_registers.h +9 -0
@@ -125,6 +125,15 @@#define INFINIPATH_E_INVALIDADDR 0x0002000000000000ULL#define INFINIPATH_E_RESET 0x0004000000000000ULL#define INFINIPATH_E_HARDWARE 0x0008000000000000ULL + +/* +* this is used to print "common" packet errors only when the +* __IPATH_ERRPKTDBG bit is set in ipath_debug. +*/ +#define INFINIPATH_E_PKTERRS ( INFINIPATH_E_SPKTLEN \ + | INFINIPATH_E_SDROPPEDDATAPKT | INFINIPATH_E_RVCRC \ + | INFINIPATH_E_RICRC | INFINIPATH_E_RSHORTPKTLEN \ + | INFINIPATH_E_REBP )/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */ /* TXEMEMPARITYERR bit 0: PIObuf, 1: PIOpbc, 2: launchfifo
drivers/infiniband/hw/ipath/ipath_stats.c +10 -4
@@ -237,11 +237,13 @@ void ipath_get_faststats(unsigned long oif ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) &&time_after (jiffies, dd->ipath_unmasktime)) {char ebuf[256 ]; -ipath_decode_err (ebuf,sizeof ebuf, +int iserr; + iserr =ipath_decode_err (ebuf,sizeof ebuf, (dd->ipath_maskederrs & ~dd-> ipath_ignorederrs));if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) & - ~(INFINIPATH_E_RRCVEGRFULL |INFINIPATH_E_RRCVHDRFULL )) + ~(INFINIPATH_E_RRCVEGRFULL |INFINIPATH_E_RRCVHDRFULL | +INFINIPATH_E_PKTERRS ))ipath_dev_err (dd,"Re-enabling masked errors " "(%s)\n" , ebuf);else {
@@ -252,8 +254,12 @@ void ipath_get_faststats(unsigned long o* them. So only complain about these at debug * level. */ -ipath_dbg ("Disabling frequent queue full errors " -"(%s)\n" , ebuf); +if (iserr) +ipath_dbg ("Re-enabling queue full errors (%s)\n" , + ebuf); +else +ipath_cdbg (ERRPKT ,"Re-enabling packet" +" problem interrupt (%s)\n" , ebuf); } dd->ipath_maskederrs = dd->ipath_ignorederrs; ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
PATCH 1/1 IB/ipath - Improve handling and reporting of parity errors, mostly cleanup
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994465 25200
# Node ID 01cde17958018b5262570cd9ea399378f95051e7
# Parent fe719d50378ce70909f96bd5e7bc8e4f28a5031b
IB/ipath - Improve handling and reporting of parity errors, mostly cleanup
drivers/infiniband/hw/ipath/ipath_driver.c +2 -1
@@ -605,8 +605,9 @@ static void __devexit cleanup_device(stripath_cdbg (VERBOSE ,"Free shadow page tid array at %p\n" , dd->ipath_pageshadow); -vfree (dd->ipath_pageshadow); + tmpp = dd->ipath_pageshadow; dd->ipath_pageshadow =NULL ; +vfree (tmpp); }/*
drivers/infiniband/hw/ipath/ipath_eeprom.c +4 -0
@@ -626,6 +626,10 @@ void ipath_get_eeprom_info(struct ipath_ }else memcpy (dd->ipath_serial, ifp->if_serial,sizeof ifp->if_serial); +if (!strstr (ifp->if_comment,"Tested successfully" )) +ipath_dev_err (dd,"Board SN %s did not pass functional " +"test: %s\n" , dd->ipath_serial, + ifp->if_comment);ipath_cdbg (VERBOSE ,"Initted GUID to %llx from eeprom\n" , (unsigned long long )be64_to_cpu (dd->ipath_guid));
drivers/infiniband/hw/ipath/ipath_iba6110.c +84 -56
214 lines not on this page · raw message
drivers/infiniband/hw/ipath/ipath_iba6120.c +39 -19
82 lines not on this page · raw message
drivers/infiniband/hw/ipath/ipath_init_chip.c +4 -0
@@ -590,6 +590,10 @@ static int init_housekeeping(struct ipat goto done; } + +/* clear diagctrl register, in case diags were running and crashed */ +ipath_write_kreg (dd, dd->ipath_kregs->kr_hwdiagctrl,0 ); +/* clear the initial reset flag, in case first driver load */ ipath_write_kreg (dd, dd->ipath_kregs->kr_errorclear,INFINIPATH_E_RESET );
drivers/infiniband/hw/ipath/ipath_intr.c +35 -3
@@ -37,11 +37,40 @@#include "ipath_verbs.h" #include "ipath_common.h" +/* +* clear (write) a pio buffer, to clear a parity error. This routine +* should only be called when in freeze mode, and the buffer should be +* canceled afterwards. +*/ +static void ipath_clrpiobuf (struct ipath_devdata *dd,u32 pnum) +{ +u32 __iomem *pbuf; +u32 dwcnt;/* dword count to write */ +if (pnum < dd->ipath_piobcnt2k) { + pbuf = (u32 __iomem *) (dd->ipath_pio2kbase + pnum * + dd->ipath_palign); + dwcnt = dd->ipath_piosize2k >>2 ; + } +else { + pbuf = (u32 __iomem *) (dd->ipath_pio4kbase + + (pnum - dd->ipath_piobcnt2k) * dd->ipath_4kalign); + dwcnt = dd->ipath_piosize4k >>2 ; + } +dev_info (&dd->pcidev->dev, +"Rewrite PIO buffer %u, to recover from parity error\n" , + pnum); + *pbuf = dwcnt+1 ;/* no flush required, since already in freeze */ +while (--dwcnt) + *pbuf++ =0 ; +} +/* * Called when we might have an error that is specific to a particular * PIO buffer, and may need to cancel that buffer, so it can be re-used. +* If rewrite is true, and bits are set in the sendbufferror registers, +* we'll write to the buffer, for error recovery on parity errors. */ -void ipath_disarm_senderrbufs (struct ipath_devdata *dd) +void ipath_disarm_senderrbufs (struct ipath_devdata *dd,int rewrite) {u32 piobcnt;unsigned long sbuf[4 ];
@@ -74,8 +103,11 @@ void ipath_disarm_senderrbufs(struct ipa }for (i =0 ; i < piobcnt; i++) -if (test_bit (i, sbuf)) +if (test_bit (i, sbuf)) { +if (rewrite) +ipath_clrpiobuf (dd, i);ipath_disarm_piobufs (dd, i,1 ); + } dd->ipath_lastcancel = jiffies+3 ;/* no armlaunch for a bit */ } }
@@ -114,7 +146,7 @@ static u64 handle_e_sum_errs(struct ipat {u64 ignore_this_time =0 ; -ipath_disarm_senderrbufs (dd); +ipath_disarm_senderrbufs (dd,0 );if ((errs &E_SUM_LINK_PKTERRS ) && !(dd->ipath_flags &IPATH_LINKACTIVE )) {/*
drivers/infiniband/hw/ipath/ipath_kernel.h +3 -1
@@ -590,7 +590,6 @@ void ipath_disable_wc(struct ipath_devdavoid ipath_disable_wc (struct ipath_devdata *dd);int ipath_count_units (int *npresentp,int *nupp,u32 *maxportsp);void ipath_shutdown_device (struct ipath_devdata *); -void ipath_disarm_senderrbufs (struct ipath_devdata *);struct file_operations ; int ipath_cdev_init(int minor, char *name, const struct file_operations *fops,
@@ -713,6 +712,7 @@ void ipath_init_iba6110_funcs(struct ipavoid ipath_init_iba6110_funcs (struct ipath_devdata *);void ipath_get_eeprom_info (struct ipath_devdata *);u64 ipath_snap_cntr (struct ipath_devdata *,ipath_creg ); +void ipath_disarm_senderrbufs (struct ipath_devdata *,int );/* * number of words used for protocol header if not set by ipath_userinit();
@@ -896,6 +896,8 @@ dma_addr_t ipath_map_single(struct pci_d#endif extern unsigned ipath_debug;/* debugging bit mask */ + +#define IPATH_MAX_PARITY_ATTEMPTS 10000/* max times to try recovery */ const char *ipath_get_unit_name (int unit);
drivers/infiniband/hw/ipath/ipath_registers.h +0 -7
@@ -308,13 +308,6 @@#define INFINIPATH_XGXS_RX_POL_SHIFT 19#define INFINIPATH_XGXS_RX_POL_MASK 0xfULL -#define INFINIPATH_RT_ADDR_MASK 0xFFFFFFFFFFULL/* 40 bits valid */ - -/* TID entries (memory), HT-only */ -#define INFINIPATH_RT_VALID 0x8000000000000000ULL -#define INFINIPATH_RT_ADDR_SHIFT 0 -#define INFINIPATH_RT_BUFSIZE_MASK 0x3FFF -#define INFINIPATH_RT_BUFSIZE_SHIFT 48/* * IPATH_PIO_MAXIBHDR is the max IB header size allowed for in our
PATCH 1/1 IB/ipath - Don't allow QP's 0 and 1 to be opened multiple times
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994465 25200
# Node ID b436c73d4fe312c3cba092d5f642de5c0ff6aa91
# Parent fddf5d03720ca586054b66d250d84233bdb3bf86 IB/ipath - Don't allow QP's 0 and 1 to be opened multiple times
drivers/infiniband/hw/ipath/ipath_qp.c +53 -38
@@ -81,11 +81,51 @@ static u32 credit_table[31] = { 32768 /* 1E */ }; -static u32 alloc_qpn (struct ipath_qp_table *qpt) + +static void get_map_page (struct ipath_qp_table *qpt,struct qpn_map *map) +{ +unsigned long page =get_zeroed_page (GFP_KERNEL ); +unsigned long flags; + +/* +* Free the page if someone raced with us installing it. +*/ + +spin_lock_irqsave (&qpt->lock, flags); +if (map->page) +free_page (page); +else + map->page = (void *)page; +spin_unlock_irqrestore (&qpt->lock, flags); +} + + +static int alloc_qpn (struct ipath_qp_table *qpt,enum ib_qp_type type) {u32 i, offset, max_scan, qpn;struct qpn_map *map; -u32 ret; +u32 ret =-1 ; + +if (type ==IB_QPT_SMI ) + ret =0 ; +else if (type ==IB_QPT_GSI ) + ret =1 ; + +if (ret !=-1 ) { + map = &qpt->map[0 ]; +if (unlikely (!map->page)) { +get_map_page (qpt, map); +if (unlikely (!map->page)) { + ret = -ENOMEM ; + goto bail; + } + } +if (!test_and_set_bit (ret, map->page)) +atomic_dec (&map->n_free); +else + ret = -EBUSY ; + goto bail; + } qpn = qpt->last +1 ;if (qpn >=QPN_MAX )
@@ -95,19 +135,7 @@ static u32 alloc_qpn(struct ipath_qp_tab max_scan = qpt->nmaps - !offset;for (i =0 ;;) {if (unlikely (!map->page)) { -unsigned long page =get_zeroed_page (GFP_KERNEL ); -unsigned long flags; - -/* -* Free the page if someone raced with us -* installing it: -*/ -spin_lock_irqsave (&qpt->lock, flags); -if (map->page) -free_page (page); -else - map->page = (void *)page; -spin_unlock_irqrestore (&qpt->lock, flags); +get_map_page (qpt, map);if (unlikely (!map->page))break ; }
@@ -151,7 +179,7 @@ static u32 alloc_qpn(struct ipath_qp_tab qpn =mk_qpn (qpt, map, offset); } - ret =0 ; + ret = -ENOMEM ; bail:return ret;
@@ -180,29 +208,19 @@ static int ipath_alloc_qpn(struct ipath_ enum ib_qp_type type) {unsigned long flags; -u32 qpn;int ret; -if (type ==IB_QPT_SMI ) - qpn =0 ; -else if (type ==IB_QPT_GSI ) - qpn =1 ; -else { -/* Allocate the next available QPN */ - qpn =alloc_qpn (qpt); -if (qpn ==0 ) { - ret = -ENOMEM ; - goto bail; - } - } - qp->ibqp.qp_num = qpn; + ret =alloc_qpn (qpt, type); +if (ret <0 ) + goto bail; + qp->ibqp.qp_num = ret;/* Add the QP to the hash table. */ spin_lock_irqsave (&qpt->lock, flags); - qpn %= qpt->max; - qp->next = qpt->table[qpn]; - qpt->table[qpn] = qp; + ret %= qpt->max; + qp->next = qpt->table[ret]; + qpt->table[ret] = qp;atomic_inc (&qp->refcount);spin_unlock_irqrestore (&qpt->lock, flags);
@@ -245,9 +263,7 @@ static void ipath_free_qp(struct ipath_qif (!fnd)return ; -/* If QPN is not reserved, mark QPN free in the bitmap. */ -if (qp->ibqp.qp_num >1 ) -free_qpn (qpt, qp->ibqp.qp_num); +free_qpn (qpt, qp->ibqp.qp_num);wait_event (qp->wait, !atomic_read (&qp->refcount)); }
@@ -270,8 +286,7 @@ void ipath_free_all_qps(struct ipath_qp_while (qp) { nqp = qp->next; -if (qp->ibqp.qp_num >1 ) -free_qpn (qpt, qp->ibqp.qp_num); +free_qpn (qpt, qp->ibqp.qp_num);if (!atomic_dec_and_test (&qp->refcount) || !ipath_destroy_qp (&qp->ibqp))ipath_dbg ("QP memory leak!\n" );
PATCH 1/1 IB/ipath - fix bad argument to clear_bit that trashed memory and/or crashed
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994465 25200
# Node ID 84a9691cf7ff54ce76de402d2353a451ba9c555b
# Parent c793dc8a526564b73018924a707bcb21052f8f36
IB/ipath - fix bad argument to clear_bit that trashed memory and/or crashed
Code was converted from a &= ~mask to clear_bit, but the bit was left shifted instead of being used directly, so we were either trashing memory several pages away, or sometimes taking a kernel page fault on an invalid page.
drivers/infiniband/hw/ipath/ipath_intr.c +2 -3
@@ -842,11 +842,10 @@ static void handle_urcv(struct ipath_devstruct ipath_portdata *pd = dd->ipath_pd[i];if (portr & (1 << i) && pd && pd->port_cnt &&test_bit (IPATH_PORT_WAITING_RCV , &pd->port_flag)) { -int rcbit;clear_bit (IPATH_PORT_WAITING_RCV , &pd->port_flag); - rcbit = i +INFINIPATH_R_INTRAVAIL_SHIFT ; -clear_bit (1UL << rcbit, &dd->ipath_rcvctrl); +clear_bit (i +INFINIPATH_R_INTRAVAIL_SHIFT , + &dd->ipath_rcvctrl);wake_up_interruptible (&pd->port_wait); rcvdint =1 ; }
PATCH 1/1 IB/ipath - fix PSN update for RC retries
In reply to Bryan O'Sullivan# HG changeset patch
# User Ralph Campbell <[email protected]> # Date 1173994464 25200
# Node ID 4050989280f08d81d06642e3d6cf5c3ea4397107 # Parent ec38d8f91d79a765cf53aaa7e8a59622418f2c9f IB/ipath - fix PSN update for RC retries
This patch fixes a number of bugs with updating the PSN for retries of RC requests.
drivers/infiniband/hw/ipath/ipath_rc.c +39 -28
@@ -444,7 +444,7 @@ int ipath_make_rc_req(struct ipath_qp *q qp->s_psn = wqe->lpsn +1 ; else { qp->s_psn++; -if ((int )(qp->s_psn - qp->s_next_psn) >0 ) +if (ipath_cmp24 (qp->s_psn, qp->s_next_psn) >0 ) qp->s_next_psn = qp->s_psn; }/*
@@ -471,7 +471,7 @@ int ipath_make_rc_req(struct ipath_qp *q/* FALLTHROUGH */ case OP (SEND_MIDDLE ): bth2 = qp->s_psn++ &IPATH_PSN_MASK ; -if ((int )(qp->s_psn - qp->s_next_psn) >0 ) +if (ipath_cmp24 (qp->s_psn, qp->s_next_psn) >0 ) qp->s_next_psn = qp->s_psn; ss = &qp->s_sge; len = qp->s_len;
@@ -507,7 +507,7 @@ int ipath_make_rc_req(struct ipath_qp *q/* FALLTHROUGH */ case OP (RDMA_WRITE_MIDDLE ): bth2 = qp->s_psn++ &IPATH_PSN_MASK ; -if ((int )(qp->s_psn - qp->s_next_psn) >0 ) +if (ipath_cmp24 (qp->s_psn, qp->s_next_psn) >0 ) qp->s_next_psn = qp->s_psn; ss = &qp->s_sge; len = qp->s_len;
@@ -546,7 +546,7 @@ int ipath_make_rc_req(struct ipath_qp *q qp->s_state =OP (RDMA_READ_REQUEST ); hwords +=sizeof (ohdr->u.rc.reth) /sizeof (u32); bth2 = qp->s_psn++ &IPATH_PSN_MASK ; -if ((int )(qp->s_psn - qp->s_next_psn) >0 ) +if (ipath_cmp24 (qp->s_psn, qp->s_next_psn) >0 ) qp->s_next_psn = qp->s_psn; ss =NULL ; len =0 ;
@@ -779,7 +779,7 @@ void ipath_restart_rc(struct ipath_qp *qif (wqe->wr.opcode ==IB_WR_RDMA_READ ) dev->n_rc_resends++;else - dev->n_rc_resends += (int )qp->s_psn - (int )psn; + dev->n_rc_resends += (qp->s_psn - psn) &IPATH_PSN_MASK ;reset_psn (qp, psn);tasklet_hi_schedule (&qp->s_task);
@@ -915,15 +915,19 @@ static int do_rc_ack(struct ipath_qp *qpif (qp->s_last == qp->s_cur) {if (++qp->s_cur >= qp->s_size) qp->s_cur =0 ; + qp->s_last = qp->s_cur; +if (qp->s_last == qp->s_tail) +break ; wqe =get_swqe_ptr (qp, qp->s_cur); qp->s_state =OP (SEND_LAST ); qp->s_psn = wqe->psn; - } -if (++qp->s_last >= qp->s_size) - qp->s_last =0 ; - wqe =get_swqe_ptr (qp, qp->s_last); -if (qp->s_last == qp->s_tail) -break ; + }else { +if (++qp->s_last >= qp->s_size) + qp->s_last =0 ; +if (qp->s_last == qp->s_tail) +break ; + wqe =get_swqe_ptr (qp, qp->s_last); + } }switch (aeth >>29 ) {
@@ -935,6 +939,18 @@ static int do_rc_ack(struct ipath_qp *qplist_add_tail (&qp->timerwait, &dev->pending[dev->pending_index]);spin_unlock (&dev->pending_lock); +/* +* If we get a partial ACK for a resent operation, +* we can stop resending the earlier packets and +* continue with the next packet the receiver wants. +*/ +if (ipath_cmp24 (qp->s_psn, psn) <=0 ) { +reset_psn (qp, psn +1 ); +tasklet_hi_schedule (&qp->s_task); + } + }else if (ipath_cmp24 (qp->s_psn, psn) <=0 ) { + qp->s_state =OP (SEND_LAST ); + qp->s_psn = psn +1 ; }ipath_get_credit (qp, aeth); qp->s_rnr_retry = qp->s_rnr_retry_cnt;
@@ -945,22 +961,23 @@ static int do_rc_ack(struct ipath_qp *qpcase 1 :/* RNR NAK */ dev->n_rnr_naks++; +if (qp->s_last == qp->s_tail) + goto bail;if (qp->s_rnr_retry ==0 ) { -if (qp->s_last == qp->s_tail) - goto bail; - wc.status =IB_WC_RNR_RETRY_EXC_ERR ; goto class_b; }if (qp->s_rnr_retry_cnt <7 ) qp->s_rnr_retry--; -if (qp->s_last == qp->s_tail) - goto bail;/* The last valid PSN is the previous PSN. */ update_last_psn (qp, psn -1 ); - dev->n_rc_resends += (int )qp->s_psn - (int )psn; +if (wqe->wr.opcode ==IB_WR_RDMA_READ ) + dev->n_rc_resends++; +else + dev->n_rc_resends += + (qp->s_psn - psn) &IPATH_PSN_MASK ;reset_psn (qp, psn);
@@ -971,26 +988,20 @@ static int do_rc_ack(struct ipath_qp *qp goto bail;case 3 :/* NAK */ -/* The last valid PSN seen is the previous request's. */ -if (qp->s_last != qp->s_tail) -update_last_psn (qp, wqe->psn -1 ); +if (qp->s_last == qp->s_tail) + goto bail; +/* The last valid PSN is the previous PSN. */ +update_last_psn (qp, psn -1 );switch ((aeth >>IPATH_AETH_CREDIT_SHIFT ) &IPATH_AETH_CREDIT_MASK ) {case 0 :/* PSN sequence error */ dev->n_seq_naks++;/* -* Back up to the responder's expected PSN. XXX +* Back up to the responder's expected PSN. * Note that we might get a NAK in the middle of an * RDMA READ response which terminates the RDMA * READ. */ -if (qp->s_last == qp->s_tail) -break ; - -if (ipath_cmp24 (psn, wqe->psn) <0 ) -break ; - -/* Retry the request. */ ipath_restart_rc (qp, psn, &wc);break ;
PATCH 1/1 IB/ipath - fix QP error completion queue entries
In reply to Bryan O'Sullivan# HG changeset patch
# User Ralph Campbell <[email protected]> # Date 1173994464 25200
# Node ID ec38d8f91d79a765cf53aaa7e8a59622418f2c9f # Parent 187ff5af5e5dd2b1f2ca48ba6ad0056ce7fc7403 IB/ipath - fix QP error completion queue entries
When switching to the QP error state, the completion queue entries (error or flush) were not being generated correctly.
drivers/infiniband/hw/ipath/ipath_qp.c +5 -3
@@ -361,7 +361,7 @@ static void ipath_reset_qp(struct ipath_* @err: the receive completion error to signal if a RWQE is active * * Flushes both send and receive work queues. -* QP s_lock should be held and interrupts disabled. +* The QP s_lock should be held and interrupts disabled. */ void ipath_error_qp (struct ipath_qp *qp,enum ib_wc_status err)
@@ -393,6 +393,8 @@ void ipath_error_qp(struct ipath_qp *qp, wc.port_num =0 ;if (qp->r_wrid_valid) { qp->r_wrid_valid =0 ; + wc.wr_id = qp->r_wr_id; + wc.opcode =IB_WC_RECV ; wc.status = err;ipath_cq_enter (to_icq (qp->ibqp.send_cq), &wc,1 ); }
@@ -972,7 +974,7 @@ bail:* @wc: the WC responsible for putting the QP in this state * * Flushes the send work queue. -* The QP s_lock should be held. +* The QP s_lock should be held and interrupts disabled. */ void ipath_sqerror_qp (struct ipath_qp *qp,struct ib_wc *wc)
@@ -998,12 +1000,12 @@ void ipath_sqerror_qp(struct ipath_qp *q wc->status =IB_WC_WR_FLUSH_ERR ;while (qp->s_last != qp->s_head) { + wqe =get_swqe_ptr (qp, qp->s_last); wc->wr_id = wqe->wr.wr_id; wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode];ipath_cq_enter (to_icq (qp->ibqp.send_cq), wc,1 );if (++qp->s_last >= qp->s_size) qp->s_last =0 ; - wqe =get_swqe_ptr (qp, qp->s_last); } qp->s_cur = qp->s_tail = qp->s_head; qp->state =IB_QPS_SQE ;
drivers/infiniband/hw/ipath/ipath_rc.c +2 -0
@@ -895,8 +895,10 @@ static int do_rc_ack(struct ipath_qp *qp wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; wc.vendor_err =0 ; wc.byte_len = wqe->length; + wc.imm_data =0 ; wc.qp = &qp->ibqp; wc.src_qp = qp->remote_qpn; + wc.wc_flags =0 ; wc.pkey_index =0 ; wc.slid = qp->remote_ah_attr.dlid; wc.sl = qp->remote_ah_attr.sl;
PATCH 1/1 IB/ipath - fix driver crash (in interrupt or during unload) after chip reset
In reply to Bryan O'Sullivan# HG changeset patch
# User Michael Albaugh <[email protected]>
# Date 1173994465 25200
# Node ID 3e81a6b18b42bbe6dffab382fb26d754dfdf83a1
# Parent 01cde17958018b5262570cd9ea399378f95051e7
IB/ipath - fix driver crash (in interrupt or during unload) after chip reset
Re-init of the kernel structures after a chip reset was leaving the portdata structure for port zero in an inconsistent state, and a pointer to it either stale (in re-init code) or NULL (in devdata) Fixing the order of operations on this struct, and the condition for interrupt access, prevents the crashes.
drivers/infiniband/hw/ipath/ipath_init_chip.c +35 -12
@@ -216,6 +216,20 @@ static int bringup_link(struct ipath_devreturn ret; } +static struct ipath_portdata *create_portdata0 (struct ipath_devdata *dd) +{ +struct ipath_portdata *pd =NULL ; + + pd =kzalloc (sizeof (*pd),GFP_KERNEL ); +if (pd) { + pd->port_dd = dd; + pd->port_cnt =1 ; +/* The port 0 pkey table is used by the layer interface. */ + pd->port_pkeys[0 ] =IPATH_DEFAULT_P_KEY ; + } +return pd; +} +static int init_chip_first (struct ipath_devdata *dd,struct ipath_portdata **pdp) {
@@ -271,20 +285,16 @@ static int init_chip_first(struct ipath_ goto done; } - dd->ipath_pd[0 ] =kzalloc (sizeof (*pd),GFP_KERNEL ); - -if (!dd->ipath_pd[0 ]) { + pd =create_portdata0 (dd); + +if (!pd) {ipath_dev_err (dd,"Unable to allocate portdata for port " "0, failing\n" ); ret = -ENOMEM ; goto done; } - pd = dd->ipath_pd[0 ]; - pd->port_dd = dd; - pd->port_port =0 ; - pd->port_cnt =1 ; -/* The port 0 pkey table is used by the layer interface. */ - pd->port_pkeys[0 ] =IPATH_DEFAULT_P_KEY ; + dd->ipath_pd[0 ] = pd; + dd->ipath_rcvtidcnt =ipath_read_kreg32 (dd, dd->ipath_kregs->kr_rcvtidcnt); dd->ipath_rcvtidbase =
@@ -838,11 +848,24 @@ int ipath_init_chip(struct ipath_devdata* Set up the port 0 (kernel) rcvhdr q and egr TIDs. If doing * re-init, the simplest way to handle this is to free * existing, and re-allocate. +* Need to re-create rest of port 0 portdata as well. */ if (reinit) { -struct ipath_portdata *pd = dd->ipath_pd[0 ]; - dd->ipath_pd[0 ] =NULL ; -ipath_free_pddata (dd, pd); +/* Alloc and init new ipath_portdata for port0, +* Then free old pd. Could lead to fragmentation, but also +* makes later support for hot-swap easier. +*/ +struct ipath_portdata *npd; + npd =create_portdata0 (dd); +if (npd) { +ipath_free_pddata (dd, pd); + dd->ipath_pd[0 ] = pd = npd; + }else { +ipath_dev_err (dd,"Unable to allocate portdata for" +" port 0, failing\n" ); + ret = -ENOMEM ; + goto done; + } } dd->ipath_f_tidtemplate (dd); ret =ipath_create_rcvhdrq (dd, pd);
drivers/infiniband/hw/ipath/ipath_stats.c +1 -1
@@ -207,7 +207,7 @@ void ipath_get_faststats(unsigned long o* don't access the chip while running diags, or memory diags can * fail */ -if (!dd->ipath_kregbase || !(dd->ipath_flags &IPATH_PRESENT ) || +if (!dd->ipath_kregbase || !(dd->ipath_flags &IPATH_INITTED ) || ipath_diag_inuse)/* but re-arm the timer, for diags case; won't hurt other */ goto done;
PATCH 1/1 IB/ipath - prevent random program use of diags interface
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994465 25200
# Node ID 284c34f2adddd16f7cb4fe48a2f6fbe9ad4beea5 # Parent e9895e2ad504a2590b0943c037d1fa5f9568fda3 IB/ipath - prevent random program use of diags interface
To prevent random utility reads and writes of the diag interface to the chip, we first require a handshake of reading from offset 0 and writing to offset 0 before any other reads or writes can be done through the
diags device. Otherwise chip errors can be triggered.
drivers/infiniband/hw/ipath/ipath_diag.c +14 -5
@@ -296,7 +296,7 @@ static int ipath_diag_open(struct inode } fp->private_data = dd; - ipath_diag_inuse =1 ; + ipath_diag_inuse =-2 ; diag_set_link =0 ; ret =0 ;
@@ -461,6 +461,8 @@ static ssize_t ipath_diag_read(struct fielse if ((count %4 ) || (*off %4 ))/* address or length is not 32-bit aligned, hence invalid */ ret = -EINVAL ; +else if (ipath_diag_inuse <1 && (*off || count !=8 )) + ret = -EINVAL ;/* prevent cat /dev/ipath_diag* */ else if ((count %8 ) || (*off %8 ))/* address or length not 64-bit aligned; do 32-bit reads */ ret =ipath_read_umem32 (dd, data, kreg_base + *off, count);
@@ -470,6 +472,8 @@ static ssize_t ipath_diag_read(struct fiif (ret >=0 ) { *off += count; ret = count; +if (ipath_diag_inuse ==-2 ) + ipath_diag_inuse++; }return ret;
@@ -489,6 +493,9 @@ static ssize_t ipath_diag_write(struct felse if ((count %4 ) || (*off %4 ))/* address or length is not 32-bit aligned, hence invalid */ ret = -EINVAL ; +else if ((ipath_diag_inuse ==-1 && (*off || count !=8 )) || + ipath_diag_inuse ==-2 )/* read qw off 0, write qw off 0 */ + ret = -EINVAL ;/* before any other write allowed */ else if ((count %8 ) || (*off %8 ))/* address or length not 64-bit aligned; do 32-bit writes */ ret =ipath_write_umem32 (dd, kreg_base + *off, data, count);
@@ -498,7 +505,9 @@ static ssize_t ipath_diag_write(struct fif (ret >=0 ) { *off += count; ret = count; - } - -return ret; -} +if (ipath_diag_inuse ==-1 ) + ipath_diag_inuse =1 ;/* all read/write OK now */ + } + +return ret; +}
PATCH 1/1 IB/ipath - cleaner shutdown at driver unload, disable IB link earlier
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994465 25200
# Node ID fddf5d03720ca586054b66d250d84233bdb3bf86
# Parent 284c34f2adddd16f7cb4fe48a2f6fbe9ad4beea5 IB/ipath - cleaner shutdown at driver unload, disable IB link earlier
Moved the code that shuts down the IB link earlier in the unload process, to be sure no new packets can arrive while we are unloading.
drivers/infiniband/hw/ipath/ipath_driver.c +6 -2
@@ -536,8 +536,6 @@ static void __devexit cleanup_device(str {int port; -ipath_shutdown_device (dd); -if (*dd->ipath_statusp &IPATH_STATUS_CHIP_PRESENT ) {/* can't do anything more with chip; needs re-init */ *dd->ipath_statusp &= ~IPATH_STATUS_CHIP_PRESENT ;
@@ -633,6 +631,12 @@ static void __devexit ipath_remove_one(sstruct ipath_devdata *dd =pci_get_drvdata (pdev);ipath_cdbg (VERBOSE ,"removing, pdev=%p, dd=%p\n" , pdev, dd); + +/* +* disable the IB link early, to be sure no new packets arrive, which +* complicates the shutdown process +*/ +ipath_shutdown_device (dd);if (dd->verbs_dev)ipath_unregister_ib_device (dd->verbs_dev);
PATCH 1/1 IB/ipath - On unrecoverable errors, force link dow, LEDs off
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994465 25200
# Node ID e9895e2ad504a2590b0943c037d1fa5f9568fda3 # Parent 3e81a6b18b42bbe6dffab382fb26d754dfdf83a1 IB/ipath - On unrecoverable errors, force link dow, LEDs off
If the chip is no longer usable, LEDs should be turned off so system can be found easily in the cluster.
Also some minor reorganizing so both chips print hardware error message at same point and only if there were unrecovered errors
drivers/infiniband/hw/ipath/ipath_iba6110.c +11 -1
@@ -42,6 +42,9 @@#include "ipath_kernel.h" #include "ipath_registers.h" + +static void ipath_setup_ht_setextled (struct ipath_devdata *,u64 ,u64 ); +/* * This lists the InfiniPath registers, in the actual chip layout.
@@ -572,9 +575,14 @@ static void ipath_ht_handle_hwerrors(str* make the complaint once, in case it's stuck * or recurring, and we get here multiple * times. +* force link down, so switch knows, and +* LEDs are turned off */ -ipath_dev_err (dd,"%s hardware error\n" , msg);if (dd->ipath_flags &IPATH_INITTED ) { +ipath_set_linkstate (dd,IPATH_IB_LINKDOWN ); +ipath_setup_ht_setextled (dd, +INFINIPATH_IBCS_L_STATE_DOWN , +INFINIPATH_IBCS_LT_STATE_DISABLED );ipath_dev_err (dd,"Fatal Hardware Error (freeze " "mode), no longer usable, SN %.16s\n" , dd->ipath_serial);
@@ -592,6 +600,8 @@ static void ipath_ht_handle_hwerrors(str }else *msg =0 ;/* recovered from all of them */ +if (*msg) +ipath_dev_err (dd,"%s hardware error\n" , msg);if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg)/* * for status file; if no trailing brace is copied,
drivers/infiniband/hw/ipath/ipath_iba6120.c +10 -1
@@ -42,6 +42,8 @@#include "ipath_kernel.h" #include "ipath_registers.h" + +static void ipath_setup_pe_setextled (struct ipath_devdata *,u64 ,u64 );/* * This file contains all the chip-specific register information and
@@ -407,8 +409,14 @@ static void ipath_pe_handle_hwerrors(str* if any set that we aren't ignoring only make the * complaint once, in case it's stuck or recurring, * and we get here multiple times +* Force link down, so switch knows, and +* LEDs are turned off */ if (dd->ipath_flags &IPATH_INITTED ) { +ipath_set_linkstate (dd,IPATH_IB_LINKDOWN ); +ipath_setup_pe_setextled (dd, +INFINIPATH_IBCS_L_STATE_DOWN , +INFINIPATH_IBCS_LT_STATE_DISABLED );ipath_dev_err (dd,"Fatal Hardware Error (freeze " "mode), no longer usable, SN %.16s\n" , dd->ipath_serial);
@@ -482,7 +490,8 @@ static void ipath_pe_handle_hwerrors(str dd->ipath_hwerrmask); } -ipath_dev_err (dd,"%s hardware error\n" , msg); +if (*msg) +ipath_dev_err (dd,"%s hardware error\n" , msg);if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) {/* * for /sys status file ; if no trailing } is copied, we'll
PATCH 1/1 IB/ipath - fix up some debug messages
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]> # Date 1173994464 25200
# Node ID 187ff5af5e5dd2b1f2ca48ba6ad0056ce7fc7403 # Parent 02b57b02578b7ffb189de66f7886214e9d5f2045 IB/ipath - fix up some debug messages
ipath_dbg doesn't need the same prefixes that printk does.
drivers/infiniband/hw/ipath/ipath_driver.c +2 -1
@@ -1989,7 +1989,8 @@ static int __init infinipath_init(void) {int ret; - ipath_dbg(KERN_INFO DRIVER_LOAD_MSG "%s", ib_ipath_version); +if (ipath_debug & __IPATH_DBG) + printk(KERN_INFO DRIVER_LOAD_MSG "%s", ib_ipath_version);/* * These must be called before the driver is registered with
drivers/infiniband/hw/ipath/ipath_keys.c +1 -1
@@ -61,7 +61,7 @@ int ipath_alloc_lkey(struct ipath_lkey_t r = (r +1 ) & (rkt->max -1 );if (r == n) {spin_unlock_irqrestore (&rkt->lock, flags); -ipath_dbg (KERN_INFO "LKEY table full\n" ); +ipath_dbg ("LKEY table full\n" ); ret =0 ; goto bail; }
drivers/infiniband/hw/ipath/ipath_qp.c +3 -3
@@ -274,7 +274,7 @@ void ipath_free_all_qps(struct ipath_qp_free_qpn (qpt, qp->ibqp.qp_num);if (!atomic_dec_and_test (&qp->refcount) || !ipath_destroy_qp (&qp->ibqp)) -ipath_dbg (KERN_INFO "QP memory leak!\n" ); +ipath_dbg ("QP memory leak!\n" ); qp = nqp; } }
@@ -369,7 +369,7 @@ void ipath_error_qp(struct ipath_qp *qp,struct ipath_ibdev *dev =to_idev (qp->ibqp.device);struct ib_wc wc; -ipath_dbg (KERN_INFO "QP%d/%d in error state\n" , +ipath_dbg ("QP%d/%d in error state\n" , qp->ibqp.qp_num, qp->remote_qpn);spin_lock (&dev->pending_lock);
@@ -980,7 +980,7 @@ void ipath_sqerror_qp(struct ipath_qp *qstruct ipath_ibdev *dev =to_idev (qp->ibqp.device);struct ipath_swqe *wqe =get_swqe_ptr (qp, qp->s_last); -ipath_dbg (KERN_INFO "Send queue error on QP%d/%d: err: %d\n" , +ipath_dbg ("Send queue error on QP%d/%d: err: %d\n" , qp->ibqp.qp_num, qp->remote_qpn, wc->status);spin_lock (&dev->pending_lock);
PATCH 1/1 IB/ipath - force PIOAvail update entry point
In reply to Bryan O'Sullivan# HG changeset patch
# User Arthur Jones <[email protected]> # Date 1173994465 25200
# Node ID 68302e9dbd8803f937af9f02ca26a63ff43e9afa # Parent 8a013b707785accfd71589334bbf8e4029ffa892 IB/ipath - force PIOAvail update entry point.
Due to a chip bug, the PIOAvail register is not always updated to memory. This patch allows userspace to force an update.
drivers/infiniband/hw/ipath/ipath_common.h +6 -3
@@ -352,7 +352,7 @@ struct ipath_base_info {* may not be implemented; the user code must deal with this if it * cares, or it must abort after initialization reports the difference. */ -#define IPATH_USER_SWMINOR 4 +#define IPATH_USER_SWMINOR 5#define IPATH_USER_SWVERSION ((IPATH_USER_SWMAJOR<<16) | IPATH_USER_SWMINOR)
@@ -429,8 +429,11 @@ struct ipath_user_info {#define __IPATH_CMD_SLAVE_INFO 22/* return info on slave processes (for old user code) */ #define IPATH_CMD_ASSIGN_PORT 23/* allocate HCA and port */ #define IPATH_CMD_USER_INIT 24/* set up userspace */ - -#define IPATH_CMD_MAX 24 +#define IPATH_CMD_UNUSED_1 25 +#define IPATH_CMD_UNUSED_2 26 +#define IPATH_CMD_PIOAVAILUPD 27/* force an update of PIOAvail reg */ + +#define IPATH_CMD_MAX 27struct ipath_port_info {__u32 num_active;/* number of active units */
drivers/infiniband/hw/ipath/ipath_file_ops.c +33 -11
67 lines not on this page · raw message
PATCH 1/1 IB/ipath - call free_irq on chip specific initialization failure
In reply to Bryan O'Sullivan# HG changeset patch
# User Arthur Jones <[email protected]>
# Date 1173994465 25200
# Node ID 8a013b707785accfd71589334bbf8e4029ffa892
# Parent c96d13efde155eb60dc0eca0bd56e81ecd36281b IB/ipath - call free_irq on chip specific initialization failure
In initialization, if we bailed at chip specific initialization, we forgot to clean up the irq we had requested.
drivers/infiniband/hw/ipath/ipath_driver.c +4 -1
@@ -486,7 +486,7 @@ static int __devinit ipath_init_one(stru ret =ipath_init_chip (dd,0 );/* do the chip-specific init */ if (ret) - goto bail_iounmap; + goto bail_irqsetup; ret =ipath_enable_wc (dd);
@@ -504,6 +504,9 @@ static int __devinit ipath_init_one(struipath_register_ib_device (dd); goto bail; + +bail_irqsetup: +if (pdev->irq)free_irq (pdev->irq, dd); bail_iounmap:iounmap ((volatile void __iomem *) dd->ipath_kregbase);
PATCH 1/1 IB/ipath - definitions of two of RXE parity error bits were reversed
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994464 25200
# Node ID e2eec96f356a7269b46a68f29fc5e711d2f5a7a4
# Parent 3337d450afeebc553a09fe5c18ed0b2444547c24 IB/ipath - definitions of two of RXE parity error bits were reversed
The chip documentation on the expected TID vs eager TID parity error bits was reversed from what was implemented in the RTL, for both chips. This corrects the definitions.
drivers/infiniband/hw/ipath/ipath_registers.h +3 -3
@@ -128,7 +128,7 @@/* kr_hwerrclear, kr_hwerrmask, kr_hwerrstatus, bits */ /* TXEMEMPARITYERR bit 0: PIObuf, 1: PIOpbc, 2: launchfifo -* RXEMEMPARITYERR bit 0: rcvbuf, 1: lookupq, 2: eagerTID, 3: expTID +* RXEMEMPARITYERR bit 0: rcvbuf, 1: lookupq, 2: expTID, 3: eagerTID * bit 4: flag buffer, 5: datainfo, 6: header info */ #define INFINIPATH_HWE_TXEMEMPARITYERR_MASK 0xFULL#define INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT 40
@@ -143,8 +143,8 @@/* rxe mem parity errors (shift by INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) */ #define INFINIPATH_HWE_RXEMEMPARITYERR_RCVBUF 0x01ULL#define INFINIPATH_HWE_RXEMEMPARITYERR_LOOKUPQ 0x02ULL -#define INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID 0x04ULL -#define INFINIPATH_HWE_RXEMEMPARITYERR_EXPTID 0x08ULL +#define INFINIPATH_HWE_RXEMEMPARITYERR_EXPTID 0x04ULL +#define INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID 0x08ULL#define INFINIPATH_HWE_RXEMEMPARITYERR_FLAGBUF 0x10ULL#define INFINIPATH_HWE_RXEMEMPARITYERR_DATAINFO 0x20ULL#define INFINIPATH_HWE_RXEMEMPARITYERR_HDRINFO 0x40ULL
PATCH 1/1 Set of ipath patches for 2.6.22
PATCH 1/1 IB/ipath - add ability to set and clear IB local loopback
# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994464 25200
# Node ID b1d05f3486f8bba1dd3c5cbca39f06a5e1b3d6fb # Parent 0d37971d4ab0c8b6f7a8f6e8222112321982498f IB/ipath - add ability to set and clear IB local loopback
This is a sticky state. It is useful for diagnosing problems with boards versus cable/switch problems.
drivers/infiniband/hw/ipath/ipath_common.h +2 -0
@@ -78,6 +78,8 @@#define IPATH_IB_LINKINIT 3#define IPATH_IB_LINKDOWN_SLEEP 4#define IPATH_IB_LINKDOWN_DISABLE 5 +#define IPATH_IB_LINK_LOOPBACK 6/* enable local loopback */ +#define IPATH_IB_LINK_EXTERNAL 7/* normal, disable local loopback */ /* * stats maintained by the driver. For now, at least, this is global
drivers/infiniband/hw/ipath/ipath_driver.c +16 -0
@@ -1662,6 +1662,22 @@ int ipath_set_linkstate(struct ipath_dev lstate =IPATH_LINKACTIVE ;break ; +case IPATH_IB_LINK_LOOPBACK : +dev_info (&dd->pcidev->dev,"Enabling IB local loopback\n" ); + dd->ipath_ibcctrl |=INFINIPATH_IBCC_LOOPBACK ; +ipath_write_kreg (dd, dd->ipath_kregs->kr_ibcctrl, + dd->ipath_ibcctrl); + ret =0 ; + goto bail;// no state change to wait for + +case IPATH_IB_LINK_EXTERNAL : +dev_info (&dd->pcidev->dev,"Disabling IB local loopback (normal)\n" ); + dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LOOPBACK ; +ipath_write_kreg (dd, dd->ipath_kregs->kr_ibcctrl, + dd->ipath_ibcctrl); + ret =0 ; + goto bail;// no state change to wait for +default :ipath_dbg ("Invalid linkstate 0x%x requested\n" , newstate); ret = -EINVAL ;
PATCH 1/1 IB/ipath - fix user memory region creation when IOMMU present
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994464 25200
# Node ID 3337d450afeebc553a09fe5c18ed0b2444547c24 # Parent b1d05f3486f8bba1dd3c5cbca39f06a5e1b3d6fb IB/ipath - fix user memory region creation when IOMMU present
The loop which initializes the user memory region from an array of pages was using the wrong limit for the array. This worked OK when dma_map_sg() returned the same number as the number of pages. This patch fixes the problem.
drivers/infiniband/hw/ipath/ipath_mr.c +9 -3
@@ -210,9 +210,15 @@ struct ib_mr *ipath_reg_user_mr(struct i m =0 ; n =0 ;list_for_each_entry (chunk, ®ion->chunk_list, list) { -for (i =0 ; i < chunk->nmap; i++) { - mr->mr.map[m]->segs[n].vaddr = -page_address (chunk->page_list[i].page); +for (i =0 ; i < chunk->nents; i++) { +void *vaddr; + + vaddr =page_address (chunk->page_list[i].page); +if (!vaddr) { + ret =ERR_PTR (-EINVAL ); + goto bail; + } + mr->mr.map[m]->segs[n].vaddr = vaddr; mr->mr.map[m]->segs[n].length = region->page_size; n++;if (n ==IPATH_SEGSZ ) {
PATCH 1/1 IB/ipath - allow receive ports mapped into userspace to be shared
In reply to Bryan O'Sullivan# HG changeset patch
# User Mark Debbage <[email protected]>
# Date 1173994465 25200
# Node ID 5ff8f23d0e61169f598ab1d93aa6324d88c17921
# Parent 62da2fb770b66310ac06ba0190bf2bed2a5a764f IB/ipath - allow receive ports mapped into userspace to be shared
Improve port-sharing performance by allowing any process to receive packets from the shared hardware port under a spin lock for mutual exclusion. Previously, one process was nominated as the master and that process was responsible for receiving all packets from the shared hardware port and either consuming them or forwarding them to their destination. This led to starvation problems for other processes when the master process was busy in computation phases.
drivers/infiniband/hw/ipath/ipath_common.h +11 -5
@@ -1,5 +1,5 @@/* -* Copyright (c) 2006 QLogic, Inc. All rights reserved. +* Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. * * This software is available to you under a choice of one of two
@@ -318,10 +318,16 @@ struct ipath_base_info {/* address of readonly memory copy of the rcvhdrq tail register. */ __u64 spi_rcvhdr_tailaddr; -/* shared memory pages for subports if IPATH_RUNTIME_MASTER is set */ +/* shared memory pages for subports if port is shared */ __u64 spi_subport_uregbase;__u64 spi_subport_rcvegrbuf;__u64 spi_subport_rcvhdr_base; + +/* shared memory page for hardware port if it is shared */ +__u64 spi_port_uregbase; +__u64 spi_port_rcvegrbuf; +__u64 spi_port_rcvhdr_base; +__u64 spi_port_rcvhdr_tailaddr; } __attribute__ ((aligned(8)));
@@ -346,7 +352,7 @@ struct ipath_base_info {* may not be implemented; the user code must deal with this if it * cares, or it must abort after initialization reports the difference. */ -#define IPATH_USER_SWMINOR 3 +#define IPATH_USER_SWMINOR 4#define IPATH_USER_SWVERSION ((IPATH_USER_SWMAJOR<<16) | IPATH_USER_SWMINOR)
@@ -420,7 +426,7 @@ struct ipath_user_info {#define IPATH_CMD_TID_UPDATE 19/* update expected TID entries */ #define IPATH_CMD_TID_FREE 20/* free expected TID entries */ #define IPATH_CMD_SET_PART_KEY 21/* add partition key */ -#define IPATH_CMD_SLAVE_INFO 22/* return info on slave processes */ +#define __IPATH_CMD_SLAVE_INFO 22/* return info on slave processes (for old user code) */ #define IPATH_CMD_ASSIGN_PORT 23/* allocate HCA and port */ #define IPATH_CMD_USER_INIT 24/* set up userspace */
@@ -432,7 +438,7 @@ struct ipath_port_info {__u16 port;/* port on unit assigned to caller */ __u16 subport;/* subport on unit assigned to caller */ __u16 num_ports;/* number of ports available on unit */ -__u16 num_subports;/* number of subport slaves opened on port */ +__u16 num_subports;/* number of subports opened on port */ };struct ipath_tid_info {
drivers/infiniband/hw/ipath/ipath_file_ops.c +99 -84
302 lines not on this page · raw message
PATCH 1/1 IB/ipath - Fix calculation for number of kernel PIO buffers
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
# Date 1173994465 25200
# Node ID 878b6054e9ca5327db9c9438f66265afaf88b055 # Parent a023ffe32d9df8cba7d8b15c24e7918eeb236a2c IB/ipath - Fix calculation for number of kernel PIO buffers
If the module parameter "kpiobufs" is set too high, the calculation to reset it to a sane value was incorrect.
drivers/infiniband/hw/ipath/ipath_init_chip.c +16 -21
@@ -668,6 +668,7 @@ int ipath_init_chip(struct ipath_devdata {int ret =0 , i;u32 val32, kpiobufs; +u32 piobufs, uports;u64 val;struct ipath_portdata *pd =NULL ;/* keep gcc4 happy */ gfp_t gfp_flags =GFP_USER | __GFP_COMP;
@@ -702,16 +703,17 @@ int ipath_init_chip(struct ipath_devdata* the in memory DMA'ed copies of the registers. This has to * be done early, before we calculate lastport, etc. */ - val = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k; + piobufs = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k;/* * calc number of pioavail registers, and save it; we have 2 * bits per buffer. */ - dd->ipath_pioavregs =ALIGN (val,sizeof (u64) *BITS_PER_BYTE /2 ) + dd->ipath_pioavregs =ALIGN (piobufs,sizeof (u64) *BITS_PER_BYTE /2 ) / (sizeof (u64) *BITS_PER_BYTE /2 ); + uports = dd->ipath_cfgports ? dd->ipath_cfgports -1 :0 ;if (ipath_kpiobufs ==0 ) {/* not set by user (this is default) */ -if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) >128 ) +if (piobufs >= (uports *IPATH_MIN_USER_PORT_BUFCNT ) +32 ) kpiobufs =32 ;else kpiobufs =16 ;
@@ -719,31 +721,25 @@ int ipath_init_chip(struct ipath_devdataelse kpiobufs = ipath_kpiobufs; -if (kpiobufs > - (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - - (dd->ipath_cfgports *IPATH_MIN_USER_PORT_BUFCNT ))) { - i = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - - (dd->ipath_cfgports *IPATH_MIN_USER_PORT_BUFCNT ); +if (kpiobufs + (uports *IPATH_MIN_USER_PORT_BUFCNT ) > piobufs) { + i = (int ) piobufs - + (int ) (uports *IPATH_MIN_USER_PORT_BUFCNT );if (i <0 ) i =0 ; -dev_info (&dd->pcidev->dev,"Allocating %d PIO bufs for " -"kernel leaves too few for %d user ports " +dev_info (&dd->pcidev->dev,"Allocating %d PIO bufs of " +"%d for kernel leaves too few for %d user ports " "(%d each); using %u\n" , kpiobufs, - dd->ipath_cfgports -1 , -IPATH_MIN_USER_PORT_BUFCNT , i); + piobufs, uports,IPATH_MIN_USER_PORT_BUFCNT , i);/* * shouldn't change ipath_kpiobufs, because could be * different for different devices... */ kpiobufs = i; } - dd->ipath_lastport_piobuf = - dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - kpiobufs; - dd->ipath_pbufsport = dd->ipath_cfgports >1 - ? dd->ipath_lastport_piobuf / (dd->ipath_cfgports -1 ) - :0 ; - val32 = dd->ipath_lastport_piobuf - - (dd->ipath_pbufsport * (dd->ipath_cfgports -1 )); + dd->ipath_lastport_piobuf = piobufs - kpiobufs; + dd->ipath_pbufsport = + uports ? dd->ipath_lastport_piobuf / uports :0 ; + val32 = dd->ipath_lastport_piobuf - (dd->ipath_pbufsport * uports);if (val32 >0 ) {ipath_dbg ("allocating %u pbufs/port leaves %u unused, " "add to kernel\n" , dd->ipath_pbufsport, val32);
@@ -754,8 +750,7 @@ int ipath_init_chip(struct ipath_devdata dd->ipath_lastpioindex = dd->ipath_lastport_piobuf;ipath_cdbg (VERBOSE ,"%d PIO bufs for kernel out of %d total %u " "each for %u user ports\n" , kpiobufs, - dd->ipath_piobcnt2k + dd->ipath_piobcnt4k, - dd->ipath_pbufsport, dd->ipath_cfgports -1 ); + piobufs, dd->ipath_pbufsport, uports); dd->ipath_f_early_init (dd);
PATCH 1/1 IB/ipath - Discard multicast packets without a GRH
In reply to Bryan O'Sullivan# HG changeset patch
# User Bryan O'Sullivan <[email protected]> # Date 1173994465 25200
# Node ID c96d13efde155eb60dc0eca0bd56e81ecd36281b # Parent 878b6054e9ca5327db9c9438f66265afaf88b055 IB/ipath - Discard multicast packets without a GRH
This patch fixes a bug where multicast packets without a GRH were not being dropped as per the IB spec.
drivers/infiniband/hw/ipath/ipath_verbs.c +5 -2
@@ -438,6 +438,10 @@ void ipath_ib_rcv(struct ipath_ibdev *destruct ipath_mcast *mcast;struct ipath_mcast_qp *p; +if (lnh !=IPATH_LRH_GRH ) { + dev->n_pkt_drops++; + goto bail; + } mcast =ipath_mcast_find (&hdr->u.l.grh.dgid);if (mcast ==NULL ) { dev->n_pkt_drops++;
@@ -445,8 +449,7 @@ void ipath_ib_rcv(struct ipath_ibdev *de } dev->n_multicast_rcv++;list_for_each_entry_rcu (p, &mcast->qp_list, list) -ipath_qp_rcv (dev, hdr, lnh ==IPATH_LRH_GRH , data, - tlen, p->qp); +ipath_qp_rcv (dev, hdr,1 , data, tlen, p->qp);/* * Notify ipath_multicast_detach() if it is waiting for us * to finish.
PATCH 1/1 IB/ipath - support larger IB_QP_MAX_DEST_RD_ATOMIC and IB_QP_MAX_QP_RD_ATOMIC
In reply to Bryan O'Sullivan# HG changeset patch
# User Ralph Campbell <[email protected]>
# Date 1173994464 25200
# Node ID 02b57b02578b7ffb189de66f7886214e9d5f2045
# Parent 78ae7bddbd5e205adc12993ad2956e0402ca01d7
IB/ipath - support larger IB_QP_MAX_DEST_RD_ATOMIC and IB_QP_MAX_QP_RD_ATOMIC
This patch adds support for multiple RDMA reads and atomics to be sent before an ACK is required to be seen by the requester.
drivers/infiniband/hw/ipath/ipath_qp.c +20 -6
@@ -320,7 +320,8 @@ static void ipath_reset_qp(struct ipath_ qp->remote_qpn =0 ; qp->qkey =0 ; qp->qp_access_flags =0 ; -clear_bit (IPATH_S_BUSY , &qp->s_flags); + qp->s_busy =0 ; + qp->s_flags &= ~IPATH_S_SIGNAL_REQ_WR ; qp->s_hdrwords =0 ; qp->s_psn =0 ; qp->r_psn =0 ;
@@ -333,7 +334,6 @@ static void ipath_reset_qp(struct ipath_ qp->r_state =IB_OPCODE_UC_SEND_LAST ; } qp->s_ack_state =IB_OPCODE_RC_ACKNOWLEDGE ; - qp->r_ack_state =IB_OPCODE_RC_ACKNOWLEDGE ; qp->r_nak_state =0 ; qp->r_wrid_valid =0 ; qp->s_rnr_timeout =0 ;
@@ -344,6 +344,10 @@ static void ipath_reset_qp(struct ipath_ qp->s_ssn =1 ; qp->s_lsn =0 ; qp->s_wait_credit =0 ; +memset (qp->s_ack_queue,0 ,sizeof (qp->s_ack_queue)); + qp->r_head_ack_queue =0 ; + qp->s_tail_ack_queue =0 ; + qp->s_num_rd_atomic =0 ;if (qp->r_rq.wq) { qp->r_rq.wq->head =0 ; qp->r_rq.wq->tail =0 ;
@@ -503,6 +507,10 @@ int ipath_modify_qp(struct ib_qp *ibqp, attr->path_mig_state != IB_MIG_REARM) goto inval; +if (attr_mask &IB_QP_MAX_DEST_RD_ATOMIC ) +if (attr->max_dest_rd_atomic >IPATH_MAX_RDMA_ATOMIC ) + goto inval; +switch (new_state) {case IB_QPS_RESET :ipath_reset_qp (qp);
@@ -558,6 +566,12 @@ int ipath_modify_qp(struct ib_qp *ibqp,if (attr_mask &IB_QP_QKEY ) qp->qkey = attr->qkey; + +if (attr_mask &IB_QP_MAX_DEST_RD_ATOMIC ) + qp->r_max_rd_atomic = attr->max_dest_rd_atomic; + +if (attr_mask &IB_QP_MAX_QP_RD_ATOMIC ) + qp->s_max_rd_atomic = attr->max_rd_atomic; qp->state = new_state;spin_unlock_irqrestore (&qp->s_lock, flags);
@@ -598,8 +612,8 @@ int ipath_query_qp(struct ib_qp *ibqp, s attr->alt_pkey_index =0 ; attr->en_sqd_async_notify =0 ; attr->sq_draining =0 ; - attr->max_rd_atomic =1 ; - attr->max_dest_rd_atomic =1 ; + attr->max_rd_atomic = qp->s_max_rd_atomic; + attr->max_dest_rd_atomic = qp->r_max_rd_atomic; attr->min_rnr_timer = qp->r_min_rnr_timer; attr->port_num =1 ; attr->timeout = qp->timeout;
@@ -614,7 +628,7 @@ int ipath_query_qp(struct ib_qp *ibqp, s init_attr->recv_cq = qp->ibqp.recv_cq; init_attr->srq = qp->ibqp.srq; init_attr->cap = attr->cap; -if (qp->s_flags & (1 <<IPATH_S_SIGNAL_REQ_WR )) +if (qp->s_flags &IPATH_S_SIGNAL_REQ_WR ) init_attr->sq_sig_type =IB_SIGNAL_REQ_WR ;else init_attr->sq_sig_type =IB_SIGNAL_ALL_WR ;
@@ -786,7 +800,7 @@ struct ib_qp *ipath_create_qp(struct ib_ qp->s_size = init_attr->cap.max_send_wr +1 ; qp->s_max_sge = init_attr->cap.max_send_sge;if (init_attr->sq_sig_type ==IB_SIGNAL_REQ_WR ) - qp->s_flags =1 <<IPATH_S_SIGNAL_REQ_WR ; + qp->s_flags =IPATH_S_SIGNAL_REQ_WR ;else qp->s_flags =0 ; dev =to_idev (ibpd->device);
drivers/infiniband/hw/ipath/ipath_rc.c +473 -365
1,219 lines not on this page · raw message
drivers/infiniband/hw/ipath/ipath_ruc.c +30 -28
138 lines not on this page · raw message
drivers/infiniband/hw/ipath/ipath_uc.c +3 -3
@@ -42,7 +42,7 @@ static void complete_last_send(struct ip {if (++qp->s_last == qp->s_size) qp->s_last =0 ; -if (!test_bit (IPATH_S_SIGNAL_REQ_WR , &qp->s_flags) || +if (!(qp->s_flags &IPATH_S_SIGNAL_REQ_WR ) || (wqe->wr.send_flags &IB_SEND_SIGNALED )) { wc->wr_id = wqe->wr.wr_id; wc->status =IB_WC_SUCCESS ;
@@ -344,13 +344,13 @@ void ipath_uc_rcv(struct ipath_ibdev *de send_first:if (qp->r_reuse_sge) { qp->r_reuse_sge =0 ; - qp->r_sge = qp->s_rdma_sge; + qp->r_sge = qp->s_rdma_read_sge; }else if (!ipath_get_rwqe (qp,0 )) { dev->n_pkt_drops++; goto done; }/* Save the WQE so we can reuse it in case of an error. */ - qp->s_rdma_sge = qp->r_sge; + qp->s_rdma_read_sge = qp->r_sge; qp->r_rcv_len =0 ;if (opcode ==OP (SEND_ONLY )) goto send_last;
drivers/infiniband/hw/ipath/ipath_ud.c +1 -1
@@ -467,7 +467,7 @@ int ipath_post_ud_send(struct ipath_qp * done:/* Queue the completion status entry. */ -if (!test_bit (IPATH_S_SIGNAL_REQ_WR , &qp->s_flags) || +if (!(qp->s_flags &IPATH_S_SIGNAL_REQ_WR ) || (wr->send_flags &IB_SEND_SIGNALED )) { wc.wr_id = wr->wr_id; wc.status =IB_WC_SUCCESS ;
drivers/infiniband/hw/ipath/ipath_verbs.c +3 -4
@@ -773,7 +773,6 @@ int ipath_verbs_send(struct ipath_devdat/* +1 is for the qword padding of pbc */ plen = hdrwords + ((len +3 ) >>2 ) +1 ;if (unlikely ((plen <<2 ) > dd->ipath_ibmaxlen)) { -ipath_dbg ("packet len 0x%x too long, failing\n" , plen); ret = -EINVAL ; goto bail; }
@@ -980,14 +979,14 @@ static int ipath_query_device(struct ib_ props->max_cqe = ib_ipath_max_cqes; props->max_mr = dev->lk_table.max; props->max_pd = ib_ipath_max_pds; - props->max_qp_rd_atom =1 ; - props->max_qp_init_rd_atom =1 ; + props->max_qp_rd_atom =IPATH_MAX_RDMA_ATOMIC ; + props->max_qp_init_rd_atom =255 ;/* props->max_res_rd_atom */ props->max_srq = ib_ipath_max_srqs; props->max_srq_wr = ib_ipath_max_srq_wrs; props->max_srq_sge = ib_ipath_max_srq_sges;/* props->local_ca_ack_delay */ - props->atomic_cap =IB_ATOMIC_HCA ; + props->atomic_cap =IB_ATOMIC_GLOB ; props->max_pkeys =ipath_get_npkeys (dev->dd); props->max_mcast_grp = ib_ipath_max_mcast_grps; props->max_mcast_qp_attach = ib_ipath_max_mcast_qp_attached;
drivers/infiniband/hw/ipath/ipath_verbs.h +37 -15
125 lines not on this page · raw message
PATCH 1/1 IB/ipath - NMI cpu lockup if local loopback used
In reply to Bryan O'Sullivan# HG changeset patch
# User Ralph Campbell <[email protected]> # Date 1173994464 25200
# Node ID 78ae7bddbd5e205adc12993ad2956e0402ca01d7 # Parent fa38a027a0853a80c4f7dfc50345c89f195bc85b IB/ipath - NMI cpu lockup if local loopback used
If a post send is done in loopback and there is no receive queue entry, the sending QP is put on a timeout list for a while so the receiver has a chance to post a receive buffer. If the another post send is done, the code incorrectly tried to put the QP on the timeout list again an corrupted the timeout list. This eventually leads to a spin lock deadlock NMI due to the timer function looping forever with the lock held.
drivers/infiniband/hw/ipath/ipath_ruc.c +2 -1
@@ -265,7 +265,8 @@ again: again:spin_lock_irqsave (&sqp->s_lock, flags); -if (!(ib_ipath_state_ops[sqp->state] &IPATH_PROCESS_SEND_OK )) { +if (!(ib_ipath_state_ops[sqp->state] &IPATH_PROCESS_SEND_OK ) || + qp->s_rnr_timeout) {spin_unlock_irqrestore (&sqp->s_lock, flags); goto done; }
Are these really all for 2.6.22? Some of them seem like bugfixes that you would want in 2.6.21...
Re: [PATCH 01 of 33] IB/ipath - add ability to set and clear IB local loopback
In reply to Bryan O'SullivanThis patch format is somewhat inconvenient:
Quoted 2 lines
# HG changeset patch
# User Bryan O'Sullivan <[email protected]>
I assume this is the real author of the patch (as opposed to the sender of the email)? git would prefer to see
From: Bryan O'Sullivan <[email protected]>
in the body of the email.
Quoted 3 lines
# Date 1173994464 25200
# Node IDb1d05f3486f8bba1dd3c5cbca39f06a5e1b3d6fb# Parent0d37971d4ab0c8b6f7a8f6e8222112321982498f
And all of these "#" lines get put into the patch description.
Quoted 1 line
IB/ipath - add ability to set and clear IB local loopback
No need to duplicate the subject line.
And incidentally, it would be better to use "IB/ipath: " instead of "IB/ipath -" as a prefix, to match the canonical style of "<subsystem>: " for patch headers.
Don't worry about resending, I can fix this up, but it would be nice not to have to worry about it.
Re: [PATCH 33 of 33] IB/ipath - fix drift between WCs in user and kernel space
In reply to Bryan O'SullivanFor example this seems like it should go in 2.6.21 -- otherwise userspace verbs are completely broken with ipath, right? It's really my fault for breaking it, but I don't see why we want to release with a bug like that.
- R.
Re: [PATCH 12 of 33] IB/ipath - fix bad argument to clear_bit that trashed memory and/or crashed
In reply to Bryan O'SullivanSimilarly -- shouldn't an obvious memory corruption fix be in 2.6.21?
Re: [PATCH 14 of 33] IB/ipath - fix port sharing on powerpc
In reply to Bryan O'SullivanQuoted 7 lines
The port sharing feature mixed kernel virtual addresses as well as physical addresses for the offset used to describe the mmap address to map the InfiniPath hardware into user space. This had a conflict on powerpc. The new scheme converts it to a physical address so it doesn't conflict with chip addresses and yet still fits in 40/44 bits so it isn't truncated by 32-bit applications calling
mmap64().
drivers/infiniband/hw/ipath/ipath_file_ops.c static const struct file_operations ipat
Quoted 10 lines
drivers/infiniband/hw/ipath/ipath_file_ops.c +9
-0+/* +* Convert kernel virtual addresses to physical addresses so they don't +* potentially conflict with the chip addresses used as mmap offsets. +* It doesn't really matter what mmap offset we use as long as we can +* interpret it correctly. +*/ + paddr =page_to_pfn (page) <<PAGE_SHIFT ; + +return paddr;
what guarantee is there that physical addresses fit into any number of bits? Couldn't I have a NUMA system or something that puts physical memory starting at an offset of 1 << 48 or whatever?
- R.
Re: [PATCH 01 of 33] IB/ipath - add ability to set and clear IB local loopback
In reply to Roland DreierQuoted 1 line · Roland Dreier
This patch format is somewhat inconvenient:
Yeah, I didn't intend for those extra bits of header cruft to go into the patchset (there's a "--plain" option to "hg email" that I forgot to use). Sorry about that.
Quoted 3 lines
And incidentally, it would be better to use "IB/ipath: " instead of "IB/ipath -" as a prefix, to match the canonical style of "<subsystem>: " for patch headers.
OK.
<b
I just queued all of this for 2.6.22.
Is there any chance of getting a fix for the use-after-free that can be caused by allocating something from userspace, failing to mmap the buffer and then exiting? To see what happens, look at how ipath_create_cq sticks a struct ipath_mmap_info into the pending mmap "list" (and yes it would be much cleaner to just use struct list_head here rather than reimplementing a linked list yourself), and then look at how ipath_destroy_cq() frees the same structure without checking if it has been removed from the pending mmap list.
- R.
Roland Dreier
AppliedRe: [PATCH 14 of 33] IB/ipath - fix port sharing on powerpc
In reply to Bryan O'SullivanI applied this, but I still think there's some more work to do in this area:
Quoted 6 lines
The port sharing feature mixed kernel virtual addresses as well as physical addresses for the offset used to describe the mmap address to map the InfiniPath hardware into user space. This had a conflict on powerpc. The new scheme converts it to a physical address so it doesn't conflict with chip addresses and yet still fits in 40/44 bits so it isn't truncated by 32-bit applications calling
mmap64().
there's no guarantee that a physical address fits in 40 or 44 or 63 bits on a 64 bit platform. So you've fixed this problem on the platforms you test for now, but it could easily crop up again...
Quoted 8 lines
Is there any chance of getting a fix for the use-after-free that can be caused by allocating something from userspace, failing to mmap the buffer and then exiting? To see what happens, look at how
ipath_create_cqsticks a structipath_mmap_infointo the pending mmap "list" (and yes it would be much cleaner to just use structlist_headhere rather than reimplementing a linked list yourself), and then look at howipath_destroy_cq()frees the same structure without checking if it has been removed from the pending mmap list.
By the way, would it help get this fixed if I opened a bug on openfabrics.org? Or is that a waste of time?
Quoted 11 lines · Roland Dreier
Quoted 8 lines
Is there any chance of getting a fix for the use-after-free that can be caused by allocating something from userspace, failing to mmap the buffer and then exiting? To see what happens, look at how
ipath_create_cqsticks a structipath_mmap_infointo the pending mmap "list" (and yes it would be much cleaner to just use structlist_headhere rather than reimplementing a linked list yourself), and then look at howipath_destroy_cq()frees the same structure without checking if it has been removed from the pending mmap list.By the way, would it help get this fixed if I opened a bug on openfabrics.org? Or is that a waste of time?
We're tracking it here (bug 12010 on our internal bugzilla), and it's on my list to get done "soon". I'm currently in the middle of some other bug fixes, but when I get to a good stopping point, I'll get this fixed.
Shouldn't be too difficult.
If you'd like to track it yourself, feel free to open an OpenFabrics bug. I'll update the bug when I get a patch done.
Regards,
Robert.
Quoted 10 lines · Roland Dreier
I just queued all of this for 2.6.22.
Is there any chance of getting a fix for the use-after-free that can be caused by allocating something from userspace, failing to mmap the buffer and then exiting? To see what happens, look at how
ipath_create_cqsticks a structipath_mmap_infointo the pending mmap "list" (and yes it would be much cleaner to just use structlist_headhere rather than reimplementing a linked list yourself), and then look at howipath_destroy_cq()frees the same structure without checking if it has been removed from the pending mmap list.
BTW: any idea how this ever got triggered? The only way I can see is if you're either not using libipathverbs and libibverbs and you just create the CQ some other way, which seems unlikely. Do you know how Jason triggered this bug?
I'm also going to fix a problem where hitting the maximum number of CQs causes an error return, but doesn't clean up the pending list and thus leaks memory.
Regards,
Robert.
Quoted 4 lines
BTW: any idea how this ever got triggered? The only way I can see is if you're either not using libipathverbs and libibverbs and you just create the CQ some other way, which seems unlikely. Do you know how Jason triggered this bug?
Yes, it was because he was using 32-bit userspace and so it was impossible to libipathverbs to mmap the address the kernel driver was looking for. So the mmap failed and the pending mmap never got taken off the list.
- R.
Quoted 9 lines · Roland Dreier
Quoted 4 lines
BTW: any idea how this ever got triggered? The only way I can see is if you're either not using libipathverbs and libibverbs and you just create the CQ some other way, which seems unlikely. Do you know how Jason triggered this bug?
Yes, it was because he was using 32-bit userspace and so it was impossible to libipathverbs to mmap the address the kernel driver was looking for. So the mmap failed and the pending mmap never got taken off the list.
Oh, OK. Got it. That problem is on my list, too, along with the other pending_mmap-related cleanups you suggested. Hopefully I'll have a patch finished tonight.