Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 96176
b: refs/heads/master
c: e2ab41c
h: refs/heads/master
v: v3
  • Loading branch information
Dave Olson authored and Roland Dreier committed May 7, 2008
1 parent ae43732 commit 9b600b4
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 203 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2889d1ef1240591fa4c72a6753e0a8d1c6e18140
refs/heads/master: e2ab41cae418108f376ad1634d7507f56379f7a2
128 changes: 116 additions & 12 deletions trunk/drivers/infiniband/hw/ipath/ipath_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1428,6 +1428,40 @@ static void ipath_update_pio_bufs(struct ipath_devdata *dd)
spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
}

/*
* used to force update of pioavailshadow if we can't get a pio buffer.
* Needed primarily due to exitting freeze mode after recovering
* from errors. Done lazily, because it's safer (known to not
* be writing pio buffers).
*/
static void ipath_reset_availshadow(struct ipath_devdata *dd)
{
int i, im;
unsigned long flags;

spin_lock_irqsave(&ipath_pioavail_lock, flags);
for (i = 0; i < dd->ipath_pioavregs; i++) {
u64 val, oldval;
/* deal with 6110 chip bug on high register #s */
im = (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS)) ?
i ^ 1 : i;
val = le64_to_cpu(dd->ipath_pioavailregs_dma[im]);
/*
* busy out the buffers not in the kernel avail list,
* without changing the generation bits.
*/
oldval = dd->ipath_pioavailshadow[i];
dd->ipath_pioavailshadow[i] = val |
((~dd->ipath_pioavailkernel[i] <<
INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT) &
0xaaaaaaaaaaaaaaaaULL); /* All BUSY bits in qword */
if (oldval != dd->ipath_pioavailshadow[i])
ipath_dbg("shadow[%d] was %Lx, now %lx\n",
i, oldval, dd->ipath_pioavailshadow[i]);
}
spin_unlock_irqrestore(&ipath_pioavail_lock, flags);
}

/**
* ipath_setrcvhdrsize - set the receive header size
* @dd: the infinipath device
Expand Down Expand Up @@ -1482,9 +1516,12 @@ static noinline void no_pio_bufs(struct ipath_devdata *dd)
*/
ipath_stats.sps_nopiobufs++;
if (!(++dd->ipath_consec_nopiobuf % 100000)) {
ipath_dbg("%u pio sends with no bufavail; dmacopy: "
"%llx %llx %llx %llx; shadow: %lx %lx %lx %lx\n",
ipath_force_pio_avail_update(dd); /* at start */
ipath_dbg("%u tries no piobufavail ts%lx; dmacopy: "
"%llx %llx %llx %llx\n"
"ipath shadow: %lx %lx %lx %lx\n",
dd->ipath_consec_nopiobuf,
(unsigned long)get_cycles(),
(unsigned long long) le64_to_cpu(dma[0]),
(unsigned long long) le64_to_cpu(dma[1]),
(unsigned long long) le64_to_cpu(dma[2]),
Expand All @@ -1496,14 +1533,17 @@ static noinline void no_pio_bufs(struct ipath_devdata *dd)
*/
if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) >
(sizeof(shadow[0]) * 4 * 4))
ipath_dbg("2nd group: dmacopy: %llx %llx "
"%llx %llx; shadow: %lx %lx %lx %lx\n",
ipath_dbg("2nd group: dmacopy: "
"%llx %llx %llx %llx\n"
"ipath shadow: %lx %lx %lx %lx\n",
(unsigned long long)le64_to_cpu(dma[4]),
(unsigned long long)le64_to_cpu(dma[5]),
(unsigned long long)le64_to_cpu(dma[6]),
(unsigned long long)le64_to_cpu(dma[7]),
shadow[4], shadow[5], shadow[6],
shadow[7]);
shadow[4], shadow[5], shadow[6], shadow[7]);

/* at end, so update likely happened */
ipath_reset_availshadow(dd);
}
}

Expand Down Expand Up @@ -1652,19 +1692,46 @@ void ipath_chg_pioavailkernel(struct ipath_devdata *dd, unsigned start,
unsigned len, int avail)
{
unsigned long flags;
unsigned end;
unsigned end, cnt = 0, next;

/* There are two bits per send buffer (busy and generation) */
start *= 2;
len *= 2;
end = start + len;
end = start + len * 2;

/* Set or clear the generation bits. */
spin_lock_irqsave(&ipath_pioavail_lock, flags);
/* Set or clear the busy bit in the shadow. */
while (start < end) {
if (avail) {
__clear_bit(start + INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT,
dd->ipath_pioavailshadow);
unsigned long dma;
int i, im;
/*
* the BUSY bit will never be set, because we disarm
* the user buffers before we hand them back to the
* kernel. We do have to make sure the generation
* bit is set correctly in shadow, since it could
* have changed many times while allocated to user.
* We can't use the bitmap functions on the full
* dma array because it is always little-endian, so
* we have to flip to host-order first.
* BITS_PER_LONG is slightly wrong, since it's
* always 64 bits per register in chip...
* We only work on 64 bit kernels, so that's OK.
*/
/* deal with 6110 chip bug on high register #s */
i = start / BITS_PER_LONG;
im = (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS)) ?
i ^ 1 : i;
__clear_bit(INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT
+ start, dd->ipath_pioavailshadow);
dma = (unsigned long) le64_to_cpu(
dd->ipath_pioavailregs_dma[im]);
if (test_bit((INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT
+ start) % BITS_PER_LONG, &dma))
__set_bit(INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT
+ start, dd->ipath_pioavailshadow);
else
__clear_bit(INFINIPATH_SENDPIOAVAIL_CHECK_SHIFT
+ start, dd->ipath_pioavailshadow);
__set_bit(start, dd->ipath_pioavailkernel);
} else {
__set_bit(start + INFINIPATH_SENDPIOAVAIL_BUSY_SHIFT,
Expand All @@ -1673,7 +1740,44 @@ void ipath_chg_pioavailkernel(struct ipath_devdata *dd, unsigned start,
}
start += 2;
}

if (dd->ipath_pioupd_thresh) {
end = 2 * (dd->ipath_piobcnt2k + dd->ipath_piobcnt4k);
next = find_first_bit(dd->ipath_pioavailkernel, end);
while (next < end) {
cnt++;
next = find_next_bit(dd->ipath_pioavailkernel, end,
next + 1);
}
}
spin_unlock_irqrestore(&ipath_pioavail_lock, flags);

/*
* When moving buffers from kernel to user, if number assigned to
* the user is less than the pio update threshold, and threshold
* is supported (cnt was computed > 0), drop the update threshold
* so we update at least once per allocated number of buffers.
* In any case, if the kernel buffers are less than the threshold,
* drop the threshold. We don't bother increasing it, having once
* decreased it, since it would typically just cycle back and forth.
* If we don't decrease below buffers in use, we can wait a long
* time for an update, until some other context uses PIO buffers.
*/
if (!avail && len < cnt)
cnt = len;
if (cnt < dd->ipath_pioupd_thresh) {
dd->ipath_pioupd_thresh = cnt;
ipath_dbg("Decreased pio update threshold to %u\n",
dd->ipath_pioupd_thresh);
spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
dd->ipath_sendctrl &= ~(INFINIPATH_S_UPDTHRESH_MASK
<< INFINIPATH_S_UPDTHRESH_SHIFT);
dd->ipath_sendctrl |= dd->ipath_pioupd_thresh
<< INFINIPATH_S_UPDTHRESH_SHIFT;
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
dd->ipath_sendctrl);
spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
}
}

/**
Expand Down
72 changes: 30 additions & 42 deletions trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,47 +173,25 @@ static int ipath_get_base_info(struct file *fp,
(void *) dd->ipath_statusp -
(void *) dd->ipath_pioavailregs_dma;
if (!shared) {
kinfo->spi_piocnt = dd->ipath_pbufsport;
kinfo->spi_piocnt = pd->port_piocnt;
kinfo->spi_piobufbase = (u64) pd->port_piobufs;
kinfo->__spi_uregbase = (u64) dd->ipath_uregbase +
dd->ipath_ureg_align * pd->port_port;
} else if (master) {
kinfo->spi_piocnt = (dd->ipath_pbufsport / subport_cnt) +
(dd->ipath_pbufsport % subport_cnt);
kinfo->spi_piocnt = (pd->port_piocnt / subport_cnt) +
(pd->port_piocnt % subport_cnt);
/* Master's PIO buffers are after all the slave's */
kinfo->spi_piobufbase = (u64) pd->port_piobufs +
dd->ipath_palign *
(dd->ipath_pbufsport - kinfo->spi_piocnt);
(pd->port_piocnt - kinfo->spi_piocnt);
} else {
unsigned slave = subport_fp(fp) - 1;

kinfo->spi_piocnt = dd->ipath_pbufsport / subport_cnt;
kinfo->spi_piocnt = pd->port_piocnt / subport_cnt;
kinfo->spi_piobufbase = (u64) pd->port_piobufs +
dd->ipath_palign * kinfo->spi_piocnt * slave;
}

/*
* Set the PIO avail update threshold to no larger
* than the number of buffers per process. Note that
* we decrease it here, but won't ever increase it.
*/
if (dd->ipath_pioupd_thresh &&
kinfo->spi_piocnt < dd->ipath_pioupd_thresh) {
unsigned long flags;

dd->ipath_pioupd_thresh = kinfo->spi_piocnt;
ipath_dbg("Decreased pio update threshold to %u\n",
dd->ipath_pioupd_thresh);
spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
dd->ipath_sendctrl &= ~(INFINIPATH_S_UPDTHRESH_MASK
<< INFINIPATH_S_UPDTHRESH_SHIFT);
dd->ipath_sendctrl |= dd->ipath_pioupd_thresh
<< INFINIPATH_S_UPDTHRESH_SHIFT;
ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
dd->ipath_sendctrl);
spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
}

if (shared) {
kinfo->spi_port_uregbase = (u64) dd->ipath_uregbase +
dd->ipath_ureg_align * pd->port_port;
Expand Down Expand Up @@ -1309,19 +1287,19 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
ureg = dd->ipath_uregbase + dd->ipath_ureg_align * pd->port_port;
if (!pd->port_subport_cnt) {
/* port is not shared */
piocnt = dd->ipath_pbufsport;
piocnt = pd->port_piocnt;
piobufs = pd->port_piobufs;
} else if (!subport_fp(fp)) {
/* caller is the master */
piocnt = (dd->ipath_pbufsport / pd->port_subport_cnt) +
(dd->ipath_pbufsport % pd->port_subport_cnt);
piocnt = (pd->port_piocnt / pd->port_subport_cnt) +
(pd->port_piocnt % pd->port_subport_cnt);
piobufs = pd->port_piobufs +
dd->ipath_palign * (dd->ipath_pbufsport - piocnt);
dd->ipath_palign * (pd->port_piocnt - piocnt);
} else {
unsigned slave = subport_fp(fp) - 1;

/* caller is a slave */
piocnt = dd->ipath_pbufsport / pd->port_subport_cnt;
piocnt = pd->port_piocnt / pd->port_subport_cnt;
piobufs = pd->port_piobufs + dd->ipath_palign * piocnt * slave;
}

Expand Down Expand Up @@ -1633,9 +1611,6 @@ static int try_alloc_port(struct ipath_devdata *dd, int port,
port_fp(fp) = pd;
pd->port_pid = current->pid;
strncpy(pd->port_comm, current->comm, sizeof(pd->port_comm));
ipath_chg_pioavailkernel(dd,
dd->ipath_pbufsport * (pd->port_port - 1),
dd->ipath_pbufsport, 0);
ipath_stats.sps_ports++;
ret = 0;
} else
Expand Down Expand Up @@ -1938,11 +1913,25 @@ static int ipath_do_user_init(struct file *fp,

/* for now we do nothing with rcvhdrcnt: uinfo->spu_rcvhdrcnt */

/* some ports may get extra buffers, calculate that here */
if (pd->port_port <= dd->ipath_ports_extrabuf)
pd->port_piocnt = dd->ipath_pbufsport + 1;
else
pd->port_piocnt = dd->ipath_pbufsport;

/* for right now, kernel piobufs are at end, so port 1 is at 0 */
if (pd->port_port <= dd->ipath_ports_extrabuf)
pd->port_pio_base = (dd->ipath_pbufsport + 1)
* (pd->port_port - 1);
else
pd->port_pio_base = dd->ipath_ports_extrabuf +
dd->ipath_pbufsport * (pd->port_port - 1);
pd->port_piobufs = dd->ipath_piobufbase +
dd->ipath_pbufsport * (pd->port_port - 1) * dd->ipath_palign;
ipath_cdbg(VERBOSE, "Set base of piobufs for port %u to 0x%x\n",
pd->port_port, pd->port_piobufs);
pd->port_pio_base * dd->ipath_palign;
ipath_cdbg(VERBOSE, "piobuf base for port %u is 0x%x, piocnt %u,"
" first pio %u\n", pd->port_port, pd->port_piobufs,
pd->port_piocnt, pd->port_pio_base);
ipath_chg_pioavailkernel(dd, pd->port_pio_base, pd->port_piocnt, 0);

/*
* Now allocate the rcvhdr Q and eager TIDs; skip the TID
Expand Down Expand Up @@ -2107,7 +2096,6 @@ static int ipath_close(struct inode *in, struct file *fp)
}

if (dd->ipath_kregbase) {
int i;
/* atomically clear receive enable port and intr avail. */
clear_bit(dd->ipath_r_portenable_shift + port,
&dd->ipath_rcvctrl);
Expand Down Expand Up @@ -2136,9 +2124,9 @@ static int ipath_close(struct inode *in, struct file *fp)
ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr,
pd->port_port, dd->ipath_dummy_hdrq_phys);

i = dd->ipath_pbufsport * (port - 1);
ipath_disarm_piobufs(dd, i, dd->ipath_pbufsport);
ipath_chg_pioavailkernel(dd, i, dd->ipath_pbufsport, 1);
ipath_disarm_piobufs(dd, pd->port_pio_base, pd->port_piocnt);
ipath_chg_pioavailkernel(dd, pd->port_pio_base,
pd->port_piocnt, 1);

dd->ipath_f_clear_tids(dd, pd->port_port);

Expand Down
21 changes: 6 additions & 15 deletions trunk/drivers/infiniband/hw/ipath/ipath_iba7220.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ static void ipath_7220_txe_recover(struct ipath_devdata *dd)

dev_info(&dd->pcidev->dev,
"Recovering from TXE PIO parity error\n");
ipath_disarm_senderrbufs(dd, 1);
ipath_disarm_senderrbufs(dd);
}


Expand Down Expand Up @@ -675,10 +675,8 @@ static void ipath_7220_handle_hwerrors(struct ipath_devdata *dd, char *msg,
ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
if ((ctrl & INFINIPATH_C_FREEZEMODE) && !ipath_diag_inuse) {
/*
* Parity errors in send memory are recoverable,
* just cancel the send (if indicated in * sendbuffererror),
* count the occurrence, unfreeze (if no other handled
* hardware error bits are set), and continue.
* Parity errors in send memory are recoverable by h/w
* just do housekeeping, exit freeze mode and continue.
*/
if (hwerrs & ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
Expand All @@ -687,13 +685,6 @@ static void ipath_7220_handle_hwerrors(struct ipath_devdata *dd, char *msg,
hwerrs &= ~((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF |
INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC)
<< INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT);
if (!hwerrs) {
/* else leave in freeze mode */
ipath_write_kreg(dd,
dd->ipath_kregs->kr_control,
dd->ipath_control);
goto bail;
}
}
if (hwerrs) {
/*
Expand Down Expand Up @@ -723,8 +714,8 @@ static void ipath_7220_handle_hwerrors(struct ipath_devdata *dd, char *msg,
*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
dd->ipath_flags &= ~IPATH_INITTED;
} else {
ipath_dbg("Clearing freezemode on ignored hardware "
"error\n");
ipath_dbg("Clearing freezemode on ignored or "
"recovered hardware error\n");
ipath_clear_freeze(dd);
}
}
Expand Down Expand Up @@ -1967,7 +1958,7 @@ static void ipath_7220_config_ports(struct ipath_devdata *dd, ushort cfgports)
dd->ipath_rcvctrl);
dd->ipath_p0_rcvegrcnt = 2048; /* always */
if (dd->ipath_flags & IPATH_HAS_SEND_DMA)
dd->ipath_pioreserved = 1; /* reserve a buffer */
dd->ipath_pioreserved = 3; /* kpiobufs used for PIO */
}


Expand Down
Loading

0 comments on commit 9b600b4

Please sign in to comment.