| .. | .. |
|---|
| 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 | } |
|---|