Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/kernel.h>
0003 #include <linux/types.h>
0004 #include <linux/module.h>
0005 #include <linux/list.h>
0006 #include <linux/pci.h>
0007 #include <linux/dma-mapping.h>
0008 #include <linux/pagemap.h>
0009 #include <linux/sched.h>
0010 #include <linux/dmapool.h>
0011 #include <linux/mempool.h>
0012 #include <linux/spinlock.h>
0013 #include <linux/kthread.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/errno.h>
0016 #include <linux/ioport.h>
0017 #include <linux/in.h>
0018 #include <linux/ip.h>
0019 #include <linux/ipv6.h>
0020 #include <net/ipv6.h>
0021 #include <linux/tcp.h>
0022 #include <linux/udp.h>
0023 #include <linux/if_arp.h>
0024 #include <linux/if_ether.h>
0025 #include <linux/netdevice.h>
0026 #include <linux/etherdevice.h>
0027 #include <linux/ethtool.h>
0028 #include <linux/skbuff.h>
0029 #include <linux/rtnetlink.h>
0030 #include <linux/if_vlan.h>
0031 #include <linux/delay.h>
0032 #include <linux/mm.h>
0033 #include <linux/vmalloc.h>
0034 
0035 #include "qlge.h"
0036 
0037 struct qlge_stats {
0038     char stat_string[ETH_GSTRING_LEN];
0039     int sizeof_stat;
0040     int stat_offset;
0041 };
0042 
0043 #define QL_SIZEOF(m) sizeof_field(struct qlge_adapter, m)
0044 #define QL_OFF(m) offsetof(struct qlge_adapter, m)
0045 
0046 static const struct qlge_stats qlge_gstrings_stats[] = {
0047     {"tx_pkts", QL_SIZEOF(nic_stats.tx_pkts), QL_OFF(nic_stats.tx_pkts)},
0048     {"tx_bytes", QL_SIZEOF(nic_stats.tx_bytes), QL_OFF(nic_stats.tx_bytes)},
0049     {"tx_mcast_pkts", QL_SIZEOF(nic_stats.tx_mcast_pkts),
0050                     QL_OFF(nic_stats.tx_mcast_pkts)},
0051     {"tx_bcast_pkts", QL_SIZEOF(nic_stats.tx_bcast_pkts),
0052                     QL_OFF(nic_stats.tx_bcast_pkts)},
0053     {"tx_ucast_pkts", QL_SIZEOF(nic_stats.tx_ucast_pkts),
0054                     QL_OFF(nic_stats.tx_ucast_pkts)},
0055     {"tx_ctl_pkts", QL_SIZEOF(nic_stats.tx_ctl_pkts),
0056                     QL_OFF(nic_stats.tx_ctl_pkts)},
0057     {"tx_pause_pkts", QL_SIZEOF(nic_stats.tx_pause_pkts),
0058                     QL_OFF(nic_stats.tx_pause_pkts)},
0059     {"tx_64_pkts", QL_SIZEOF(nic_stats.tx_64_pkt),
0060                     QL_OFF(nic_stats.tx_64_pkt)},
0061     {"tx_65_to_127_pkts", QL_SIZEOF(nic_stats.tx_65_to_127_pkt),
0062                     QL_OFF(nic_stats.tx_65_to_127_pkt)},
0063     {"tx_128_to_255_pkts", QL_SIZEOF(nic_stats.tx_128_to_255_pkt),
0064                     QL_OFF(nic_stats.tx_128_to_255_pkt)},
0065     {"tx_256_511_pkts", QL_SIZEOF(nic_stats.tx_256_511_pkt),
0066                     QL_OFF(nic_stats.tx_256_511_pkt)},
0067     {"tx_512_to_1023_pkts", QL_SIZEOF(nic_stats.tx_512_to_1023_pkt),
0068                     QL_OFF(nic_stats.tx_512_to_1023_pkt)},
0069     {"tx_1024_to_1518_pkts", QL_SIZEOF(nic_stats.tx_1024_to_1518_pkt),
0070                     QL_OFF(nic_stats.tx_1024_to_1518_pkt)},
0071     {"tx_1519_to_max_pkts", QL_SIZEOF(nic_stats.tx_1519_to_max_pkt),
0072                     QL_OFF(nic_stats.tx_1519_to_max_pkt)},
0073     {"tx_undersize_pkts", QL_SIZEOF(nic_stats.tx_undersize_pkt),
0074                     QL_OFF(nic_stats.tx_undersize_pkt)},
0075     {"tx_oversize_pkts", QL_SIZEOF(nic_stats.tx_oversize_pkt),
0076                     QL_OFF(nic_stats.tx_oversize_pkt)},
0077     {"rx_bytes", QL_SIZEOF(nic_stats.rx_bytes), QL_OFF(nic_stats.rx_bytes)},
0078     {"rx_bytes_ok", QL_SIZEOF(nic_stats.rx_bytes_ok),
0079                     QL_OFF(nic_stats.rx_bytes_ok)},
0080     {"rx_pkts", QL_SIZEOF(nic_stats.rx_pkts), QL_OFF(nic_stats.rx_pkts)},
0081     {"rx_pkts_ok", QL_SIZEOF(nic_stats.rx_pkts_ok),
0082                     QL_OFF(nic_stats.rx_pkts_ok)},
0083     {"rx_bcast_pkts", QL_SIZEOF(nic_stats.rx_bcast_pkts),
0084                     QL_OFF(nic_stats.rx_bcast_pkts)},
0085     {"rx_mcast_pkts", QL_SIZEOF(nic_stats.rx_mcast_pkts),
0086                     QL_OFF(nic_stats.rx_mcast_pkts)},
0087     {"rx_ucast_pkts", QL_SIZEOF(nic_stats.rx_ucast_pkts),
0088                     QL_OFF(nic_stats.rx_ucast_pkts)},
0089     {"rx_undersize_pkts", QL_SIZEOF(nic_stats.rx_undersize_pkts),
0090                     QL_OFF(nic_stats.rx_undersize_pkts)},
0091     {"rx_oversize_pkts", QL_SIZEOF(nic_stats.rx_oversize_pkts),
0092                     QL_OFF(nic_stats.rx_oversize_pkts)},
0093     {"rx_jabber_pkts", QL_SIZEOF(nic_stats.rx_jabber_pkts),
0094                     QL_OFF(nic_stats.rx_jabber_pkts)},
0095     {"rx_undersize_fcerr_pkts",
0096         QL_SIZEOF(nic_stats.rx_undersize_fcerr_pkts),
0097                 QL_OFF(nic_stats.rx_undersize_fcerr_pkts)},
0098     {"rx_drop_events", QL_SIZEOF(nic_stats.rx_drop_events),
0099                     QL_OFF(nic_stats.rx_drop_events)},
0100     {"rx_fcerr_pkts", QL_SIZEOF(nic_stats.rx_fcerr_pkts),
0101                     QL_OFF(nic_stats.rx_fcerr_pkts)},
0102     {"rx_align_err", QL_SIZEOF(nic_stats.rx_align_err),
0103                     QL_OFF(nic_stats.rx_align_err)},
0104     {"rx_symbol_err", QL_SIZEOF(nic_stats.rx_symbol_err),
0105                     QL_OFF(nic_stats.rx_symbol_err)},
0106     {"rx_mac_err", QL_SIZEOF(nic_stats.rx_mac_err),
0107                     QL_OFF(nic_stats.rx_mac_err)},
0108     {"rx_ctl_pkts", QL_SIZEOF(nic_stats.rx_ctl_pkts),
0109                     QL_OFF(nic_stats.rx_ctl_pkts)},
0110     {"rx_pause_pkts", QL_SIZEOF(nic_stats.rx_pause_pkts),
0111                     QL_OFF(nic_stats.rx_pause_pkts)},
0112     {"rx_64_pkts", QL_SIZEOF(nic_stats.rx_64_pkts),
0113                     QL_OFF(nic_stats.rx_64_pkts)},
0114     {"rx_65_to_127_pkts", QL_SIZEOF(nic_stats.rx_65_to_127_pkts),
0115                     QL_OFF(nic_stats.rx_65_to_127_pkts)},
0116     {"rx_128_255_pkts", QL_SIZEOF(nic_stats.rx_128_255_pkts),
0117                     QL_OFF(nic_stats.rx_128_255_pkts)},
0118     {"rx_256_511_pkts", QL_SIZEOF(nic_stats.rx_256_511_pkts),
0119                     QL_OFF(nic_stats.rx_256_511_pkts)},
0120     {"rx_512_to_1023_pkts", QL_SIZEOF(nic_stats.rx_512_to_1023_pkts),
0121                     QL_OFF(nic_stats.rx_512_to_1023_pkts)},
0122     {"rx_1024_to_1518_pkts", QL_SIZEOF(nic_stats.rx_1024_to_1518_pkts),
0123                     QL_OFF(nic_stats.rx_1024_to_1518_pkts)},
0124     {"rx_1519_to_max_pkts", QL_SIZEOF(nic_stats.rx_1519_to_max_pkts),
0125                     QL_OFF(nic_stats.rx_1519_to_max_pkts)},
0126     {"rx_len_err_pkts", QL_SIZEOF(nic_stats.rx_len_err_pkts),
0127                     QL_OFF(nic_stats.rx_len_err_pkts)},
0128     {"rx_code_err", QL_SIZEOF(nic_stats.rx_code_err),
0129                     QL_OFF(nic_stats.rx_code_err)},
0130     {"rx_oversize_err", QL_SIZEOF(nic_stats.rx_oversize_err),
0131                     QL_OFF(nic_stats.rx_oversize_err)},
0132     {"rx_undersize_err", QL_SIZEOF(nic_stats.rx_undersize_err),
0133                     QL_OFF(nic_stats.rx_undersize_err)},
0134     {"rx_preamble_err", QL_SIZEOF(nic_stats.rx_preamble_err),
0135                     QL_OFF(nic_stats.rx_preamble_err)},
0136     {"rx_frame_len_err", QL_SIZEOF(nic_stats.rx_frame_len_err),
0137                     QL_OFF(nic_stats.rx_frame_len_err)},
0138     {"rx_crc_err", QL_SIZEOF(nic_stats.rx_crc_err),
0139                     QL_OFF(nic_stats.rx_crc_err)},
0140     {"rx_err_count", QL_SIZEOF(nic_stats.rx_err_count),
0141                     QL_OFF(nic_stats.rx_err_count)},
0142     {"tx_cbfc_pause_frames0", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames0),
0143                 QL_OFF(nic_stats.tx_cbfc_pause_frames0)},
0144     {"tx_cbfc_pause_frames1", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames1),
0145                 QL_OFF(nic_stats.tx_cbfc_pause_frames1)},
0146     {"tx_cbfc_pause_frames2", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames2),
0147                 QL_OFF(nic_stats.tx_cbfc_pause_frames2)},
0148     {"tx_cbfc_pause_frames3", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames3),
0149                 QL_OFF(nic_stats.tx_cbfc_pause_frames3)},
0150     {"tx_cbfc_pause_frames4", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames4),
0151                 QL_OFF(nic_stats.tx_cbfc_pause_frames4)},
0152     {"tx_cbfc_pause_frames5", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames5),
0153                 QL_OFF(nic_stats.tx_cbfc_pause_frames5)},
0154     {"tx_cbfc_pause_frames6", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames6),
0155                 QL_OFF(nic_stats.tx_cbfc_pause_frames6)},
0156     {"tx_cbfc_pause_frames7", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames7),
0157                 QL_OFF(nic_stats.tx_cbfc_pause_frames7)},
0158     {"rx_cbfc_pause_frames0", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames0),
0159                 QL_OFF(nic_stats.rx_cbfc_pause_frames0)},
0160     {"rx_cbfc_pause_frames1", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames1),
0161                 QL_OFF(nic_stats.rx_cbfc_pause_frames1)},
0162     {"rx_cbfc_pause_frames2", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames2),
0163                 QL_OFF(nic_stats.rx_cbfc_pause_frames2)},
0164     {"rx_cbfc_pause_frames3", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames3),
0165                 QL_OFF(nic_stats.rx_cbfc_pause_frames3)},
0166     {"rx_cbfc_pause_frames4", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames4),
0167                 QL_OFF(nic_stats.rx_cbfc_pause_frames4)},
0168     {"rx_cbfc_pause_frames5", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames5),
0169                 QL_OFF(nic_stats.rx_cbfc_pause_frames5)},
0170     {"rx_cbfc_pause_frames6", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames6),
0171                 QL_OFF(nic_stats.rx_cbfc_pause_frames6)},
0172     {"rx_cbfc_pause_frames7", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames7),
0173                 QL_OFF(nic_stats.rx_cbfc_pause_frames7)},
0174     {"rx_nic_fifo_drop", QL_SIZEOF(nic_stats.rx_nic_fifo_drop),
0175                     QL_OFF(nic_stats.rx_nic_fifo_drop)},
0176 };
0177 
0178 static const char qlge_gstrings_test[][ETH_GSTRING_LEN] = {
0179     "Loopback test  (offline)"
0180 };
0181 
0182 #define QLGE_TEST_LEN (sizeof(qlge_gstrings_test) / ETH_GSTRING_LEN)
0183 #define QLGE_STATS_LEN ARRAY_SIZE(qlge_gstrings_stats)
0184 #define QLGE_RCV_MAC_ERR_STATS  7
0185 
0186 static int qlge_update_ring_coalescing(struct qlge_adapter *qdev)
0187 {
0188     int i, status = 0;
0189     struct rx_ring *rx_ring;
0190     struct cqicb *cqicb;
0191 
0192     if (!netif_running(qdev->ndev))
0193         return status;
0194 
0195     /* Skip the default queue, and update the outbound handler
0196      * queues if they changed.
0197      */
0198     cqicb = (struct cqicb *)&qdev->rx_ring[qdev->rss_ring_count];
0199     if (le16_to_cpu(cqicb->irq_delay) != qdev->tx_coalesce_usecs ||
0200         le16_to_cpu(cqicb->pkt_delay) != qdev->tx_max_coalesced_frames) {
0201         for (i = qdev->rss_ring_count; i < qdev->rx_ring_count; i++) {
0202             rx_ring = &qdev->rx_ring[i];
0203             cqicb = (struct cqicb *)rx_ring;
0204             cqicb->irq_delay = cpu_to_le16(qdev->tx_coalesce_usecs);
0205             cqicb->pkt_delay =
0206                 cpu_to_le16(qdev->tx_max_coalesced_frames);
0207             cqicb->flags = FLAGS_LI;
0208             status = qlge_write_cfg(qdev, cqicb, sizeof(*cqicb),
0209                         CFG_LCQ, rx_ring->cq_id);
0210             if (status) {
0211                 netif_err(qdev, ifup, qdev->ndev,
0212                       "Failed to load CQICB.\n");
0213                 goto exit;
0214             }
0215         }
0216     }
0217 
0218     /* Update the inbound (RSS) handler queues if they changed. */
0219     cqicb = (struct cqicb *)&qdev->rx_ring[0];
0220     if (le16_to_cpu(cqicb->irq_delay) != qdev->rx_coalesce_usecs ||
0221         le16_to_cpu(cqicb->pkt_delay) != qdev->rx_max_coalesced_frames) {
0222         for (i = 0; i < qdev->rss_ring_count; i++, rx_ring++) {
0223             rx_ring = &qdev->rx_ring[i];
0224             cqicb = (struct cqicb *)rx_ring;
0225             cqicb->irq_delay = cpu_to_le16(qdev->rx_coalesce_usecs);
0226             cqicb->pkt_delay =
0227                 cpu_to_le16(qdev->rx_max_coalesced_frames);
0228             cqicb->flags = FLAGS_LI;
0229             status = qlge_write_cfg(qdev, cqicb, sizeof(*cqicb),
0230                         CFG_LCQ, rx_ring->cq_id);
0231             if (status) {
0232                 netif_err(qdev, ifup, qdev->ndev,
0233                       "Failed to load CQICB.\n");
0234                 goto exit;
0235             }
0236         }
0237     }
0238 exit:
0239     return status;
0240 }
0241 
0242 static void qlge_update_stats(struct qlge_adapter *qdev)
0243 {
0244     u32 i;
0245     u64 data;
0246     u64 *iter = &qdev->nic_stats.tx_pkts;
0247 
0248     spin_lock(&qdev->stats_lock);
0249     if (qlge_sem_spinlock(qdev, qdev->xg_sem_mask)) {
0250         netif_err(qdev, drv, qdev->ndev,
0251               "Couldn't get xgmac sem.\n");
0252         goto quit;
0253     }
0254     /*
0255      * Get TX statistics.
0256      */
0257     for (i = 0x200; i < 0x280; i += 8) {
0258         if (qlge_read_xgmac_reg64(qdev, i, &data)) {
0259             netif_err(qdev, drv, qdev->ndev,
0260                   "Error reading status register 0x%.04x.\n",
0261                   i);
0262             goto end;
0263         } else {
0264             *iter = data;
0265         }
0266         iter++;
0267     }
0268 
0269     /*
0270      * Get RX statistics.
0271      */
0272     for (i = 0x300; i < 0x3d0; i += 8) {
0273         if (qlge_read_xgmac_reg64(qdev, i, &data)) {
0274             netif_err(qdev, drv, qdev->ndev,
0275                   "Error reading status register 0x%.04x.\n",
0276                   i);
0277             goto end;
0278         } else {
0279             *iter = data;
0280         }
0281         iter++;
0282     }
0283 
0284     /* Update receive mac error statistics */
0285     iter += QLGE_RCV_MAC_ERR_STATS;
0286 
0287     /*
0288      * Get Per-priority TX pause frame counter statistics.
0289      */
0290     for (i = 0x500; i < 0x540; i += 8) {
0291         if (qlge_read_xgmac_reg64(qdev, i, &data)) {
0292             netif_err(qdev, drv, qdev->ndev,
0293                   "Error reading status register 0x%.04x.\n",
0294                   i);
0295             goto end;
0296         } else {
0297             *iter = data;
0298         }
0299         iter++;
0300     }
0301 
0302     /*
0303      * Get Per-priority RX pause frame counter statistics.
0304      */
0305     for (i = 0x568; i < 0x5a8; i += 8) {
0306         if (qlge_read_xgmac_reg64(qdev, i, &data)) {
0307             netif_err(qdev, drv, qdev->ndev,
0308                   "Error reading status register 0x%.04x.\n",
0309                   i);
0310             goto end;
0311         } else {
0312             *iter = data;
0313         }
0314         iter++;
0315     }
0316 
0317     /*
0318      * Get RX NIC FIFO DROP statistics.
0319      */
0320     if (qlge_read_xgmac_reg64(qdev, 0x5b8, &data)) {
0321         netif_err(qdev, drv, qdev->ndev,
0322               "Error reading status register 0x%.04x.\n", i);
0323         goto end;
0324     } else {
0325         *iter = data;
0326     }
0327 end:
0328     qlge_sem_unlock(qdev, qdev->xg_sem_mask);
0329 quit:
0330     spin_unlock(&qdev->stats_lock);
0331 }
0332 
0333 static void qlge_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
0334 {
0335     int index;
0336 
0337     switch (stringset) {
0338     case ETH_SS_TEST:
0339         memcpy(buf, *qlge_gstrings_test, QLGE_TEST_LEN * ETH_GSTRING_LEN);
0340         break;
0341     case ETH_SS_STATS:
0342         for (index = 0; index < QLGE_STATS_LEN; index++) {
0343             memcpy(buf + index * ETH_GSTRING_LEN,
0344                    qlge_gstrings_stats[index].stat_string,
0345                    ETH_GSTRING_LEN);
0346         }
0347         break;
0348     }
0349 }
0350 
0351 static int qlge_get_sset_count(struct net_device *dev, int sset)
0352 {
0353     switch (sset) {
0354     case ETH_SS_TEST:
0355         return QLGE_TEST_LEN;
0356     case ETH_SS_STATS:
0357         return QLGE_STATS_LEN;
0358     default:
0359         return -EOPNOTSUPP;
0360     }
0361 }
0362 
0363 static void
0364 qlge_get_ethtool_stats(struct net_device *ndev,
0365                struct ethtool_stats *stats, u64 *data)
0366 {
0367     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0368     int index, length;
0369 
0370     length = QLGE_STATS_LEN;
0371     qlge_update_stats(qdev);
0372 
0373     for (index = 0; index < length; index++) {
0374         char *p = (char *)qdev +
0375             qlge_gstrings_stats[index].stat_offset;
0376         *data++ = (qlge_gstrings_stats[index].sizeof_stat ==
0377                sizeof(u64)) ? *(u64 *)p : (*(u32 *)p);
0378     }
0379 }
0380 
0381 static int qlge_get_link_ksettings(struct net_device *ndev,
0382                    struct ethtool_link_ksettings *ecmd)
0383 {
0384     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0385     u32 supported, advertising;
0386 
0387     supported = SUPPORTED_10000baseT_Full;
0388     advertising = ADVERTISED_10000baseT_Full;
0389 
0390     if ((qdev->link_status & STS_LINK_TYPE_MASK) ==
0391         STS_LINK_TYPE_10GBASET) {
0392         supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
0393         advertising |= (ADVERTISED_TP | ADVERTISED_Autoneg);
0394         ecmd->base.port = PORT_TP;
0395         ecmd->base.autoneg = AUTONEG_ENABLE;
0396     } else {
0397         supported |= SUPPORTED_FIBRE;
0398         advertising |= ADVERTISED_FIBRE;
0399         ecmd->base.port = PORT_FIBRE;
0400     }
0401 
0402     ecmd->base.speed = SPEED_10000;
0403     ecmd->base.duplex = DUPLEX_FULL;
0404 
0405     ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.supported,
0406                         supported);
0407     ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.advertising,
0408                         advertising);
0409 
0410     return 0;
0411 }
0412 
0413 static void qlge_get_drvinfo(struct net_device *ndev,
0414                  struct ethtool_drvinfo *drvinfo)
0415 {
0416     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0417 
0418     strscpy(drvinfo->driver, qlge_driver_name, sizeof(drvinfo->driver));
0419     strscpy(drvinfo->version, qlge_driver_version,
0420         sizeof(drvinfo->version));
0421     snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
0422          "v%d.%d.%d",
0423          (qdev->fw_rev_id & 0x00ff0000) >> 16,
0424          (qdev->fw_rev_id & 0x0000ff00) >> 8,
0425          (qdev->fw_rev_id & 0x000000ff));
0426     strscpy(drvinfo->bus_info, pci_name(qdev->pdev),
0427         sizeof(drvinfo->bus_info));
0428 }
0429 
0430 static void qlge_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
0431 {
0432     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0433     unsigned short ssys_dev = qdev->pdev->subsystem_device;
0434 
0435     /* WOL is only supported for mezz card. */
0436     if (ssys_dev == QLGE_MEZZ_SSYS_ID_068 ||
0437         ssys_dev == QLGE_MEZZ_SSYS_ID_180) {
0438         wol->supported = WAKE_MAGIC;
0439         wol->wolopts = qdev->wol;
0440     }
0441 }
0442 
0443 static int qlge_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
0444 {
0445     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0446     unsigned short ssys_dev = qdev->pdev->subsystem_device;
0447 
0448     /* WOL is only supported for mezz card. */
0449     if (ssys_dev != QLGE_MEZZ_SSYS_ID_068 &&
0450         ssys_dev != QLGE_MEZZ_SSYS_ID_180) {
0451         netif_info(qdev, drv, qdev->ndev,
0452                "WOL is only supported for mezz card\n");
0453         return -EOPNOTSUPP;
0454     }
0455     if (wol->wolopts & ~WAKE_MAGIC)
0456         return -EINVAL;
0457     qdev->wol = wol->wolopts;
0458 
0459     netif_info(qdev, drv, qdev->ndev, "Set wol option 0x%x\n", qdev->wol);
0460     return 0;
0461 }
0462 
0463 static int qlge_set_phys_id(struct net_device *ndev,
0464                 enum ethtool_phys_id_state state)
0465 
0466 {
0467     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0468 
0469     switch (state) {
0470     case ETHTOOL_ID_ACTIVE:
0471         /* Save the current LED settings */
0472         if (qlge_mb_get_led_cfg(qdev))
0473             return -EIO;
0474 
0475         /* Start blinking */
0476         qlge_mb_set_led_cfg(qdev, QL_LED_BLINK);
0477         return 0;
0478 
0479     case ETHTOOL_ID_INACTIVE:
0480         /* Restore LED settings */
0481         if (qlge_mb_set_led_cfg(qdev, qdev->led_config))
0482             return -EIO;
0483         return 0;
0484 
0485     default:
0486         return -EINVAL;
0487     }
0488 }
0489 
0490 static int qlge_start_loopback(struct qlge_adapter *qdev)
0491 {
0492     if (netif_carrier_ok(qdev->ndev)) {
0493         set_bit(QL_LB_LINK_UP, &qdev->flags);
0494         netif_carrier_off(qdev->ndev);
0495     } else {
0496         clear_bit(QL_LB_LINK_UP, &qdev->flags);
0497     }
0498     qdev->link_config |= CFG_LOOPBACK_PCS;
0499     return qlge_mb_set_port_cfg(qdev);
0500 }
0501 
0502 static void qlge_stop_loopback(struct qlge_adapter *qdev)
0503 {
0504     qdev->link_config &= ~CFG_LOOPBACK_PCS;
0505     qlge_mb_set_port_cfg(qdev);
0506     if (test_bit(QL_LB_LINK_UP, &qdev->flags)) {
0507         netif_carrier_on(qdev->ndev);
0508         clear_bit(QL_LB_LINK_UP, &qdev->flags);
0509     }
0510 }
0511 
0512 static void qlge_create_lb_frame(struct sk_buff *skb,
0513                  unsigned int frame_size)
0514 {
0515     memset(skb->data, 0xFF, frame_size);
0516     frame_size &= ~1;
0517     memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
0518     skb->data[frame_size / 2 + 10] = (unsigned char)0xBE;
0519     skb->data[frame_size / 2 + 12] = (unsigned char)0xAF;
0520 }
0521 
0522 void qlge_check_lb_frame(struct qlge_adapter *qdev,
0523              struct sk_buff *skb)
0524 {
0525     unsigned int frame_size = skb->len;
0526 
0527     if ((*(skb->data + 3) == 0xFF) &&
0528         (*(skb->data + frame_size / 2 + 10) == 0xBE) &&
0529         (*(skb->data + frame_size / 2 + 12) == 0xAF)) {
0530         atomic_dec(&qdev->lb_count);
0531         return;
0532     }
0533 }
0534 
0535 static int qlge_run_loopback_test(struct qlge_adapter *qdev)
0536 {
0537     int i;
0538     netdev_tx_t rc;
0539     struct sk_buff *skb;
0540     unsigned int size = SMALL_BUF_MAP_SIZE;
0541 
0542     for (i = 0; i < 64; i++) {
0543         skb = netdev_alloc_skb(qdev->ndev, size);
0544         if (!skb)
0545             return -ENOMEM;
0546 
0547         skb->queue_mapping = 0;
0548         skb_put(skb, size);
0549         qlge_create_lb_frame(skb, size);
0550         rc = qlge_lb_send(skb, qdev->ndev);
0551         if (rc != NETDEV_TX_OK)
0552             return -EPIPE;
0553         atomic_inc(&qdev->lb_count);
0554     }
0555     /* Give queue time to settle before testing results. */
0556     usleep_range(2000, 2100);
0557     qlge_clean_lb_rx_ring(&qdev->rx_ring[0], 128);
0558     return atomic_read(&qdev->lb_count) ? -EIO : 0;
0559 }
0560 
0561 static int qlge_loopback_test(struct qlge_adapter *qdev, u64 *data)
0562 {
0563     *data = qlge_start_loopback(qdev);
0564     if (*data)
0565         goto out;
0566     *data = qlge_run_loopback_test(qdev);
0567 out:
0568     qlge_stop_loopback(qdev);
0569     return *data;
0570 }
0571 
0572 static void qlge_self_test(struct net_device *ndev,
0573                struct ethtool_test *eth_test, u64 *data)
0574 {
0575     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0576 
0577     memset(data, 0, sizeof(u64) * QLGE_TEST_LEN);
0578 
0579     if (netif_running(ndev)) {
0580         set_bit(QL_SELFTEST, &qdev->flags);
0581         if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
0582             /* Offline tests */
0583             if (qlge_loopback_test(qdev, &data[0]))
0584                 eth_test->flags |= ETH_TEST_FL_FAILED;
0585 
0586         } else {
0587             /* Online tests */
0588             data[0] = 0;
0589         }
0590         clear_bit(QL_SELFTEST, &qdev->flags);
0591         /* Give link time to come up after
0592          * port configuration changes.
0593          */
0594         msleep_interruptible(4 * 1000);
0595     } else {
0596         netif_err(qdev, drv, qdev->ndev,
0597               "is down, Loopback test will fail.\n");
0598         eth_test->flags |= ETH_TEST_FL_FAILED;
0599     }
0600 }
0601 
0602 static int qlge_get_regs_len(struct net_device *ndev)
0603 {
0604     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0605 
0606     if (!test_bit(QL_FRC_COREDUMP, &qdev->flags))
0607         return sizeof(struct qlge_mpi_coredump);
0608     else
0609         return sizeof(struct qlge_reg_dump);
0610 }
0611 
0612 static void qlge_get_regs(struct net_device *ndev,
0613               struct ethtool_regs *regs, void *p)
0614 {
0615     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0616 
0617     qlge_get_dump(qdev, p);
0618     if (!test_bit(QL_FRC_COREDUMP, &qdev->flags))
0619         regs->len = sizeof(struct qlge_mpi_coredump);
0620     else
0621         regs->len = sizeof(struct qlge_reg_dump);
0622 }
0623 
0624 static int qlge_get_coalesce(struct net_device *ndev,
0625                  struct ethtool_coalesce *c,
0626                  struct kernel_ethtool_coalesce *kernel_coal,
0627                  struct netlink_ext_ack *extack)
0628 {
0629     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0630 
0631     c->rx_coalesce_usecs = qdev->rx_coalesce_usecs;
0632     c->tx_coalesce_usecs = qdev->tx_coalesce_usecs;
0633 
0634     /* This chip coalesces as follows:
0635      * If a packet arrives, hold off interrupts until
0636      * cqicb->int_delay expires, but if no other packets arrive don't
0637      * wait longer than cqicb->pkt_int_delay. But ethtool doesn't use a
0638      * timer to coalesce on a frame basis.  So, we have to take ethtool's
0639      * max_coalesced_frames value and convert it to a delay in microseconds.
0640      * We do this by using a basic thoughput of 1,000,000 frames per
0641      * second @ (1024 bytes).  This means one frame per usec. So it's a
0642      * simple one to one ratio.
0643      */
0644     c->rx_max_coalesced_frames = qdev->rx_max_coalesced_frames;
0645     c->tx_max_coalesced_frames = qdev->tx_max_coalesced_frames;
0646 
0647     return 0;
0648 }
0649 
0650 static int qlge_set_coalesce(struct net_device *ndev,
0651                  struct ethtool_coalesce *c,
0652                  struct kernel_ethtool_coalesce *kernel_coal,
0653                  struct netlink_ext_ack *extack)
0654 {
0655     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0656 
0657     /* Validate user parameters. */
0658     if (c->rx_coalesce_usecs > qdev->rx_ring_size / 2)
0659         return -EINVAL;
0660     /* Don't wait more than 10 usec. */
0661     if (c->rx_max_coalesced_frames > MAX_INTER_FRAME_WAIT)
0662         return -EINVAL;
0663     if (c->tx_coalesce_usecs > qdev->tx_ring_size / 2)
0664         return -EINVAL;
0665     if (c->tx_max_coalesced_frames > MAX_INTER_FRAME_WAIT)
0666         return -EINVAL;
0667 
0668     /* Verify a change took place before updating the hardware. */
0669     if (qdev->rx_coalesce_usecs == c->rx_coalesce_usecs &&
0670         qdev->tx_coalesce_usecs == c->tx_coalesce_usecs &&
0671         qdev->rx_max_coalesced_frames == c->rx_max_coalesced_frames &&
0672         qdev->tx_max_coalesced_frames == c->tx_max_coalesced_frames)
0673         return 0;
0674 
0675     qdev->rx_coalesce_usecs = c->rx_coalesce_usecs;
0676     qdev->tx_coalesce_usecs = c->tx_coalesce_usecs;
0677     qdev->rx_max_coalesced_frames = c->rx_max_coalesced_frames;
0678     qdev->tx_max_coalesced_frames = c->tx_max_coalesced_frames;
0679 
0680     return qlge_update_ring_coalescing(qdev);
0681 }
0682 
0683 static void qlge_get_pauseparam(struct net_device *ndev,
0684                 struct ethtool_pauseparam *pause)
0685 {
0686     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0687 
0688     qlge_mb_get_port_cfg(qdev);
0689     if (qdev->link_config & CFG_PAUSE_STD) {
0690         pause->rx_pause = 1;
0691         pause->tx_pause = 1;
0692     }
0693 }
0694 
0695 static int qlge_set_pauseparam(struct net_device *ndev,
0696                    struct ethtool_pauseparam *pause)
0697 {
0698     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0699 
0700     if ((pause->rx_pause) && (pause->tx_pause))
0701         qdev->link_config |= CFG_PAUSE_STD;
0702     else if (!pause->rx_pause && !pause->tx_pause)
0703         qdev->link_config &= ~CFG_PAUSE_STD;
0704     else
0705         return -EINVAL;
0706 
0707     return qlge_mb_set_port_cfg(qdev);
0708 }
0709 
0710 static u32 qlge_get_msglevel(struct net_device *ndev)
0711 {
0712     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0713 
0714     return qdev->msg_enable;
0715 }
0716 
0717 static void qlge_set_msglevel(struct net_device *ndev, u32 value)
0718 {
0719     struct qlge_adapter *qdev = netdev_to_qdev(ndev);
0720 
0721     qdev->msg_enable = value;
0722 }
0723 
0724 const struct ethtool_ops qlge_ethtool_ops = {
0725     .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
0726                      ETHTOOL_COALESCE_MAX_FRAMES,
0727     .get_drvinfo = qlge_get_drvinfo,
0728     .get_wol = qlge_get_wol,
0729     .set_wol = qlge_set_wol,
0730     .get_regs_len   = qlge_get_regs_len,
0731     .get_regs = qlge_get_regs,
0732     .get_msglevel = qlge_get_msglevel,
0733     .set_msglevel = qlge_set_msglevel,
0734     .get_link = ethtool_op_get_link,
0735     .set_phys_id         = qlge_set_phys_id,
0736     .self_test       = qlge_self_test,
0737     .get_pauseparam      = qlge_get_pauseparam,
0738     .set_pauseparam      = qlge_set_pauseparam,
0739     .get_coalesce = qlge_get_coalesce,
0740     .set_coalesce = qlge_set_coalesce,
0741     .get_sset_count = qlge_get_sset_count,
0742     .get_strings = qlge_get_strings,
0743     .get_ethtool_stats = qlge_get_ethtool_stats,
0744     .get_link_ksettings = qlge_get_link_ksettings,
0745 };
0746