hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/ethernet/ti/cpsw_ale.c
....@@ -104,23 +104,37 @@
104104
105105 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
106106 {
107
- int idx;
107
+ int idx, idx2;
108
+ u32 hi_val = 0;
108109
109110 idx = start / 32;
111
+ idx2 = (start + bits - 1) / 32;
112
+ /* Check if bits to be fetched exceed a word */
113
+ if (idx != idx2) {
114
+ idx2 = 2 - idx2; /* flip */
115
+ hi_val = ale_entry[idx2] << ((idx2 * 32) - start);
116
+ }
110117 start -= idx * 32;
111118 idx = 2 - idx; /* flip */
112
- return (ale_entry[idx] >> start) & BITMASK(bits);
119
+ return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits);
113120 }
114121
115122 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
116123 u32 value)
117124 {
118
- int idx;
125
+ int idx, idx2;
119126
120127 value &= BITMASK(bits);
121
- idx = start / 32;
128
+ idx = start / 32;
129
+ idx2 = (start + bits - 1) / 32;
130
+ /* Check if bits to be set exceed a word */
131
+ if (idx != idx2) {
132
+ idx2 = 2 - idx2; /* flip */
133
+ ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32)));
134
+ ale_entry[idx2] |= (value >> ((idx2 * 32) - start));
135
+ }
122136 start -= idx * 32;
123
- idx = 2 - idx; /* flip */
137
+ idx = 2 - idx; /* flip */
124138 ale_entry[idx] &= ~(BITMASK(bits) << start);
125139 ale_entry[idx] |= (value << start);
126140 }