0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <linux/export.h>
0035 #include <linux/string.h>
0036
0037 #include <rdma/ib_pack.h>
0038
0039 static u64 value_read(int offset, int size, void *structure)
0040 {
0041 switch (size) {
0042 case 1: return *(u8 *) (structure + offset);
0043 case 2: return be16_to_cpup((__be16 *) (structure + offset));
0044 case 4: return be32_to_cpup((__be32 *) (structure + offset));
0045 case 8: return be64_to_cpup((__be64 *) (structure + offset));
0046 default:
0047 pr_warn("Field size %d bits not handled\n", size * 8);
0048 return 0;
0049 }
0050 }
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 void ib_pack(const struct ib_field *desc,
0063 int desc_len,
0064 void *structure,
0065 void *buf)
0066 {
0067 int i;
0068
0069 for (i = 0; i < desc_len; ++i) {
0070 if (desc[i].size_bits <= 32) {
0071 int shift;
0072 u32 val;
0073 __be32 mask;
0074 __be32 *addr;
0075
0076 shift = 32 - desc[i].offset_bits - desc[i].size_bits;
0077 if (desc[i].struct_size_bytes)
0078 val = value_read(desc[i].struct_offset_bytes,
0079 desc[i].struct_size_bytes,
0080 structure) << shift;
0081 else
0082 val = 0;
0083
0084 mask = cpu_to_be32(((1ull << desc[i].size_bits) - 1) << shift);
0085 addr = (__be32 *) buf + desc[i].offset_words;
0086 *addr = (*addr & ~mask) | (cpu_to_be32(val) & mask);
0087 } else if (desc[i].size_bits <= 64) {
0088 int shift;
0089 u64 val;
0090 __be64 mask;
0091 __be64 *addr;
0092
0093 shift = 64 - desc[i].offset_bits - desc[i].size_bits;
0094 if (desc[i].struct_size_bytes)
0095 val = value_read(desc[i].struct_offset_bytes,
0096 desc[i].struct_size_bytes,
0097 structure) << shift;
0098 else
0099 val = 0;
0100
0101 mask = cpu_to_be64((~0ull >> (64 - desc[i].size_bits)) << shift);
0102 addr = (__be64 *) ((__be32 *) buf + desc[i].offset_words);
0103 *addr = (*addr & ~mask) | (cpu_to_be64(val) & mask);
0104 } else {
0105 if (desc[i].offset_bits % 8 ||
0106 desc[i].size_bits % 8) {
0107 pr_warn("Structure field %s of size %d bits is not byte-aligned\n",
0108 desc[i].field_name, desc[i].size_bits);
0109 }
0110
0111 if (desc[i].struct_size_bytes)
0112 memcpy(buf + desc[i].offset_words * 4 +
0113 desc[i].offset_bits / 8,
0114 structure + desc[i].struct_offset_bytes,
0115 desc[i].size_bits / 8);
0116 else
0117 memset(buf + desc[i].offset_words * 4 +
0118 desc[i].offset_bits / 8,
0119 0,
0120 desc[i].size_bits / 8);
0121 }
0122 }
0123 }
0124 EXPORT_SYMBOL(ib_pack);
0125
0126 static void value_write(int offset, int size, u64 val, void *structure)
0127 {
0128 switch (size * 8) {
0129 case 8: *( u8 *) (structure + offset) = val; break;
0130 case 16: *(__be16 *) (structure + offset) = cpu_to_be16(val); break;
0131 case 32: *(__be32 *) (structure + offset) = cpu_to_be32(val); break;
0132 case 64: *(__be64 *) (structure + offset) = cpu_to_be64(val); break;
0133 default:
0134 pr_warn("Field size %d bits not handled\n", size * 8);
0135 }
0136 }
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148 void ib_unpack(const struct ib_field *desc,
0149 int desc_len,
0150 void *buf,
0151 void *structure)
0152 {
0153 int i;
0154
0155 for (i = 0; i < desc_len; ++i) {
0156 if (!desc[i].struct_size_bytes)
0157 continue;
0158
0159 if (desc[i].size_bits <= 32) {
0160 int shift;
0161 u32 val;
0162 u32 mask;
0163 __be32 *addr;
0164
0165 shift = 32 - desc[i].offset_bits - desc[i].size_bits;
0166 mask = ((1ull << desc[i].size_bits) - 1) << shift;
0167 addr = (__be32 *) buf + desc[i].offset_words;
0168 val = (be32_to_cpup(addr) & mask) >> shift;
0169 value_write(desc[i].struct_offset_bytes,
0170 desc[i].struct_size_bytes,
0171 val,
0172 structure);
0173 } else if (desc[i].size_bits <= 64) {
0174 int shift;
0175 u64 val;
0176 u64 mask;
0177 __be64 *addr;
0178
0179 shift = 64 - desc[i].offset_bits - desc[i].size_bits;
0180 mask = (~0ull >> (64 - desc[i].size_bits)) << shift;
0181 addr = (__be64 *) buf + desc[i].offset_words;
0182 val = (be64_to_cpup(addr) & mask) >> shift;
0183 value_write(desc[i].struct_offset_bytes,
0184 desc[i].struct_size_bytes,
0185 val,
0186 structure);
0187 } else {
0188 if (desc[i].offset_bits % 8 ||
0189 desc[i].size_bits % 8) {
0190 pr_warn("Structure field %s of size %d bits is not byte-aligned\n",
0191 desc[i].field_name, desc[i].size_bits);
0192 }
0193
0194 memcpy(structure + desc[i].struct_offset_bytes,
0195 buf + desc[i].offset_words * 4 +
0196 desc[i].offset_bits / 8,
0197 desc[i].size_bits / 8);
0198 }
0199 }
0200 }
0201 EXPORT_SYMBOL(ib_unpack);