Add support for Flash Update

Submitted by:nrapendra.singh@qlogic.com;vaishali.kulkarni@qlogic.com;davidcs@freebsd.org
Approved by:davidcs@freebsd.org
MFC after:5 days
This commit is contained in:
davidcs 2016-04-12 22:31:48 +00:00
parent b38b6a219d
commit 5e2c24a43d
3 changed files with 400 additions and 5 deletions

View File

@ -13653,49 +13653,60 @@ bxe_get_tunable_params(struct bxe_softc *sc)
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, caddr_t data, int fflag,
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,7 +18936,8 @@ bxe_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
case BXE_GRC_DUMP_SIZE:
dump->pci_func = sc->pcie_func;
dump->grcdump_size = (bxe_get_total_regs_len32(sc) * sizeof(uint32_t)) +
dump->grcdump_size =
(bxe_get_total_regs_len32(sc) * sizeof(uint32_t)) +
sizeof(struct dump_header);
break;
@ -18787,6 +18957,92 @@ bxe_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
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;
}

View File

@ -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);

View File

@ -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_ */