Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

IB/core: Fix unaligned accesses

Addresses the following kernel logs seen during boot of sparc systems:

Kernel unaligned access at TPC[103bce50] cm_find_listen+0x34/0xf8 [ib_cm]
Kernel unaligned access at TPC[103bce50] cm_find_listen+0x34/0xf8 [ib_cm]
Kernel unaligned access at TPC[103bce50] cm_find_listen+0x34/0xf8 [ib_cm]
Kernel unaligned access at TPC[103bce50] cm_find_listen+0x34/0xf8 [ib_cm]
Kernel unaligned access at TPC[103bce50] cm_find_listen+0x34/0xf8 [ib_cm]

Signed-off-by: David Ahern <david.ahern@oracle.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>

authored by

David Ahern and committed by
Doug Ledford
0d0f738f 471e7058

+17 -17
+11 -12
drivers/infiniband/core/cm.c
··· 437 437 return cm_id_priv; 438 438 } 439 439 440 - static void cm_mask_copy(u8 *dst, u8 *src, u8 *mask) 440 + static void cm_mask_copy(u32 *dst, const u32 *src, const u32 *mask) 441 441 { 442 442 int i; 443 443 444 - for (i = 0; i < IB_CM_COMPARE_SIZE / sizeof(unsigned long); i++) 445 - ((unsigned long *) dst)[i] = ((unsigned long *) src)[i] & 446 - ((unsigned long *) mask)[i]; 444 + for (i = 0; i < IB_CM_COMPARE_SIZE; i++) 445 + dst[i] = src[i] & mask[i]; 447 446 } 448 447 449 448 static int cm_compare_data(struct ib_cm_compare_data *src_data, 450 449 struct ib_cm_compare_data *dst_data) 451 450 { 452 - u8 src[IB_CM_COMPARE_SIZE]; 453 - u8 dst[IB_CM_COMPARE_SIZE]; 451 + u32 src[IB_CM_COMPARE_SIZE]; 452 + u32 dst[IB_CM_COMPARE_SIZE]; 454 453 455 454 if (!src_data || !dst_data) 456 455 return 0; 457 456 458 457 cm_mask_copy(src, src_data->data, dst_data->mask); 459 458 cm_mask_copy(dst, dst_data->data, src_data->mask); 460 - return memcmp(src, dst, IB_CM_COMPARE_SIZE); 459 + return memcmp(src, dst, sizeof(src)); 461 460 } 462 461 463 - static int cm_compare_private_data(u8 *private_data, 462 + static int cm_compare_private_data(u32 *private_data, 464 463 struct ib_cm_compare_data *dst_data) 465 464 { 466 - u8 src[IB_CM_COMPARE_SIZE]; 465 + u32 src[IB_CM_COMPARE_SIZE]; 467 466 468 467 if (!dst_data) 469 468 return 0; 470 469 471 470 cm_mask_copy(src, private_data, dst_data->mask); 472 - return memcmp(src, dst_data->data, IB_CM_COMPARE_SIZE); 471 + return memcmp(src, dst_data->data, sizeof(src)); 473 472 } 474 473 475 474 /* ··· 537 538 538 539 static struct cm_id_private * cm_find_listen(struct ib_device *device, 539 540 __be64 service_id, 540 - u8 *private_data) 541 + u32 *private_data) 541 542 { 542 543 struct rb_node *node = cm.listen_service_table.rb_node; 543 544 struct cm_id_private *cm_id_priv; ··· 952 953 cm_mask_copy(cm_id_priv->compare_data->data, 953 954 compare_data->data, compare_data->mask); 954 955 memcpy(cm_id_priv->compare_data->mask, compare_data->mask, 955 - IB_CM_COMPARE_SIZE); 956 + sizeof(compare_data->mask)); 956 957 } 957 958 958 959 cm_id->state = IB_CM_LISTEN;
+2 -2
drivers/infiniband/core/cm_msgs.h
··· 103 103 /* local ACK timeout:5, rsvd:3 */ 104 104 u8 alt_offset139; 105 105 106 - u8 private_data[IB_CM_REQ_PRIVATE_DATA_SIZE]; 106 + u32 private_data[IB_CM_REQ_PRIVATE_DATA_SIZE / sizeof(u32)]; 107 107 108 108 } __attribute__ ((packed)); 109 109 ··· 801 801 __be16 rsvd; 802 802 __be64 service_id; 803 803 804 - u8 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE]; 804 + u32 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE / sizeof(u32)]; 805 805 } __attribute__ ((packed)); 806 806 807 807 struct cm_sidr_rep_msg {
+4 -3
include/rdma/ib_cm.h
··· 105 105 IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE = 216, 106 106 IB_CM_SIDR_REP_PRIVATE_DATA_SIZE = 136, 107 107 IB_CM_SIDR_REP_INFO_LENGTH = 72, 108 - IB_CM_COMPARE_SIZE = 64 108 + /* compare done u32 at a time */ 109 + IB_CM_COMPARE_SIZE = (64 / sizeof(u32)) 109 110 }; 110 111 111 112 struct ib_cm_id; ··· 338 337 #define IB_SDP_SERVICE_ID_MASK cpu_to_be64(0xFFFFFFFFFFFF0000ULL) 339 338 340 339 struct ib_cm_compare_data { 341 - u8 data[IB_CM_COMPARE_SIZE]; 342 - u8 mask[IB_CM_COMPARE_SIZE]; 340 + u32 data[IB_CM_COMPARE_SIZE]; 341 + u32 mask[IB_CM_COMPARE_SIZE]; 343 342 }; 344 343 345 344 /**