.. | .. |
---|
104 | 104 | |
---|
105 | 105 | static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits) |
---|
106 | 106 | { |
---|
107 | | - int idx; |
---|
| 107 | + int idx, idx2; |
---|
| 108 | + u32 hi_val = 0; |
---|
108 | 109 | |
---|
109 | 110 | 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 | + } |
---|
110 | 117 | start -= idx * 32; |
---|
111 | 118 | idx = 2 - idx; /* flip */ |
---|
112 | | - return (ale_entry[idx] >> start) & BITMASK(bits); |
---|
| 119 | + return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits); |
---|
113 | 120 | } |
---|
114 | 121 | |
---|
115 | 122 | static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits, |
---|
116 | 123 | u32 value) |
---|
117 | 124 | { |
---|
118 | | - int idx; |
---|
| 125 | + int idx, idx2; |
---|
119 | 126 | |
---|
120 | 127 | 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 | + } |
---|
122 | 136 | start -= idx * 32; |
---|
123 | | - idx = 2 - idx; /* flip */ |
---|
| 137 | + idx = 2 - idx; /* flip */ |
---|
124 | 138 | ale_entry[idx] &= ~(BITMASK(bits) << start); |
---|
125 | 139 | ale_entry[idx] |= (value << start); |
---|
126 | 140 | } |
---|