svn commit: r297884 - head/sys/dev/bxe

David C Somayajulu davidcs at FreeBSD.org
Tue Apr 12 22:31:49 UTC 2016


Author: davidcs
Date: Tue Apr 12 22:31:48 2016
New Revision: 297884
URL: https://svnweb.freebsd.org/changeset/base/297884

Log:
  Add support for Flash Update
  
  Submitted by:nrapendra.singh at qlogic.com;vaishali.kulkarni at qlogic.com;davidcs at freebsd.org
  Approved by:davidcs at freebsd.org
  MFC after:5 days

Modified:
  head/sys/dev/bxe/bxe.c
  head/sys/dev/bxe/bxe.h
  head/sys/dev/bxe/bxe_ioctl.h

Modified: head/sys/dev/bxe/bxe.c
==============================================================================
--- head/sys/dev/bxe/bxe.c	Tue Apr 12 22:11:29 2016	(r297883)
+++ head/sys/dev/bxe/bxe.c	Tue Apr 12 22:31:48 2016	(r297884)
@@ -13653,49 +13653,60 @@ bxe_get_tunable_params(struct bxe_softc 
           sc->udp_rss);
 }
 
-static void
+static int
 bxe_media_detect(struct bxe_softc *sc)
 {
+    int port_type;
     uint32_t phy_idx = bxe_get_cur_phy_idx(sc);
+
     switch (sc->link_params.phy[phy_idx].media_type) {
     case ELINK_ETH_PHY_SFPP_10G_FIBER:
     case ELINK_ETH_PHY_XFP_FIBER:
         BLOGI(sc, "Found 10Gb Fiber media.\n");
         sc->media = IFM_10G_SR;
+        port_type = PORT_FIBRE;
         break;
     case ELINK_ETH_PHY_SFP_1G_FIBER:
         BLOGI(sc, "Found 1Gb Fiber media.\n");
         sc->media = IFM_1000_SX;
+        port_type = PORT_FIBRE;
         break;
     case ELINK_ETH_PHY_KR:
     case ELINK_ETH_PHY_CX4:
         BLOGI(sc, "Found 10GBase-CX4 media.\n");
         sc->media = IFM_10G_CX4;
+        port_type = PORT_FIBRE;
         break;
     case ELINK_ETH_PHY_DA_TWINAX:
         BLOGI(sc, "Found 10Gb Twinax media.\n");
         sc->media = IFM_10G_TWINAX;
+        port_type = PORT_DA;
         break;
     case ELINK_ETH_PHY_BASE_T:
         if (sc->link_params.speed_cap_mask[0] &
             PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) {
             BLOGI(sc, "Found 10GBase-T media.\n");
             sc->media = IFM_10G_T;
+            port_type = PORT_TP;
         } else {
             BLOGI(sc, "Found 1000Base-T media.\n");
             sc->media = IFM_1000_T;
+            port_type = PORT_TP;
         }
         break;
     case ELINK_ETH_PHY_NOT_PRESENT:
         BLOGI(sc, "Media not present.\n");
         sc->media = 0;
+        port_type = PORT_OTHER;
         break;
     case ELINK_ETH_PHY_UNSPECIFIED:
     default:
         BLOGI(sc, "Unknown media!\n");
         sc->media = 0;
+        port_type = PORT_OTHER;
         break;
     }
+    return port_type;
 }
 
 #define GET_FIELD(value, fname)                     \
@@ -18714,6 +18725,14 @@ bxe_add_cdev(struct bxe_softc *sc)
     if (sc->grc_dump == NULL)
         return (-1);
 
+    sc->eeprom = malloc(BXE_EEPROM_MAX_DATA_LEN, M_DEVBUF, M_NOWAIT);
+
+    if (sc->eeprom == NULL) {
+        BLOGW(sc, "Unable to alloc for eeprom size buffer\n");
+        free(sc->grc_dump, M_DEVBUF); sc->grc_dump = NULL;
+        return (-1);
+    }
+
     sc->ioctl_dev = make_dev(&bxe_cdevsw,
                             sc->ifp->if_dunit,
                             UID_ROOT,
@@ -18725,6 +18744,8 @@ bxe_add_cdev(struct bxe_softc *sc)
     if (sc->ioctl_dev == NULL) {
 
         free(sc->grc_dump, M_DEVBUF);
+        free(sc->eeprom, M_DEVBUF);
+        sc->eeprom = NULL;
 
         return (-1);
     }
@@ -18740,12 +18761,152 @@ bxe_del_cdev(struct bxe_softc *sc)
     if (sc->ioctl_dev != NULL)
         destroy_dev(sc->ioctl_dev);
 
-    if (sc->grc_dump == NULL)
+    if (sc->grc_dump != NULL)
         free(sc->grc_dump, M_DEVBUF);
 
+    if (sc->eeprom != NULL) {
+        free(sc->eeprom, M_DEVBUF);
+        sc->eeprom = NULL;
+    }
+
     return;
 }
 
+static bool bxe_is_nvram_accessible(struct bxe_softc *sc)
+{
+
+    if ((if_getdrvflags(sc->ifp) & IFF_DRV_RUNNING) == 0)
+        return FALSE;
+
+    return TRUE;
+}
+
+
+static int
+bxe_wr_eeprom(struct bxe_softc *sc, void *data, uint32_t offset, uint32_t len)
+{
+    int rval = 0;
+
+    if(!bxe_is_nvram_accessible(sc)) {
+        BLOGW(sc, "Cannot access eeprom when interface is down\n");
+        return (-EAGAIN);
+    }
+    rval = bxe_nvram_write(sc, offset, (uint8_t *)data, len);
+
+
+   return (rval);
+}
+
+static int
+bxe_rd_eeprom(struct bxe_softc *sc, void *data, uint32_t offset, uint32_t len)
+{
+    int rval = 0;
+
+    if(!bxe_is_nvram_accessible(sc)) {
+        BLOGW(sc, "Cannot access eeprom when interface is down\n");
+        return (-EAGAIN);
+    }
+    rval = bxe_nvram_read(sc, offset, (uint8_t *)data, len);
+
+   return (rval);
+}
+
+static int
+bxe_eeprom_rd_wr(struct bxe_softc *sc, bxe_eeprom_t *eeprom)
+{
+    int rval = 0;
+
+    switch (eeprom->eeprom_cmd) {
+
+    case BXE_EEPROM_CMD_SET_EEPROM:
+
+        rval = copyin(eeprom->eeprom_data, sc->eeprom,
+                       eeprom->eeprom_data_len);
+
+        if (rval)
+            break;
+
+        rval = bxe_wr_eeprom(sc, sc->eeprom, eeprom->eeprom_offset,
+                       eeprom->eeprom_data_len);
+        break;
+
+    case BXE_EEPROM_CMD_GET_EEPROM:
+
+        rval = bxe_rd_eeprom(sc, sc->eeprom, eeprom->eeprom_offset,
+                       eeprom->eeprom_data_len);
+
+        if (rval) {
+            break;
+        }
+
+        rval = copyout(sc->eeprom, eeprom->eeprom_data,
+                       eeprom->eeprom_data_len);
+        break;
+
+    default:
+            rval = EINVAL;
+            break;
+    }
+
+    if (rval) {
+        BLOGW(sc, "ioctl cmd %d  failed rval %d\n", eeprom->eeprom_cmd, rval);
+    }
+
+    return (rval);
+}
+
+static int
+bxe_get_settings(struct bxe_softc *sc, bxe_dev_setting_t *dev_p)
+{
+    uint32_t ext_phy_config;
+    int port = SC_PORT(sc);
+    int cfg_idx = bxe_get_link_cfg_idx(sc);
+
+    dev_p->supported = sc->port.supported[cfg_idx] |
+            (sc->port.supported[cfg_idx ^ 1] &
+            (ELINK_SUPPORTED_TP | ELINK_SUPPORTED_FIBRE));
+    dev_p->advertising = sc->port.advertising[cfg_idx];
+    if(sc->link_params.phy[bxe_get_cur_phy_idx(sc)].media_type ==
+        ELINK_ETH_PHY_SFP_1G_FIBER) {
+        dev_p->supported = ~(ELINK_SUPPORTED_10000baseT_Full);
+        dev_p->advertising &= ~(ADVERTISED_10000baseT_Full);
+    }
+    if ((sc->state == BXE_STATE_OPEN) && sc->link_vars.link_up &&
+        !(sc->flags & BXE_MF_FUNC_DIS)) {
+        dev_p->duplex = sc->link_vars.duplex;
+        if (IS_MF(sc) && !BXE_NOMCP(sc))
+            dev_p->speed = bxe_get_mf_speed(sc);
+        else
+            dev_p->speed = sc->link_vars.line_speed;
+    } else {
+        dev_p->duplex = DUPLEX_UNKNOWN;
+        dev_p->speed = SPEED_UNKNOWN;
+    }
+
+    dev_p->port = bxe_media_detect(sc);
+
+    ext_phy_config = SHMEM_RD(sc,
+                         dev_info.port_hw_config[port].external_phy_config);
+    if((ext_phy_config & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK) ==
+        PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+        dev_p->phy_address =  sc->port.phy_addr;
+    else if(((ext_phy_config & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK) !=
+            PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) &&
+        ((ext_phy_config & PORT_HW_CFG_XGXS_EXT_PHY_TYPE_MASK) !=
+            PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN))
+        dev_p->phy_address = ELINK_XGXS_EXT_PHY_ADDR(ext_phy_config);
+    else
+        dev_p->phy_address = 0;
+
+    if(sc->link_params.req_line_speed[cfg_idx] == ELINK_SPEED_AUTO_NEG)
+        dev_p->autoneg = AUTONEG_ENABLE;
+    else
+       dev_p->autoneg = AUTONEG_DISABLE;
+
+
+    return 0;
+}
+
 static int
 bxe_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
         struct thread *td)
@@ -18755,6 +18916,14 @@ bxe_eioctl(struct cdev *dev, u_long cmd,
     device_t            pci_dev;
     bxe_grcdump_t       *dump = NULL;
     int grc_dump_size;
+    bxe_drvinfo_t   *drv_infop = NULL;
+    bxe_dev_setting_t  *dev_p;
+    bxe_dev_setting_t  dev_set;
+    bxe_get_regs_t  *reg_p;
+    bxe_reg_rdw_t *reg_rdw_p;
+    bxe_pcicfg_rdw_t *cfg_rdw_p;
+    bxe_perm_mac_addr_t *mac_addr_p;
+
 
     if ((sc = (struct bxe_softc *)dev->si_drv1) == NULL)
         return ENXIO;
@@ -18767,14 +18936,15 @@ bxe_eioctl(struct cdev *dev, u_long cmd,
 
         case BXE_GRC_DUMP_SIZE:
             dump->pci_func = sc->pcie_func;
-            dump->grcdump_size = (bxe_get_total_regs_len32(sc) * sizeof(uint32_t)) +
-					sizeof(struct  dump_header);
+            dump->grcdump_size =
+                (bxe_get_total_regs_len32(sc) * sizeof(uint32_t)) +
+                     sizeof(struct  dump_header);
             break;
 
         case BXE_GRC_DUMP:
             
             grc_dump_size = (bxe_get_total_regs_len32(sc) * sizeof(uint32_t)) +
-				sizeof(struct  dump_header);
+                                sizeof(struct  dump_header);
 
             if ((sc->grc_dump == NULL) || (dump->grcdump == NULL) ||
                 (dump->grcdump_size < grc_dump_size) || (!sc->grcdump_done)) {
@@ -18787,6 +18957,92 @@ bxe_eioctl(struct cdev *dev, u_long cmd,
 
             break;
 
+        case BXE_DRV_INFO:
+            drv_infop = (bxe_drvinfo_t *)data;
+            snprintf(drv_infop->drv_name, BXE_DRV_NAME_LENGTH, "%s", "bxe");
+            snprintf(drv_infop->drv_version, BXE_DRV_VERSION_LENGTH, "v:%s",
+                BXE_DRIVER_VERSION);
+            snprintf(drv_infop->mfw_version, BXE_MFW_VERSION_LENGTH, "%s",
+                sc->devinfo.bc_ver_str);
+            snprintf(drv_infop->stormfw_version, BXE_STORMFW_VERSION_LENGTH,
+                "%s", sc->fw_ver_str);
+            drv_infop->eeprom_dump_len = sc->devinfo.flash_size;
+            drv_infop->reg_dump_len =
+                (bxe_get_total_regs_len32(sc) * sizeof(uint32_t))
+                    + sizeof(struct  dump_header);
+            snprintf(drv_infop->bus_info, BXE_BUS_INFO_LENGTH, "%d:%d:%d",
+                sc->pcie_bus, sc->pcie_device, sc->pcie_func);
+            break;
+        case BXE_DEV_SETTING:
+            dev_p = (bxe_dev_setting_t *)data;
+            bxe_get_settings(sc, &dev_set);
+            dev_p->supported = dev_set.supported;
+            dev_p->advertising = dev_set.advertising;
+            dev_p->speed = dev_set.speed;
+            dev_p->duplex = dev_set.duplex;
+            dev_p->port = dev_set.port;
+            dev_p->phy_address = dev_set.phy_address;
+            dev_p->autoneg = dev_set.autoneg;
+
+            break;
+
+        case BXE_GET_REGS:
+
+            reg_p = (bxe_get_regs_t *)data;
+            grc_dump_size = reg_p->reg_buf_len;
+
+            if (sc->grc_dump == NULL) { 
+                rval = EINVAL;
+                break;
+            }
+
+            if(!sc->grcdump_done) {
+                bxe_grc_dump(sc);
+            }
+            if(sc->grcdump_done) {
+                rval = copyout(sc->grc_dump, reg_p->reg_buf, grc_dump_size);
+                sc->grcdump_done = 0;
+            }
+
+            break;
+        case BXE_RDW_REG:
+            reg_rdw_p = (bxe_reg_rdw_t *)data;
+            if((reg_rdw_p->reg_cmd == BXE_READ_REG_CMD) &&
+                (reg_rdw_p->reg_access_type == BXE_REG_ACCESS_DIRECT))
+                reg_rdw_p->reg_val = REG_RD(sc, reg_rdw_p->reg_id);
+
+            if((reg_rdw_p->reg_cmd == BXE_WRITE_REG_CMD) &&
+                (reg_rdw_p->reg_access_type == BXE_REG_ACCESS_DIRECT))
+                REG_WR(sc, reg_rdw_p->reg_id, reg_rdw_p->reg_val);
+
+            break;
+
+        case BXE_RDW_PCICFG:
+            cfg_rdw_p = (bxe_pcicfg_rdw_t *)data;
+            if(cfg_rdw_p->cfg_cmd == BXE_READ_PCICFG) {
+
+                cfg_rdw_p->cfg_val = pci_read_config(sc->dev, cfg_rdw_p->cfg_id,
+                                         cfg_rdw_p->cfg_width);
+
+            } else if(cfg_rdw_p->cfg_cmd == BXE_WRITE_PCICFG) {
+                pci_write_config(sc->dev, cfg_rdw_p->cfg_id, cfg_rdw_p->cfg_val,
+                            cfg_rdw_p->cfg_width);
+            } else {
+                BLOGW(sc, "BXE_RDW_PCICFG ioctl wrong cmd passed\n");
+            }
+            break;
+
+        case BXE_MAC_ADDR:
+            mac_addr_p = (bxe_perm_mac_addr_t *)data;
+            snprintf(mac_addr_p->mac_addr_str, sizeof(sc->mac_addr_str), "%s",
+                sc->mac_addr_str);
+            break;
+
+        case BXE_EEPROM:
+            rval = bxe_eeprom_rd_wr(sc, (bxe_eeprom_t *)data);
+            break;
+
+
         default:
             break;
     }

Modified: head/sys/dev/bxe/bxe.h
==============================================================================
--- head/sys/dev/bxe/bxe.h	Tue Apr 12 22:11:29 2016	(r297883)
+++ head/sys/dev/bxe/bxe.h	Tue Apr 12 22:31:48 2016	(r297884)
@@ -1788,6 +1788,7 @@ struct bxe_softc {
     struct cdev *ioctl_dev;
     void *grc_dump;
     int grcdump_done;
+    void *eeprom;
 }; /* struct bxe_softc */
 
 /* IOCTL sub-commands for edebug and firmware upgrade */
@@ -2109,6 +2110,28 @@ static const uint32_t dmae_reg_go_c[] = 
 #define PCI_PM_D0    1
 #define PCI_PM_D3hot 2
 
+#ifndef DUPLEX_UNKNOWN
+#define DUPLEX_UNKNOWN (0xff)
+#endif
+
+#ifndef SPEED_UNKNOWN
+#define SPEED_UNKNOWN (-1)
+#endif
+
+/* Enable or disable autonegotiation. */
+#define AUTONEG_DISABLE         0x00
+#define AUTONEG_ENABLE          0x01
+
+/* Which connector port. */
+#define PORT_TP                 0x00
+#define PORT_AUI                0x01
+#define PORT_MII                0x02
+#define PORT_FIBRE              0x03
+#define PORT_BNC                0x04
+#define PORT_DA                 0x05
+#define PORT_NONE               0xef
+#define PORT_OTHER              0xff
+
 int  bxe_test_bit(int nr, volatile unsigned long * addr);
 void bxe_set_bit(unsigned int nr, volatile unsigned long * addr);
 void bxe_clear_bit(int nr, volatile unsigned long * addr);

Modified: head/sys/dev/bxe/bxe_ioctl.h
==============================================================================
--- head/sys/dev/bxe/bxe_ioctl.h	Tue Apr 12 22:11:29 2016	(r297883)
+++ head/sys/dev/bxe/bxe_ioctl.h	Tue Apr 12 22:31:48 2016	(r297884)
@@ -42,6 +42,86 @@ struct bxe_grcdump {
 };
 typedef struct bxe_grcdump bxe_grcdump_t;
 
+#define BXE_DRV_NAME_LENGTH             32
+#define BXE_DRV_VERSION_LENGTH          32
+#define BXE_MFW_VERSION_LENGTH          32
+#define BXE_STORMFW_VERSION_LENGTH      32
+#define BXE_BUS_INFO_LENGTH             32
+
+struct bxe_drvinfo {
+    char drv_name[BXE_DRV_NAME_LENGTH];
+    char drv_version[BXE_DRV_VERSION_LENGTH];
+    char mfw_version[BXE_MFW_VERSION_LENGTH];
+    char stormfw_version[BXE_STORMFW_VERSION_LENGTH];
+    uint32_t eeprom_dump_len; /* in bytes */
+    uint32_t reg_dump_len; /* in bytes */
+    char bus_info[BXE_BUS_INFO_LENGTH];
+};
+typedef struct bxe_drvinfo bxe_drvinfo_t;
+
+struct bxe_dev_setting {
+
+    uint32_t supported;  /* Features this interface supports */
+    uint32_t advertising;/* Features this interface advertises */
+    uint32_t speed;      /* The forced speed, 10Mb, 100Mb, gigabit */
+    uint32_t duplex;     /* Duplex, half or full */
+    uint32_t port;       /* Which connector port */
+    uint32_t phy_address;/* port number*/
+    uint32_t autoneg;    /* Enable or disable autonegotiation */
+};
+typedef struct bxe_dev_setting bxe_dev_setting_t;
+
+struct bxe_get_regs {
+    void *reg_buf;
+    uint32_t reg_buf_len;
+};
+typedef struct bxe_get_regs bxe_get_regs_t;
+
+#define BXE_EEPROM_MAX_DATA_LEN   524288
+
+struct bxe_eeprom {
+    uint32_t eeprom_cmd;
+#define BXE_EEPROM_CMD_SET_EEPROM       0x01
+#define BXE_EEPROM_CMD_GET_EEPROM       0x02
+
+    void *eeprom_data;
+    uint32_t eeprom_offset;
+    uint32_t eeprom_data_len;
+    uint32_t eeprom_magic;
+};
+typedef struct bxe_eeprom bxe_eeprom_t;
+
+struct bxe_reg_rdw {
+    uint32_t reg_cmd;
+#define BXE_READ_REG_CMD                0x01
+#define BXE_WRITE_REG_CMD               0x02
+
+    uint32_t reg_id;
+    uint32_t reg_val;
+    uint32_t reg_access_type;
+#define BXE_REG_ACCESS_DIRECT           0x01
+#define BXE_REG_ACCESS_INDIRECT         0x02
+};
+
+typedef struct bxe_reg_rdw bxe_reg_rdw_t;
+
+struct bxe_pcicfg_rdw {
+    uint32_t cfg_cmd;
+#define BXE_READ_PCICFG                 0x01
+#define BXE_WRITE_PCICFG                0x01
+    uint32_t cfg_id;
+    uint32_t cfg_val;
+    uint32_t cfg_width;
+};
+
+typedef struct bxe_pcicfg_rdw bxe_pcicfg_rdw_t;
+
+struct bxe_perm_mac_addr {
+    char mac_addr_str[32];
+};
+
+typedef struct bxe_perm_mac_addr bxe_perm_mac_addr_t;
+
 
 /*
  * Read grcdump size
@@ -53,5 +133,41 @@ typedef struct bxe_grcdump bxe_grcdump_t
  */
 #define BXE_GRC_DUMP          _IOWR('e', 2, bxe_grcdump_t)
 
+/*
+ * Read driver info
+ */
+#define BXE_DRV_INFO          _IOR('e', 3, bxe_drvinfo_t)
+
+/*
+ * Read Device Setting
+ */
+#define BXE_DEV_SETTING       _IOR('e', 4, bxe_dev_setting_t)
+
+/*
+ * Get Registers
+ */
+#define BXE_GET_REGS          _IOR('e', 5, bxe_get_regs_t)
+
+/*
+ * Get/Set EEPROM
+ */
+#define BXE_EEPROM            _IOWR('e', 6, bxe_eeprom_t)
+
+/*
+ * read/write a register
+ */
+#define BXE_RDW_REG           _IOWR('e', 7, bxe_reg_rdw_t)
+
+/*
+ * read/write PCIcfg
+ */
+#define BXE_RDW_PCICFG        _IOWR('e', 8, bxe_reg_rdw_t)
+
+/*
+ * get permanent mac address
+ */
+
+#define BXE_MAC_ADDR          _IOWR('e', 9, bxe_perm_mac_addr_t)
+
 
 #endif /* #ifndef _QLNX_IOCTL_H_ */


More information about the svn-src-head mailing list