0001
0002
0003
0004 #include "e1000.h"
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
0015 {
0016 u32 i;
0017 u8 sum = 0;
0018
0019 if (!buffer)
0020 return 0;
0021
0022 for (i = 0; i < length; i++)
0023 sum += buffer[i];
0024
0025 return (u8)(0 - sum);
0026 }
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 static s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
0039 {
0040 u32 hicr;
0041 u8 i;
0042
0043 if (!hw->mac.arc_subsystem_valid) {
0044 e_dbg("ARC subsystem not valid.\n");
0045 return -E1000_ERR_HOST_INTERFACE_COMMAND;
0046 }
0047
0048
0049 hicr = er32(HICR);
0050 if (!(hicr & E1000_HICR_EN)) {
0051 e_dbg("E1000_HOST_EN bit disabled.\n");
0052 return -E1000_ERR_HOST_INTERFACE_COMMAND;
0053 }
0054
0055 for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
0056 hicr = er32(HICR);
0057 if (!(hicr & E1000_HICR_C))
0058 break;
0059 mdelay(1);
0060 }
0061
0062 if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
0063 e_dbg("Previous command timeout failed.\n");
0064 return -E1000_ERR_HOST_INTERFACE_COMMAND;
0065 }
0066
0067 return 0;
0068 }
0069
0070
0071
0072
0073
0074
0075
0076
0077 bool e1000e_check_mng_mode_generic(struct e1000_hw *hw)
0078 {
0079 u32 fwsm = er32(FWSM);
0080
0081 return (fwsm & E1000_FWSM_MODE_MASK) ==
0082 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
0083 }
0084
0085
0086
0087
0088
0089
0090
0091
0092 bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
0093 {
0094 struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
0095 u32 *buffer = (u32 *)&hw->mng_cookie;
0096 u32 offset;
0097 s32 ret_val, hdr_csum, csum;
0098 u8 i, len;
0099
0100 hw->mac.tx_pkt_filtering = true;
0101
0102
0103 if (!hw->mac.ops.check_mng_mode(hw)) {
0104 hw->mac.tx_pkt_filtering = false;
0105 return hw->mac.tx_pkt_filtering;
0106 }
0107
0108
0109
0110
0111 ret_val = e1000_mng_enable_host_if(hw);
0112 if (ret_val) {
0113 hw->mac.tx_pkt_filtering = false;
0114 return hw->mac.tx_pkt_filtering;
0115 }
0116
0117
0118 len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
0119 offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
0120 for (i = 0; i < len; i++)
0121 *(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF,
0122 offset + i);
0123 hdr_csum = hdr->checksum;
0124 hdr->checksum = 0;
0125 csum = e1000_calculate_checksum((u8 *)hdr,
0126 E1000_MNG_DHCP_COOKIE_LENGTH);
0127
0128
0129
0130
0131 if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
0132 hw->mac.tx_pkt_filtering = true;
0133 return hw->mac.tx_pkt_filtering;
0134 }
0135
0136
0137 if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
0138 hw->mac.tx_pkt_filtering = false;
0139
0140 return hw->mac.tx_pkt_filtering;
0141 }
0142
0143
0144
0145
0146
0147
0148
0149
0150 static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
0151 struct e1000_host_mng_command_header *hdr)
0152 {
0153 u16 i, length = sizeof(struct e1000_host_mng_command_header);
0154
0155
0156
0157 hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
0158
0159 length >>= 2;
0160
0161 for (i = 0; i < length; i++) {
0162 E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i, *((u32 *)hdr + i));
0163 e1e_flush();
0164 }
0165
0166 return 0;
0167 }
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181 static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer,
0182 u16 length, u16 offset, u8 *sum)
0183 {
0184 u8 *tmp;
0185 u8 *bufptr = buffer;
0186 u32 data = 0;
0187 u16 remaining, i, j, prev_bytes;
0188
0189
0190
0191 if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
0192 return -E1000_ERR_PARAM;
0193
0194 tmp = (u8 *)&data;
0195 prev_bytes = offset & 0x3;
0196 offset >>= 2;
0197
0198 if (prev_bytes) {
0199 data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset);
0200 for (j = prev_bytes; j < sizeof(u32); j++) {
0201 *(tmp + j) = *bufptr++;
0202 *sum += *(tmp + j);
0203 }
0204 E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data);
0205 length -= j - prev_bytes;
0206 offset++;
0207 }
0208
0209 remaining = length & 0x3;
0210 length -= remaining;
0211
0212
0213 length >>= 2;
0214
0215
0216
0217
0218 for (i = 0; i < length; i++) {
0219 for (j = 0; j < sizeof(u32); j++) {
0220 *(tmp + j) = *bufptr++;
0221 *sum += *(tmp + j);
0222 }
0223
0224 E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
0225 }
0226 if (remaining) {
0227 for (j = 0; j < sizeof(u32); j++) {
0228 if (j < remaining)
0229 *(tmp + j) = *bufptr++;
0230 else
0231 *(tmp + j) = 0;
0232
0233 *sum += *(tmp + j);
0234 }
0235 E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
0236 }
0237
0238 return 0;
0239 }
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249 s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
0250 {
0251 struct e1000_host_mng_command_header hdr;
0252 s32 ret_val;
0253 u32 hicr;
0254
0255 hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
0256 hdr.command_length = length;
0257 hdr.reserved1 = 0;
0258 hdr.reserved2 = 0;
0259 hdr.checksum = 0;
0260
0261
0262 ret_val = e1000_mng_enable_host_if(hw);
0263 if (ret_val)
0264 return ret_val;
0265
0266
0267 ret_val = e1000_mng_host_if_write(hw, buffer, length,
0268 sizeof(hdr), &(hdr.checksum));
0269 if (ret_val)
0270 return ret_val;
0271
0272
0273 ret_val = e1000_mng_write_cmd_header(hw, &hdr);
0274 if (ret_val)
0275 return ret_val;
0276
0277
0278 hicr = er32(HICR);
0279 ew32(HICR, hicr | E1000_HICR_C);
0280
0281 return 0;
0282 }
0283
0284
0285
0286
0287
0288
0289
0290
0291 bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
0292 {
0293 u32 manc;
0294 u32 fwsm, factps;
0295
0296 manc = er32(MANC);
0297
0298 if (!(manc & E1000_MANC_RCV_TCO_EN))
0299 return false;
0300
0301 if (hw->mac.has_fwsm) {
0302 fwsm = er32(FWSM);
0303 factps = er32(FACTPS);
0304
0305 if (!(factps & E1000_FACTPS_MNGCG) &&
0306 ((fwsm & E1000_FWSM_MODE_MASK) ==
0307 (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)))
0308 return true;
0309 } else if ((hw->mac.type == e1000_82574) ||
0310 (hw->mac.type == e1000_82583)) {
0311 u16 data;
0312 s32 ret_val;
0313
0314 factps = er32(FACTPS);
0315 ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
0316 if (ret_val)
0317 return false;
0318
0319 if (!(factps & E1000_FACTPS_MNGCG) &&
0320 ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
0321 (e1000_mng_mode_pt << 13)))
0322 return true;
0323 } else if ((manc & E1000_MANC_SMBUS_EN) &&
0324 !(manc & E1000_MANC_ASF_EN)) {
0325 return true;
0326 }
0327
0328 return false;
0329 }