Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 1999 - 2018 Intel Corporation. */
0003 
0004 #include "e1000.h"
0005 
0006 /**
0007  *  e1000_calculate_checksum - Calculate checksum for buffer
0008  *  @buffer: pointer to EEPROM
0009  *  @length: size of EEPROM to calculate a checksum for
0010  *
0011  *  Calculates the checksum for some buffer on a specified length.  The
0012  *  checksum calculated is returned.
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  *  e1000_mng_enable_host_if - Checks host interface is enabled
0030  *  @hw: pointer to the HW structure
0031  *
0032  *  Returns 0 upon success, else -E1000_ERR_HOST_INTERFACE_COMMAND
0033  *
0034  *  This function checks whether the HOST IF is enabled for command operation
0035  *  and also checks whether the previous command is completed.  It busy waits
0036  *  in case of previous command is not completed.
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     /* Check that the host interface is enabled. */
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     /* check the previous command is completed */
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  *  e1000e_check_mng_mode_generic - Generic check management mode
0072  *  @hw: pointer to the HW structure
0073  *
0074  *  Reads the firmware semaphore register and returns true (>0) if
0075  *  manageability is enabled, else false (0).
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  *  e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx
0087  *  @hw: pointer to the HW structure
0088  *
0089  *  Enables packet filtering on transmit packets if manageability is enabled
0090  *  and host interface is enabled.
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     /* No manageability, no filtering */
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     /* If we can't read from the host interface for whatever
0109      * reason, disable filtering.
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     /* Read in the header.  Length and offset are in dwords. */
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     /* If either the checksums or signature don't match, then
0128      * the cookie area isn't considered valid, in which case we
0129      * take the safe route of assuming Tx filtering is enabled.
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     /* Cookie area is valid, make the final check for filtering. */
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  *  e1000_mng_write_cmd_header - Writes manageability command header
0145  *  @hw: pointer to the HW structure
0146  *  @hdr: pointer to the host interface command header
0147  *
0148  *  Writes the command header after does the checksum calculation.
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     /* Write the whole command header structure with new checksum. */
0156 
0157     hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
0158 
0159     length >>= 2;
0160     /* Write the relevant command block into the ram area. */
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  *  e1000_mng_host_if_write - Write to the manageability host interface
0171  *  @hw: pointer to the HW structure
0172  *  @buffer: pointer to the host interface buffer
0173  *  @length: size of the buffer
0174  *  @offset: location in the buffer to write to
0175  *  @sum: sum of the data (not checksum)
0176  *
0177  *  This function writes the buffer content at the offset given on the host if.
0178  *  It also does alignment considerations to do the writes in most efficient
0179  *  way.  Also fills up the sum of the buffer in *buffer parameter.
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     /* sum = only sum of the data and it is not checksum */
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     /* Calculate length in DWORDs */
0213     length >>= 2;
0214 
0215     /* The device driver writes the relevant command block into the
0216      * ram area.
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  *  e1000e_mng_write_dhcp_info - Writes DHCP info to host interface
0243  *  @hw: pointer to the HW structure
0244  *  @buffer: pointer to the host interface
0245  *  @length: size of the buffer
0246  *
0247  *  Writes the DHCP information to the host interface.
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     /* Enable the host interface */
0262     ret_val = e1000_mng_enable_host_if(hw);
0263     if (ret_val)
0264         return ret_val;
0265 
0266     /* Populate the host interface with the contents of "buffer". */
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     /* Write the manageability command header */
0273     ret_val = e1000_mng_write_cmd_header(hw, &hdr);
0274     if (ret_val)
0275         return ret_val;
0276 
0277     /* Tell the ARC a new command is pending. */
0278     hicr = er32(HICR);
0279     ew32(HICR, hicr | E1000_HICR_C);
0280 
0281     return 0;
0282 }
0283 
0284 /**
0285  *  e1000e_enable_mng_pass_thru - Check if management passthrough is needed
0286  *  @hw: pointer to the HW structure
0287  *
0288  *  Verifies the hardware needs to leave interface enabled so that frames can
0289  *  be directed to and from the management interface.
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 }