diff options
Diffstat (limited to 'drivers/infiniband/hw/qib')
| -rw-r--r-- | drivers/infiniband/hw/qib/qib.h | 3 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_file_ops.c | 16 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_iba7220.c | 26 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_iba7322.c | 97 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_intr.c | 6 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_mad.c | 78 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_mad.h | 143 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_pcie.c | 8 | ||||
| -rw-r--r-- | drivers/infiniband/hw/qib/qib_sysfs.c | 14 | 
9 files changed, 168 insertions, 223 deletions
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index 769a1d9da4b..c9624ea8720 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -1012,6 +1012,8 @@ struct qib_devdata {  	u8 psxmitwait_supported;  	/* cycle length of PS* counters in HW (in picoseconds) */  	u16 psxmitwait_check_rate; +	/* high volume overflow errors defered to tasklet */ +	struct tasklet_struct error_tasklet;  };  /* hol_state values */ @@ -1433,6 +1435,7 @@ extern struct mutex qib_mutex;  struct qib_hwerror_msgs {  	u64 mask;  	const char *msg; +	size_t sz;  };  #define QLOGIC_IB_HWE_MSG(a, b) { .mask = a, .msg = b } diff --git a/drivers/infiniband/hw/qib/qib_file_ops.c b/drivers/infiniband/hw/qib/qib_file_ops.c index 406fca50d03..26253039d2c 100644 --- a/drivers/infiniband/hw/qib/qib_file_ops.c +++ b/drivers/infiniband/hw/qib/qib_file_ops.c @@ -1527,6 +1527,7 @@ done_chk_sdma:  		struct qib_filedata *fd = fp->private_data;  		const struct qib_ctxtdata *rcd = fd->rcd;  		const struct qib_devdata *dd = rcd->dd; +		unsigned int weight;  		if (dd->flags & QIB_HAS_SEND_DMA) {  			fd->pq = qib_user_sdma_queue_create(&dd->pcidev->dev, @@ -1545,8 +1546,8 @@ done_chk_sdma:  		 * it just means that sooner or later we don't recommend  		 * a cpu, and let the scheduler do it's best.  		 */ -		if (!ret && cpus_weight(current->cpus_allowed) >= -		    qib_cpulist_count) { +		weight = cpumask_weight(tsk_cpus_allowed(current)); +		if (!ret && weight >= qib_cpulist_count) {  			int cpu;  			cpu = find_first_zero_bit(qib_cpulist,  						  qib_cpulist_count); @@ -1554,13 +1555,13 @@ done_chk_sdma:  				__set_bit(cpu, qib_cpulist);  				fd->rec_cpu_num = cpu;  			} -		} else if (cpus_weight(current->cpus_allowed) == 1 && -			test_bit(first_cpu(current->cpus_allowed), +		} else if (weight == 1 && +			test_bit(cpumask_first(tsk_cpus_allowed(current)),  				 qib_cpulist))  			qib_devinfo(dd->pcidev, "%s PID %u affinity "  				    "set to cpu %d; already allocated\n",  				    current->comm, current->pid, -				    first_cpu(current->cpus_allowed)); +				    cpumask_first(tsk_cpus_allowed(current)));  	}  	mutex_unlock(&qib_mutex); @@ -1904,8 +1905,9 @@ int qib_set_uevent_bits(struct qib_pportdata *ppd, const int evtbit)  	struct qib_ctxtdata *rcd;  	unsigned ctxt;  	int ret = 0; +	unsigned long flags; -	spin_lock(&ppd->dd->uctxt_lock); +	spin_lock_irqsave(&ppd->dd->uctxt_lock, flags);  	for (ctxt = ppd->dd->first_user_ctxt; ctxt < ppd->dd->cfgctxts;  	     ctxt++) {  		rcd = ppd->dd->rcd[ctxt]; @@ -1924,7 +1926,7 @@ int qib_set_uevent_bits(struct qib_pportdata *ppd, const int evtbit)  		ret = 1;  		break;  	} -	spin_unlock(&ppd->dd->uctxt_lock); +	spin_unlock_irqrestore(&ppd->dd->uctxt_lock, flags);  	return ret;  } diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index c765a2eb04c..e1f947446c2 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -2434,6 +2434,7 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)  	int lsb, ret = 0, setforce = 0;  	u16 lcmd, licmd;  	unsigned long flags; +	u32 tmp = 0;  	switch (which) {  	case QIB_IB_CFG_LIDLMC: @@ -2467,9 +2468,6 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)  		maskr = IBA7220_IBC_WIDTH_MASK;  		lsb = IBA7220_IBC_WIDTH_SHIFT;  		setforce = 1; -		spin_lock_irqsave(&ppd->lflags_lock, flags); -		ppd->lflags |= QIBL_IB_FORCE_NOTIFY; -		spin_unlock_irqrestore(&ppd->lflags_lock, flags);  		break;  	case QIB_IB_CFG_SPD_ENB: /* set allowed Link speeds */ @@ -2643,6 +2641,28 @@ static int qib_7220_set_ib_cfg(struct qib_pportdata *ppd, int which, u32 val)  			goto bail;  		}  		qib_set_ib_7220_lstate(ppd, lcmd, licmd); + +		maskr = IBA7220_IBC_WIDTH_MASK; +		lsb = IBA7220_IBC_WIDTH_SHIFT; +		tmp = (ppd->cpspec->ibcddrctrl >> lsb) & maskr; +		/* If the width active on the chip does not match the +		 * width in the shadow register, write the new active +		 * width to the chip. +		 * We don't have to worry about speed as the speed is taken +		 * care of by set_7220_ibspeed_fast called by ib_updown. +		 */ +		if (ppd->link_width_enabled-1 != tmp) { +			ppd->cpspec->ibcddrctrl &= ~(maskr << lsb); +			ppd->cpspec->ibcddrctrl |= +				(((u64)(ppd->link_width_enabled-1) & maskr) << +				 lsb); +			qib_write_kreg(dd, kr_ibcddrctrl, +				       ppd->cpspec->ibcddrctrl); +			qib_write_kreg(dd, kr_scratch, 0); +			spin_lock_irqsave(&ppd->lflags_lock, flags); +			ppd->lflags |= QIBL_IB_FORCE_NOTIFY; +			spin_unlock_irqrestore(&ppd->lflags_lock, flags); +		}  		goto bail;  	case QIB_IB_CFG_HRTBT: /* set Heartbeat off/enable/auto */ diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 9f53e68a096..5ea9ece23b3 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -114,6 +114,10 @@ static ushort qib_singleport;  module_param_named(singleport, qib_singleport, ushort, S_IRUGO);  MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space"); +static ushort qib_krcvq01_no_msi; +module_param_named(krcvq01_no_msi, qib_krcvq01_no_msi, ushort, S_IRUGO); +MODULE_PARM_DESC(krcvq01_no_msi, "No MSI for kctx < 2"); +  /*   * Receive header queue sizes   */ @@ -397,7 +401,6 @@ MODULE_PARM_DESC(txselect, \  #define crp_txdroppedpkt CREG_IDX(TxDroppedPktCnt)  #define crp_txhdrerr CREG_IDX(TxHeadersErrCnt)  #define crp_txlenerr CREG_IDX(TxLenErrCnt) -#define crp_txlenerr CREG_IDX(TxLenErrCnt)  #define crp_txminmaxlenerr CREG_IDX(TxMaxMinLenErrCnt)  #define crp_txsdmadesc CREG_IDX(TxSDmaDescCnt)  #define crp_txunderrun CREG_IDX(TxUnderrunCnt) @@ -469,6 +472,8 @@ static u8 ib_rate_to_delay[IB_RATE_120_GBPS + 1] = {  #define IB_7322_LT_STATE_RECOVERIDLE     0x0f  #define IB_7322_LT_STATE_CFGENH          0x10  #define IB_7322_LT_STATE_CFGTEST         0x11 +#define IB_7322_LT_STATE_CFGWAITRMTTEST  0x12 +#define IB_7322_LT_STATE_CFGWAITENH      0x13  /* link state machine states from IBC */  #define IB_7322_L_STATE_DOWN             0x0 @@ -498,8 +503,10 @@ static const u8 qib_7322_physportstate[0x20] = {  		IB_PHYSPORTSTATE_LINK_ERR_RECOVER,  	[IB_7322_LT_STATE_CFGENH] = IB_PHYSPORTSTATE_CFG_ENH,  	[IB_7322_LT_STATE_CFGTEST] = IB_PHYSPORTSTATE_CFG_TRAIN, -	[0x12] = IB_PHYSPORTSTATE_CFG_TRAIN, -	[0x13] = IB_PHYSPORTSTATE_CFG_WAIT_ENH, +	[IB_7322_LT_STATE_CFGWAITRMTTEST] = +		IB_PHYSPORTSTATE_CFG_TRAIN, +	[IB_7322_LT_STATE_CFGWAITENH] = +		IB_PHYSPORTSTATE_CFG_WAIT_ENH,  	[0x14] = IB_PHYSPORTSTATE_CFG_TRAIN,  	[0x15] = IB_PHYSPORTSTATE_CFG_TRAIN,  	[0x16] = IB_PHYSPORTSTATE_CFG_TRAIN, @@ -1103,9 +1110,9 @@ static inline u32 read_7322_creg32_port(const struct qib_pportdata *ppd,  #define AUTONEG_TRIES 3 /* sequential retries to negotiate DDR */  #define HWE_AUTO(fldname) { .mask = SYM_MASK(HwErrMask, fldname##Mask), \ -	.msg = #fldname } +	.msg = #fldname , .sz = sizeof(#fldname) }  #define HWE_AUTO_P(fldname, port) { .mask = SYM_MASK(HwErrMask, \ -	fldname##Mask##_##port), .msg = #fldname } +	fldname##Mask##_##port), .msg = #fldname , .sz = sizeof(#fldname) }  static const struct qib_hwerror_msgs qib_7322_hwerror_msgs[] = {  	HWE_AUTO_P(IBSerdesPClkNotDetect, 1),  	HWE_AUTO_P(IBSerdesPClkNotDetect, 0), @@ -1123,14 +1130,16 @@ static const struct qib_hwerror_msgs qib_7322_hwerror_msgs[] = {  	HWE_AUTO_P(IBCBusFromSPCParityErr, 0),  	HWE_AUTO(statusValidNoEop),  	HWE_AUTO(LATriggered), -	{ .mask = 0 } +	{ .mask = 0, .sz = 0 }  };  #define E_AUTO(fldname) { .mask = SYM_MASK(ErrMask, fldname##Mask), \ -	.msg = #fldname } +	.msg = #fldname, .sz = sizeof(#fldname) }  #define E_P_AUTO(fldname) { .mask = SYM_MASK(ErrMask_0, fldname##Mask), \ -	.msg = #fldname } +	.msg = #fldname, .sz = sizeof(#fldname) }  static const struct qib_hwerror_msgs qib_7322error_msgs[] = { +	E_AUTO(RcvEgrFullErr), +	E_AUTO(RcvHdrFullErr),  	E_AUTO(ResetNegated),  	E_AUTO(HardwareErr),  	E_AUTO(InvalidAddrErr), @@ -1143,9 +1152,7 @@ static const struct qib_hwerror_msgs qib_7322error_msgs[] = {  	E_AUTO(SendSpecialTriggerErr),  	E_AUTO(SDmaWrongPortErr),  	E_AUTO(SDmaBufMaskDuplicateErr), -	E_AUTO(RcvHdrFullErr), -	E_AUTO(RcvEgrFullErr), -	{ .mask = 0 } +	{ .mask = 0, .sz = 0 }  };  static const struct  qib_hwerror_msgs qib_7322p_error_msgs[] = { @@ -1155,7 +1162,8 @@ static const struct  qib_hwerror_msgs qib_7322p_error_msgs[] = {  	/*  	 * SDmaHaltErr is not really an error, make it clearer;  	 */ -	{.mask = SYM_MASK(ErrMask_0, SDmaHaltErrMask), .msg = "SDmaHalted"}, +	{.mask = SYM_MASK(ErrMask_0, SDmaHaltErrMask), .msg = "SDmaHalted", +		.sz = 11},  	E_P_AUTO(SDmaDescAddrMisalignErr),  	E_P_AUTO(SDmaUnexpDataErr),  	E_P_AUTO(SDmaMissingDwErr), @@ -1191,7 +1199,7 @@ static const struct  qib_hwerror_msgs qib_7322p_error_msgs[] = {  	E_P_AUTO(RcvICRCErr),  	E_P_AUTO(RcvVCRCErr),  	E_P_AUTO(RcvFormatErr), -	{ .mask = 0 } +	{ .mask = 0, .sz = 0 }  };  /* @@ -1199,17 +1207,17 @@ static const struct  qib_hwerror_msgs qib_7322p_error_msgs[] = {   * context   */  #define INTR_AUTO(fldname) { .mask = SYM_MASK(IntMask, fldname##Mask), \ -	.msg = #fldname } +	.msg = #fldname, .sz = sizeof(#fldname) }  /* Below generates "auto-message" for interrupts specific to a port */  #define INTR_AUTO_P(fldname) { .mask = MASK_ACROSS(\  	SYM_LSB(IntMask, fldname##Mask##_0), \  	SYM_LSB(IntMask, fldname##Mask##_1)), \ -	.msg = #fldname "_P" } +	.msg = #fldname "_P", .sz = sizeof(#fldname "_P") }  /* For some reason, the SerDesTrimDone bits are reversed */  #define INTR_AUTO_PI(fldname) { .mask = MASK_ACROSS(\  	SYM_LSB(IntMask, fldname##Mask##_1), \  	SYM_LSB(IntMask, fldname##Mask##_0)), \ -	.msg = #fldname "_P" } +	.msg = #fldname "_P", .sz = sizeof(#fldname "_P") }  /*   * Below generates "auto-message" for interrupts specific to a context,   * with ctxt-number appended @@ -1217,7 +1225,7 @@ static const struct  qib_hwerror_msgs qib_7322p_error_msgs[] = {  #define INTR_AUTO_C(fldname) { .mask = MASK_ACROSS(\  	SYM_LSB(IntMask, fldname##0IntMask), \  	SYM_LSB(IntMask, fldname##17IntMask)), \ -	.msg = #fldname "_C"} +	.msg = #fldname "_C", .sz = sizeof(#fldname "_C") }  static const struct  qib_hwerror_msgs qib_7322_intr_msgs[] = {  	INTR_AUTO_P(SDmaInt), @@ -1231,11 +1239,12 @@ static const struct  qib_hwerror_msgs qib_7322_intr_msgs[] = {  	INTR_AUTO_P(SendDoneInt),  	INTR_AUTO(SendBufAvailInt),  	INTR_AUTO_C(RcvAvail), -	{ .mask = 0 } +	{ .mask = 0, .sz = 0 }  };  #define TXSYMPTOM_AUTO_P(fldname) \ -	{ .mask = SYM_MASK(SendHdrErrSymptom_0, fldname), .msg = #fldname } +	{ .mask = SYM_MASK(SendHdrErrSymptom_0, fldname), \ +	.msg = #fldname, .sz = sizeof(#fldname) }  static const struct  qib_hwerror_msgs hdrchk_msgs[] = {  	TXSYMPTOM_AUTO_P(NonKeyPacket),  	TXSYMPTOM_AUTO_P(GRHFail), @@ -1244,7 +1253,7 @@ static const struct  qib_hwerror_msgs hdrchk_msgs[] = {  	TXSYMPTOM_AUTO_P(SLIDFail),  	TXSYMPTOM_AUTO_P(RawIPV6),  	TXSYMPTOM_AUTO_P(PacketTooSmall), -	{ .mask = 0 } +	{ .mask = 0, .sz = 0 }  };  #define IBA7322_HDRHEAD_PKTINT_SHIFT 32 /* interrupt cnt in upper 32 bits */ @@ -1289,7 +1298,7 @@ static void err_decode(char *msg, size_t len, u64 errs,  	u64 these, lmask;  	int took, multi, n = 0; -	while (msp && msp->mask) { +	while (errs && msp && msp->mask) {  		multi = (msp->mask & (msp->mask - 1));  		while (errs & msp->mask) {  			these = (errs & msp->mask); @@ -1300,9 +1309,14 @@ static void err_decode(char *msg, size_t len, u64 errs,  					*msg++ = ',';  					len--;  				} -				took = scnprintf(msg, len, "%s", msp->msg); +				BUG_ON(!msp->sz); +				/* msp->sz counts the nul */ +				took = min_t(size_t, msp->sz - (size_t)1, len); +				memcpy(msg,  msp->msg, took);  				len -= took;  				msg += took; +				if (len) +					*msg = '\0';  			}  			errs &= ~lmask;  			if (len && multi) { @@ -1640,6 +1654,14 @@ done:  	return;  } +static void qib_error_tasklet(unsigned long data) +{ +	struct qib_devdata *dd = (struct qib_devdata *)data; + +	handle_7322_errors(dd); +	qib_write_kreg(dd, kr_errmask, dd->cspec->errormask); +} +  static void reenable_chase(unsigned long opaque)  {  	struct qib_pportdata *ppd = (struct qib_pportdata *)opaque; @@ -1692,7 +1714,9 @@ static void handle_serdes_issues(struct qib_pportdata *ppd, u64 ibcst)  		break;  	} -	if (ibclt == IB_7322_LT_STATE_CFGTEST && +	if (((ibclt >= IB_7322_LT_STATE_CFGTEST && +	      ibclt <= IB_7322_LT_STATE_CFGWAITENH) || +	     ibclt == IB_7322_LT_STATE_LINKUP) &&  	    (ibcst & SYM_MASK(IBCStatusA_0, LinkSpeedQDR))) {  		force_h1(ppd);  		ppd->cpspec->qdr_reforce = 1; @@ -2719,8 +2743,10 @@ static noinline void unlikely_7322_intr(struct qib_devdata *dd, u64 istat)  		unknown_7322_ibits(dd, istat);  	if (istat & QIB_I_GPIO)  		unknown_7322_gpio_intr(dd); -	if (istat & QIB_I_C_ERROR) -		handle_7322_errors(dd); +	if (istat & QIB_I_C_ERROR) { +		qib_write_kreg(dd, kr_errmask, 0ULL); +		tasklet_schedule(&dd->error_tasklet); +	}  	if (istat & INT_MASK_P(Err, 0) && dd->rcd[0])  		handle_7322_p_errors(dd->rcd[0]->ppd);  	if (istat & INT_MASK_P(Err, 1) && dd->rcd[1]) @@ -3119,6 +3145,8 @@ try_intx:  			arg = dd->rcd[ctxt];  			if (!arg)  				continue; +			if (qib_krcvq01_no_msi && ctxt < 2) +				continue;  			lsb = QIB_I_RCVAVAIL_LSB + ctxt;  			handler = qib_7322pintr;  			name = QIB_DRV_NAME " (kctx)"; @@ -3153,6 +3181,8 @@ try_intx:  	for (i = 0; i < ARRAY_SIZE(redirect); i++)  		qib_write_kreg(dd, kr_intredirect + i, redirect[i]);  	dd->cspec->main_int_mask = mask; +	tasklet_init(&dd->error_tasklet, qib_error_tasklet, +		(unsigned long)dd);  bail:;  } @@ -6782,6 +6812,10 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev,  		    (i >= ARRAY_SIZE(irq_table) &&  		     dd->rcd[i - ARRAY_SIZE(irq_table)]))  			actual_cnt++; +	/* reduce by ctxt's < 2 */ +	if (qib_krcvq01_no_msi) +		actual_cnt -= dd->num_pports; +  	tabsize = actual_cnt;  	dd->cspec->msix_entries = kmalloc(tabsize *  			sizeof(struct msix_entry), GFP_KERNEL); @@ -7301,12 +7335,17 @@ static void ibsd_wr_allchans(struct qib_pportdata *ppd, int addr, unsigned data,  static void serdes_7322_los_enable(struct qib_pportdata *ppd, int enable)  {  	u64 data = qib_read_kreg_port(ppd, krp_serdesctrl); -	printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS %s\n", -		ppd->dd->unit, ppd->port, (enable ? "on" : "off")); -	if (enable) +	u8 state = SYM_FIELD(data, IBSerdesCtrl_0, RXLOSEN); + +	if (enable && !state) { +		printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS on\n", +			ppd->dd->unit, ppd->port);  		data |= SYM_MASK(IBSerdesCtrl_0, RXLOSEN); -	else +	} else if (!enable && state) { +		printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS off\n", +			ppd->dd->unit, ppd->port);  		data &= ~SYM_MASK(IBSerdesCtrl_0, RXLOSEN); +	}  	qib_write_kreg_port(ppd, krp_serdesctrl, data);  } diff --git a/drivers/infiniband/hw/qib/qib_intr.c b/drivers/infiniband/hw/qib/qib_intr.c index a693c56ec8a..6ae57d23004 100644 --- a/drivers/infiniband/hw/qib/qib_intr.c +++ b/drivers/infiniband/hw/qib/qib_intr.c @@ -96,8 +96,12 @@ void qib_handle_e_ibstatuschanged(struct qib_pportdata *ppd, u64 ibcs)  	 * states, or if it transitions from any of the up (INIT or better)  	 * states into any of the down states (except link recovery), then  	 * call the chip-specific code to take appropriate actions. +	 * +	 * ppd->lflags could be 0 if this is the first time the interrupt +	 * handlers has been called but the link is already up.  	 */ -	if (lstate >= IB_PORT_INIT && (ppd->lflags & QIBL_LINKDOWN) && +	if (lstate >= IB_PORT_INIT && +	    (!ppd->lflags || (ppd->lflags & QIBL_LINKDOWN)) &&  	    ltstate == IB_PHYSPORTSTATE_LINKUP) {  		/* transitioned to UP */  		if (dd->f_ib_updown(ppd, 1, ibcs)) diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c index 8fd3df5bf04..3b3745f261f 100644 --- a/drivers/infiniband/hw/qib/qib_mad.c +++ b/drivers/infiniband/hw/qib/qib_mad.c @@ -1125,22 +1125,22 @@ static int subn_trap_repress(struct ib_smp *smp, struct ib_device *ibdev,  	return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;  } -static int pma_get_classportinfo(struct ib_perf *pmp, +static int pma_get_classportinfo(struct ib_pma_mad *pmp,  				 struct ib_device *ibdev)  { -	struct ib_pma_classportinfo *p = -		(struct ib_pma_classportinfo *)pmp->data; +	struct ib_class_port_info *p = +		(struct ib_class_port_info *)pmp->data;  	struct qib_devdata *dd = dd_from_ibdev(ibdev);  	memset(pmp->data, 0, sizeof(pmp->data)); -	if (pmp->attr_mod != 0) -		pmp->status |= IB_SMP_INVALID_FIELD; +	if (pmp->mad_hdr.attr_mod != 0) +		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;  	/* Note that AllPortSelect is not valid */  	p->base_version = 1;  	p->class_version = 1; -	p->cap_mask = IB_PMA_CLASS_CAP_EXT_WIDTH; +	p->capability_mask = IB_PMA_CLASS_CAP_EXT_WIDTH;  	/*  	 * Set the most significant bit of CM2 to indicate support for  	 * congestion statistics @@ -1154,7 +1154,7 @@ static int pma_get_classportinfo(struct ib_perf *pmp,  	return reply((struct ib_smp *) pmp);  } -static int pma_get_portsamplescontrol(struct ib_perf *pmp, +static int pma_get_portsamplescontrol(struct ib_pma_mad *pmp,  				      struct ib_device *ibdev, u8 port)  {  	struct ib_pma_portsamplescontrol *p = @@ -1169,8 +1169,8 @@ static int pma_get_portsamplescontrol(struct ib_perf *pmp,  	memset(pmp->data, 0, sizeof(pmp->data));  	p->port_select = port_select; -	if (pmp->attr_mod != 0 || port_select != port) { -		pmp->status |= IB_SMP_INVALID_FIELD; +	if (pmp->mad_hdr.attr_mod != 0 || port_select != port) { +		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;  		goto bail;  	}  	spin_lock_irqsave(&ibp->lock, flags); @@ -1192,7 +1192,7 @@ bail:  	return reply((struct ib_smp *) pmp);  } -static int pma_set_portsamplescontrol(struct ib_perf *pmp, +static int pma_set_portsamplescontrol(struct ib_pma_mad *pmp,  				      struct ib_device *ibdev, u8 port)  {  	struct ib_pma_portsamplescontrol *p = @@ -1205,8 +1205,8 @@ static int pma_set_portsamplescontrol(struct ib_perf *pmp,  	u8 status, xmit_flags;  	int ret; -	if (pmp->attr_mod != 0 || p->port_select != port) { -		pmp->status |= IB_SMP_INVALID_FIELD; +	if (pmp->mad_hdr.attr_mod != 0 || p->port_select != port) { +		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;  		ret = reply((struct ib_smp *) pmp);  		goto bail;  	} @@ -1321,7 +1321,7 @@ static u64 get_cache_hw_sample_counters(struct qib_pportdata *ppd,  	return ret;  } -static int pma_get_portsamplesresult(struct ib_perf *pmp, +static int pma_get_portsamplesresult(struct ib_pma_mad *pmp,  				     struct ib_device *ibdev, u8 port)  {  	struct ib_pma_portsamplesresult *p = @@ -1360,7 +1360,7 @@ static int pma_get_portsamplesresult(struct ib_perf *pmp,  	return reply((struct ib_smp *) pmp);  } -static int pma_get_portsamplesresult_ext(struct ib_perf *pmp, +static int pma_get_portsamplesresult_ext(struct ib_pma_mad *pmp,  					 struct ib_device *ibdev, u8 port)  {  	struct ib_pma_portsamplesresult_ext *p = @@ -1402,7 +1402,7 @@ static int pma_get_portsamplesresult_ext(struct ib_perf *pmp,  	return reply((struct ib_smp *) pmp);  } -static int pma_get_portcounters(struct ib_perf *pmp, +static int pma_get_portcounters(struct ib_pma_mad *pmp,  				struct ib_device *ibdev, u8 port)  {  	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *) @@ -1436,8 +1436,8 @@ static int pma_get_portcounters(struct ib_perf *pmp,  	memset(pmp->data, 0, sizeof(pmp->data));  	p->port_select = port_select; -	if (pmp->attr_mod != 0 || port_select != port) -		pmp->status |= IB_SMP_INVALID_FIELD; +	if (pmp->mad_hdr.attr_mod != 0 || port_select != port) +		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;  	if (cntrs.symbol_error_counter > 0xFFFFUL)  		p->symbol_error_counter = cpu_to_be16(0xFFFF); @@ -1472,7 +1472,7 @@ static int pma_get_portcounters(struct ib_perf *pmp,  		cntrs.local_link_integrity_errors = 0xFUL;  	if (cntrs.excessive_buffer_overrun_errors > 0xFUL)  		cntrs.excessive_buffer_overrun_errors = 0xFUL; -	p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) | +	p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) |  		cntrs.excessive_buffer_overrun_errors;  	if (cntrs.vl15_dropped > 0xFFFFUL)  		p->vl15_dropped = cpu_to_be16(0xFFFF); @@ -1500,7 +1500,7 @@ static int pma_get_portcounters(struct ib_perf *pmp,  	return reply((struct ib_smp *) pmp);  } -static int pma_get_portcounters_cong(struct ib_perf *pmp, +static int pma_get_portcounters_cong(struct ib_pma_mad *pmp,  				     struct ib_device *ibdev, u8 port)  {  	/* Congestion PMA packets start at offset 24 not 64 */ @@ -1510,7 +1510,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,  	struct qib_ibport *ibp = to_iport(ibdev, port);  	struct qib_pportdata *ppd = ppd_from_ibp(ibp);  	struct qib_devdata *dd = dd_from_ppd(ppd); -	u32 port_select = be32_to_cpu(pmp->attr_mod) & 0xFF; +	u32 port_select = be32_to_cpu(pmp->mad_hdr.attr_mod) & 0xFF;  	u64 xmit_wait_counter;  	unsigned long flags; @@ -1519,9 +1519,9 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,  	 * SET method ends up calling this anyway.  	 */  	if (!dd->psxmitwait_supported) -		pmp->status |= IB_SMP_UNSUP_METH_ATTR; +		pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;  	if (port_select != port) -		pmp->status |= IB_SMP_INVALID_FIELD; +		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;  	qib_get_counters(ppd, &cntrs);  	spin_lock_irqsave(&ppd->ibport_data.lock, flags); @@ -1603,7 +1603,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,  		cntrs.local_link_integrity_errors = 0xFUL;  	if (cntrs.excessive_buffer_overrun_errors > 0xFUL)  		cntrs.excessive_buffer_overrun_errors = 0xFUL; -	p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) | +	p->link_overrun_errors = (cntrs.local_link_integrity_errors << 4) |  		cntrs.excessive_buffer_overrun_errors;  	if (cntrs.vl15_dropped > 0xFFFFUL)  		p->vl15_dropped = cpu_to_be16(0xFFFF); @@ -1613,7 +1613,7 @@ static int pma_get_portcounters_cong(struct ib_perf *pmp,  	return reply((struct ib_smp *)pmp);  } -static int pma_get_portcounters_ext(struct ib_perf *pmp, +static int pma_get_portcounters_ext(struct ib_pma_mad *pmp,  				    struct ib_device *ibdev, u8 port)  {  	struct ib_pma_portcounters_ext *p = @@ -1626,8 +1626,8 @@ static int pma_get_portcounters_ext(struct ib_perf *pmp,  	memset(pmp->data, 0, sizeof(pmp->data));  	p->port_select = port_select; -	if (pmp->attr_mod != 0 || port_select != port) { -		pmp->status |= IB_SMP_INVALID_FIELD; +	if (pmp->mad_hdr.attr_mod != 0 || port_select != port) { +		pmp->mad_hdr.status |= IB_SMP_INVALID_FIELD;  		goto bail;  	} @@ -1652,7 +1652,7 @@ bail:  	return reply((struct ib_smp *) pmp);  } -static int pma_set_portcounters(struct ib_perf *pmp, +static int pma_set_portcounters(struct ib_pma_mad *pmp,  				struct ib_device *ibdev, u8 port)  {  	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *) @@ -1715,14 +1715,14 @@ static int pma_set_portcounters(struct ib_perf *pmp,  	return pma_get_portcounters(pmp, ibdev, port);  } -static int pma_set_portcounters_cong(struct ib_perf *pmp, +static int pma_set_portcounters_cong(struct ib_pma_mad *pmp,  				     struct ib_device *ibdev, u8 port)  {  	struct qib_ibport *ibp = to_iport(ibdev, port);  	struct qib_pportdata *ppd = ppd_from_ibp(ibp);  	struct qib_devdata *dd = dd_from_ppd(ppd);  	struct qib_verbs_counters cntrs; -	u32 counter_select = (be32_to_cpu(pmp->attr_mod) >> 24) & 0xFF; +	u32 counter_select = (be32_to_cpu(pmp->mad_hdr.attr_mod) >> 24) & 0xFF;  	int ret = 0;  	unsigned long flags; @@ -1766,7 +1766,7 @@ static int pma_set_portcounters_cong(struct ib_perf *pmp,  	return ret;  } -static int pma_set_portcounters_ext(struct ib_perf *pmp, +static int pma_set_portcounters_ext(struct ib_pma_mad *pmp,  				    struct ib_device *ibdev, u8 port)  {  	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *) @@ -1959,19 +1959,19 @@ static int process_perf(struct ib_device *ibdev, u8 port,  			struct ib_mad *in_mad,  			struct ib_mad *out_mad)  { -	struct ib_perf *pmp = (struct ib_perf *)out_mad; +	struct ib_pma_mad *pmp = (struct ib_pma_mad *)out_mad;  	int ret;  	*out_mad = *in_mad; -	if (pmp->class_version != 1) { -		pmp->status |= IB_SMP_UNSUP_VERSION; +	if (pmp->mad_hdr.class_version != 1) { +		pmp->mad_hdr.status |= IB_SMP_UNSUP_VERSION;  		ret = reply((struct ib_smp *) pmp);  		goto bail;  	} -	switch (pmp->method) { +	switch (pmp->mad_hdr.method) {  	case IB_MGMT_METHOD_GET: -		switch (pmp->attr_id) { +		switch (pmp->mad_hdr.attr_id) {  		case IB_PMA_CLASS_PORT_INFO:  			ret = pma_get_classportinfo(pmp, ibdev);  			goto bail; @@ -1994,13 +1994,13 @@ static int process_perf(struct ib_device *ibdev, u8 port,  			ret = pma_get_portcounters_cong(pmp, ibdev, port);  			goto bail;  		default: -			pmp->status |= IB_SMP_UNSUP_METH_ATTR; +			pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;  			ret = reply((struct ib_smp *) pmp);  			goto bail;  		}  	case IB_MGMT_METHOD_SET: -		switch (pmp->attr_id) { +		switch (pmp->mad_hdr.attr_id) {  		case IB_PMA_PORT_SAMPLES_CONTROL:  			ret = pma_set_portsamplescontrol(pmp, ibdev, port);  			goto bail; @@ -2014,7 +2014,7 @@ static int process_perf(struct ib_device *ibdev, u8 port,  			ret = pma_set_portcounters_cong(pmp, ibdev, port);  			goto bail;  		default: -			pmp->status |= IB_SMP_UNSUP_METH_ATTR; +			pmp->mad_hdr.status |= IB_SMP_UNSUP_METH_ATTR;  			ret = reply((struct ib_smp *) pmp);  			goto bail;  		} @@ -2030,7 +2030,7 @@ static int process_perf(struct ib_device *ibdev, u8 port,  		goto bail;  	default: -		pmp->status |= IB_SMP_UNSUP_METHOD; +		pmp->mad_hdr.status |= IB_SMP_UNSUP_METHOD;  		ret = reply((struct ib_smp *) pmp);  	} diff --git a/drivers/infiniband/hw/qib/qib_mad.h b/drivers/infiniband/hw/qib/qib_mad.h index 7840ab593bc..ecc416cdbaa 100644 --- a/drivers/infiniband/hw/qib/qib_mad.h +++ b/drivers/infiniband/hw/qib/qib_mad.h @@ -32,6 +32,8 @@   * SOFTWARE.   */ +#include <rdma/ib_pma.h> +  #define IB_SMP_UNSUP_VERSION    cpu_to_be16(0x0004)  #define IB_SMP_UNSUP_METHOD     cpu_to_be16(0x0008)  #define IB_SMP_UNSUP_METH_ATTR  cpu_to_be16(0x000C) @@ -180,109 +182,8 @@ struct ib_vl_weight_elem {  #define IB_VLARB_HIGHPRI_0_31   3  #define IB_VLARB_HIGHPRI_32_63  4 -/* - * PMA class portinfo capability mask bits - */ -#define IB_PMA_CLASS_CAP_ALLPORTSELECT  cpu_to_be16(1 << 8) -#define IB_PMA_CLASS_CAP_EXT_WIDTH      cpu_to_be16(1 << 9) -#define IB_PMA_CLASS_CAP_XMIT_WAIT      cpu_to_be16(1 << 12) - -#define IB_PMA_CLASS_PORT_INFO          cpu_to_be16(0x0001) -#define IB_PMA_PORT_SAMPLES_CONTROL     cpu_to_be16(0x0010) -#define IB_PMA_PORT_SAMPLES_RESULT      cpu_to_be16(0x0011) -#define IB_PMA_PORT_COUNTERS            cpu_to_be16(0x0012) -#define IB_PMA_PORT_COUNTERS_EXT        cpu_to_be16(0x001D) -#define IB_PMA_PORT_SAMPLES_RESULT_EXT  cpu_to_be16(0x001E)  #define IB_PMA_PORT_COUNTERS_CONG       cpu_to_be16(0xFF00) -struct ib_perf { -	u8 base_version; -	u8 mgmt_class; -	u8 class_version; -	u8 method; -	__be16 status; -	__be16 unused; -	__be64 tid; -	__be16 attr_id; -	__be16 resv; -	__be32 attr_mod; -	u8 reserved[40]; -	u8 data[192]; -} __attribute__ ((packed)); - -struct ib_pma_classportinfo { -	u8 base_version; -	u8 class_version; -	__be16 cap_mask; -	u8 reserved[3]; -	u8 resp_time_value;     /* only lower 5 bits */ -	union ib_gid redirect_gid; -	__be32 redirect_tc_sl_fl;       /* 8, 4, 20 bits respectively */ -	__be16 redirect_lid; -	__be16 redirect_pkey; -	__be32 redirect_qp;     /* only lower 24 bits */ -	__be32 redirect_qkey; -	union ib_gid trap_gid; -	__be32 trap_tc_sl_fl;   /* 8, 4, 20 bits respectively */ -	__be16 trap_lid; -	__be16 trap_pkey; -	__be32 trap_hl_qp;      /* 8, 24 bits respectively */ -	__be32 trap_qkey; -} __attribute__ ((packed)); - -struct ib_pma_portsamplescontrol { -	u8 opcode; -	u8 port_select; -	u8 tick; -	u8 counter_width;       /* only lower 3 bits */ -	__be32 counter_mask0_9; /* 2, 10 * 3, bits */ -	__be16 counter_mask10_14;       /* 1, 5 * 3, bits */ -	u8 sample_mechanisms; -	u8 sample_status;       /* only lower 2 bits */ -	__be64 option_mask; -	__be64 vendor_mask; -	__be32 sample_start; -	__be32 sample_interval; -	__be16 tag; -	__be16 counter_select[15]; -} __attribute__ ((packed)); - -struct ib_pma_portsamplesresult { -	__be16 tag; -	__be16 sample_status;   /* only lower 2 bits */ -	__be32 counter[15]; -} __attribute__ ((packed)); - -struct ib_pma_portsamplesresult_ext { -	__be16 tag; -	__be16 sample_status;   /* only lower 2 bits */ -	__be32 extended_width;  /* only upper 2 bits */ -	__be64 counter[15]; -} __attribute__ ((packed)); - -struct ib_pma_portcounters { -	u8 reserved; -	u8 port_select; -	__be16 counter_select; -	__be16 symbol_error_counter; -	u8 link_error_recovery_counter; -	u8 link_downed_counter; -	__be16 port_rcv_errors; -	__be16 port_rcv_remphys_errors; -	__be16 port_rcv_switch_relay_errors; -	__be16 port_xmit_discards; -	u8 port_xmit_constraint_errors; -	u8 port_rcv_constraint_errors; -	u8 reserved1; -	u8 lli_ebor_errors;     /* 4, 4, bits */ -	__be16 reserved2; -	__be16 vl15_dropped; -	__be32 port_xmit_data; -	__be32 port_rcv_data; -	__be32 port_xmit_packets; -	__be32 port_rcv_packets; -} __attribute__ ((packed)); -  struct ib_pma_portcounters_cong {  	u8 reserved;  	u8 reserved1; @@ -297,7 +198,7 @@ struct ib_pma_portcounters_cong {  	u8 port_xmit_constraint_errors;  	u8 port_rcv_constraint_errors;  	u8 reserved2; -	u8 lli_ebor_errors;    /* 4, 4, bits */ +	u8 link_overrun_errors; /* LocalLink: 7:4, BufferOverrun: 3:0 */  	__be16 reserved3;  	__be16 vl15_dropped;  	__be64 port_xmit_data; @@ -316,49 +217,11 @@ struct ib_pma_portcounters_cong {  /* number of 4nsec cycles equaling 2secs */  #define QIB_CONG_TIMER_PSINTERVAL               0x1DCD64EC -#define IB_PMA_SEL_SYMBOL_ERROR                 cpu_to_be16(0x0001) -#define IB_PMA_SEL_LINK_ERROR_RECOVERY          cpu_to_be16(0x0002) -#define IB_PMA_SEL_LINK_DOWNED                  cpu_to_be16(0x0004) -#define IB_PMA_SEL_PORT_RCV_ERRORS              cpu_to_be16(0x0008) -#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS      cpu_to_be16(0x0010) -#define IB_PMA_SEL_PORT_XMIT_DISCARDS           cpu_to_be16(0x0040) -#define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS  cpu_to_be16(0x0200) -#define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS    cpu_to_be16(0x0400) -#define IB_PMA_SEL_PORT_VL15_DROPPED            cpu_to_be16(0x0800) -#define IB_PMA_SEL_PORT_XMIT_DATA               cpu_to_be16(0x1000) -#define IB_PMA_SEL_PORT_RCV_DATA                cpu_to_be16(0x2000) -#define IB_PMA_SEL_PORT_XMIT_PACKETS            cpu_to_be16(0x4000) -#define IB_PMA_SEL_PORT_RCV_PACKETS             cpu_to_be16(0x8000) -  #define IB_PMA_SEL_CONG_ALL                     0x01  #define IB_PMA_SEL_CONG_PORT_DATA               0x02  #define IB_PMA_SEL_CONG_XMIT                    0x04  #define IB_PMA_SEL_CONG_ROUTING                 0x08 -struct ib_pma_portcounters_ext { -	u8 reserved; -	u8 port_select; -	__be16 counter_select; -	__be32 reserved1; -	__be64 port_xmit_data; -	__be64 port_rcv_data; -	__be64 port_xmit_packets; -	__be64 port_rcv_packets; -	__be64 port_unicast_xmit_packets; -	__be64 port_unicast_rcv_packets; -	__be64 port_multicast_xmit_packets; -	__be64 port_multicast_rcv_packets; -} __attribute__ ((packed)); - -#define IB_PMA_SELX_PORT_XMIT_DATA              cpu_to_be16(0x0001) -#define IB_PMA_SELX_PORT_RCV_DATA               cpu_to_be16(0x0002) -#define IB_PMA_SELX_PORT_XMIT_PACKETS           cpu_to_be16(0x0004) -#define IB_PMA_SELX_PORT_RCV_PACKETS            cpu_to_be16(0x0008) -#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS       cpu_to_be16(0x0010) -#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS        cpu_to_be16(0x0020) -#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS     cpu_to_be16(0x0040) -#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS      cpu_to_be16(0x0080) -  /*   * The PortSamplesControl.CounterMasks field is an array of 3 bit fields   * which specify the N'th counter's capabilities. See ch. 16.1.3.2. diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index 891cc2ff5f0..4426782ad28 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -255,7 +255,7 @@ int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent,  	u16 linkstat, speed;  	int pos = 0, pose, ret = 1; -	pose = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP); +	pose = pci_pcie_cap(dd->pcidev);  	if (!pose) {  		qib_dev_err(dd, "Can't find PCI Express capability!\n");  		/* set up something... */ @@ -509,7 +509,7 @@ static int qib_tune_pcie_coalesce(struct qib_devdata *dd)  		qib_devinfo(dd->pcidev, "Parent not root\n");  		return 1;  	} -	ppos = pci_find_capability(parent, PCI_CAP_ID_EXP); +	ppos = pci_pcie_cap(parent);  	if (!ppos)  		return 1;  	if (parent->vendor != 0x8086) @@ -578,14 +578,14 @@ static int qib_tune_pcie_caps(struct qib_devdata *dd)  		qib_devinfo(dd->pcidev, "Parent not root\n");  		goto bail;  	} -	ppos = pci_find_capability(parent, PCI_CAP_ID_EXP); +	ppos = pci_pcie_cap(parent);  	if (ppos) {  		pci_read_config_word(parent, ppos + PCI_EXP_DEVCAP, &pcaps);  		pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);  	} else  		goto bail;  	/* Find out supported and configured values for endpoint (us) */ -	epos = pci_find_capability(dd->pcidev, PCI_CAP_ID_EXP); +	epos = pci_pcie_cap(dd->pcidev);  	if (epos) {  		pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCAP, &ecaps);  		pci_read_config_word(dd->pcidev, epos + PCI_EXP_DEVCTL, &ectl); diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c index d50a33fe8bb..14d129de432 100644 --- a/drivers/infiniband/hw/qib/qib_sysfs.c +++ b/drivers/infiniband/hw/qib/qib_sysfs.c @@ -507,6 +507,18 @@ static ssize_t show_nctxts(struct device *device,  		dd->first_user_ctxt);  } +static ssize_t show_nfreectxts(struct device *device, +			   struct device_attribute *attr, char *buf) +{ +	struct qib_ibdev *dev = +		container_of(device, struct qib_ibdev, ibdev.dev); +	struct qib_devdata *dd = dd_from_dev(dev); + +	/* Return the number of free user ports (contexts) available. */ +	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->cfgctxts - +		dd->first_user_ctxt - (u32)qib_stats.sps_ctxts); +} +  static ssize_t show_serial(struct device *device,  			   struct device_attribute *attr, char *buf)  { @@ -604,6 +616,7 @@ static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);  static DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);  static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);  static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL); +static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL);  static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);  static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);  static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL); @@ -617,6 +630,7 @@ static struct device_attribute *qib_attributes[] = {  	&dev_attr_board_id,  	&dev_attr_version,  	&dev_attr_nctxts, +	&dev_attr_nfreectxts,  	&dev_attr_serial,  	&dev_attr_boardversion,  	&dev_attr_logged_errors,  |