aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIra Weiny <ira.weiny@intel.com>2016-07-27 21:08:42 -0400
committerDoug Ledford <dledford@redhat.com>2016-08-02 22:46:21 -0400
commitc49298026908a8ce9dcf01ed68734ad171cef98b (patch)
tree303688733b41eadebc1f24ccbbedb259bda9d100
parentfe508272c963d62de4183c32b6883c3d54c557ef (diff)
IB/hfi1: Allow for non-double word multiple message sizes for user SDMA
The driver pads non-double word multiple message sizes but it doesn't account for this padding when the packet length is calculated. Also, the data length is miscalculated for message sizes less than 4 bytes due to the bit representation in LRH. And there's a check for non-double word multiple message sizes that prevents these messages from being sent. This patch fixes length miscalculations and enables the functionality to send non-double word multiple message sizes. Reviewed-by: Harish Chegondi <harish.chegondi@intel.com> Signed-off-by: Sebastian Sanchez <sebastian.sanchez@intel.com> Signed-off-by: Ira Weiny <ira.weiny@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/hfi1/user_sdma.c31
-rw-r--r--include/uapi/rdma/hfi/hfi1_user.h2
2 files changed, 23 insertions, 10 deletions
diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c
index d16ed52a2cb1..1e266c95056a 100644
--- a/drivers/infiniband/hw/hfi1/user_sdma.c
+++ b/drivers/infiniband/hw/hfi1/user_sdma.c
@@ -793,14 +793,21 @@ static inline u32 compute_data_length(struct user_sdma_request *req,
793 * The size of the data of the first packet is in the header 793 * The size of the data of the first packet is in the header
794 * template. However, it includes the header and ICRC, which need 794 * template. However, it includes the header and ICRC, which need
795 * to be subtracted. 795 * to be subtracted.
796 * The minimum representable packet data length in a header is 4 bytes,
797 * therefore, when the data length request is less than 4 bytes, there's
798 * only one packet, and the packet data length is equal to that of the
799 * request data length.
796 * The size of the remaining packets is the minimum of the frag 800 * The size of the remaining packets is the minimum of the frag
797 * size (MTU) or remaining data in the request. 801 * size (MTU) or remaining data in the request.
798 */ 802 */
799 u32 len; 803 u32 len;
800 804
801 if (!req->seqnum) { 805 if (!req->seqnum) {
802 len = ((be16_to_cpu(req->hdr.lrh[2]) << 2) - 806 if (req->data_len < sizeof(u32))
803 (sizeof(tx->hdr) - 4)); 807 len = req->data_len;
808 else
809 len = ((be16_to_cpu(req->hdr.lrh[2]) << 2) -
810 (sizeof(tx->hdr) - 4));
804 } else if (req_opcode(req->info.ctrl) == EXPECTED) { 811 } else if (req_opcode(req->info.ctrl) == EXPECTED) {
805 u32 tidlen = EXP_TID_GET(req->tids[req->tididx], LEN) * 812 u32 tidlen = EXP_TID_GET(req->tids[req->tididx], LEN) *
806 PAGE_SIZE; 813 PAGE_SIZE;
@@ -830,6 +837,13 @@ static inline u32 compute_data_length(struct user_sdma_request *req,
830 return len; 837 return len;
831} 838}
832 839
840static inline u32 pad_len(u32 len)
841{
842 if (len & (sizeof(u32) - 1))
843 len += sizeof(u32) - (len & (sizeof(u32) - 1));
844 return len;
845}
846
833static inline u32 get_lrh_len(struct hfi1_pkt_header hdr, u32 len) 847static inline u32 get_lrh_len(struct hfi1_pkt_header hdr, u32 len)
834{ 848{
835 /* (Size of complete header - size of PBC) + 4B ICRC + data length */ 849 /* (Size of complete header - size of PBC) + 4B ICRC + data length */
@@ -921,7 +935,8 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
921 if (test_bit(SDMA_REQ_HAVE_AHG, &req->flags)) { 935 if (test_bit(SDMA_REQ_HAVE_AHG, &req->flags)) {
922 if (!req->seqnum) { 936 if (!req->seqnum) {
923 u16 pbclen = le16_to_cpu(req->hdr.pbc[0]); 937 u16 pbclen = le16_to_cpu(req->hdr.pbc[0]);
924 u32 lrhlen = get_lrh_len(req->hdr, datalen); 938 u32 lrhlen = get_lrh_len(req->hdr,
939 pad_len(datalen));
925 /* 940 /*
926 * Copy the request header into the tx header 941 * Copy the request header into the tx header
927 * because the HW needs a cacheline-aligned 942 * because the HW needs a cacheline-aligned
@@ -1219,16 +1234,14 @@ static int check_header_template(struct user_sdma_request *req,
1219 /* 1234 /*
1220 * Perform safety checks for any type of packet: 1235 * Perform safety checks for any type of packet:
1221 * - transfer size is multiple of 64bytes 1236 * - transfer size is multiple of 64bytes
1222 * - packet length is multiple of 4bytes 1237 * - packet length is multiple of 4 bytes
1223 * - entire request length is multiple of 4bytes
1224 * - packet length is not larger than MTU size 1238 * - packet length is not larger than MTU size
1225 * 1239 *
1226 * These checks are only done for the first packet of the 1240 * These checks are only done for the first packet of the
1227 * transfer since the header is "given" to us by user space. 1241 * transfer since the header is "given" to us by user space.
1228 * For the remainder of the packets we compute the values. 1242 * For the remainder of the packets we compute the values.
1229 */ 1243 */
1230 if (req->info.fragsize % PIO_BLOCK_SIZE || 1244 if (req->info.fragsize % PIO_BLOCK_SIZE || lrhlen & 0x3 ||
1231 lrhlen & 0x3 || req->data_len & 0x3 ||
1232 lrhlen > get_lrh_len(*hdr, req->info.fragsize)) 1245 lrhlen > get_lrh_len(*hdr, req->info.fragsize))
1233 return -EINVAL; 1246 return -EINVAL;
1234 1247
@@ -1290,7 +1303,7 @@ static int set_txreq_header(struct user_sdma_request *req,
1290 struct hfi1_pkt_header *hdr = &tx->hdr; 1303 struct hfi1_pkt_header *hdr = &tx->hdr;
1291 u16 pbclen; 1304 u16 pbclen;
1292 int ret; 1305 int ret;
1293 u32 tidval = 0, lrhlen = get_lrh_len(*hdr, datalen); 1306 u32 tidval = 0, lrhlen = get_lrh_len(*hdr, pad_len(datalen));
1294 1307
1295 /* Copy the header template to the request before modification */ 1308 /* Copy the header template to the request before modification */
1296 memcpy(hdr, &req->hdr, sizeof(*hdr)); 1309 memcpy(hdr, &req->hdr, sizeof(*hdr));
@@ -1401,7 +1414,7 @@ static int set_txreq_header_ahg(struct user_sdma_request *req,
1401 struct hfi1_user_sdma_pkt_q *pq = req->pq; 1414 struct hfi1_user_sdma_pkt_q *pq = req->pq;
1402 struct hfi1_pkt_header *hdr = &req->hdr; 1415 struct hfi1_pkt_header *hdr = &req->hdr;
1403 u16 pbclen = le16_to_cpu(hdr->pbc[0]); 1416 u16 pbclen = le16_to_cpu(hdr->pbc[0]);
1404 u32 val32, tidval = 0, lrhlen = get_lrh_len(*hdr, len); 1417 u32 val32, tidval = 0, lrhlen = get_lrh_len(*hdr, pad_len(len));
1405 1418
1406 if (PBC2LRH(pbclen) != lrhlen) { 1419 if (PBC2LRH(pbclen) != lrhlen) {
1407 /* PBC.PbcLengthDWs */ 1420 /* PBC.PbcLengthDWs */
diff --git a/include/uapi/rdma/hfi/hfi1_user.h b/include/uapi/rdma/hfi/hfi1_user.h
index 98bebf8bef55..d15e7289d835 100644
--- a/include/uapi/rdma/hfi/hfi1_user.h
+++ b/include/uapi/rdma/hfi/hfi1_user.h
@@ -75,7 +75,7 @@
75 * may not be implemented; the user code must deal with this if it 75 * may not be implemented; the user code must deal with this if it
76 * cares, or it must abort after initialization reports the difference. 76 * cares, or it must abort after initialization reports the difference.
77 */ 77 */
78#define HFI1_USER_SWMINOR 1 78#define HFI1_USER_SWMINOR 2
79 79
80/* 80/*
81 * We will encode the major/minor inside a single 32bit version number. 81 * We will encode the major/minor inside a single 32bit version number.