|
@@ -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
|
|
|
*/
|
|
@@ -1106,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),
|
|
@@ -1126,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),
|
|
@@ -1146,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[] = {
|
|
@@ -1158,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),
|
|
@@ -1194,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 }
|
|
|
};
|
|
|
|
|
|
/*
|
|
@@ -1202,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
|
|
@@ -1220,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),
|
|
@@ -1234,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),
|
|
@@ -1247,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 */
|
|
@@ -1292,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);
|
|
@@ -1303,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) {
|
|
@@ -1643,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;
|
|
@@ -2724,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])
|
|
@@ -3124,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)";
|
|
@@ -3158,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:;
|
|
|
}
|
|
|
|
|
@@ -6787,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);
|