diff options
Diffstat (limited to 'drivers/infiniband/hw/qib')
| -rw-r--r-- | drivers/infiniband/hw/qib/qib.h | 12 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_diag.c | 52 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_dma.c | 21 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_file_ops.c | 5 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_fs.c | 8 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_iba6120.c | 11 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_iba7220.c | 12 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_iba7322.c | 53 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_init.c | 104 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_mad.c | 46 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_mad.h | 14 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_mr.c | 14 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_pcie.c | 181 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_qp.c | 5 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_rc.c | 2 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_ruc.c | 1 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_ud.c | 15 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_user_sdma.c | 142 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_verbs.c | 8 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_verbs.h | 26 | 
20 files changed, 436 insertions, 296 deletions
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 1946101419a..c00ae093b6f 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -868,8 +868,10 @@ struct qib_devdata {  	/* last buffer for user use */  	u32 lastctxt_piobuf; -	/* saturating counter of (non-port-specific) device interrupts */ -	u32 int_counter; +	/* reset value */ +	u64 z_int_counter; +	/* percpu intcounter */ +	u64 __percpu *int_counter;  	/* pio bufs allocated per ctxt */  	u32 pbufsctxt; @@ -1184,7 +1186,7 @@ int qib_setup_eagerbufs(struct qib_ctxtdata *);  void qib_set_ctxtcnt(struct qib_devdata *);  int qib_create_ctxts(struct qib_devdata *dd);  struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *, u32, int); -void qib_init_pportdata(struct qib_pportdata *, struct qib_devdata *, u8, u8); +int qib_init_pportdata(struct qib_pportdata *, struct qib_devdata *, u8, u8);  void qib_free_ctxtdata(struct qib_devdata *, struct qib_ctxtdata *);  u32 qib_kreceive(struct qib_ctxtdata *, u32 *, u32 *); @@ -1449,6 +1451,10 @@ void qib_nomsi(struct qib_devdata *);  void qib_nomsix(struct qib_devdata *);  void qib_pcie_getcmd(struct qib_devdata *, u16 *, u8 *, u8 *);  void qib_pcie_reenable(struct qib_devdata *, u16, u8, u8); +/* interrupts for device */ +u64 qib_int_counter(struct qib_devdata *); +/* interrupt for all devices */ +u64 qib_sps_ints(void);  /*   * dma_addr wrappers - all 0's invalid for hw diff --git a/drivers/infiniband/hw/qib/qib_diag.c b/drivers/infiniband/hw/qib/qib_diag.c index 1686fd4bda8..5dfda4c5cc9 100644 --- a/drivers/infiniband/hw/qib/qib_diag.c +++ b/drivers/infiniband/hw/qib/qib_diag.c @@ -546,7 +546,7 @@ static ssize_t qib_diagpkt_write(struct file *fp,  				 size_t count, loff_t *off)  {  	u32 __iomem *piobuf; -	u32 plen, clen, pbufn; +	u32 plen, pbufn, maxlen_reserve;  	struct qib_diag_xpkt dp;  	u32 *tmpbuf = NULL;  	struct qib_devdata *dd; @@ -590,15 +590,20 @@ static ssize_t qib_diagpkt_write(struct file *fp,  	}  	ppd = &dd->pport[dp.port - 1]; -	/* need total length before first word written */ -	/* +1 word is for the qword padding */ -	plen = sizeof(u32) + dp.len; -	clen = dp.len >> 2; - -	if ((plen + 4) > ppd->ibmaxlen) { +	/* +	 * need total length before first word written, plus 2 Dwords. One Dword +	 * is for padding so we get the full user data when not aligned on +	 * a word boundary. The other Dword is to make sure we have room for the +	 * ICRC which gets tacked on later. +	 */ +	maxlen_reserve = 2 * sizeof(u32); +	if (dp.len > ppd->ibmaxlen - maxlen_reserve) {  		ret = -EINVAL; -		goto bail;      /* before writing pbc */ +		goto bail;  	} + +	plen = sizeof(u32) + dp.len; +  	tmpbuf = vmalloc(plen);  	if (!tmpbuf) {  		qib_devinfo(dd->pcidev, @@ -638,11 +643,11 @@ static ssize_t qib_diagpkt_write(struct file *fp,  	 */  	if (dd->flags & QIB_PIO_FLUSH_WC) {  		qib_flush_wc(); -		qib_pio_copy(piobuf + 2, tmpbuf, clen - 1); +		qib_pio_copy(piobuf + 2, tmpbuf, plen - 1);  		qib_flush_wc(); -		__raw_writel(tmpbuf[clen - 1], piobuf + clen + 1); +		__raw_writel(tmpbuf[plen - 1], piobuf + plen + 1);  	} else -		qib_pio_copy(piobuf + 2, tmpbuf, clen); +		qib_pio_copy(piobuf + 2, tmpbuf, plen);  	if (dd->flags & QIB_USE_SPCL_TRIG) {  		u32 spcl_off = (pbufn >= dd->piobcnt2k) ? 2047 : 1023; @@ -689,28 +694,23 @@ int qib_register_observer(struct qib_devdata *dd,  			  const struct diag_observer *op)  {  	struct diag_observer_list_elt *olp; -	int ret = -EINVAL; +	unsigned long flags;  	if (!dd || !op) -		goto bail; -	ret = -ENOMEM; +		return -EINVAL;  	olp = vmalloc(sizeof *olp);  	if (!olp) {  		pr_err("vmalloc for observer failed\n"); -		goto bail; +		return -ENOMEM;  	} -	if (olp) { -		unsigned long flags; -		spin_lock_irqsave(&dd->qib_diag_trans_lock, flags); -		olp->op = op; -		olp->next = dd->diag_observer_list; -		dd->diag_observer_list = olp; -		spin_unlock_irqrestore(&dd->qib_diag_trans_lock, flags); -		ret = 0; -	} -bail: -	return ret; +	spin_lock_irqsave(&dd->qib_diag_trans_lock, flags); +	olp->op = op; +	olp->next = dd->diag_observer_list; +	dd->diag_observer_list = olp; +	spin_unlock_irqrestore(&dd->qib_diag_trans_lock, flags); + +	return 0;  }  /* Remove all registered observers when device is closed */ diff --git a/drivers/infiniband/hw/qib/qib_dma.c b/drivers/infiniband/hw/qib/qib_dma.c index 2920bb39a65..59fe092b4b0 100644 --- a/drivers/infiniband/hw/qib/qib_dma.c +++ b/drivers/infiniband/hw/qib/qib_dma.c @@ -108,6 +108,10 @@ static int qib_map_sg(struct ib_device *dev, struct scatterlist *sgl,  			ret = 0;  			break;  		} +		sg->dma_address = addr + sg->offset; +#ifdef CONFIG_NEED_SG_DMA_LENGTH +		sg->dma_length = sg->length; +#endif  	}  	return ret;  } @@ -119,21 +123,6 @@ static void qib_unmap_sg(struct ib_device *dev,  	BUG_ON(!valid_dma_direction(direction));  } -static u64 qib_sg_dma_address(struct ib_device *dev, struct scatterlist *sg) -{ -	u64 addr = (u64) page_address(sg_page(sg)); - -	if (addr) -		addr += sg->offset; -	return addr; -} - -static unsigned int qib_sg_dma_len(struct ib_device *dev, -				   struct scatterlist *sg) -{ -	return sg->length; -} -  static void qib_sync_single_for_cpu(struct ib_device *dev, u64 addr,  				    size_t size, enum dma_data_direction dir)  { @@ -173,8 +162,6 @@ struct ib_dma_mapping_ops qib_dma_mapping_ops = {  	.unmap_page = qib_dma_unmap_page,  	.map_sg = qib_map_sg,  	.unmap_sg = qib_unmap_sg, -	.dma_address = qib_sg_dma_address, -	.dma_len = qib_sg_dma_len,  	.sync_single_for_cpu = qib_sync_single_for_cpu,  	.sync_single_for_device = qib_sync_single_for_device,  	.alloc_coherent = qib_dma_alloc_coherent, diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c index 275f247f9fc..b15e34eeef6 100644 --- a/drivers/infiniband/hw/qib/qib_file_ops.c +++ b/drivers/infiniband/hw/qib/qib_file_ops.c @@ -1459,7 +1459,7 @@ static int get_a_ctxt(struct file *fp, const struct qib_user_info *uinfo,  					cused++;  				else  					cfree++; -			if (pusable && cfree && cused < inuse) { +			if (cfree && cused < inuse) {  				udd = dd;  				inuse = cused;  			} @@ -1578,7 +1578,7 @@ static int do_qib_user_sdma_queue_create(struct file *fp)  	struct qib_ctxtdata *rcd = fd->rcd;  	struct qib_devdata *dd = rcd->dd; -	if (dd->flags & QIB_HAS_SEND_DMA) +	if (dd->flags & QIB_HAS_SEND_DMA) {  		fd->pq = qib_user_sdma_queue_create(&dd->pcidev->dev,  						    dd->unit, @@ -1586,6 +1586,7 @@ static int do_qib_user_sdma_queue_create(struct file *fp)  						    fd->subctxt);  		if (!fd->pq)  			return -ENOMEM; +	}  	return 0;  } diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c index f247fc6e618..cab610ccd50 100644 --- a/drivers/infiniband/hw/qib/qib_fs.c +++ b/drivers/infiniband/hw/qib/qib_fs.c @@ -105,6 +105,7 @@ static int create_file(const char *name, umode_t mode,  static ssize_t driver_stats_read(struct file *file, char __user *buf,  				 size_t count, loff_t *ppos)  { +	qib_stats.sps_ints = qib_sps_ints();  	return simple_read_from_buffer(buf, count, ppos, &qib_stats,  				       sizeof qib_stats);  } @@ -456,13 +457,13 @@ static int remove_file(struct dentry *parent, char *name)  	spin_lock(&tmp->d_lock);  	if (!(d_unhashed(tmp) && tmp->d_inode)) { -		dget_dlock(tmp);  		__d_drop(tmp);  		spin_unlock(&tmp->d_lock);  		simple_unlink(parent->d_inode, tmp);  	} else {  		spin_unlock(&tmp->d_lock);  	} +	dput(tmp);  	ret = 0;  bail: @@ -491,6 +492,7 @@ static int remove_device_files(struct super_block *sb,  		goto bail;  	} +	mutex_lock(&dir->d_inode->i_mutex);  	remove_file(dir, "counters");  	remove_file(dir, "counter_names");  	remove_file(dir, "portcounter_names"); @@ -505,8 +507,10 @@ static int remove_device_files(struct super_block *sb,  		}  	}  	remove_file(dir, "flash"); -	d_delete(dir); +	mutex_unlock(&dir->d_inode->i_mutex);  	ret = simple_rmdir(root->d_inode, dir); +	d_delete(dir); +	dput(dir);  bail:  	mutex_unlock(&root->d_inode->i_mutex); diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 84e593d6007..d68266ac761 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -1634,9 +1634,7 @@ static irqreturn_t qib_6120intr(int irq, void *data)  		goto bail;  	} -	qib_stats.sps_ints++; -	if (dd->int_counter != (u32) -1) -		dd->int_counter++; +	this_cpu_inc(*dd->int_counter);  	if (unlikely(istat & (~QLOGIC_IB_I_BITSEXTANT |  			      QLOGIC_IB_I_GPIO | QLOGIC_IB_I_ERROR))) @@ -1808,7 +1806,8 @@ static int qib_6120_setup_reset(struct qib_devdata *dd)  	 * isn't set.  	 */  	dd->flags &= ~(QIB_INITTED | QIB_PRESENT); -	dd->int_counter = 0; /* so we check interrupts work again */ +	/* so we check interrupts work again */ +	dd->z_int_counter = qib_int_counter(dd);  	val = dd->control | QLOGIC_IB_C_RESET;  	writeq(val, &dd->kregbase[kr_control]);  	mb(); /* prevent compiler re-ordering around actual reset */ @@ -3266,7 +3265,9 @@ static int init_6120_variables(struct qib_devdata *dd)  	dd->eep_st_masks[2].errs_to_log = ERR_MASK(ResetNegated); -	qib_init_pportdata(ppd, dd, 0, 1); +	ret = qib_init_pportdata(ppd, dd, 0, 1); +	if (ret) +		goto bail;  	ppd->link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;  	ppd->link_speed_supported = QIB_IB_SDR;  	ppd->link_width_enabled = IB_WIDTH_4X; diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index 454c2e7668f..7dec89fdc12 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -1962,10 +1962,7 @@ static irqreturn_t qib_7220intr(int irq, void *data)  		goto bail;  	} -	qib_stats.sps_ints++; -	if (dd->int_counter != (u32) -1) -		dd->int_counter++; - +	this_cpu_inc(*dd->int_counter);  	if (unlikely(istat & (~QLOGIC_IB_I_BITSEXTANT |  			      QLOGIC_IB_I_GPIO | QLOGIC_IB_I_ERROR)))  		unlikely_7220_intr(dd, istat); @@ -2120,7 +2117,8 @@ static int qib_setup_7220_reset(struct qib_devdata *dd)  	 * isn't set.  	 */  	dd->flags &= ~(QIB_INITTED | QIB_PRESENT); -	dd->int_counter = 0; /* so we check interrupts work again */ +	/* so we check interrupts work again */ +	dd->z_int_counter = qib_int_counter(dd);  	val = dd->control | QLOGIC_IB_C_RESET;  	writeq(val, &dd->kregbase[kr_control]);  	mb(); /* prevent compiler reordering around actual reset */ @@ -4061,7 +4059,9 @@ static int qib_init_7220_variables(struct qib_devdata *dd)  	init_waitqueue_head(&cpspec->autoneg_wait);  	INIT_DELAYED_WORK(&cpspec->autoneg_work, autoneg_7220_work); -	qib_init_pportdata(ppd, dd, 0, 1); +	ret = qib_init_pportdata(ppd, dd, 0, 1); +	if (ret) +		goto bail;  	ppd->link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;  	ppd->link_speed_supported = QIB_IB_SDR | QIB_IB_DDR; diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 016e7429adf..a7eb32517a0 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -2395,6 +2395,11 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)  	qib_write_kreg_port(ppd, krp_ibcctrl_a, ppd->cpspec->ibcctrl_a);  	qib_write_kreg(dd, kr_scratch, 0ULL); +	/* ensure previous Tx parameters are not still forced */ +	qib_write_kreg_port(ppd, krp_tx_deemph_override, +		SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, +		reset_tx_deemphasis_override)); +  	if (qib_compat_ddr_negotiate) {  		ppd->cpspec->ibdeltainprog = 1;  		ppd->cpspec->ibsymsnap = read_7322_creg32_port(ppd, @@ -3110,9 +3115,7 @@ static irqreturn_t qib_7322intr(int irq, void *data)  		goto bail;  	} -	qib_stats.sps_ints++; -	if (dd->int_counter != (u32) -1) -		dd->int_counter++; +	this_cpu_inc(*dd->int_counter);  	/* handle "errors" of various kinds first, device ahead of port */  	if (unlikely(istat & (~QIB_I_BITSEXTANT | QIB_I_GPIO | @@ -3181,9 +3184,7 @@ static irqreturn_t qib_7322pintr(int irq, void *data)  		 */  		return IRQ_HANDLED; -	qib_stats.sps_ints++; -	if (dd->int_counter != (u32) -1) -		dd->int_counter++; +	this_cpu_inc(*dd->int_counter);  	/* Clear the interrupt bit we expect to be set. */  	qib_write_kreg(dd, kr_intclear, ((1ULL << QIB_I_RCVAVAIL_LSB) | @@ -3210,9 +3211,7 @@ static irqreturn_t qib_7322bufavail(int irq, void *data)  		 */  		return IRQ_HANDLED; -	qib_stats.sps_ints++; -	if (dd->int_counter != (u32) -1) -		dd->int_counter++; +	this_cpu_inc(*dd->int_counter);  	/* Clear the interrupt bit we expect to be set. */  	qib_write_kreg(dd, kr_intclear, QIB_I_SPIOBUFAVAIL); @@ -3243,9 +3242,7 @@ static irqreturn_t sdma_intr(int irq, void *data)  		 */  		return IRQ_HANDLED; -	qib_stats.sps_ints++; -	if (dd->int_counter != (u32) -1) -		dd->int_counter++; +	this_cpu_inc(*dd->int_counter);  	/* Clear the interrupt bit we expect to be set. */  	qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? @@ -3272,9 +3269,7 @@ static irqreturn_t sdma_idle_intr(int irq, void *data)  		 */  		return IRQ_HANDLED; -	qib_stats.sps_ints++; -	if (dd->int_counter != (u32) -1) -		dd->int_counter++; +	this_cpu_inc(*dd->int_counter);  	/* Clear the interrupt bit we expect to be set. */  	qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? @@ -3301,9 +3296,7 @@ static irqreturn_t sdma_progress_intr(int irq, void *data)  		 */  		return IRQ_HANDLED; -	qib_stats.sps_ints++; -	if (dd->int_counter != (u32) -1) -		dd->int_counter++; +	this_cpu_inc(*dd->int_counter);  	/* Clear the interrupt bit we expect to be set. */  	qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? @@ -3331,9 +3324,7 @@ static irqreturn_t sdma_cleanup_intr(int irq, void *data)  		 */  		return IRQ_HANDLED; -	qib_stats.sps_ints++; -	if (dd->int_counter != (u32) -1) -		dd->int_counter++; +	this_cpu_inc(*dd->int_counter);  	/* Clear the interrupt bit we expect to be set. */  	qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? @@ -3718,7 +3709,8 @@ static int qib_do_7322_reset(struct qib_devdata *dd)  	dd->pport->cpspec->ibsymdelta = 0;  	dd->pport->cpspec->iblnkerrdelta = 0;  	dd->pport->cpspec->ibmalfdelta = 0; -	dd->int_counter = 0; /* so we check interrupts work again */ +	/* so we check interrupts work again */ +	dd->z_int_counter = qib_int_counter(dd);  	/*  	 * Keep chip from being accessed until we are ready.  Use @@ -6190,21 +6182,20 @@ static int setup_txselect(const char *str, struct kernel_param *kp)  {  	struct qib_devdata *dd;  	unsigned long val; -	int ret; - +	char *n;  	if (strlen(str) >= MAX_ATTEN_LEN) {  		pr_info("txselect_values string too long\n");  		return -ENOSPC;  	} -	ret = kstrtoul(str, 0, &val); -	if (ret || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ + +	val = simple_strtoul(str, &n, 0); +	if (n == str || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ +  				TXDDS_MFG_SZ)) {  		pr_info("txselect_values must start with a number < %d\n",  			TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ + TXDDS_MFG_SZ); -		return ret ? ret : -EINVAL; +		return -EINVAL;  	} -  	strcpy(txselect_list, str); +  	list_for_each_entry(dd, &qib_dev_list, list)  		if (dd->deviceid == PCI_DEVICE_ID_QLOGIC_IB_7322)  			set_no_qsfp_atten(dd, 1); @@ -6553,7 +6544,11 @@ static int qib_init_7322_variables(struct qib_devdata *dd)  		}  		dd->num_pports++; -		qib_init_pportdata(ppd, dd, pidx, dd->num_pports); +		ret = qib_init_pportdata(ppd, dd, pidx, dd->num_pports); +		if (ret) { +			dd->num_pports--; +			goto bail; +		}  		ppd->link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;  		ppd->link_width_enabled = IB_WIDTH_4X; diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 24e802f4ea2..8d3c78ddc90 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c @@ -130,7 +130,6 @@ void qib_set_ctxtcnt(struct qib_devdata *dd)  int qib_create_ctxts(struct qib_devdata *dd)  {  	unsigned i; -	int ret;  	int local_node_id = pcibus_to_node(dd->pcidev->bus);  	if (local_node_id < 0) @@ -145,8 +144,7 @@ int qib_create_ctxts(struct qib_devdata *dd)  	if (!dd->rcd) {  		qib_dev_err(dd,  			"Unable to allocate ctxtdata array, failing\n"); -		ret = -ENOMEM; -		goto done; +		return -ENOMEM;  	}  	/* create (one or more) kctxt */ @@ -163,15 +161,14 @@ int qib_create_ctxts(struct qib_devdata *dd)  		if (!rcd) {  			qib_dev_err(dd,  				"Unable to allocate ctxtdata for Kernel ctxt, failing\n"); -			ret = -ENOMEM; -			goto done; +			kfree(dd->rcd); +			dd->rcd = NULL; +			return -ENOMEM;  		}  		rcd->pkeys[0] = QIB_DEFAULT_P_KEY;  		rcd->seq_cnt = 1;  	} -	ret = 0; -done: -	return ret; +	return 0;  }  /* @@ -233,7 +230,7 @@ struct qib_ctxtdata *qib_create_ctxtdata(struct qib_pportdata *ppd, u32 ctxt,  /*   * Common code for initializing the physical port structure.   */ -void qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd, +int qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd,  			u8 hw_pidx, u8 port)  {  	int size; @@ -243,6 +240,7 @@ void qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd,  	spin_lock_init(&ppd->sdma_lock);  	spin_lock_init(&ppd->lflags_lock); +	spin_lock_init(&ppd->cc_shadow_lock);  	init_waitqueue_head(&ppd->state_wait);  	init_timer(&ppd->symerr_clear_timer); @@ -250,8 +248,10 @@ void qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd,  	ppd->symerr_clear_timer.data = (unsigned long)ppd;  	ppd->qib_wq = NULL; - -	spin_lock_init(&ppd->cc_shadow_lock); +	ppd->ibport_data.pmastats = +		alloc_percpu(struct qib_pma_counters); +	if (!ppd->ibport_data.pmastats) +		return -ENOMEM;  	if (qib_cc_table_size < IB_CCT_MIN_ENTRIES)  		goto bail; @@ -299,7 +299,7 @@ void qib_init_pportdata(struct qib_pportdata *ppd, struct qib_devdata *dd,  		goto bail_3;  	} -	return; +	return 0;  bail_3:  	kfree(ppd->ccti_entries_shadow); @@ -313,7 +313,7 @@ bail_1:  bail:  	/* User is intentionally disabling the congestion control agent */  	if (!qib_cc_table_size) -		return; +		return 0;  	if (qib_cc_table_size < IB_CCT_MIN_ENTRIES) {  		qib_cc_table_size = 0; @@ -324,7 +324,7 @@ bail:  	qib_dev_err(dd, "Congestion Control Agent disabled for port %d\n",  		port); -	return; +	return 0;  }  static int init_pioavailregs(struct qib_devdata *dd) @@ -525,6 +525,7 @@ static void enable_chip(struct qib_devdata *dd)  static void verify_interrupt(unsigned long opaque)  {  	struct qib_devdata *dd = (struct qib_devdata *) opaque; +	u64 int_counter;  	if (!dd)  		return; /* being torn down */ @@ -533,7 +534,8 @@ static void verify_interrupt(unsigned long opaque)  	 * If we don't have a lid or any interrupts, let the user know and  	 * don't bother checking again.  	 */ -	if (dd->int_counter == 0) { +	int_counter = qib_int_counter(dd) - dd->z_int_counter; +	if (int_counter == 0) {  		if (!dd->f_intr_fallback(dd))  			dev_err(&dd->pcidev->dev,  				"No interrupts detected, not usable.\n"); @@ -633,6 +635,12 @@ wq_error:  	return -ENOMEM;  } +static void qib_free_pportdata(struct qib_pportdata *ppd) +{ +	free_percpu(ppd->ibport_data.pmastats); +	ppd->ibport_data.pmastats = NULL; +} +  /**   * qib_init - do the actual initialization sequence on the chip   * @dd: the qlogic_ib device @@ -920,6 +928,7 @@ static void qib_shutdown_device(struct qib_devdata *dd)  			destroy_workqueue(ppd->qib_wq);  			ppd->qib_wq = NULL;  		} +		qib_free_pportdata(ppd);  	}  	qib_update_eeprom_log(dd); @@ -1079,9 +1088,34 @@ void qib_free_devdata(struct qib_devdata *dd)  #ifdef CONFIG_DEBUG_FS  	qib_dbg_ibdev_exit(&dd->verbs_dev);  #endif +	free_percpu(dd->int_counter);  	ib_dealloc_device(&dd->verbs_dev.ibdev);  } +u64 qib_int_counter(struct qib_devdata *dd) +{ +	int cpu; +	u64 int_counter = 0; + +	for_each_possible_cpu(cpu) +		int_counter += *per_cpu_ptr(dd->int_counter, cpu); +	return int_counter; +} + +u64 qib_sps_ints(void) +{ +	unsigned long flags; +	struct qib_devdata *dd; +	u64 sps_ints = 0; + +	spin_lock_irqsave(&qib_devs_lock, flags); +	list_for_each_entry(dd, &qib_dev_list, list) { +		sps_ints += qib_int_counter(dd); +	} +	spin_unlock_irqrestore(&qib_devs_lock, flags); +	return sps_ints; +} +  /*   * Allocate our primary per-unit data structure.  Must be done via verbs   * allocator, because the verbs cleanup process both does cleanup and @@ -1097,14 +1131,10 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra)  	int ret;  	dd = (struct qib_devdata *) ib_alloc_device(sizeof(*dd) + extra); -	if (!dd) { -		dd = ERR_PTR(-ENOMEM); -		goto bail; -	} +	if (!dd) +		return ERR_PTR(-ENOMEM); -#ifdef CONFIG_DEBUG_FS -	qib_dbg_ibdev_init(&dd->verbs_dev); -#endif +	INIT_LIST_HEAD(&dd->list);  	idr_preload(GFP_KERNEL);  	spin_lock_irqsave(&qib_devs_lock, flags); @@ -1121,11 +1151,13 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra)  	if (ret < 0) {  		qib_early_err(&pdev->dev,  			      "Could not allocate unit ID: error %d\n", -ret); -#ifdef CONFIG_DEBUG_FS -		qib_dbg_ibdev_exit(&dd->verbs_dev); -#endif -		ib_dealloc_device(&dd->verbs_dev.ibdev); -		dd = ERR_PTR(ret); +		goto bail; +	} +	dd->int_counter = alloc_percpu(u64); +	if (!dd->int_counter) { +		ret = -ENOMEM; +		qib_early_err(&pdev->dev, +			      "Could not allocate per-cpu int_counter\n");  		goto bail;  	} @@ -1139,9 +1171,15 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra)  			qib_early_err(&pdev->dev,  				"Could not alloc cpulist info, cpu affinity might be wrong\n");  	} - -bail: +#ifdef CONFIG_DEBUG_FS +	qib_dbg_ibdev_init(&dd->verbs_dev); +#endif  	return dd; +bail: +	if (!list_empty(&dd->list)) +		list_del_init(&dd->list); +	ib_dealloc_device(&dd->verbs_dev.ibdev); +	return ERR_PTR(ret);;  }  /* @@ -1234,7 +1272,7 @@ static int qib_notify_dca(struct notifier_block *nb, unsigned long event,   * Do all the generic driver unit- and chip-independent memory   * allocation and initialization.   */ -static int __init qlogic_ib_init(void) +static int __init qib_ib_init(void)  {  	int ret; @@ -1278,12 +1316,12 @@ bail:  	return ret;  } -module_init(qlogic_ib_init); +module_init(qib_ib_init);  /*   * Do the non-unit driver cleanup, memory free, etc. at unload.   */ -static void __exit qlogic_ib_cleanup(void) +static void __exit qib_ib_cleanup(void)  {  	int ret; @@ -1308,7 +1346,7 @@ static void __exit qlogic_ib_cleanup(void)  	qib_dev_cleanup();  } -module_exit(qlogic_ib_cleanup); +module_exit(qib_ib_cleanup);  /* this can only be called after a successful initialization */  static void cleanup_device_data(struct qib_devdata *dd) diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c index ccb119143d2..22c720e5740 100644 --- a/drivers/infiniband/hw/qib/qib_mad.c +++ b/drivers/infiniband/hw/qib/qib_mad.c @@ -1028,7 +1028,7 @@ static int set_pkeys(struct qib_devdata *dd, u8 port, u16 *pkeys)  		event.event = IB_EVENT_PKEY_CHANGE;  		event.device = &dd->verbs_dev.ibdev; -		event.element.port_num = 1; +		event.element.port_num = port;  		ib_dispatch_event(&event);  	}  	return 0; @@ -1634,6 +1634,23 @@ static int pma_get_portcounters_cong(struct ib_pma_mad *pmp,  	return reply((struct ib_smp *)pmp);  } +static void qib_snapshot_pmacounters( +	struct qib_ibport *ibp, +	struct qib_pma_counters *pmacounters) +{ +	struct qib_pma_counters *p; +	int cpu; + +	memset(pmacounters, 0, sizeof(*pmacounters)); +	for_each_possible_cpu(cpu) { +		p = per_cpu_ptr(ibp->pmastats, cpu); +		pmacounters->n_unicast_xmit += p->n_unicast_xmit; +		pmacounters->n_unicast_rcv += p->n_unicast_rcv; +		pmacounters->n_multicast_xmit += p->n_multicast_xmit; +		pmacounters->n_multicast_rcv += p->n_multicast_rcv; +	} +} +  static int pma_get_portcounters_ext(struct ib_pma_mad *pmp,  				    struct ib_device *ibdev, u8 port)  { @@ -1642,6 +1659,7 @@ static int pma_get_portcounters_ext(struct ib_pma_mad *pmp,  	struct qib_ibport *ibp = to_iport(ibdev, port);  	struct qib_pportdata *ppd = ppd_from_ibp(ibp);  	u64 swords, rwords, spkts, rpkts, xwait; +	struct qib_pma_counters pma;  	u8 port_select = p->port_select;  	memset(pmp->data, 0, sizeof(pmp->data)); @@ -1664,10 +1682,17 @@ static int pma_get_portcounters_ext(struct ib_pma_mad *pmp,  	p->port_rcv_data = cpu_to_be64(rwords);  	p->port_xmit_packets = cpu_to_be64(spkts);  	p->port_rcv_packets = cpu_to_be64(rpkts); -	p->port_unicast_xmit_packets = cpu_to_be64(ibp->n_unicast_xmit); -	p->port_unicast_rcv_packets = cpu_to_be64(ibp->n_unicast_rcv); -	p->port_multicast_xmit_packets = cpu_to_be64(ibp->n_multicast_xmit); -	p->port_multicast_rcv_packets = cpu_to_be64(ibp->n_multicast_rcv); + +	qib_snapshot_pmacounters(ibp, &pma); + +	p->port_unicast_xmit_packets = cpu_to_be64(pma.n_unicast_xmit +		- ibp->z_unicast_xmit); +	p->port_unicast_rcv_packets = cpu_to_be64(pma.n_unicast_rcv +		- ibp->z_unicast_rcv); +	p->port_multicast_xmit_packets = cpu_to_be64(pma.n_multicast_xmit +		- ibp->z_multicast_xmit); +	p->port_multicast_rcv_packets = cpu_to_be64(pma.n_multicast_rcv +		- ibp->z_multicast_rcv);  bail:  	return reply((struct ib_smp *) pmp); @@ -1795,6 +1820,7 @@ static int pma_set_portcounters_ext(struct ib_pma_mad *pmp,  	struct qib_ibport *ibp = to_iport(ibdev, port);  	struct qib_pportdata *ppd = ppd_from_ibp(ibp);  	u64 swords, rwords, spkts, rpkts, xwait; +	struct qib_pma_counters pma;  	qib_snapshot_counters(ppd, &swords, &rwords, &spkts, &rpkts, &xwait); @@ -1810,17 +1836,19 @@ static int pma_set_portcounters_ext(struct ib_pma_mad *pmp,  	if (p->counter_select & IB_PMA_SELX_PORT_RCV_PACKETS)  		ibp->z_port_rcv_packets = rpkts; +	qib_snapshot_pmacounters(ibp, &pma); +  	if (p->counter_select & IB_PMA_SELX_PORT_UNI_XMIT_PACKETS) -		ibp->n_unicast_xmit = 0; +		ibp->z_unicast_xmit = pma.n_unicast_xmit;  	if (p->counter_select & IB_PMA_SELX_PORT_UNI_RCV_PACKETS) -		ibp->n_unicast_rcv = 0; +		ibp->z_unicast_rcv = pma.n_unicast_rcv;  	if (p->counter_select & IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS) -		ibp->n_multicast_xmit = 0; +		ibp->z_multicast_xmit = pma.n_multicast_xmit;  	if (p->counter_select & IB_PMA_SELX_PORT_MULTI_RCV_PACKETS) -		ibp->n_multicast_rcv = 0; +		ibp->z_multicast_rcv = pma.n_multicast_rcv;  	return pma_get_portcounters_ext(pmp, ibdev, port);  } diff --git a/drivers/infiniband/hw/qib/qib_mad.h b/drivers/infiniband/hw/qib/qib_mad.h index 28874f8606f..941d4d50d8e 100644 --- a/drivers/infiniband/hw/qib/qib_mad.h +++ b/drivers/infiniband/hw/qib/qib_mad.h @@ -54,7 +54,7 @@ struct ib_node_info {  	__be32 revision;  	u8 local_port_num;  	u8 vendor_id[3]; -} __attribute__ ((packed)); +} __packed;  struct ib_mad_notice_attr {  	u8 generic_type; @@ -73,7 +73,7 @@ struct ib_mad_notice_attr {  			__be16	reserved;  			__be16	lid;		/* where violation happened */  			u8	port_num;	/* where violation happened */ -		} __attribute__ ((packed)) ntc_129_131; +		} __packed ntc_129_131;  		struct {  			__be16	reserved; @@ -83,14 +83,14 @@ struct ib_mad_notice_attr {  			__be32	new_cap_mask;	/* new capability mask */  			u8	reserved3;  			u8	change_flags;	/* low 3 bits only */ -		} __attribute__ ((packed)) ntc_144; +		} __packed ntc_144;  		struct {  			__be16	reserved;  			__be16	lid;		/* lid where sys guid changed */  			__be16	reserved2;  			__be64	new_sys_guid; -		} __attribute__ ((packed)) ntc_145; +		} __packed ntc_145;  		struct {  			__be16	reserved; @@ -104,7 +104,7 @@ struct ib_mad_notice_attr {  			u8	reserved3;  			u8	dr_trunc_hop;  			u8	dr_rtn_path[30]; -		} __attribute__ ((packed)) ntc_256; +		} __packed ntc_256;  		struct {  			__be16		reserved; @@ -115,7 +115,7 @@ struct ib_mad_notice_attr {  			__be32		qp2;	/* high 8 bits reserved */  			union ib_gid	gid1;  			union ib_gid	gid2; -		} __attribute__ ((packed)) ntc_257_258; +		} __packed ntc_257_258;  	} details;  }; @@ -209,7 +209,7 @@ struct ib_pma_portcounters_cong {  	__be64 port_rcv_packets;  	__be64 port_xmit_wait;  	__be64 port_adr_events; -} __attribute__ ((packed)); +} __packed;  #define IB_PMA_CONG_HW_CONTROL_TIMER            0x00  #define IB_PMA_CONG_HW_CONTROL_SAMPLE           0x01 diff --git a/drivers/infiniband/hw/qib/qib_mr.c b/drivers/infiniband/hw/qib/qib_mr.c index e6687ded821..9bbb55347cc 100644 --- a/drivers/infiniband/hw/qib/qib_mr.c +++ b/drivers/infiniband/hw/qib/qib_mr.c @@ -232,8 +232,8 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  {  	struct qib_mr *mr;  	struct ib_umem *umem; -	struct ib_umem_chunk *chunk; -	int n, m, i; +	struct scatterlist *sg; +	int n, m, entry;  	struct ib_mr *ret;  	if (length == 0) { @@ -246,9 +246,7 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  	if (IS_ERR(umem))  		return (void *) umem; -	n = 0; -	list_for_each_entry(chunk, &umem->chunk_list, list) -		n += chunk->nents; +	n = umem->nmap;  	mr = alloc_mr(n, pd);  	if (IS_ERR(mr)) { @@ -268,11 +266,10 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  		mr->mr.page_shift = ilog2(umem->page_size);  	m = 0;  	n = 0; -	list_for_each_entry(chunk, &umem->chunk_list, list) { -		for (i = 0; i < chunk->nents; i++) { +	for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {  			void *vaddr; -			vaddr = page_address(sg_page(&chunk->page_list[i])); +			vaddr = page_address(sg_page(sg));  			if (!vaddr) {  				ret = ERR_PTR(-EINVAL);  				goto bail; @@ -284,7 +281,6 @@ struct ib_mr *qib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,  				m++;  				n = 0;  			} -		}  	}  	ret = &mr->ibmr; diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index 3f14009fb66..61a0046efb7 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -51,8 +51,8 @@   * file calls, even though this violates some   * expectations of harmlessness.   */ -static int qib_tune_pcie_caps(struct qib_devdata *); -static int qib_tune_pcie_coalesce(struct qib_devdata *); +static void qib_tune_pcie_caps(struct qib_devdata *); +static void qib_tune_pcie_coalesce(struct qib_devdata *);  /*   * Do all the common PCIe setup and initialization. @@ -197,46 +197,47 @@ static void qib_msix_setup(struct qib_devdata *dd, int pos, u32 *msixcnt,  			   struct qib_msix_entry *qib_msix_entry)  {  	int ret; -	u32 tabsize = 0; -	u16 msix_flags; +	int nvec = *msixcnt;  	struct msix_entry *msix_entry;  	int i; +	ret = pci_msix_vec_count(dd->pcidev); +	if (ret < 0) +		goto do_intx; + +	nvec = min(nvec, ret); +  	/* We can't pass qib_msix_entry array to qib_msix_setup  	 * so use a dummy msix_entry array and copy the allocated  	 * irq back to the qib_msix_entry array. */ -	msix_entry = kmalloc(*msixcnt * sizeof(*msix_entry), GFP_KERNEL); -	if (!msix_entry) { -		ret = -ENOMEM; +	msix_entry = kmalloc(nvec * sizeof(*msix_entry), GFP_KERNEL); +	if (!msix_entry)  		goto do_intx; -	} -	for (i = 0; i < *msixcnt; i++) + +	for (i = 0; i < nvec; i++)  		msix_entry[i] = qib_msix_entry[i].msix; -	pci_read_config_word(dd->pcidev, pos + PCI_MSIX_FLAGS, &msix_flags); -	tabsize = 1 + (msix_flags & PCI_MSIX_FLAGS_QSIZE); -	if (tabsize > *msixcnt) -		tabsize = *msixcnt; -	ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize); -	if (ret > 0) { -		tabsize = ret; -		ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize); -	} -do_intx: -	if (ret) { -		qib_dev_err(dd, -			"pci_enable_msix %d vectors failed: %d, falling back to INTx\n", -			tabsize, ret); -		tabsize = 0; -	} -	for (i = 0; i < tabsize; i++) +	ret = pci_enable_msix_range(dd->pcidev, msix_entry, 1, nvec); +	if (ret < 0) +		goto free_msix_entry; +	else +		nvec = ret; + +	for (i = 0; i < nvec; i++)  		qib_msix_entry[i].msix = msix_entry[i]; +  	kfree(msix_entry); -	*msixcnt = tabsize; +	*msixcnt = nvec; +	return; -	if (ret) -		qib_enable_intx(dd->pcidev); +free_msix_entry: +	kfree(msix_entry); +do_intx: +	qib_dev_err(dd, "pci_enable_msix_range %d vectors failed: %d, " +			"falling back to INTx\n", nvec, ret); +	*msixcnt = 0; +	qib_enable_intx(dd->pcidev);  }  /** @@ -476,30 +477,6 @@ void qib_pcie_reenable(struct qib_devdata *dd, u16 cmd, u8 iline, u8 cline)  			"pci_enable_device failed after reset: %d\n", r);  } -/* code to adjust PCIe capabilities. */ - -static int fld2val(int wd, int mask) -{ -	int lsbmask; - -	if (!mask) -		return 0; -	wd &= mask; -	lsbmask = mask ^ (mask & (mask - 1)); -	wd /= lsbmask; -	return wd; -} - -static int val2fld(int wd, int mask) -{ -	int lsbmask; - -	if (!mask) -		return 0; -	lsbmask = mask ^ (mask & (mask - 1)); -	wd *= lsbmask; -	return wd; -}  static int qib_pcie_coalesce;  module_param_named(pcie_coalesce, qib_pcie_coalesce, int, S_IRUGO); @@ -511,7 +488,7 @@ MODULE_PARM_DESC(pcie_coalesce, "tune PCIe colescing on some Intel chipsets");   * of these chipsets, with some BIOS settings, and enabling it on those   * systems may result in the system crashing, and/or data corruption.   */ -static int qib_tune_pcie_coalesce(struct qib_devdata *dd) +static void qib_tune_pcie_coalesce(struct qib_devdata *dd)  {  	int r;  	struct pci_dev *parent; @@ -519,18 +496,18 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)  	u32 mask, bits, val;  	if (!qib_pcie_coalesce) -		return 0; +		return;  	/* Find out supported and configured values for parent (root) */  	parent = dd->pcidev->bus->self;  	if (parent->bus->parent) {  		qib_devinfo(dd->pcidev, "Parent not root\n"); -		return 1; +		return;  	}  	if (!pci_is_pcie(parent)) -		return 1; +		return;  	if (parent->vendor != 0x8086) -		return 1; +		return;  	/*  	 *  - bit 12: Max_rdcmp_Imt_EN: need to set to 1 @@ -563,13 +540,12 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)  		mask = (3U << 24) | (7U << 10);  	} else {  		/* not one of the chipsets that we know about */ -		return 1; +		return;  	}  	pci_read_config_dword(parent, 0x48, &val);  	val &= ~mask;  	val |= bits;  	r = pci_write_config_dword(parent, 0x48, val); -	return 0;  }  /* @@ -580,55 +556,44 @@ static int qib_pcie_caps;  module_param_named(pcie_caps, qib_pcie_caps, int, S_IRUGO);  MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (0..3), ReadReq (4..7)"); -static int qib_tune_pcie_caps(struct qib_devdata *dd) +static void qib_tune_pcie_caps(struct qib_devdata *dd)  { -	int ret = 1; /* Assume the worst */  	struct pci_dev *parent; -	u16 pcaps, pctl, ecaps, ectl; -	int rc_sup, ep_sup; -	int rc_cur, ep_cur; +	u16 rc_mpss, rc_mps, ep_mpss, ep_mps; +	u16 rc_mrrs, ep_mrrs, max_mrrs;  	/* Find out supported and configured values for parent (root) */  	parent = dd->pcidev->bus->self; -	if (parent->bus->parent) { +	if (!pci_is_root_bus(parent->bus)) {  		qib_devinfo(dd->pcidev, "Parent not root\n"); -		goto bail; +		return;  	}  	if (!pci_is_pcie(parent) || !pci_is_pcie(dd->pcidev)) -		goto bail; -	pcie_capability_read_word(parent, PCI_EXP_DEVCAP, &pcaps); -	pcie_capability_read_word(parent, PCI_EXP_DEVCTL, &pctl); +		return; + +	rc_mpss = parent->pcie_mpss; +	rc_mps = ffs(pcie_get_mps(parent)) - 8;  	/* Find out supported and configured values for endpoint (us) */ -	pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCAP, &ecaps); -	pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVCTL, &ectl); +	ep_mpss = dd->pcidev->pcie_mpss; +	ep_mps = ffs(pcie_get_mps(dd->pcidev)) - 8; -	ret = 0;  	/* Find max payload supported by root, endpoint */ -	rc_sup = fld2val(pcaps, PCI_EXP_DEVCAP_PAYLOAD); -	ep_sup = fld2val(ecaps, PCI_EXP_DEVCAP_PAYLOAD); -	if (rc_sup > ep_sup) -		rc_sup = ep_sup; - -	rc_cur = fld2val(pctl, PCI_EXP_DEVCTL_PAYLOAD); -	ep_cur = fld2val(ectl, PCI_EXP_DEVCTL_PAYLOAD); +	if (rc_mpss > ep_mpss) +		rc_mpss = ep_mpss;  	/* If Supported greater than limit in module param, limit it */ -	if (rc_sup > (qib_pcie_caps & 7)) -		rc_sup = qib_pcie_caps & 7; +	if (rc_mpss > (qib_pcie_caps & 7)) +		rc_mpss = qib_pcie_caps & 7;  	/* If less than (allowed, supported), bump root payload */ -	if (rc_sup > rc_cur) { -		rc_cur = rc_sup; -		pctl = (pctl & ~PCI_EXP_DEVCTL_PAYLOAD) | -			val2fld(rc_cur, PCI_EXP_DEVCTL_PAYLOAD); -		pcie_capability_write_word(parent, PCI_EXP_DEVCTL, pctl); +	if (rc_mpss > rc_mps) { +		rc_mps = rc_mpss; +		pcie_set_mps(parent, 128 << rc_mps);  	}  	/* If less than (allowed, supported), bump endpoint payload */ -	if (rc_sup > ep_cur) { -		ep_cur = rc_sup; -		ectl = (ectl & ~PCI_EXP_DEVCTL_PAYLOAD) | -			val2fld(ep_cur, PCI_EXP_DEVCTL_PAYLOAD); -		pcie_capability_write_word(dd->pcidev, PCI_EXP_DEVCTL, ectl); +	if (rc_mpss > ep_mps) { +		ep_mps = rc_mpss; +		pcie_set_mps(dd->pcidev, 128 << ep_mps);  	}  	/* @@ -636,26 +601,22 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)  	 * No field for max supported, but PCIe spec limits it to 4096,  	 * which is code '5' (log2(4096) - 7)  	 */ -	rc_sup = 5; -	if (rc_sup > ((qib_pcie_caps >> 4) & 7)) -		rc_sup = (qib_pcie_caps >> 4) & 7; -	rc_cur = fld2val(pctl, PCI_EXP_DEVCTL_READRQ); -	ep_cur = fld2val(ectl, PCI_EXP_DEVCTL_READRQ); - -	if (rc_sup > rc_cur) { -		rc_cur = rc_sup; -		pctl = (pctl & ~PCI_EXP_DEVCTL_READRQ) | -			val2fld(rc_cur, PCI_EXP_DEVCTL_READRQ); -		pcie_capability_write_word(parent, PCI_EXP_DEVCTL, pctl); +	max_mrrs = 5; +	if (max_mrrs > ((qib_pcie_caps >> 4) & 7)) +		max_mrrs = (qib_pcie_caps >> 4) & 7; + +	max_mrrs = 128 << max_mrrs; +	rc_mrrs = pcie_get_readrq(parent); +	ep_mrrs = pcie_get_readrq(dd->pcidev); + +	if (max_mrrs > rc_mrrs) { +		rc_mrrs = max_mrrs; +		pcie_set_readrq(parent, rc_mrrs);  	} -	if (rc_sup > ep_cur) { -		ep_cur = rc_sup; -		ectl = (ectl & ~PCI_EXP_DEVCTL_READRQ) | -			val2fld(ep_cur, PCI_EXP_DEVCTL_READRQ); -		pcie_capability_write_word(dd->pcidev, PCI_EXP_DEVCTL, ectl); +	if (max_mrrs > ep_mrrs) { +		ep_mrrs = max_mrrs; +		pcie_set_readrq(dd->pcidev, ep_mrrs);  	} -bail: -	return ret;  }  /* End of PCIe capability tuning */ diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c index 3cca55b51e5..7fcc150d603 100644 --- a/drivers/infiniband/hw/qib/qib_qp.c +++ b/drivers/infiniband/hw/qib/qib_qp.c @@ -585,7 +585,7 @@ int qib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,  	new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;  	if (!ib_modify_qp_is_ok(cur_state, new_state, ibqp->qp_type, -				attr_mask)) +				attr_mask, IB_LINK_LAYER_UNSPECIFIED))  		goto inval;  	if (attr_mask & IB_QP_AV) { @@ -985,7 +985,8 @@ struct ib_qp *qib_create_qp(struct ib_pd *ibpd,  	struct ib_qp *ret;  	if (init_attr->cap.max_send_sge > ib_qib_max_sges || -	    init_attr->cap.max_send_wr > ib_qib_max_qp_wrs) { +	    init_attr->cap.max_send_wr > ib_qib_max_qp_wrs || +	    init_attr->create_flags) {  		ret = ERR_PTR(-EINVAL);  		goto bail;  	} diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c index 3ab341320ea..2f2501890c4 100644 --- a/drivers/infiniband/hw/qib/qib_rc.c +++ b/drivers/infiniband/hw/qib/qib_rc.c @@ -752,7 +752,7 @@ void qib_send_rc_ack(struct qib_qp *qp)  	qib_flush_wc();  	qib_sendbuf_done(dd, pbufn); -	ibp->n_unicast_xmit++; +	this_cpu_inc(ibp->pmastats->n_unicast_xmit);  	goto done;  queue_ack: diff --git a/drivers/infiniband/hw/qib/qib_ruc.c b/drivers/infiniband/hw/qib/qib_ruc.c index 357b6cfcd46..4c07a8b34ff 100644 --- a/drivers/infiniband/hw/qib/qib_ruc.c +++ b/drivers/infiniband/hw/qib/qib_ruc.c @@ -703,6 +703,7 @@ void qib_make_ruc_header(struct qib_qp *qp, struct qib_other_headers *ohdr,  	ohdr->bth[0] = cpu_to_be32(bth0);  	ohdr->bth[1] = cpu_to_be32(qp->remote_qpn);  	ohdr->bth[2] = cpu_to_be32(bth2); +	this_cpu_inc(ibp->pmastats->n_unicast_xmit);  }  /** diff --git a/drivers/infiniband/hw/qib/qib_ud.c b/drivers/infiniband/hw/qib/qib_ud.c index d6c7fe7f88d..aaf7039f8ed 100644 --- a/drivers/infiniband/hw/qib/qib_ud.c +++ b/drivers/infiniband/hw/qib/qib_ud.c @@ -57,13 +57,20 @@ static void qib_ud_loopback(struct qib_qp *sqp, struct qib_swqe *swqe)  	struct qib_sge *sge;  	struct ib_wc wc;  	u32 length; +	enum ib_qp_type sqptype, dqptype;  	qp = qib_lookup_qpn(ibp, swqe->wr.wr.ud.remote_qpn);  	if (!qp) {  		ibp->n_pkt_drops++;  		return;  	} -	if (qp->ibqp.qp_type != sqp->ibqp.qp_type || + +	sqptype = sqp->ibqp.qp_type == IB_QPT_GSI ? +			IB_QPT_UD : sqp->ibqp.qp_type; +	dqptype = qp->ibqp.qp_type == IB_QPT_GSI ? +			IB_QPT_UD : qp->ibqp.qp_type; + +	if (dqptype != sqptype ||  	    !(ib_qib_state_ops[qp->state] & QIB_PROCESS_RECV_OK)) {  		ibp->n_pkt_drops++;  		goto drop; @@ -273,11 +280,11 @@ int qib_make_ud_req(struct qib_qp *qp)  	ah_attr = &to_iah(wqe->wr.wr.ud.ah)->attr;  	if (ah_attr->dlid >= QIB_MULTICAST_LID_BASE) {  		if (ah_attr->dlid != QIB_PERMISSIVE_LID) -			ibp->n_multicast_xmit++; +			this_cpu_inc(ibp->pmastats->n_multicast_xmit);  		else -			ibp->n_unicast_xmit++; +			this_cpu_inc(ibp->pmastats->n_unicast_xmit);  	} else { -		ibp->n_unicast_xmit++; +		this_cpu_inc(ibp->pmastats->n_unicast_xmit);  		lid = ah_attr->dlid & ~((1 << ppd->lmc) - 1);  		if (unlikely(lid == ppd->lid)) {  			/* diff --git a/drivers/infiniband/hw/qib/qib_user_sdma.c b/drivers/infiniband/hw/qib/qib_user_sdma.c index d0a0ea0c14d..d2806cae234 100644 --- a/drivers/infiniband/hw/qib/qib_user_sdma.c +++ b/drivers/infiniband/hw/qib/qib_user_sdma.c @@ -52,6 +52,17 @@  /* attempt to drain the queue for 5secs */  #define QIB_USER_SDMA_DRAIN_TIMEOUT 500 +/* + * track how many times a process open this driver. + */ +static struct rb_root qib_user_sdma_rb_root = RB_ROOT; + +struct qib_user_sdma_rb_node { +	struct rb_node node; +	int refcount; +	pid_t pid; +}; +  struct qib_user_sdma_pkt {  	struct list_head list;  /* list element */ @@ -120,15 +131,60 @@ struct qib_user_sdma_queue {  	/* dma page table */  	struct rb_root dma_pages_root; +	struct qib_user_sdma_rb_node *sdma_rb_node; +  	/* protect everything above... */  	struct mutex lock;  }; +static struct qib_user_sdma_rb_node * +qib_user_sdma_rb_search(struct rb_root *root, pid_t pid) +{ +	struct qib_user_sdma_rb_node *sdma_rb_node; +	struct rb_node *node = root->rb_node; + +	while (node) { +		sdma_rb_node = container_of(node, +			struct qib_user_sdma_rb_node, node); +		if (pid < sdma_rb_node->pid) +			node = node->rb_left; +		else if (pid > sdma_rb_node->pid) +			node = node->rb_right; +		else +			return sdma_rb_node; +	} +	return NULL; +} + +static int +qib_user_sdma_rb_insert(struct rb_root *root, struct qib_user_sdma_rb_node *new) +{ +	struct rb_node **node = &(root->rb_node); +	struct rb_node *parent = NULL; +	struct qib_user_sdma_rb_node *got; + +	while (*node) { +		got = container_of(*node, struct qib_user_sdma_rb_node, node); +		parent = *node; +		if (new->pid < got->pid) +			node = &((*node)->rb_left); +		else if (new->pid > got->pid) +			node = &((*node)->rb_right); +		else +			return 0; +	} + +	rb_link_node(&new->node, parent, node); +	rb_insert_color(&new->node, root); +	return 1; +} +  struct qib_user_sdma_queue *  qib_user_sdma_queue_create(struct device *dev, int unit, int ctxt, int sctxt)  {  	struct qib_user_sdma_queue *pq =  		kmalloc(sizeof(struct qib_user_sdma_queue), GFP_KERNEL); +	struct qib_user_sdma_rb_node *sdma_rb_node;  	if (!pq)  		goto done; @@ -138,6 +194,7 @@ qib_user_sdma_queue_create(struct device *dev, int unit, int ctxt, int sctxt)  	pq->num_pending = 0;  	pq->num_sending = 0;  	pq->added = 0; +	pq->sdma_rb_node = NULL;  	INIT_LIST_HEAD(&pq->sent);  	spin_lock_init(&pq->sent_lock); @@ -163,8 +220,30 @@ qib_user_sdma_queue_create(struct device *dev, int unit, int ctxt, int sctxt)  	pq->dma_pages_root = RB_ROOT; +	sdma_rb_node = qib_user_sdma_rb_search(&qib_user_sdma_rb_root, +					current->pid); +	if (sdma_rb_node) { +		sdma_rb_node->refcount++; +	} else { +		int ret; +		sdma_rb_node = kmalloc(sizeof( +			struct qib_user_sdma_rb_node), GFP_KERNEL); +		if (!sdma_rb_node) +			goto err_rb; + +		sdma_rb_node->refcount = 1; +		sdma_rb_node->pid = current->pid; + +		ret = qib_user_sdma_rb_insert(&qib_user_sdma_rb_root, +					sdma_rb_node); +		BUG_ON(ret == 0); +	} +	pq->sdma_rb_node = sdma_rb_node; +  	goto done; +err_rb: +	dma_pool_destroy(pq->header_cache);  err_slab:  	kmem_cache_destroy(pq->pkt_slab);  err_kfree: @@ -594,8 +673,7 @@ static int qib_user_sdma_pin_pages(const struct qib_devdata *dd,  		else  			j = npages; -		ret = get_user_pages(current, current->mm, addr, -			     j, 0, 1, pages, NULL); +		ret = get_user_pages_fast(addr, j, 0, pages);  		if (ret != j) {  			i = 0;  			j = ret; @@ -1021,8 +1099,13 @@ void qib_user_sdma_queue_destroy(struct qib_user_sdma_queue *pq)  	if (!pq)  		return; -	kmem_cache_destroy(pq->pkt_slab); +	pq->sdma_rb_node->refcount--; +	if (pq->sdma_rb_node->refcount == 0) { +		rb_erase(&pq->sdma_rb_node->node, &qib_user_sdma_rb_root); +		kfree(pq->sdma_rb_node); +	}  	dma_pool_destroy(pq->header_cache); +	kmem_cache_destroy(pq->pkt_slab);  	kfree(pq);  } @@ -1242,26 +1325,52 @@ static int qib_user_sdma_push_pkts(struct qib_pportdata *ppd,  				 struct qib_user_sdma_queue *pq,  				 struct list_head *pktlist, int count)  { -	int ret = 0;  	unsigned long flags;  	if (unlikely(!(ppd->lflags & QIBL_LINKACTIVE)))  		return -ECOMM; -	spin_lock_irqsave(&ppd->sdma_lock, flags); - -	if (unlikely(!__qib_sdma_running(ppd))) { -		ret = -ECOMM; -		goto unlock; +	/* non-blocking mode */ +	if (pq->sdma_rb_node->refcount > 1) { +		spin_lock_irqsave(&ppd->sdma_lock, flags); +		if (unlikely(!__qib_sdma_running(ppd))) { +			spin_unlock_irqrestore(&ppd->sdma_lock, flags); +			return -ECOMM; +		} +		pq->num_pending += count; +		list_splice_tail_init(pktlist, &ppd->sdma_userpending); +		qib_user_sdma_send_desc(ppd, &ppd->sdma_userpending); +		spin_unlock_irqrestore(&ppd->sdma_lock, flags); +		return 0;  	} +	/* In this case, descriptors from this process are not +	 * linked to ppd pending queue, interrupt handler +	 * won't update this process, it is OK to directly +	 * modify without sdma lock. +	 */ + +  	pq->num_pending += count; -	list_splice_tail_init(pktlist, &ppd->sdma_userpending); -	qib_user_sdma_send_desc(ppd, &ppd->sdma_userpending); +	/* +	 * Blocking mode for single rail process, we must +	 * release/regain sdma_lock to give other process +	 * chance to make progress. This is important for +	 * performance. +	 */ +	do { +		spin_lock_irqsave(&ppd->sdma_lock, flags); +		if (unlikely(!__qib_sdma_running(ppd))) { +			spin_unlock_irqrestore(&ppd->sdma_lock, flags); +			return -ECOMM; +		} +		qib_user_sdma_send_desc(ppd, pktlist); +		if (!list_empty(pktlist)) +			qib_sdma_make_progress(ppd); +		spin_unlock_irqrestore(&ppd->sdma_lock, flags); +	} while (!list_empty(pktlist)); -unlock: -	spin_unlock_irqrestore(&ppd->sdma_lock, flags); -	return ret; +	return 0;  }  int qib_user_sdma_writev(struct qib_ctxtdata *rcd, @@ -1291,14 +1400,11 @@ int qib_user_sdma_writev(struct qib_ctxtdata *rcd,  		qib_user_sdma_queue_clean(ppd, pq);  	while (dim) { -		int mxp = 8; +		int mxp = 1;  		int ndesc = 0; -		down_write(¤t->mm->mmap_sem);  		ret = qib_user_sdma_queue_pkts(dd, ppd, pq,  				iov, dim, &list, &mxp, &ndesc); -		up_write(¤t->mm->mmap_sem); -  		if (ret < 0)  			goto done_unlock;  		else { diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index 092b0bb1bb7..9bcfbd84298 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c @@ -662,7 +662,7 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen)  		mcast = qib_mcast_find(ibp, &hdr->u.l.grh.dgid);  		if (mcast == NULL)  			goto drop; -		ibp->n_multicast_rcv++; +		this_cpu_inc(ibp->pmastats->n_multicast_rcv);  		list_for_each_entry_rcu(p, &mcast->qp_list, list)  			qib_qp_rcv(rcd, hdr, 1, data, tlen, p->qp);  		/* @@ -678,8 +678,8 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen)  					&rcd->lookaside_qp->refcount))  					wake_up(  					 &rcd->lookaside_qp->wait); -					rcd->lookaside_qp = NULL; -				} +				rcd->lookaside_qp = NULL; +			}  		}  		if (!rcd->lookaside_qp) {  			qp = qib_lookup_qpn(ibp, qp_num); @@ -689,7 +689,7 @@ void qib_ib_rcv(struct qib_ctxtdata *rcd, void *rhdr, void *data, u32 tlen)  			rcd->lookaside_qpn = qp_num;  		} else  			qp = rcd->lookaside_qp; -		ibp->n_unicast_rcv++; +		this_cpu_inc(ibp->pmastats->n_unicast_rcv);  		qib_qp_rcv(rcd, hdr, lnh == QIB_LRH_GRH, data, tlen, qp);  	}  	return; diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h index 012e2c7575a..bfc8948fdd3 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.h +++ b/drivers/infiniband/hw/qib/qib_verbs.h @@ -150,14 +150,14 @@ struct ib_reth {  	__be64 vaddr;  	__be32 rkey;  	__be32 length; -} __attribute__ ((packed)); +} __packed;  struct ib_atomic_eth {  	__be32 vaddr[2];        /* unaligned so access as 2 32-bit words */  	__be32 rkey;  	__be64 swap_data;  	__be64 compare_data; -} __attribute__ ((packed)); +} __packed;  struct qib_other_headers {  	__be32 bth[3]; @@ -178,7 +178,7 @@ struct qib_other_headers {  		__be32 aeth;  		struct ib_atomic_eth atomic_eth;  	} u; -} __attribute__ ((packed)); +} __packed;  /*   * Note that UD packets with a GRH header are 8+40+12+8 = 68 bytes @@ -195,12 +195,12 @@ struct qib_ib_header {  		} l;  		struct qib_other_headers oth;  	} u; -} __attribute__ ((packed)); +} __packed;  struct qib_pio_header {  	__le32 pbc[2];  	struct qib_ib_header hdr; -} __attribute__ ((packed)); +} __packed;  /*   * There is one struct qib_mcast for each multicast GID. @@ -664,6 +664,13 @@ struct qib_opcode_stats_perctx {  	struct qib_opcode_stats stats[128];  }; +struct qib_pma_counters { +	u64 n_unicast_xmit;     /* total unicast packets sent */ +	u64 n_unicast_rcv;      /* total unicast packets received */ +	u64 n_multicast_xmit;   /* total multicast packets sent */ +	u64 n_multicast_rcv;    /* total multicast packets received */ +}; +  struct qib_ibport {  	struct qib_qp __rcu *qp0;  	struct qib_qp __rcu *qp1; @@ -680,10 +687,11 @@ struct qib_ibport {  	__be64 mkey;  	__be64 guids[QIB_GUIDS_PER_PORT	- 1];	/* writable GUIDs */  	u64 tid;		/* TID for traps */ -	u64 n_unicast_xmit;     /* total unicast packets sent */ -	u64 n_unicast_rcv;      /* total unicast packets received */ -	u64 n_multicast_xmit;   /* total multicast packets sent */ -	u64 n_multicast_rcv;    /* total multicast packets received */ +	struct qib_pma_counters __percpu *pmastats; +	u64 z_unicast_xmit;     /* starting count for PMA */ +	u64 z_unicast_rcv;      /* starting count for PMA */ +	u64 z_multicast_xmit;   /* starting count for PMA */ +	u64 z_multicast_rcv;    /* starting count for PMA */  	u64 z_symbol_error_counter;             /* starting count for PMA */  	u64 z_link_error_recovery_counter;      /* starting count for PMA */  	u64 z_link_downed_counter;              /* starting count for PMA */  | 
