diff options
author | Ralph Campbell <ralph.campbell@qlogic.com> | 2008-04-17 00:09:29 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-04-17 00:09:29 -0400 |
commit | 9355fb6a064723c71e80e9c78de3140b43bfb52d (patch) | |
tree | dd0fffeb6633aed6cb2c946a05bf33e05f2e9436 /drivers/infiniband/hw/ipath/ipath_driver.c | |
parent | 2ba3f56eb402672ff83601b5990b219d39577636 (diff) |
IB/ipath: Add support for 7220 receive queue changes
Newer HCAs have a HW option to write a sequence number to each receive
queue entry and avoid a separate DMA of the tail register to memory.
This patch adds support for these changes.
Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_driver.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 194 |
1 files changed, 105 insertions, 89 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 58fcb355f59..d1bbee50b5b 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -41,7 +41,6 @@ | |||
41 | 41 | ||
42 | #include "ipath_kernel.h" | 42 | #include "ipath_kernel.h" |
43 | #include "ipath_verbs.h" | 43 | #include "ipath_verbs.h" |
44 | #include "ipath_common.h" | ||
45 | 44 | ||
46 | static void ipath_update_pio_bufs(struct ipath_devdata *); | 45 | static void ipath_update_pio_bufs(struct ipath_devdata *); |
47 | 46 | ||
@@ -720,6 +719,8 @@ static void __devexit cleanup_device(struct ipath_devdata *dd) | |||
720 | tmpp = dd->ipath_pageshadow; | 719 | tmpp = dd->ipath_pageshadow; |
721 | dd->ipath_pageshadow = NULL; | 720 | dd->ipath_pageshadow = NULL; |
722 | vfree(tmpp); | 721 | vfree(tmpp); |
722 | |||
723 | dd->ipath_egrtidbase = NULL; | ||
723 | } | 724 | } |
724 | 725 | ||
725 | /* | 726 | /* |
@@ -1078,18 +1079,17 @@ static void ipath_rcv_hdrerr(struct ipath_devdata *dd, | |||
1078 | u32 eflags, | 1079 | u32 eflags, |
1079 | u32 l, | 1080 | u32 l, |
1080 | u32 etail, | 1081 | u32 etail, |
1081 | u64 *rc) | 1082 | __le32 *rhf_addr, |
1083 | struct ipath_message_header *hdr) | ||
1082 | { | 1084 | { |
1083 | char emsg[128]; | 1085 | char emsg[128]; |
1084 | struct ipath_message_header *hdr; | ||
1085 | 1086 | ||
1086 | get_rhf_errstring(eflags, emsg, sizeof emsg); | 1087 | get_rhf_errstring(eflags, emsg, sizeof emsg); |
1087 | hdr = (struct ipath_message_header *)&rc[1]; | ||
1088 | ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u " | 1088 | ipath_cdbg(PKT, "RHFerrs %x hdrqtail=%x typ=%u " |
1089 | "tlen=%x opcode=%x egridx=%x: %s\n", | 1089 | "tlen=%x opcode=%x egridx=%x: %s\n", |
1090 | eflags, l, | 1090 | eflags, l, |
1091 | ipath_hdrget_rcv_type((__le32 *) rc), | 1091 | ipath_hdrget_rcv_type(rhf_addr), |
1092 | ipath_hdrget_length_in_bytes((__le32 *) rc), | 1092 | ipath_hdrget_length_in_bytes(rhf_addr), |
1093 | be32_to_cpu(hdr->bth[0]) >> 24, | 1093 | be32_to_cpu(hdr->bth[0]) >> 24, |
1094 | etail, emsg); | 1094 | etail, emsg); |
1095 | 1095 | ||
@@ -1114,55 +1114,52 @@ static void ipath_rcv_hdrerr(struct ipath_devdata *dd, | |||
1114 | */ | 1114 | */ |
1115 | void ipath_kreceive(struct ipath_portdata *pd) | 1115 | void ipath_kreceive(struct ipath_portdata *pd) |
1116 | { | 1116 | { |
1117 | u64 *rc; | ||
1118 | struct ipath_devdata *dd = pd->port_dd; | 1117 | struct ipath_devdata *dd = pd->port_dd; |
1118 | __le32 *rhf_addr; | ||
1119 | void *ebuf; | 1119 | void *ebuf; |
1120 | const u32 rsize = dd->ipath_rcvhdrentsize; /* words */ | 1120 | const u32 rsize = dd->ipath_rcvhdrentsize; /* words */ |
1121 | const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */ | 1121 | const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize; /* words */ |
1122 | u32 etail = -1, l, hdrqtail; | 1122 | u32 etail = -1, l, hdrqtail; |
1123 | struct ipath_message_header *hdr; | 1123 | struct ipath_message_header *hdr; |
1124 | u32 eflags, i, etype, tlen, pkttot = 0, updegr=0, reloop=0; | 1124 | u32 eflags, i, etype, tlen, pkttot = 0, updegr = 0, reloop = 0; |
1125 | static u64 totcalls; /* stats, may eventually remove */ | 1125 | static u64 totcalls; /* stats, may eventually remove */ |
1126 | 1126 | int last; | |
1127 | if (!dd->ipath_hdrqtailptr) { | ||
1128 | ipath_dev_err(dd, | ||
1129 | "hdrqtailptr not set, can't do receives\n"); | ||
1130 | goto bail; | ||
1131 | } | ||
1132 | 1127 | ||
1133 | l = pd->port_head; | 1128 | l = pd->port_head; |
1134 | hdrqtail = ipath_get_rcvhdrtail(pd); | 1129 | rhf_addr = (__le32 *) pd->port_rcvhdrq + l + dd->ipath_rhf_offset; |
1135 | if (l == hdrqtail) | 1130 | if (dd->ipath_flags & IPATH_NODMA_RTAIL) { |
1136 | goto bail; | 1131 | u32 seq = ipath_hdrget_seq(rhf_addr); |
1137 | 1132 | ||
1138 | reloop: | 1133 | if (seq != pd->port_seq_cnt) |
1139 | for (i = 0; l != hdrqtail; i++) { | 1134 | goto bail; |
1140 | u32 qp; | 1135 | hdrqtail = 0; |
1141 | u8 *bthbytes; | 1136 | } else { |
1142 | 1137 | hdrqtail = ipath_get_rcvhdrtail(pd); | |
1143 | rc = (u64 *) (pd->port_rcvhdrq + (l << 2)); | 1138 | if (l == hdrqtail) |
1144 | hdr = (struct ipath_message_header *)&rc[1]; | 1139 | goto bail; |
1145 | /* | 1140 | smp_rmb(); |
1146 | * could make a network order version of IPATH_KD_QP, and | 1141 | } |
1147 | * do the obvious shift before masking to speed this up. | ||
1148 | */ | ||
1149 | qp = ntohl(hdr->bth[1]) & 0xffffff; | ||
1150 | bthbytes = (u8 *) hdr->bth; | ||
1151 | 1142 | ||
1152 | eflags = ipath_hdrget_err_flags((__le32 *) rc); | 1143 | reloop: |
1153 | etype = ipath_hdrget_rcv_type((__le32 *) rc); | 1144 | for (last = 0, i = 1; !last; i++) { |
1145 | hdr = dd->ipath_f_get_msgheader(dd, rhf_addr); | ||
1146 | eflags = ipath_hdrget_err_flags(rhf_addr); | ||
1147 | etype = ipath_hdrget_rcv_type(rhf_addr); | ||
1154 | /* total length */ | 1148 | /* total length */ |
1155 | tlen = ipath_hdrget_length_in_bytes((__le32 *) rc); | 1149 | tlen = ipath_hdrget_length_in_bytes(rhf_addr); |
1156 | ebuf = NULL; | 1150 | ebuf = NULL; |
1157 | if (etype != RCVHQ_RCV_TYPE_EXPECTED) { | 1151 | if ((dd->ipath_flags & IPATH_NODMA_RTAIL) ? |
1152 | ipath_hdrget_use_egr_buf(rhf_addr) : | ||
1153 | (etype != RCVHQ_RCV_TYPE_EXPECTED)) { | ||
1158 | /* | 1154 | /* |
1159 | * it turns out that the chips uses an eager buffer | 1155 | * It turns out that the chip uses an eager buffer |
1160 | * for all non-expected packets, whether it "needs" | 1156 | * for all non-expected packets, whether it "needs" |
1161 | * one or not. So always get the index, but don't | 1157 | * one or not. So always get the index, but don't |
1162 | * set ebuf (so we try to copy data) unless the | 1158 | * set ebuf (so we try to copy data) unless the |
1163 | * length requires it. | 1159 | * length requires it. |
1164 | */ | 1160 | */ |
1165 | etail = ipath_hdrget_index((__le32 *) rc); | 1161 | etail = ipath_hdrget_index(rhf_addr); |
1162 | updegr = 1; | ||
1166 | if (tlen > sizeof(*hdr) || | 1163 | if (tlen > sizeof(*hdr) || |
1167 | etype == RCVHQ_RCV_TYPE_NON_KD) | 1164 | etype == RCVHQ_RCV_TYPE_NON_KD) |
1168 | ebuf = ipath_get_egrbuf(dd, etail); | 1165 | ebuf = ipath_get_egrbuf(dd, etail); |
@@ -1173,75 +1170,91 @@ reloop: | |||
1173 | * packets; only ipathhdrerr should be set. | 1170 | * packets; only ipathhdrerr should be set. |
1174 | */ | 1171 | */ |
1175 | 1172 | ||
1176 | if (etype != RCVHQ_RCV_TYPE_NON_KD && etype != | 1173 | if (etype != RCVHQ_RCV_TYPE_NON_KD && |
1177 | RCVHQ_RCV_TYPE_ERROR && ipath_hdrget_ipath_ver( | 1174 | etype != RCVHQ_RCV_TYPE_ERROR && |
1178 | hdr->iph.ver_port_tid_offset) != | 1175 | ipath_hdrget_ipath_ver(hdr->iph.ver_port_tid_offset) != |
1179 | IPS_PROTO_VERSION) { | 1176 | IPS_PROTO_VERSION) |
1180 | ipath_cdbg(PKT, "Bad InfiniPath protocol version " | 1177 | ipath_cdbg(PKT, "Bad InfiniPath protocol version " |
1181 | "%x\n", etype); | 1178 | "%x\n", etype); |
1182 | } | ||
1183 | 1179 | ||
1184 | if (unlikely(eflags)) | 1180 | if (unlikely(eflags)) |
1185 | ipath_rcv_hdrerr(dd, eflags, l, etail, rc); | 1181 | ipath_rcv_hdrerr(dd, eflags, l, etail, rhf_addr, hdr); |
1186 | else if (etype == RCVHQ_RCV_TYPE_NON_KD) { | 1182 | else if (etype == RCVHQ_RCV_TYPE_NON_KD) { |
1187 | ipath_ib_rcv(dd->verbs_dev, rc + 1, ebuf, tlen); | 1183 | ipath_ib_rcv(dd->verbs_dev, (u32 *)hdr, ebuf, tlen); |
1188 | if (dd->ipath_lli_counter) | 1184 | if (dd->ipath_lli_counter) |
1189 | dd->ipath_lli_counter--; | 1185 | dd->ipath_lli_counter--; |
1186 | } else if (etype == RCVHQ_RCV_TYPE_EAGER) { | ||
1187 | u8 opcode = be32_to_cpu(hdr->bth[0]) >> 24; | ||
1188 | u32 qp = be32_to_cpu(hdr->bth[1]) & 0xffffff; | ||
1190 | ipath_cdbg(PKT, "typ %x, opcode %x (eager, " | 1189 | ipath_cdbg(PKT, "typ %x, opcode %x (eager, " |
1191 | "qp=%x), len %x; ignored\n", | 1190 | "qp=%x), len %x; ignored\n", |
1192 | etype, bthbytes[0], qp, tlen); | 1191 | etype, opcode, qp, tlen); |
1193 | } | 1192 | } |
1194 | else if (etype == RCVHQ_RCV_TYPE_EAGER) | ||
1195 | ipath_cdbg(PKT, "typ %x, opcode %x (eager, " | ||
1196 | "qp=%x), len %x; ignored\n", | ||
1197 | etype, bthbytes[0], qp, tlen); | ||
1198 | else if (etype == RCVHQ_RCV_TYPE_EXPECTED) | 1193 | else if (etype == RCVHQ_RCV_TYPE_EXPECTED) |
1199 | ipath_dbg("Bug: Expected TID, opcode %x; ignored\n", | 1194 | ipath_dbg("Bug: Expected TID, opcode %x; ignored\n", |
1200 | be32_to_cpu(hdr->bth[0]) & 0xff); | 1195 | be32_to_cpu(hdr->bth[0]) >> 24); |
1201 | else { | 1196 | else { |
1202 | /* | 1197 | /* |
1203 | * error packet, type of error unknown. | 1198 | * error packet, type of error unknown. |
1204 | * Probably type 3, but we don't know, so don't | 1199 | * Probably type 3, but we don't know, so don't |
1205 | * even try to print the opcode, etc. | 1200 | * even try to print the opcode, etc. |
1201 | * Usually caused by a "bad packet", that has no | ||
1202 | * BTH, when the LRH says it should. | ||
1206 | */ | 1203 | */ |
1207 | ipath_dbg("Error Pkt, but no eflags! egrbuf %x, " | 1204 | ipath_cdbg(ERRPKT, "Error Pkt, but no eflags! egrbuf" |
1208 | "len %x\nhdrq@%lx;hdrq+%x rhf: %llx; " | 1205 | " %x, len %x hdrq+%x rhf: %Lx\n", |
1209 | "hdr %llx %llx %llx %llx %llx\n", | 1206 | etail, tlen, l, |
1210 | etail, tlen, (unsigned long) rc, l, | 1207 | le64_to_cpu(*(__le64 *) rhf_addr)); |
1211 | (unsigned long long) rc[0], | 1208 | if (ipath_debug & __IPATH_ERRPKTDBG) { |
1212 | (unsigned long long) rc[1], | 1209 | u32 j, *d, dw = rsize-2; |
1213 | (unsigned long long) rc[2], | 1210 | if (rsize > (tlen>>2)) |
1214 | (unsigned long long) rc[3], | 1211 | dw = tlen>>2; |
1215 | (unsigned long long) rc[4], | 1212 | d = (u32 *)hdr; |
1216 | (unsigned long long) rc[5]); | 1213 | printk(KERN_DEBUG "EPkt rcvhdr(%x dw):\n", |
1214 | dw); | ||
1215 | for (j = 0; j < dw; j++) | ||
1216 | printk(KERN_DEBUG "%8x%s", d[j], | ||
1217 | (j%8) == 7 ? "\n" : " "); | ||
1218 | printk(KERN_DEBUG ".\n"); | ||
1219 | } | ||
1217 | } | 1220 | } |
1218 | l += rsize; | 1221 | l += rsize; |
1219 | if (l >= maxcnt) | 1222 | if (l >= maxcnt) |
1220 | l = 0; | 1223 | l = 0; |
1221 | if (etype != RCVHQ_RCV_TYPE_EXPECTED) | 1224 | rhf_addr = (__le32 *) pd->port_rcvhdrq + |
1222 | updegr = 1; | 1225 | l + dd->ipath_rhf_offset; |
1226 | if (dd->ipath_flags & IPATH_NODMA_RTAIL) { | ||
1227 | u32 seq = ipath_hdrget_seq(rhf_addr); | ||
1228 | |||
1229 | if (++pd->port_seq_cnt > 13) | ||
1230 | pd->port_seq_cnt = 1; | ||
1231 | if (seq != pd->port_seq_cnt) | ||
1232 | last = 1; | ||
1233 | } else if (l == hdrqtail) | ||
1234 | last = 1; | ||
1223 | /* | 1235 | /* |
1224 | * update head regs on last packet, and every 16 packets. | 1236 | * update head regs on last packet, and every 16 packets. |
1225 | * Reduce bus traffic, while still trying to prevent | 1237 | * Reduce bus traffic, while still trying to prevent |
1226 | * rcvhdrq overflows, for when the queue is nearly full | 1238 | * rcvhdrq overflows, for when the queue is nearly full |
1227 | */ | 1239 | */ |
1228 | if (l == hdrqtail || (i && !(i&0xf))) { | 1240 | if (last || !(i & 0xf)) { |
1229 | u64 lval; | 1241 | u64 lval = l; |
1230 | if (l == hdrqtail) | 1242 | |
1231 | /* request IBA6120 interrupt only on last */ | 1243 | /* request IBA6120 and 7220 interrupt only on last */ |
1232 | lval = dd->ipath_rhdrhead_intr_off | l; | 1244 | if (last) |
1233 | else | 1245 | lval |= dd->ipath_rhdrhead_intr_off; |
1234 | lval = l; | 1246 | ipath_write_ureg(dd, ur_rcvhdrhead, lval, |
1235 | ipath_write_ureg(dd, ur_rcvhdrhead, lval, 0); | 1247 | pd->port_port); |
1236 | if (updegr) { | 1248 | if (updegr) { |
1237 | ipath_write_ureg(dd, ur_rcvegrindexhead, | 1249 | ipath_write_ureg(dd, ur_rcvegrindexhead, |
1238 | etail, 0); | 1250 | etail, pd->port_port); |
1239 | updegr = 0; | 1251 | updegr = 0; |
1240 | } | 1252 | } |
1241 | } | 1253 | } |
1242 | } | 1254 | } |
1243 | 1255 | ||
1244 | if (!dd->ipath_rhdrhead_intr_off && !reloop) { | 1256 | if (!dd->ipath_rhdrhead_intr_off && !reloop && |
1257 | !(dd->ipath_flags & IPATH_NODMA_RTAIL)) { | ||
1245 | /* IBA6110 workaround; we can have a race clearing chip | 1258 | /* IBA6110 workaround; we can have a race clearing chip |
1246 | * interrupt with another interrupt about to be delivered, | 1259 | * interrupt with another interrupt about to be delivered, |
1247 | * and can clear it before it is delivered on the GPIO | 1260 | * and can clear it before it is delivered on the GPIO |
@@ -1638,19 +1651,27 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd, | |||
1638 | ret = -ENOMEM; | 1651 | ret = -ENOMEM; |
1639 | goto bail; | 1652 | goto bail; |
1640 | } | 1653 | } |
1641 | pd->port_rcvhdrtail_kvaddr = dma_alloc_coherent( | 1654 | |
1642 | &dd->pcidev->dev, PAGE_SIZE, &phys_hdrqtail, GFP_KERNEL); | 1655 | if (!(dd->ipath_flags & IPATH_NODMA_RTAIL)) { |
1643 | if (!pd->port_rcvhdrtail_kvaddr) { | 1656 | pd->port_rcvhdrtail_kvaddr = dma_alloc_coherent( |
1644 | ipath_dev_err(dd, "attempt to allocate 1 page " | 1657 | &dd->pcidev->dev, PAGE_SIZE, &phys_hdrqtail, |
1645 | "for port %u rcvhdrqtailaddr failed\n", | 1658 | GFP_KERNEL); |
1646 | pd->port_port); | 1659 | if (!pd->port_rcvhdrtail_kvaddr) { |
1647 | ret = -ENOMEM; | 1660 | ipath_dev_err(dd, "attempt to allocate 1 page " |
1648 | dma_free_coherent(&dd->pcidev->dev, amt, | 1661 | "for port %u rcvhdrqtailaddr " |
1649 | pd->port_rcvhdrq, pd->port_rcvhdrq_phys); | 1662 | "failed\n", pd->port_port); |
1650 | pd->port_rcvhdrq = NULL; | 1663 | ret = -ENOMEM; |
1651 | goto bail; | 1664 | dma_free_coherent(&dd->pcidev->dev, amt, |
1665 | pd->port_rcvhdrq, | ||
1666 | pd->port_rcvhdrq_phys); | ||
1667 | pd->port_rcvhdrq = NULL; | ||
1668 | goto bail; | ||
1669 | } | ||
1670 | pd->port_rcvhdrqtailaddr_phys = phys_hdrqtail; | ||
1671 | ipath_cdbg(VERBOSE, "port %d hdrtailaddr, %llx " | ||
1672 | "physical\n", pd->port_port, | ||
1673 | (unsigned long long) phys_hdrqtail); | ||
1652 | } | 1674 | } |
1653 | pd->port_rcvhdrqtailaddr_phys = phys_hdrqtail; | ||
1654 | 1675 | ||
1655 | pd->port_rcvhdrq_size = amt; | 1676 | pd->port_rcvhdrq_size = amt; |
1656 | 1677 | ||
@@ -1660,10 +1681,6 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd, | |||
1660 | (unsigned long) pd->port_rcvhdrq_phys, | 1681 | (unsigned long) pd->port_rcvhdrq_phys, |
1661 | (unsigned long) pd->port_rcvhdrq_size, | 1682 | (unsigned long) pd->port_rcvhdrq_size, |
1662 | pd->port_port); | 1683 | pd->port_port); |
1663 | |||
1664 | ipath_cdbg(VERBOSE, "port %d hdrtailaddr, %llx physical\n", | ||
1665 | pd->port_port, | ||
1666 | (unsigned long long) phys_hdrqtail); | ||
1667 | } | 1684 | } |
1668 | else | 1685 | else |
1669 | ipath_cdbg(VERBOSE, "reuse port %d rcvhdrq @%p %llx phys; " | 1686 | ipath_cdbg(VERBOSE, "reuse port %d rcvhdrq @%p %llx phys; " |
@@ -1687,7 +1704,6 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd, | |||
1687 | ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr, | 1704 | ipath_write_kreg_port(dd, dd->ipath_kregs->kr_rcvhdraddr, |
1688 | pd->port_port, pd->port_rcvhdrq_phys); | 1705 | pd->port_port, pd->port_rcvhdrq_phys); |
1689 | 1706 | ||
1690 | ret = 0; | ||
1691 | bail: | 1707 | bail: |
1692 | return ret; | 1708 | return ret; |
1693 | } | 1709 | } |
@@ -2222,7 +2238,7 @@ void ipath_free_pddata(struct ipath_devdata *dd, struct ipath_portdata *pd) | |||
2222 | ipath_cdbg(VERBOSE, "free closed port %d " | 2238 | ipath_cdbg(VERBOSE, "free closed port %d " |
2223 | "ipath_port0_skbinfo @ %p\n", pd->port_port, | 2239 | "ipath_port0_skbinfo @ %p\n", pd->port_port, |
2224 | skbinfo); | 2240 | skbinfo); |
2225 | for (e = 0; e < dd->ipath_rcvegrcnt; e++) | 2241 | for (e = 0; e < dd->ipath_p0_rcvegrcnt; e++) |
2226 | if (skbinfo[e].skb) { | 2242 | if (skbinfo[e].skb) { |
2227 | pci_unmap_single(dd->pcidev, skbinfo[e].phys, | 2243 | pci_unmap_single(dd->pcidev, skbinfo[e].phys, |
2228 | dd->ipath_ibmaxlen, | 2244 | dd->ipath_ibmaxlen, |