aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorRobert Walsh <robert.walsh@qlogic.com>2007-06-18 17:24:49 -0400
committerRoland Dreier <rolandd@cisco.com>2007-07-09 23:12:26 -0400
commitf2d042313e420002b06715675963cfab48ed2597 (patch)
treeae149c8d21220aff9157952e39a7632be8c7ba61 /drivers/infiniband
parentb506e1dc59726a1c608f26e7294b9fe186255139 (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')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_common.h11
-rw-r--r--drivers/infiniband/hw/ipath/ipath_file_ops.c125
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c38
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h8
4 files changed, 131 insertions, 51 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
index f70788c25ea6..b4b786d0dfca 100644
--- a/drivers/infiniband/hw/ipath/ipath_common.h
+++ b/drivers/infiniband/hw/ipath/ipath_common.h
@@ -431,8 +431,15 @@ struct ipath_user_info {
431#define IPATH_CMD_UNUSED_1 25 431#define IPATH_CMD_UNUSED_1 25
432#define IPATH_CMD_UNUSED_2 26 432#define IPATH_CMD_UNUSED_2 26
433#define IPATH_CMD_PIOAVAILUPD 27 /* force an update of PIOAvail reg */ 433#define IPATH_CMD_PIOAVAILUPD 27 /* force an update of PIOAvail reg */
434#define IPATH_CMD_POLL_TYPE 28 /* set the kind of polling we want */
434 435
435#define IPATH_CMD_MAX 27 436#define IPATH_CMD_MAX 28
437
438/*
439 * Poll types
440 */
441#define IPATH_POLL_TYPE_URGENT 0x01
442#define IPATH_POLL_TYPE_OVERFLOW 0x02
436 443
437struct ipath_port_info { 444struct ipath_port_info {
438 __u32 num_active; /* number of active units */ 445 __u32 num_active; /* number of active units */
@@ -473,6 +480,8 @@ struct ipath_cmd {
473 __u16 part_key; 480 __u16 part_key;
474 /* user address of __u32 bitmask of active slaves */ 481 /* user address of __u32 bitmask of active slaves */
475 __u64 slave_mask_addr; 482 __u64 slave_mask_addr;
483 /* type of polling we want */
484 __u16 poll_type;
476 } cmd; 485 } cmd;
477}; 486};
478 487
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
1344static unsigned int ipath_poll(struct file *fp, 1344static 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
1375static 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
1422static 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
1402bail:
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)
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
index 948091f7d5ac..f8aac8e932f5 100644
--- a/drivers/infiniband/hw/ipath/ipath_intr.c
+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
@@ -680,6 +680,17 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
680 chkerrpkts = 1; 680 chkerrpkts = 1;
681 dd->ipath_lastrcvhdrqtails[i] = tl; 681 dd->ipath_lastrcvhdrqtails[i] = tl;
682 pd->port_hdrqfull++; 682 pd->port_hdrqfull++;
683 if (test_bit(IPATH_PORT_WAITING_OVERFLOW,
684 &pd->port_flag)) {
685 clear_bit(
686 IPATH_PORT_WAITING_OVERFLOW,
687 &pd->port_flag);
688 set_bit(
689 IPATH_PORT_WAITING_OVERFLOW,
690 &pd->int_flag);
691 wake_up_interruptible(
692 &pd->port_wait);
693 }
683 } 694 }
684 } 695 }
685 } 696 }
@@ -877,14 +888,25 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
877 dd->ipath_i_rcvurg_mask); 888 dd->ipath_i_rcvurg_mask);
878 for (i = 1; i < dd->ipath_cfgports; i++) { 889 for (i = 1; i < dd->ipath_cfgports; i++) {
879 struct ipath_portdata *pd = dd->ipath_pd[i]; 890 struct ipath_portdata *pd = dd->ipath_pd[i];
880 if (portr & (1 << i) && pd && pd->port_cnt && 891 if (portr & (1 << i) && pd && pd->port_cnt) {
881 test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) { 892 if (test_bit(IPATH_PORT_WAITING_RCV,
882 clear_bit(IPATH_PORT_WAITING_RCV, 893 &pd->port_flag)) {
883 &pd->port_flag); 894 clear_bit(IPATH_PORT_WAITING_RCV,
884 clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT, 895 &pd->port_flag);
885 &dd->ipath_rcvctrl); 896 set_bit(IPATH_PORT_WAITING_RCV,
886 wake_up_interruptible(&pd->port_wait); 897 &pd->int_flag);
887 rcvdint = 1; 898 clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
899 &dd->ipath_rcvctrl);
900 wake_up_interruptible(&pd->port_wait);
901 rcvdint = 1;
902 } else if (test_bit(IPATH_PORT_WAITING_URG,
903 &pd->port_flag)) {
904 clear_bit(IPATH_PORT_WAITING_URG,
905 &pd->port_flag);
906 set_bit(IPATH_PORT_WAITING_URG,
907 &pd->int_flag);
908 wake_up_interruptible(&pd->port_wait);
909 }
888 } 910 }
889 } 911 }
890 if (rcvdint) { 912 if (rcvdint) {
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index 2e85aeca5eac..034c283990e8 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -127,6 +127,8 @@ struct ipath_portdata {
127 u32 port_tidcursor; 127 u32 port_tidcursor;
128 /* next expected TID to check */ 128 /* next expected TID to check */
129 unsigned long port_flag; 129 unsigned long port_flag;
130 /* what happened */
131 unsigned long int_flag;
130 /* WAIT_RCV that timed out, no interrupt */ 132 /* WAIT_RCV that timed out, no interrupt */
131 u32 port_rcvwait_to; 133 u32 port_rcvwait_to;
132 /* WAIT_PIO that timed out, no interrupt */ 134 /* WAIT_PIO that timed out, no interrupt */
@@ -155,6 +157,8 @@ struct ipath_portdata {
155 u32 userversion; 157 u32 userversion;
156 /* Bitmask of active slaves */ 158 /* Bitmask of active slaves */
157 u32 active_slaves; 159 u32 active_slaves;
160 /* Type of packets or conditions we want to poll for */
161 u16 poll_type;
158}; 162};
159 163
160struct sk_buff; 164struct sk_buff;
@@ -754,6 +758,10 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
754#define IPATH_PORT_WAITING_PIO 3 758#define IPATH_PORT_WAITING_PIO 3
755 /* master has not finished initializing */ 759 /* master has not finished initializing */
756#define IPATH_PORT_MASTER_UNINIT 4 760#define IPATH_PORT_MASTER_UNINIT 4
761 /* waiting for an urgent packet to arrive */
762#define IPATH_PORT_WAITING_URG 5
763 /* waiting for a header overflow */
764#define IPATH_PORT_WAITING_OVERFLOW 6
757 765
758/* free up any allocated data at closes */ 766/* free up any allocated data at closes */
759void ipath_free_data(struct ipath_portdata *dd); 767void ipath_free_data(struct ipath_portdata *dd);