On Tue, Feb 13, 2018 at 06:26:48PM -0500, Bryan Whitehead wrote:
> Add main source files for new lan743x driver
> 
> Signed-off-by: Bryan Whitehead <bryan.whiteh...@microchip.com>
> ---
>  drivers/net/ethernet/microchip/lan743x_main.c | 2964 
> +++++++++++++++++++++++++
>  drivers/net/ethernet/microchip/lan743x_main.h | 1331 +++++++++++
>  2 files changed, 4295 insertions(+)
>  create mode 100644 drivers/net/ethernet/microchip/lan743x_main.c
>  create mode 100644 drivers/net/ethernet/microchip/lan743x_main.h
> 
> diff --git a/drivers/net/ethernet/microchip/lan743x_main.c 
> b/drivers/net/ethernet/microchip/lan743x_main.c
> new file mode 100644
> index 0000000..6cfb439
> --- /dev/null
> +++ b/drivers/net/ethernet/microchip/lan743x_main.c
> @@ -0,0 +1,2964 @@
> +/*
> + * Copyright (C) 2018 Microchip Technology
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "lan743x_main.h"
> +
> +#define LAN743X_COMPONENT_FLAG_PCI          BIT(0)
> +#define LAN743X_COMPONENT_FLAG_CSR          BIT(1)
> +#define LAN743X_COMPONENT_FLAG_INTR         BIT(2)
> +#define LAN743X_COMPONENT_FLAG_DP           BIT(3)
> +#define LAN743X_COMPONENT_FLAG_MAC          BIT(4)
> +#define LAN743X_COMPONENT_FLAG_PHY          BIT(5)
> +#define LAN743X_COMPONENT_FLAG_RFE          BIT(6)
> +#define LAN743X_COMPONENT_FLAG_FCT          BIT(7)
> +#define LAN743X_COMPONENT_FLAG_TX(channel)  BIT(16 + (channel))
> +#define LAN743X_COMPONENT_FLAG_RX(channel)  BIT(20 + (channel))
> +
> +#define LAN743X_INIT_FLAG_NETDEV_REGISTERED  BIT(24)
> +#define LAN743X_INIT_FLAG_MDIOBUS_ALLOCATED  BIT(25)
> +#define LAN743X_INIT_FLAG_MDIOBUS_REGISTERED BIT(26)

Hi Bryan

It seems odd to have some defines in lan743x_main.h and some inline.
It is probably better to have them all in one place.

> +static int lan743x_csr_light_reset(struct lan743x_adapter *adapter)
> +{
> +     unsigned long timeout;
> +     u32 data;
> +
> +     data = lan743x_csr_read(adapter, HW_CFG);
> +     data |= HW_CFG_LRST_;
> +     lan743x_csr_write(adapter, HW_CFG, data);
> +     timeout = jiffies + (10 * HZ);
> +     do {
> +             if (time_after(jiffies, timeout))
> +                     return -EIO;
> +             msleep(100);
> +             data = lan743x_csr_read(adapter, HW_CFG);
> +     } while (data & HW_CFG_LRST_);

You could probably use readx_poll_timeout() here.

> +
> +     return 0;
> +}
> +
> +static int lan743x_csr_wait_for_bit(struct lan743x_adapter *adapter,
> +                                 int offset, u32 bit_mask,
> +                                 int target_value, int usleep_min,
> +                                 int usleep_max, int count)
> +{
> +     int timeout = count;
> +     int current_value;
> +     int ret = -EIO;
> +
> +     while (timeout) {
> +             current_value = (lan743x_csr_read(adapter, offset) & bit_mask)
> +                             ? 1 : 0;
> +             if (target_value == current_value) {
> +                     ret = 0;
> +                     break;
> +             }
> +             usleep_range(usleep_min, usleep_max);
> +             timeout--;
> +     }

And here as well.

> +     return ret;
> +}
> +
> +static int lan743x_csr_init(struct lan743x_adapter *adapter)
> +{
> +     struct lan743x_csr *csr = &adapter->csr;
> +     resource_size_t bar_start, bar_length;
> +     int result;
> +
> +     bar_start = pci_resource_start(adapter->pci.pdev, 0);
> +     bar_length = pci_resource_len(adapter->pci.pdev, 0);
> +     csr->csr_address = ioremap(bar_start, bar_length);

devm_ioremap() will make your cleanup code simpler.

> +     if (!csr->csr_address) {
> +             result = -ENOMEM;
> +             goto clean_up;
> +     }
> +
> +     csr->id_rev = lan743x_csr_read(adapter, ID_REV);
> +     csr->fpga_rev = lan743x_csr_read(adapter, FPGA_REV);
> +     netif_info(adapter, probe, adapter->netdev,
> +                "ID_REV = 0x%08X, FPGA_REV = %d.%d\n",
> +                csr->id_rev, (csr->fpga_rev) & 0x000000FF,
> +                ((csr->fpga_rev) >> 8) & 0x000000FF);
> +     if ((csr->id_rev & 0xFFF00000) != 0x74300000) {
> +             result = -ENODEV;
> +             goto clean_up;
> +     }

You have:

define ID_REV_CHIP_ID_MASK_                 (0xFFFF0000)
#define ID_REV_CHIP_ID_7430_                 (0x7430)
#define ID_REV_CHIP_REV_MASK_                        (0x0000FFFF)
#define ID_REV_CHIP_REV_A0_                  (0x00000000)
#define ID_REV_CHIP_REV_B0_                  (0x00000010)

#define FPGA_REV                                (0x04)      
#define FPGA_REV_MINOR_MASK_                    (0x0000FF00)
#define FPGA_REV_MAJOR_MASK_                    (0x000000FF)

Why not use them.

> +     csr->flags = LAN743X_CSR_FLAG_SUPPORTS_INTR_AUTO_SET_CLR;
> +     switch (csr->id_rev & ID_REV_CHIP_REV_MASK_) {
> +     case ID_REV_CHIP_REV_A0_:
> +             csr->flags |= LAN743X_CSR_FLAG_IS_A0;
> +             csr->flags &= ~LAN743X_CSR_FLAG_SUPPORTS_INTR_AUTO_SET_CLR;
> +             break;
> +     case ID_REV_CHIP_REV_B0_:
> +             csr->flags |= LAN743X_CSR_FLAG_IS_B0;
> +             break;
> +     }
> +
> +     result = lan743x_csr_light_reset(adapter);
> +     if (result)
> +             goto clean_up;
> +     return 0;
> +clean_up:
> +     if (csr->csr_address)
> +             iounmap(csr->csr_address);
> +     return result;
> +}

> +static int lan743x_intr_register_isr(struct lan743x_adapter *adapter,
> +                                  int vector_index, u32 flags,
> +                                  u32 int_mask,
> +                                  lan743x_vector_handler handler,
> +                                  void *context)
> +{
> +     struct lan743x_vector *vector = &adapter->intr.vector_list
> +                                     [vector_index];
> +     int ret;
> +
> +     vector->adapter = adapter;
> +     vector->flags = flags;
> +     vector->vector_index = vector_index;
> +     vector->int_mask = int_mask;
> +     vector->handler = handler;
> +     vector->context = context;
> +     ret = request_irq(vector->irq,
> +                       lan743x_intr_entry_isr,
> +                       (flags & LAN743X_VECTOR_FLAG_IRQ_SHARED) ?
> +                       IRQF_SHARED : 0,
> +                       DRIVER_NAME,
> +                       vector);

devm_request_irq()?

> +static int lan743x_intr_open(struct lan743x_adapter *adapter)
> +{
> +#if LAN743X_TRY_MSIX
> +     struct msix_entry msix_entries[LAN743X_MAX_VECTOR_COUNT];
> +#endif
> +     struct lan743x_intr *intr = &adapter->intr;
> +     u32 int_vec_en_auto_clr = 0;
> +     u32 int_vec_map0 = 0;
> +     u32 int_vec_map1 = 0;
> +     int ret = -ENODEV;
> +     int index = 0;
> +     u32 flags = 0;
> +
> +     intr->number_of_vectors = 0;
> +#if LAN743X_TRY_MSIX

It is better to use

        if (IS_ENABLED(CONFIG_LAN743X_TRY_MSIX)) {

The compiler will then detect problems in the code, even when it is
disabled, and still optimize it out. In general, we don't like #ifdefs.

> +     memset(&msix_entries[0], 0,
> +            sizeof(struct msix_entry) * LAN743X_MAX_VECTOR_COUNT);
> +     for (index = 0; index < LAN743X_MAX_VECTOR_COUNT; index++)
> +             msix_entries[index].entry = index;
> +     ret = pci_enable_msix_range(adapter->pci.pdev,
> +                                 msix_entries, 1,
> +                                 1 + LAN743X_USED_TX_CHANNELS +
> +                                 LAN743X_USED_RX_CHANNELS);
> +     if (ret > 0) {
> +             intr->flags |= INTR_FLAG_MSIX_ENABLED;
> +             intr->number_of_vectors = ret;
> +             intr->using_vectors = true;
> +             for (index = 0; index < intr->number_of_vectors; index++)
> +                     intr->vector_list[index].irq = msix_entries
> +                                                    [index].vector;
> +             netif_info(adapter, ifup, adapter->netdev,
> +                        "using MSIX interrupts, number of vectors = %d\n",
> +                        intr->number_of_vectors);
> +     }
> +#endif
> +#if LAN743X_TRY_MSI
> +     if (!intr->number_of_vectors) {
> +             if (!(adapter->csr.flags & LAN743X_CSR_FLAG_IS_A0)) {
> +                     if (!pci_enable_msi(adapter->pci.pdev)) {
> +                             intr->flags |= INTR_FLAG_MSI_ENABLED;
> +                             intr->number_of_vectors = 1;
> +                             intr->using_vectors = true;
> +                             intr->vector_list[0].irq =
> +                                     adapter->pci.pdev->irq;
> +                             netif_info(adapter, ifup, adapter->netdev,
> +                                        "using MSI interrupts, number of 
> vectors = %d\n",
> +                                        intr->number_of_vectors);
> +                     }
> +             }
> +     }
> +#endif

> +static int lan743x_mac_mii_wait_till_not_busy(struct lan743x_adapter 
> *adapter)
> +{
> +     unsigned long start_time = jiffies;
> +     u32 data;
> +
> +     do {
> +             data = lan743x_csr_read(adapter, MAC_MII_ACC);
> +             if (!(data & MAC_MII_ACC_MII_BUSY_))
> +                     return 0;
> +     } while (!time_after(jiffies, start_time + HZ));

Another possible use of readx_poll_timeout.

> +static void lan743x_mac_set_address(struct lan743x_adapter *adapter,
> +                                 u8 *addr)
> +{
> +     u32 addr_lo, addr_hi;
> +
> +     addr_lo = addr[0] |
> +             addr[1] << 8 |
> +             addr[2] << 16 |
> +             addr[3] << 24;
> +     addr_hi = addr[4] |
> +             addr[5] << 8;
> +     lan743x_csr_write(adapter, MAC_RX_ADDRL, addr_lo);
> +     lan743x_csr_write(adapter, MAC_RX_ADDRH, addr_hi);
> +     ether_addr_copy(adapter->mac.mac_address, addr);
> +     netif_info(adapter, drv, adapter->netdev,
> +                "MAC address set to %02X:%02X:%02X:%02X:%02X:%02X\n",

%pM ?

> +                addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
> +}
> +
> +static int lan743x_mac_init(struct lan743x_adapter *adapter)
> +{
> +     struct lan743x_mac *mac = &adapter->mac;
> +     bool mac_address_valid = true;
> +     struct net_device *netdev;
> +     u32 mac_addr_hi = 0;
> +     u32 mac_addr_lo = 0;
> +     u32 data;
> +     int ret;
> +
> +     netdev = adapter->netdev;
> +     lan743x_csr_write(adapter, MAC_CR, MAC_CR_RST_);
> +     ret = lan743x_csr_wait_for_bit(adapter, MAC_CR, MAC_CR_RST_,
> +                                    0, 1000, 20000, 100);
> +     if (ret)
> +             return ret;
> +
> +     /* setup auto duplex, and speed detection */
> +     data = lan743x_csr_read(adapter, MAC_CR);
> +     data |= MAC_CR_ADD_ | MAC_CR_ASD_;
> +     data |= MAC_CR_CNTR_RST_;
> +     lan743x_csr_write(adapter, MAC_CR, data);
> +     mac_addr_hi = lan743x_csr_read(adapter, MAC_RX_ADDRH);
> +     mac_addr_lo = lan743x_csr_read(adapter, MAC_RX_ADDRL);
> +     mac->mac_address[0] = mac_addr_lo & 0xFF;
> +     mac->mac_address[1] = (mac_addr_lo >> 8) & 0xFF;
> +     mac->mac_address[2] = (mac_addr_lo >> 16) & 0xFF;
> +     mac->mac_address[3] = (mac_addr_lo >> 24) & 0xFF;
> +     mac->mac_address[4] = mac_addr_hi & 0xFF;
> +     mac->mac_address[5] = (mac_addr_hi >> 8) & 0xFF;
> +     if (((mac_addr_hi & 0x0000FFFF) == 0x0000FFFF) &&
> +         mac_addr_lo == 0xFFFFFFFF) {
> +             mac_address_valid = false;
> +     } else if (!is_valid_ether_addr(mac->mac_address)) {
> +             mac_address_valid = false;
> +     }
> +     if (!mac_address_valid)
> +             random_ether_addr(mac->mac_address);
> +     lan743x_mac_set_address(adapter, mac->mac_address);
> +     netif_info(adapter, probe, adapter->netdev,
> +                "MAC Address = %02X:%02X:%02X:%02X:%02X:%02X\n",
> +                mac->mac_address[0], mac->mac_address[1],
> +                mac->mac_address[2], mac->mac_address[3],
> +                mac->mac_address[4], mac->mac_address[5]);

lan743x_mac_set_address() prints it. Why print it again?

> +     ether_addr_copy(netdev->dev_addr, mac->mac_address);
> +     return 0;
> +}
> +

> +
> +/* PHY */
> +#define PHY_FLAG_OPENED     BIT(0)
> +#define PHY_FLAG_ATTACHED   BIT(1)
> +static int lan743x_phy_reset(struct lan743x_adapter *adapter)
> +{
> +     unsigned long timeout;
> +     u32 data;
> +
> +     data = lan743x_csr_read(adapter, PMT_CTL);
> +     data |= PMT_CTL_ETH_PHY_RST_;
> +     lan743x_csr_write(adapter, PMT_CTL, data);
> +     timeout = jiffies + HZ;
> +     do {
> +             if (time_after(jiffies, timeout))
> +                     return -EIO;
> +             msleep(50);
> +             data = lan743x_csr_read(adapter, PMT_CTL);
> +     } while ((data & PMT_CTL_ETH_PHY_RST_) || !(data & PMT_CTL_READY_));

readx_poll_timeout()

> +     return 0;
> +}
> +

> +static void lan743x_phy_link_status_change(struct net_device *netdev)
> +{
> +     struct lan743x_adapter *adapter = netdev_priv(netdev);
> +     struct phy_device *phydev = netdev->phydev;
> +
> +     if (phydev) {
> +             if (phydev->state == PHY_RUNNING) {
> +                     struct ethtool_link_ksettings ksettings;
> +                     struct lan743x_phy *phy = NULL;
> +                     int remote_advertisement = 0;
> +                     int local_advertisement = 0;
> +
> +                     phy = &adapter->phy;
> +                     memset(&ksettings, 0, sizeof(ksettings));
> +                     phy_ethtool_get_link_ksettings(netdev, &ksettings);
> +                     local_advertisement = phy_read(phydev, MII_ADVERTISE);
> +                     if (local_advertisement < 0)
> +                             goto done;

A bit unusual to use a goto here, since this is not error handling, or
dealing with a mutex. Maybe just return;

> +                     remote_advertisement = phy_read(phydev, MII_LPA);
> +                     if (remote_advertisement < 0)
> +                             goto done;
> +                     netif_info(adapter, link, adapter->netdev,
> +                                "link UP: speed: %u duplex: %d anadv: 0x%04x 
> anlpa: 0x%04x\n",
> +                                ksettings.base.speed, ksettings.base.duplex,
> +                                local_advertisement, remote_advertisement);

phy_print_status()

> +                     lan743x_phy_update_flowcontrol(adapter,
> +                                                    ksettings.base.duplex,
> +                                                    local_advertisement,
> +                                                    remote_advertisement);
> +             } else if (phydev->state == PHY_NOLINK) {
> +                     netif_info(adapter, link, adapter->netdev,
> +                                "link DOWN\n");

Here too.

> +             }
> +     }
> +done:
> +     return;
> +}
> +

> +static int lan743x_phy_open(struct lan743x_adapter *adapter)
> +{
> +     struct lan743x_phy *phy = &adapter->phy;
> +     struct phy_device *phydev;
> +     struct net_device *netdev;
> +     int ret = -EIO;
> +     u32 mii_adv;
> +
> +     netdev = adapter->netdev;
> +     phydev = phy_find_first(adapter->mdiobus);
> +     if (!phydev) {
> +             ret = -EIO;
> +             goto clean_up;
> +     }
> +     ret = phy_connect_direct(netdev, phydev,
> +                              lan743x_phy_link_status_change,
> +                              PHY_INTERFACE_MODE_GMII);
> +     if (ret) {
> +             ret = -EIO;

Why change the error code phy_connect_direct() returned?

> +             goto clean_up;
> +     }
> +     phy->flags |= PHY_FLAG_ATTACHED;
> +
> +     /* MAC doesn't support 1000T Half */
> +     phydev->supported &= ~SUPPORTED_1000baseT_Half;
> +     /* support both flow controls */
> +     phy->fc_request_control = (FLOW_CTRL_RX | FLOW_CTRL_TX);
> +     phydev->advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause);
> +     mii_adv = (u32)mii_advertise_flowctrl(phy->fc_request_control);
> +     phydev->advertising |= mii_adv_to_ethtool_adv_t(mii_adv);
> +     phy->fc_autoneg = phydev->autoneg;
> +
> +     /* PHY interrupt enabled here */
> +     phy_start(phydev);
> +     phy_start_aneg(phydev);
> +     phy->flags |= PHY_FLAG_OPENED;
> +     return 0;
> +clean_up:
> +     lan743x_phy_close(adapter);
> +     return ret;
> +}
> +

> +static int lan743x_mdiobus_init(struct lan743x_adapter *adapter)
> +{
> +     int ret;
> +
> +     adapter->mdiobus = mdiobus_alloc();

devm_mdiobus_alloc() ?

> +     if (!(adapter->mdiobus)) {
> +             ret = -ENOMEM;
> +             goto clean_up;
> +     }
> +     adapter->init_flags |= LAN743X_INIT_FLAG_MDIOBUS_ALLOCATED;
> +     adapter->mdiobus->priv = (void *)adapter;
> +     adapter->mdiobus->read = lan743x_mdiobus_read;
> +     adapter->mdiobus->write = lan743x_mdiobus_write;
> +     adapter->mdiobus->name = "lan743x-mdiobus";
> +     snprintf(adapter->mdiobus->id, MII_BUS_ID_SIZE,
> +              "pci-%s", pci_name(adapter->pci.pdev));
> +
> +     /* set to internal PHY id */
> +     adapter->mdiobus->phy_mask = ~(int)BIT(1);

phy_mask is a u32.

> +
> +     /* register mdiobus */
> +     ret = mdiobus_register(adapter->mdiobus);
> +     if (ret < 0)
> +             goto clean_up;
> +     adapter->init_flags |= LAN743X_INIT_FLAG_MDIOBUS_REGISTERED;
> +     return 0;
> +clean_up:
> +     if (adapter->mdiobus)
> +             mdiobus_free(adapter->mdiobus);
> +     adapter->init_flags &= ~(LAN743X_INIT_FLAG_MDIOBUS_REGISTERED |
> +                              LAN743X_INIT_FLAG_MDIOBUS_ALLOCATED);
> +     return ret;
> +}
> +
> +/* lan743x_pcidev_probe - Device Initialization Routine
> + * @pdev: PCI device information struct
> + * @id: entry in lan743x_pci_tbl
> + *
> + * Returns 0 on success, negative on failure
> + *
> + * initializes an adapter identified by a pci_dev structure.
> + * The OS initialization, configuring of the adapter private structure,
> + * and a hardware reset occur.
> + **/
> +static int lan743x_pcidev_probe(struct pci_dev *pdev,
> +                             const struct pci_device_id *id)
> +{
> +     struct lan743x_adapter *adapter = NULL;
> +     struct net_device *netdev = NULL;
> +     int ret = -ENODEV;
> +
> +     netdev = alloc_etherdev(sizeof(struct lan743x_adapter));

devm_alloc_etherdev() ?

> +     if (!netdev)
> +             goto clean_up;
> +     SET_NETDEV_DEV(netdev, &pdev->dev);
> +     pci_set_drvdata(pdev, netdev);
> +     adapter = netdev_priv(netdev);
> +     adapter->netdev = netdev;
> +     adapter->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE |
> +                           NETIF_MSG_LINK | NETIF_MSG_IFUP |
> +                           NETIF_MSG_IFDOWN | NETIF_MSG_TX_QUEUED;
> +     netdev->max_mtu = LAN743X_MAX_FRAME_SIZE;
> +     ret = lan743x_pci_init(adapter, pdev);
> +     if (ret)
> +             goto clean_up;
> +     adapter->init_flags |= LAN743X_COMPONENT_FLAG_PCI;
> +     ret = lan743x_csr_init(adapter);
> +     if (ret)
> +             goto clean_up;
> +     adapter->init_flags |= LAN743X_COMPONENT_FLAG_CSR;
> +     ret = lan743x_hardware_init(adapter, pdev);
> +     if (ret)
> +             goto clean_up;
> +     ret = lan743x_mdiobus_init(adapter);
> +     if (ret)
> +             goto clean_up;
> +     adapter->netdev->netdev_ops = &lan743x_netdev_ops;
> +     adapter->netdev->features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_CSUM;
> +     adapter->netdev->hw_features = adapter->netdev->features;
> +     ret = register_netdev(adapter->netdev);
> +     if (ret < 0)
> +             goto clean_up;
> +     adapter->init_flags |= LAN743X_INIT_FLAG_NETDEV_REGISTERED;
> +     netif_info(adapter, probe, adapter->netdev, "Probe succeeded\n");
> +     return 0;
> +
> +clean_up:
> +     if (adapter) {
> +             netif_warn(adapter, probe, adapter->netdev,
> +                        "Incomplete initialization, performing clean up\n");
> +             lan743x_full_cleanup(adapter);
> +     }
> +     return ret;
> +}

> +++ b/drivers/net/ethernet/microchip/lan743x_main.h

> +u32 lan743x_csr_read(struct lan743x_adapter *adapter, int offset);
> +void lan743x_csr_write(struct lan743x_adapter *adapter, int offset, u32 
> data);

Why are these needed?

> +
> +/* INTERRUPTS */
> +typedef void(*lan743x_vector_handler)(void *context, u32 int_sts, u32 flags);

And this.

    Andrew 

Reply via email to