123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848 |
- /* SPDX-License-Identifier: GPL-2.0+ */
- /* Copyright (C) 2018 Microchip Technology Inc. */
- #include <linux/netdevice.h>
- #include "lan743x_main.h"
- #include "lan743x_ethtool.h"
- #include <linux/net_tstamp.h>
- #include <linux/pci.h>
- #include <linux/phy.h>
- /* eeprom */
- #define LAN743X_EEPROM_MAGIC (0x74A5)
- #define LAN743X_OTP_MAGIC (0x74F3)
- #define EEPROM_INDICATOR_1 (0xA5)
- #define EEPROM_INDICATOR_2 (0xAA)
- #define EEPROM_MAC_OFFSET (0x01)
- #define MAX_EEPROM_SIZE (512)
- #define MAX_OTP_SIZE (1024)
- #define OTP_INDICATOR_1 (0xF3)
- #define OTP_INDICATOR_2 (0xF7)
- static int lan743x_otp_power_up(struct lan743x_adapter *adapter)
- {
- u32 reg_value;
- reg_value = lan743x_csr_read(adapter, OTP_PWR_DN);
- if (reg_value & OTP_PWR_DN_PWRDN_N_) {
- /* clear it and wait to be cleared */
- reg_value &= ~OTP_PWR_DN_PWRDN_N_;
- lan743x_csr_write(adapter, OTP_PWR_DN, reg_value);
- usleep_range(100, 20000);
- }
- return 0;
- }
- static void lan743x_otp_power_down(struct lan743x_adapter *adapter)
- {
- u32 reg_value;
- reg_value = lan743x_csr_read(adapter, OTP_PWR_DN);
- if (!(reg_value & OTP_PWR_DN_PWRDN_N_)) {
- /* set power down bit */
- reg_value |= OTP_PWR_DN_PWRDN_N_;
- lan743x_csr_write(adapter, OTP_PWR_DN, reg_value);
- }
- }
- static void lan743x_otp_set_address(struct lan743x_adapter *adapter,
- u32 address)
- {
- lan743x_csr_write(adapter, OTP_ADDR_HIGH, (address >> 8) & 0x03);
- lan743x_csr_write(adapter, OTP_ADDR_LOW, address & 0xFF);
- }
- static void lan743x_otp_read_go(struct lan743x_adapter *adapter)
- {
- lan743x_csr_write(adapter, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
- lan743x_csr_write(adapter, OTP_CMD_GO, OTP_CMD_GO_GO_);
- }
- static int lan743x_otp_wait_till_not_busy(struct lan743x_adapter *adapter)
- {
- unsigned long timeout;
- u32 reg_val;
- timeout = jiffies + HZ;
- do {
- if (time_after(jiffies, timeout)) {
- netif_warn(adapter, drv, adapter->netdev,
- "Timeout on OTP_STATUS completion\n");
- return -EIO;
- }
- udelay(1);
- reg_val = lan743x_csr_read(adapter, OTP_STATUS);
- } while (reg_val & OTP_STATUS_BUSY_);
- return 0;
- }
- static int lan743x_otp_read(struct lan743x_adapter *adapter, u32 offset,
- u32 length, u8 *data)
- {
- int ret;
- int i;
- if (offset + length > MAX_OTP_SIZE)
- return -EINVAL;
- ret = lan743x_otp_power_up(adapter);
- if (ret < 0)
- return ret;
- ret = lan743x_otp_wait_till_not_busy(adapter);
- if (ret < 0)
- return ret;
- for (i = 0; i < length; i++) {
- lan743x_otp_set_address(adapter, offset + i);
- lan743x_otp_read_go(adapter);
- ret = lan743x_otp_wait_till_not_busy(adapter);
- if (ret < 0)
- return ret;
- data[i] = lan743x_csr_read(adapter, OTP_READ_DATA);
- }
- lan743x_otp_power_down(adapter);
- return 0;
- }
- static int lan743x_otp_write(struct lan743x_adapter *adapter, u32 offset,
- u32 length, u8 *data)
- {
- int ret;
- int i;
- if (offset + length > MAX_OTP_SIZE)
- return -EINVAL;
- ret = lan743x_otp_power_up(adapter);
- if (ret < 0)
- return ret;
- ret = lan743x_otp_wait_till_not_busy(adapter);
- if (ret < 0)
- return ret;
- /* set to BYTE program mode */
- lan743x_csr_write(adapter, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
- for (i = 0; i < length; i++) {
- lan743x_otp_set_address(adapter, offset + i);
- lan743x_csr_write(adapter, OTP_PRGM_DATA, data[i]);
- lan743x_csr_write(adapter, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
- lan743x_csr_write(adapter, OTP_CMD_GO, OTP_CMD_GO_GO_);
- ret = lan743x_otp_wait_till_not_busy(adapter);
- if (ret < 0)
- return ret;
- }
- lan743x_otp_power_down(adapter);
- return 0;
- }
- static int lan743x_eeprom_wait(struct lan743x_adapter *adapter)
- {
- unsigned long start_time = jiffies;
- u32 val;
- do {
- val = lan743x_csr_read(adapter, E2P_CMD);
- if (!(val & E2P_CMD_EPC_BUSY_) ||
- (val & E2P_CMD_EPC_TIMEOUT_))
- break;
- usleep_range(40, 100);
- } while (!time_after(jiffies, start_time + HZ));
- if (val & (E2P_CMD_EPC_TIMEOUT_ | E2P_CMD_EPC_BUSY_)) {
- netif_warn(adapter, drv, adapter->netdev,
- "EEPROM read operation timeout\n");
- return -EIO;
- }
- return 0;
- }
- static int lan743x_eeprom_confirm_not_busy(struct lan743x_adapter *adapter)
- {
- unsigned long start_time = jiffies;
- u32 val;
- do {
- val = lan743x_csr_read(adapter, E2P_CMD);
- if (!(val & E2P_CMD_EPC_BUSY_))
- return 0;
- usleep_range(40, 100);
- } while (!time_after(jiffies, start_time + HZ));
- netif_warn(adapter, drv, adapter->netdev, "EEPROM is busy\n");
- return -EIO;
- }
- static int lan743x_eeprom_read(struct lan743x_adapter *adapter,
- u32 offset, u32 length, u8 *data)
- {
- int retval;
- u32 val;
- int i;
- if (offset + length > MAX_EEPROM_SIZE)
- return -EINVAL;
- retval = lan743x_eeprom_confirm_not_busy(adapter);
- if (retval)
- return retval;
- for (i = 0; i < length; i++) {
- val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_READ_;
- val |= (offset & E2P_CMD_EPC_ADDR_MASK_);
- lan743x_csr_write(adapter, E2P_CMD, val);
- retval = lan743x_eeprom_wait(adapter);
- if (retval < 0)
- return retval;
- val = lan743x_csr_read(adapter, E2P_DATA);
- data[i] = val & 0xFF;
- offset++;
- }
- return 0;
- }
- static int lan743x_eeprom_write(struct lan743x_adapter *adapter,
- u32 offset, u32 length, u8 *data)
- {
- int retval;
- u32 val;
- int i;
- if (offset + length > MAX_EEPROM_SIZE)
- return -EINVAL;
- retval = lan743x_eeprom_confirm_not_busy(adapter);
- if (retval)
- return retval;
- /* Issue write/erase enable command */
- val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWEN_;
- lan743x_csr_write(adapter, E2P_CMD, val);
- retval = lan743x_eeprom_wait(adapter);
- if (retval < 0)
- return retval;
- for (i = 0; i < length; i++) {
- /* Fill data register */
- val = data[i];
- lan743x_csr_write(adapter, E2P_DATA, val);
- /* Send "write" command */
- val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_WRITE_;
- val |= (offset & E2P_CMD_EPC_ADDR_MASK_);
- lan743x_csr_write(adapter, E2P_CMD, val);
- retval = lan743x_eeprom_wait(adapter);
- if (retval < 0)
- return retval;
- offset++;
- }
- return 0;
- }
- static void lan743x_ethtool_get_drvinfo(struct net_device *netdev,
- struct ethtool_drvinfo *info)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
- strlcpy(info->bus_info,
- pci_name(adapter->pdev), sizeof(info->bus_info));
- }
- static u32 lan743x_ethtool_get_msglevel(struct net_device *netdev)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- return adapter->msg_enable;
- }
- static void lan743x_ethtool_set_msglevel(struct net_device *netdev,
- u32 msglevel)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- adapter->msg_enable = msglevel;
- }
- static int lan743x_ethtool_get_eeprom_len(struct net_device *netdev)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP)
- return MAX_OTP_SIZE;
- return MAX_EEPROM_SIZE;
- }
- static int lan743x_ethtool_get_eeprom(struct net_device *netdev,
- struct ethtool_eeprom *ee, u8 *data)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- int ret = 0;
- if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP)
- ret = lan743x_otp_read(adapter, ee->offset, ee->len, data);
- else
- ret = lan743x_eeprom_read(adapter, ee->offset, ee->len, data);
- return ret;
- }
- static int lan743x_ethtool_set_eeprom(struct net_device *netdev,
- struct ethtool_eeprom *ee, u8 *data)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- int ret = -EINVAL;
- if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP) {
- /* Beware! OTP is One Time Programming ONLY! */
- if (ee->magic == LAN743X_OTP_MAGIC) {
- ret = lan743x_otp_write(adapter, ee->offset,
- ee->len, data);
- }
- } else {
- if (ee->magic == LAN743X_EEPROM_MAGIC) {
- ret = lan743x_eeprom_write(adapter, ee->offset,
- ee->len, data);
- }
- }
- return ret;
- }
- static const char lan743x_set0_hw_cnt_strings[][ETH_GSTRING_LEN] = {
- "RX FCS Errors",
- "RX Alignment Errors",
- "Rx Fragment Errors",
- "RX Jabber Errors",
- "RX Undersize Frame Errors",
- "RX Oversize Frame Errors",
- "RX Dropped Frames",
- "RX Unicast Byte Count",
- "RX Broadcast Byte Count",
- "RX Multicast Byte Count",
- "RX Unicast Frames",
- "RX Broadcast Frames",
- "RX Multicast Frames",
- "RX Pause Frames",
- "RX 64 Byte Frames",
- "RX 65 - 127 Byte Frames",
- "RX 128 - 255 Byte Frames",
- "RX 256 - 511 Bytes Frames",
- "RX 512 - 1023 Byte Frames",
- "RX 1024 - 1518 Byte Frames",
- "RX Greater 1518 Byte Frames",
- };
- static const char lan743x_set1_sw_cnt_strings[][ETH_GSTRING_LEN] = {
- "RX Queue 0 Frames",
- "RX Queue 1 Frames",
- "RX Queue 2 Frames",
- "RX Queue 3 Frames",
- };
- static const char lan743x_set2_hw_cnt_strings[][ETH_GSTRING_LEN] = {
- "RX Total Frames",
- "EEE RX LPI Transitions",
- "EEE RX LPI Time",
- "RX Counter Rollover Status",
- "TX FCS Errors",
- "TX Excess Deferral Errors",
- "TX Carrier Errors",
- "TX Bad Byte Count",
- "TX Single Collisions",
- "TX Multiple Collisions",
- "TX Excessive Collision",
- "TX Late Collisions",
- "TX Unicast Byte Count",
- "TX Broadcast Byte Count",
- "TX Multicast Byte Count",
- "TX Unicast Frames",
- "TX Broadcast Frames",
- "TX Multicast Frames",
- "TX Pause Frames",
- "TX 64 Byte Frames",
- "TX 65 - 127 Byte Frames",
- "TX 128 - 255 Byte Frames",
- "TX 256 - 511 Bytes Frames",
- "TX 512 - 1023 Byte Frames",
- "TX 1024 - 1518 Byte Frames",
- "TX Greater 1518 Byte Frames",
- "TX Total Frames",
- "EEE TX LPI Transitions",
- "EEE TX LPI Time",
- "TX Counter Rollover Status",
- };
- static const u32 lan743x_set0_hw_cnt_addr[] = {
- STAT_RX_FCS_ERRORS,
- STAT_RX_ALIGNMENT_ERRORS,
- STAT_RX_FRAGMENT_ERRORS,
- STAT_RX_JABBER_ERRORS,
- STAT_RX_UNDERSIZE_FRAME_ERRORS,
- STAT_RX_OVERSIZE_FRAME_ERRORS,
- STAT_RX_DROPPED_FRAMES,
- STAT_RX_UNICAST_BYTE_COUNT,
- STAT_RX_BROADCAST_BYTE_COUNT,
- STAT_RX_MULTICAST_BYTE_COUNT,
- STAT_RX_UNICAST_FRAMES,
- STAT_RX_BROADCAST_FRAMES,
- STAT_RX_MULTICAST_FRAMES,
- STAT_RX_PAUSE_FRAMES,
- STAT_RX_64_BYTE_FRAMES,
- STAT_RX_65_127_BYTE_FRAMES,
- STAT_RX_128_255_BYTE_FRAMES,
- STAT_RX_256_511_BYTES_FRAMES,
- STAT_RX_512_1023_BYTE_FRAMES,
- STAT_RX_1024_1518_BYTE_FRAMES,
- STAT_RX_GREATER_1518_BYTE_FRAMES,
- };
- static const u32 lan743x_set2_hw_cnt_addr[] = {
- STAT_RX_TOTAL_FRAMES,
- STAT_EEE_RX_LPI_TRANSITIONS,
- STAT_EEE_RX_LPI_TIME,
- STAT_RX_COUNTER_ROLLOVER_STATUS,
- STAT_TX_FCS_ERRORS,
- STAT_TX_EXCESS_DEFERRAL_ERRORS,
- STAT_TX_CARRIER_ERRORS,
- STAT_TX_BAD_BYTE_COUNT,
- STAT_TX_SINGLE_COLLISIONS,
- STAT_TX_MULTIPLE_COLLISIONS,
- STAT_TX_EXCESSIVE_COLLISION,
- STAT_TX_LATE_COLLISIONS,
- STAT_TX_UNICAST_BYTE_COUNT,
- STAT_TX_BROADCAST_BYTE_COUNT,
- STAT_TX_MULTICAST_BYTE_COUNT,
- STAT_TX_UNICAST_FRAMES,
- STAT_TX_BROADCAST_FRAMES,
- STAT_TX_MULTICAST_FRAMES,
- STAT_TX_PAUSE_FRAMES,
- STAT_TX_64_BYTE_FRAMES,
- STAT_TX_65_127_BYTE_FRAMES,
- STAT_TX_128_255_BYTE_FRAMES,
- STAT_TX_256_511_BYTES_FRAMES,
- STAT_TX_512_1023_BYTE_FRAMES,
- STAT_TX_1024_1518_BYTE_FRAMES,
- STAT_TX_GREATER_1518_BYTE_FRAMES,
- STAT_TX_TOTAL_FRAMES,
- STAT_EEE_TX_LPI_TRANSITIONS,
- STAT_EEE_TX_LPI_TIME,
- STAT_TX_COUNTER_ROLLOVER_STATUS
- };
- static const char lan743x_priv_flags_strings[][ETH_GSTRING_LEN] = {
- "OTP_ACCESS",
- };
- static void lan743x_ethtool_get_strings(struct net_device *netdev,
- u32 stringset, u8 *data)
- {
- switch (stringset) {
- case ETH_SS_STATS:
- memcpy(data, lan743x_set0_hw_cnt_strings,
- sizeof(lan743x_set0_hw_cnt_strings));
- memcpy(&data[sizeof(lan743x_set0_hw_cnt_strings)],
- lan743x_set1_sw_cnt_strings,
- sizeof(lan743x_set1_sw_cnt_strings));
- memcpy(&data[sizeof(lan743x_set0_hw_cnt_strings) +
- sizeof(lan743x_set1_sw_cnt_strings)],
- lan743x_set2_hw_cnt_strings,
- sizeof(lan743x_set2_hw_cnt_strings));
- break;
- case ETH_SS_PRIV_FLAGS:
- memcpy(data, lan743x_priv_flags_strings,
- sizeof(lan743x_priv_flags_strings));
- break;
- }
- }
- static void lan743x_ethtool_get_ethtool_stats(struct net_device *netdev,
- struct ethtool_stats *stats,
- u64 *data)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- int data_index = 0;
- u32 buf;
- int i;
- for (i = 0; i < ARRAY_SIZE(lan743x_set0_hw_cnt_addr); i++) {
- buf = lan743x_csr_read(adapter, lan743x_set0_hw_cnt_addr[i]);
- data[data_index++] = (u64)buf;
- }
- for (i = 0; i < ARRAY_SIZE(adapter->rx); i++)
- data[data_index++] = (u64)(adapter->rx[i].frame_count);
- for (i = 0; i < ARRAY_SIZE(lan743x_set2_hw_cnt_addr); i++) {
- buf = lan743x_csr_read(adapter, lan743x_set2_hw_cnt_addr[i]);
- data[data_index++] = (u64)buf;
- }
- }
- static u32 lan743x_ethtool_get_priv_flags(struct net_device *netdev)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- return adapter->flags;
- }
- static int lan743x_ethtool_set_priv_flags(struct net_device *netdev, u32 flags)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- adapter->flags = flags;
- return 0;
- }
- static int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset)
- {
- switch (sset) {
- case ETH_SS_STATS:
- {
- int ret;
- ret = ARRAY_SIZE(lan743x_set0_hw_cnt_strings);
- ret += ARRAY_SIZE(lan743x_set1_sw_cnt_strings);
- ret += ARRAY_SIZE(lan743x_set2_hw_cnt_strings);
- return ret;
- }
- case ETH_SS_PRIV_FLAGS:
- return ARRAY_SIZE(lan743x_priv_flags_strings);
- default:
- return -EOPNOTSUPP;
- }
- }
- static int lan743x_ethtool_get_rxnfc(struct net_device *netdev,
- struct ethtool_rxnfc *rxnfc,
- u32 *rule_locs)
- {
- switch (rxnfc->cmd) {
- case ETHTOOL_GRXFH:
- rxnfc->data = 0;
- switch (rxnfc->flow_type) {
- case TCP_V4_FLOW:case UDP_V4_FLOW:
- case TCP_V6_FLOW:case UDP_V6_FLOW:
- rxnfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
- /* fall through */
- case IPV4_FLOW: case IPV6_FLOW:
- rxnfc->data |= RXH_IP_SRC | RXH_IP_DST;
- return 0;
- }
- break;
- case ETHTOOL_GRXRINGS:
- rxnfc->data = LAN743X_USED_RX_CHANNELS;
- return 0;
- }
- return -EOPNOTSUPP;
- }
- static u32 lan743x_ethtool_get_rxfh_key_size(struct net_device *netdev)
- {
- return 40;
- }
- static u32 lan743x_ethtool_get_rxfh_indir_size(struct net_device *netdev)
- {
- return 128;
- }
- static int lan743x_ethtool_get_rxfh(struct net_device *netdev,
- u32 *indir, u8 *key, u8 *hfunc)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- if (indir) {
- int dw_index;
- int byte_index = 0;
- for (dw_index = 0; dw_index < 32; dw_index++) {
- u32 four_entries =
- lan743x_csr_read(adapter, RFE_INDX(dw_index));
- byte_index = dw_index << 2;
- indir[byte_index + 0] =
- ((four_entries >> 0) & 0x000000FF);
- indir[byte_index + 1] =
- ((four_entries >> 8) & 0x000000FF);
- indir[byte_index + 2] =
- ((four_entries >> 16) & 0x000000FF);
- indir[byte_index + 3] =
- ((four_entries >> 24) & 0x000000FF);
- }
- }
- if (key) {
- int dword_index;
- int byte_index = 0;
- for (dword_index = 0; dword_index < 10; dword_index++) {
- u32 four_entries =
- lan743x_csr_read(adapter,
- RFE_HASH_KEY(dword_index));
- byte_index = dword_index << 2;
- key[byte_index + 0] =
- ((four_entries >> 0) & 0x000000FF);
- key[byte_index + 1] =
- ((four_entries >> 8) & 0x000000FF);
- key[byte_index + 2] =
- ((four_entries >> 16) & 0x000000FF);
- key[byte_index + 3] =
- ((four_entries >> 24) & 0x000000FF);
- }
- }
- if (hfunc)
- (*hfunc) = ETH_RSS_HASH_TOP;
- return 0;
- }
- static int lan743x_ethtool_set_rxfh(struct net_device *netdev,
- const u32 *indir, const u8 *key,
- const u8 hfunc)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
- return -EOPNOTSUPP;
- if (indir) {
- u32 indir_value = 0;
- int dword_index = 0;
- int byte_index = 0;
- for (dword_index = 0; dword_index < 32; dword_index++) {
- byte_index = dword_index << 2;
- indir_value =
- (((indir[byte_index + 0] & 0x000000FF) << 0) |
- ((indir[byte_index + 1] & 0x000000FF) << 8) |
- ((indir[byte_index + 2] & 0x000000FF) << 16) |
- ((indir[byte_index + 3] & 0x000000FF) << 24));
- lan743x_csr_write(adapter, RFE_INDX(dword_index),
- indir_value);
- }
- }
- if (key) {
- int dword_index = 0;
- int byte_index = 0;
- u32 key_value = 0;
- for (dword_index = 0; dword_index < 10; dword_index++) {
- byte_index = dword_index << 2;
- key_value =
- ((((u32)(key[byte_index + 0])) << 0) |
- (((u32)(key[byte_index + 1])) << 8) |
- (((u32)(key[byte_index + 2])) << 16) |
- (((u32)(key[byte_index + 3])) << 24));
- lan743x_csr_write(adapter, RFE_HASH_KEY(dword_index),
- key_value);
- }
- }
- return 0;
- }
- static int lan743x_ethtool_get_ts_info(struct net_device *netdev,
- struct ethtool_ts_info *ts_info)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
- SOF_TIMESTAMPING_RX_SOFTWARE |
- SOF_TIMESTAMPING_SOFTWARE |
- SOF_TIMESTAMPING_TX_HARDWARE |
- SOF_TIMESTAMPING_RX_HARDWARE |
- SOF_TIMESTAMPING_RAW_HARDWARE;
- if (adapter->ptp.ptp_clock)
- ts_info->phc_index = ptp_clock_index(adapter->ptp.ptp_clock);
- else
- ts_info->phc_index = -1;
- ts_info->tx_types = BIT(HWTSTAMP_TX_OFF) |
- BIT(HWTSTAMP_TX_ON) |
- BIT(HWTSTAMP_TX_ONESTEP_SYNC);
- ts_info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
- BIT(HWTSTAMP_FILTER_ALL);
- return 0;
- }
- static int lan743x_ethtool_get_eee(struct net_device *netdev,
- struct ethtool_eee *eee)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- struct phy_device *phydev = netdev->phydev;
- u32 buf;
- int ret;
- if (!phydev)
- return -EIO;
- if (!phydev->drv) {
- netif_err(adapter, drv, adapter->netdev,
- "Missing PHY Driver\n");
- return -EIO;
- }
- ret = phy_ethtool_get_eee(phydev, eee);
- if (ret < 0)
- return ret;
- buf = lan743x_csr_read(adapter, MAC_CR);
- if (buf & MAC_CR_EEE_EN_) {
- eee->eee_enabled = true;
- eee->eee_active = !!(eee->advertised & eee->lp_advertised);
- eee->tx_lpi_enabled = true;
- /* EEE_TX_LPI_REQ_DLY & tx_lpi_timer are same uSec unit */
- buf = lan743x_csr_read(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT);
- eee->tx_lpi_timer = buf;
- } else {
- eee->eee_enabled = false;
- eee->eee_active = false;
- eee->tx_lpi_enabled = false;
- eee->tx_lpi_timer = 0;
- }
- return 0;
- }
- static int lan743x_ethtool_set_eee(struct net_device *netdev,
- struct ethtool_eee *eee)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- struct phy_device *phydev = NULL;
- u32 buf = 0;
- int ret = 0;
- if (!netdev)
- return -EINVAL;
- adapter = netdev_priv(netdev);
- if (!adapter)
- return -EINVAL;
- phydev = netdev->phydev;
- if (!phydev)
- return -EIO;
- if (!phydev->drv) {
- netif_err(adapter, drv, adapter->netdev,
- "Missing PHY Driver\n");
- return -EIO;
- }
- if (eee->eee_enabled) {
- ret = phy_init_eee(phydev, 0);
- if (ret) {
- netif_err(adapter, drv, adapter->netdev,
- "EEE initialization failed\n");
- return ret;
- }
- buf = (u32)eee->tx_lpi_timer;
- lan743x_csr_write(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT, buf);
- buf = lan743x_csr_read(adapter, MAC_CR);
- buf |= MAC_CR_EEE_EN_;
- lan743x_csr_write(adapter, MAC_CR, buf);
- } else {
- buf = lan743x_csr_read(adapter, MAC_CR);
- buf &= ~MAC_CR_EEE_EN_;
- lan743x_csr_write(adapter, MAC_CR, buf);
- }
- return phy_ethtool_set_eee(phydev, eee);
- }
- #ifdef CONFIG_PM
- static void lan743x_ethtool_get_wol(struct net_device *netdev,
- struct ethtool_wolinfo *wol)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- wol->supported = 0;
- wol->wolopts = 0;
- if (netdev->phydev)
- phy_ethtool_get_wol(netdev->phydev, wol);
- wol->supported |= WAKE_BCAST | WAKE_UCAST | WAKE_MCAST |
- WAKE_MAGIC | WAKE_PHY | WAKE_ARP;
- wol->wolopts |= adapter->wolopts;
- }
- static int lan743x_ethtool_set_wol(struct net_device *netdev,
- struct ethtool_wolinfo *wol)
- {
- struct lan743x_adapter *adapter = netdev_priv(netdev);
- adapter->wolopts = 0;
- if (wol->wolopts & WAKE_UCAST)
- adapter->wolopts |= WAKE_UCAST;
- if (wol->wolopts & WAKE_MCAST)
- adapter->wolopts |= WAKE_MCAST;
- if (wol->wolopts & WAKE_BCAST)
- adapter->wolopts |= WAKE_BCAST;
- if (wol->wolopts & WAKE_MAGIC)
- adapter->wolopts |= WAKE_MAGIC;
- if (wol->wolopts & WAKE_PHY)
- adapter->wolopts |= WAKE_PHY;
- if (wol->wolopts & WAKE_ARP)
- adapter->wolopts |= WAKE_ARP;
- device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts);
- return netdev->phydev ? phy_ethtool_set_wol(netdev->phydev, wol)
- : -ENETDOWN;
- }
- #endif /* CONFIG_PM */
- const struct ethtool_ops lan743x_ethtool_ops = {
- .get_drvinfo = lan743x_ethtool_get_drvinfo,
- .get_msglevel = lan743x_ethtool_get_msglevel,
- .set_msglevel = lan743x_ethtool_set_msglevel,
- .get_link = ethtool_op_get_link,
- .get_eeprom_len = lan743x_ethtool_get_eeprom_len,
- .get_eeprom = lan743x_ethtool_get_eeprom,
- .set_eeprom = lan743x_ethtool_set_eeprom,
- .get_strings = lan743x_ethtool_get_strings,
- .get_ethtool_stats = lan743x_ethtool_get_ethtool_stats,
- .get_priv_flags = lan743x_ethtool_get_priv_flags,
- .set_priv_flags = lan743x_ethtool_set_priv_flags,
- .get_sset_count = lan743x_ethtool_get_sset_count,
- .get_rxnfc = lan743x_ethtool_get_rxnfc,
- .get_rxfh_key_size = lan743x_ethtool_get_rxfh_key_size,
- .get_rxfh_indir_size = lan743x_ethtool_get_rxfh_indir_size,
- .get_rxfh = lan743x_ethtool_get_rxfh,
- .set_rxfh = lan743x_ethtool_set_rxfh,
- .get_ts_info = lan743x_ethtool_get_ts_info,
- .get_eee = lan743x_ethtool_get_eee,
- .set_eee = lan743x_ethtool_set_eee,
- .get_link_ksettings = phy_ethtool_get_link_ksettings,
- .set_link_ksettings = phy_ethtool_set_link_ksettings,
- #ifdef CONFIG_PM
- .get_wol = lan743x_ethtool_get_wol,
- .set_wol = lan743x_ethtool_set_wol,
- #endif
- };
|