diff options
author | Robert Walsh <robert.walsh@qlogic.com> | 2007-06-18 17:24:49 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2007-07-09 23:12:26 -0400 |
commit | f2d042313e420002b06715675963cfab48ed2597 (patch) | |
tree | ae149c8d21220aff9157952e39a7632be8c7ba61 /drivers/infiniband/hw/ipath/ipath_file_ops.c | |
parent | b506e1dc59726a1c608f26e7294b9fe186255139 (diff) |
IB/ipath: ipath_poll fixups and enhancements
Fix ipath_poll and enhance it so we can poll for urgent packets or
regular packets and receive notifications of when a header queue
overflows.
Signed-off-by: Robert Walsh <robert.walsh@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_file_ops.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_file_ops.c | 125 |
1 files changed, 83 insertions, 42 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index a47479608f48..33ab0d6b80ff 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c | |||
@@ -1341,65 +1341,98 @@ bail: | |||
1341 | return ret; | 1341 | return ret; |
1342 | } | 1342 | } |
1343 | 1343 | ||
1344 | static unsigned int ipath_poll(struct file *fp, | 1344 | static unsigned int ipath_poll_urgent(struct ipath_portdata *pd, |
1345 | struct poll_table_struct *pt) | 1345 | struct file *fp, |
1346 | struct poll_table_struct *pt) | ||
1346 | { | 1347 | { |
1347 | struct ipath_portdata *pd; | ||
1348 | u32 head, tail; | ||
1349 | int bit; | ||
1350 | unsigned pollflag = 0; | 1348 | unsigned pollflag = 0; |
1351 | struct ipath_devdata *dd; | 1349 | struct ipath_devdata *dd; |
1352 | 1350 | ||
1353 | pd = port_fp(fp); | ||
1354 | if (!pd) | ||
1355 | goto bail; | ||
1356 | dd = pd->port_dd; | 1351 | dd = pd->port_dd; |
1357 | 1352 | ||
1358 | bit = pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT; | 1353 | if (test_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag)) { |
1359 | set_bit(bit, &dd->ipath_rcvctrl); | 1354 | pollflag |= POLLERR; |
1355 | clear_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag); | ||
1356 | } | ||
1360 | 1357 | ||
1361 | /* | 1358 | if (test_bit(IPATH_PORT_WAITING_URG, &pd->int_flag)) { |
1362 | * Before blocking, make sure that head is still == tail, | 1359 | pollflag |= POLLIN | POLLRDNORM; |
1363 | * reading from the chip, so we can be sure the interrupt | 1360 | clear_bit(IPATH_PORT_WAITING_URG, &pd->int_flag); |
1364 | * enable has made it to the chip. If not equal, disable | 1361 | } |
1365 | * interrupt again and return immediately. This avoids races, | ||
1366 | * and the overhead of the chip read doesn't matter much at | ||
1367 | * this point, since we are waiting for something anyway. | ||
1368 | */ | ||
1369 | 1362 | ||
1370 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | 1363 | if (!pollflag) { |
1371 | dd->ipath_rcvctrl); | 1364 | set_bit(IPATH_PORT_WAITING_URG, &pd->port_flag); |
1365 | if (pd->poll_type & IPATH_POLL_TYPE_OVERFLOW) | ||
1366 | set_bit(IPATH_PORT_WAITING_OVERFLOW, | ||
1367 | &pd->port_flag); | ||
1368 | |||
1369 | poll_wait(fp, &pd->port_wait, pt); | ||
1370 | } | ||
1371 | |||
1372 | return pollflag; | ||
1373 | } | ||
1374 | |||
1375 | static unsigned int ipath_poll_next(struct ipath_portdata *pd, | ||
1376 | struct file *fp, | ||
1377 | struct poll_table_struct *pt) | ||
1378 | { | ||
1379 | u32 head, tail; | ||
1380 | unsigned pollflag = 0; | ||
1381 | struct ipath_devdata *dd; | ||
1382 | |||
1383 | dd = pd->port_dd; | ||
1372 | 1384 | ||
1373 | head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port); | 1385 | head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port); |
1374 | tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port); | 1386 | tail = *(volatile u64 *)pd->port_rcvhdrtail_kvaddr; |
1387 | |||
1388 | if (test_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag)) { | ||
1389 | pollflag |= POLLERR; | ||
1390 | clear_bit(IPATH_PORT_WAITING_OVERFLOW, &pd->int_flag); | ||
1391 | } | ||
1375 | 1392 | ||
1376 | if (tail == head) { | 1393 | if (tail != head || |
1394 | test_bit(IPATH_PORT_WAITING_RCV, &pd->int_flag)) { | ||
1395 | pollflag |= POLLIN | POLLRDNORM; | ||
1396 | clear_bit(IPATH_PORT_WAITING_RCV, &pd->int_flag); | ||
1397 | } | ||
1398 | |||
1399 | if (!pollflag) { | ||
1377 | set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag); | 1400 | set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag); |
1401 | if (pd->poll_type & IPATH_POLL_TYPE_OVERFLOW) | ||
1402 | set_bit(IPATH_PORT_WAITING_OVERFLOW, | ||
1403 | &pd->port_flag); | ||
1404 | |||
1405 | set_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT, | ||
1406 | &dd->ipath_rcvctrl); | ||
1407 | |||
1408 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | ||
1409 | dd->ipath_rcvctrl); | ||
1410 | |||
1378 | if (dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */ | 1411 | if (dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */ |
1379 | (void)ipath_write_ureg(dd, ur_rcvhdrhead, | 1412 | ipath_write_ureg(dd, ur_rcvhdrhead, |
1380 | dd->ipath_rhdrhead_intr_off | 1413 | dd->ipath_rhdrhead_intr_off | head, |
1381 | | head, pd->port_port); | 1414 | pd->port_port); |
1382 | poll_wait(fp, &pd->port_wait, pt); | ||
1383 | 1415 | ||
1384 | if (test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) { | 1416 | poll_wait(fp, &pd->port_wait, pt); |
1385 | /* timed out, no packets received */ | ||
1386 | clear_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag); | ||
1387 | pd->port_rcvwait_to++; | ||
1388 | } | ||
1389 | else | ||
1390 | pollflag = POLLIN | POLLRDNORM; | ||
1391 | } | ||
1392 | else { | ||
1393 | /* it's already happened; don't do wait_event overhead */ | ||
1394 | pollflag = POLLIN | POLLRDNORM; | ||
1395 | pd->port_rcvnowait++; | ||
1396 | } | 1417 | } |
1397 | 1418 | ||
1398 | clear_bit(bit, &dd->ipath_rcvctrl); | 1419 | return pollflag; |
1399 | ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, | 1420 | } |
1400 | dd->ipath_rcvctrl); | 1421 | |
1422 | static unsigned int ipath_poll(struct file *fp, | ||
1423 | struct poll_table_struct *pt) | ||
1424 | { | ||
1425 | struct ipath_portdata *pd; | ||
1426 | unsigned pollflag; | ||
1427 | |||
1428 | pd = port_fp(fp); | ||
1429 | if (!pd) | ||
1430 | pollflag = 0; | ||
1431 | else if (pd->poll_type & IPATH_POLL_TYPE_URGENT) | ||
1432 | pollflag = ipath_poll_urgent(pd, fp, pt); | ||
1433 | else | ||
1434 | pollflag = ipath_poll_next(pd, fp, pt); | ||
1401 | 1435 | ||
1402 | bail: | ||
1403 | return pollflag; | 1436 | return pollflag; |
1404 | } | 1437 | } |
1405 | 1438 | ||
@@ -2173,6 +2206,11 @@ static ssize_t ipath_write(struct file *fp, const char __user *data, | |||
2173 | src = NULL; | 2206 | src = NULL; |
2174 | dest = NULL; | 2207 | dest = NULL; |
2175 | break; | 2208 | break; |
2209 | case IPATH_CMD_POLL_TYPE: | ||
2210 | copy = sizeof(cmd.cmd.poll_type); | ||
2211 | dest = &cmd.cmd.poll_type; | ||
2212 | src = &ucmd->cmd.poll_type; | ||
2213 | break; | ||
2176 | default: | 2214 | default: |
2177 | ret = -EINVAL; | 2215 | ret = -EINVAL; |
2178 | goto bail; | 2216 | goto bail; |
@@ -2245,6 +2283,9 @@ static ssize_t ipath_write(struct file *fp, const char __user *data, | |||
2245 | case IPATH_CMD_PIOAVAILUPD: | 2283 | case IPATH_CMD_PIOAVAILUPD: |
2246 | ret = ipath_force_pio_avail_update(pd->port_dd); | 2284 | ret = ipath_force_pio_avail_update(pd->port_dd); |
2247 | break; | 2285 | break; |
2286 | case IPATH_CMD_POLL_TYPE: | ||
2287 | pd->poll_type = cmd.cmd.poll_type; | ||
2288 | break; | ||
2248 | } | 2289 | } |
2249 | 2290 | ||
2250 | if (ret >= 0) | 2291 | if (ret >= 0) |