From d9d426af6bfb4b7f407191395fffbfe42b1ea129 Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Wed, 30 Dec 2015 01:28:56 -0500 Subject: [PATCH 01/10] be2net: fix VF link state transition from disabled to auto The VF link state setting transition from "disable" to "auto" does not work due to a bug in SET_LOGICAL_LINK_CONFIG_V1 cmd in FW. This issue could not be fixed in FW due to some backward compatibility issues it causes with some released drivers. The issue has been fixed by introducing a new version (v2) of the cmd from 10.6 FW onwards. In v2, to set the VF link state to auto, both PLINK_ENABLE and PLINK_TRACK bits have to be set to 1. The VF link state setting feature now works on Lancer chips too from FW ver 10.6.315.0 onwards. Signed-off-by: Suresh Reddy Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 35 +++++++++++++++------ drivers/net/ethernet/emulex/benet/be_cmds.h | 3 +- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 1795c935ff023..8083eca608087 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -4260,16 +4260,13 @@ int be_cmd_get_active_profile(struct be_adapter *adapter, u16 *profile_id) return status; } -int be_cmd_set_logical_link_config(struct be_adapter *adapter, - int link_state, u8 domain) +int __be_cmd_set_logical_link_config(struct be_adapter *adapter, + int link_state, int version, u8 domain) { struct be_mcc_wrb *wrb; struct be_cmd_req_set_ll_link *req; int status; - if (BEx_chip(adapter) || lancer_chip(adapter)) - return -EOPNOTSUPP; - spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -4284,14 +4281,15 @@ int be_cmd_set_logical_link_config(struct be_adapter *adapter, OPCODE_COMMON_SET_LOGICAL_LINK_CONFIG, sizeof(*req), wrb, NULL); - req->hdr.version = 1; + req->hdr.version = version; req->hdr.domain = domain; - if (link_state == IFLA_VF_LINK_STATE_ENABLE) - req->link_config |= 1; + if (link_state == IFLA_VF_LINK_STATE_ENABLE || + link_state == IFLA_VF_LINK_STATE_AUTO) + req->link_config |= PLINK_ENABLE; if (link_state == IFLA_VF_LINK_STATE_AUTO) - req->link_config |= 1 << PLINK_TRACK_SHIFT; + req->link_config |= PLINK_TRACK; status = be_mcc_notify_wait(adapter); err: @@ -4299,6 +4297,25 @@ int be_cmd_set_logical_link_config(struct be_adapter *adapter, return status; } +int be_cmd_set_logical_link_config(struct be_adapter *adapter, + int link_state, u8 domain) +{ + int status; + + if (BEx_chip(adapter)) + return -EOPNOTSUPP; + + status = __be_cmd_set_logical_link_config(adapter, link_state, + 2, domain); + + /* Version 2 of the command will not be recognized by older FW. + * On such a failure issue version 1 of the command. + */ + if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST) + status = __be_cmd_set_logical_link_config(adapter, link_state, + 1, domain); + return status; +} int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, int wrb_payload_size, u16 *cmd_status, u16 *ext_status) { diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 91155ea74f342..9690c3aa5d474 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -2246,7 +2246,8 @@ struct be_cmd_resp_get_iface_list { }; /*************** Set logical link ********************/ -#define PLINK_TRACK_SHIFT 8 +#define PLINK_ENABLE BIT(0) +#define PLINK_TRACK BIT(8) struct be_cmd_req_set_ll_link { struct be_cmd_req_hdr hdr; u32 link_config; /* Bit 0: UP_DOWN, Bit 9: PLINK */ From ac0f5fba632023a39be26ac42afd5cfc1f2cc0b4 Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Wed, 30 Dec 2015 01:28:57 -0500 Subject: [PATCH 02/10] be2net: avoid configuring VEPA mode on BE3 BE3 chip doesn't support VEPA mode. Signed-off-by: Suresh Reddy Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 34e324f20d804..2f76cbeab1e49 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -5108,6 +5108,9 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, return -EINVAL; mode = nla_get_u16(attr); + if (BE3_chip(adapter) && mode == BRIDGE_MODE_VEPA) + return -EOPNOTSUPP; + if (mode != BRIDGE_MODE_VEPA && mode != BRIDGE_MODE_VEB) return -EINVAL; From 8836ff48b92296bd70b2aa86883a245eaca7001a Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Wed, 30 Dec 2015 01:28:58 -0500 Subject: [PATCH 03/10] be2net: cleanup FW flash image related macro defines Many constant definitions relating to the FW-image layout (such as section offset values) were defined in decimal format rather than hexa-decimal. This makes this part of the code un-readable. Also some defines related to BE2 are labeld "g2" and defines related to BE3 are labeled "g3". This patch cleans up all of this to make this code more readable. Signed-off-by: Suresh Reddy Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.h | 141 +++++++++++--------- drivers/net/ethernet/emulex/benet/be_main.c | 78 +++++------ 2 files changed, 118 insertions(+), 101 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 9690c3aa5d474..8c6b606f0e909 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -1207,68 +1207,85 @@ struct be_cmd_resp_get_beacon_state { /* Flashrom related descriptors */ #define MAX_FLASH_COMP 32 -#define OPTYPE_ISCSI_ACTIVE 0 -#define OPTYPE_REDBOOT 1 -#define OPTYPE_BIOS 2 -#define OPTYPE_PXE_BIOS 3 -#define OPTYPE_OFFSET_SPECIFIED 7 -#define OPTYPE_FCOE_BIOS 8 -#define OPTYPE_ISCSI_BACKUP 9 -#define OPTYPE_FCOE_FW_ACTIVE 10 -#define OPTYPE_FCOE_FW_BACKUP 11 -#define OPTYPE_NCSI_FW 13 -#define OPTYPE_REDBOOT_DIR 18 -#define OPTYPE_REDBOOT_CONFIG 19 -#define OPTYPE_SH_PHY_FW 21 -#define OPTYPE_FLASHISM_JUMPVECTOR 22 -#define OPTYPE_UFI_DIR 23 -#define OPTYPE_PHY_FW 99 - -#define FLASH_BIOS_IMAGE_MAX_SIZE_g2 262144 /* Max OPTION ROM image sz */ -#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g2 262144 /* Max Redboot image sz */ -#define FLASH_IMAGE_MAX_SIZE_g2 1310720 /* Max firmware image size */ - -#define FLASH_NCSI_IMAGE_MAX_SIZE_g3 262144 -#define FLASH_PHY_FW_IMAGE_MAX_SIZE_g3 262144 -#define FLASH_BIOS_IMAGE_MAX_SIZE_g3 524288 /* Max OPTION ROM image sz */ -#define FLASH_REDBOOT_IMAGE_MAX_SIZE_g3 1048576 /* Max Redboot image sz */ -#define FLASH_IMAGE_MAX_SIZE_g3 2097152 /* Max firmware image size */ - -/* Offsets for components on Flash. */ -#define FLASH_REDBOOT_START_g2 0 -#define FLASH_FCoE_BIOS_START_g2 524288 -#define FLASH_iSCSI_PRIMARY_IMAGE_START_g2 1048576 -#define FLASH_iSCSI_BACKUP_IMAGE_START_g2 2359296 -#define FLASH_FCoE_PRIMARY_IMAGE_START_g2 3670016 -#define FLASH_FCoE_BACKUP_IMAGE_START_g2 4980736 -#define FLASH_iSCSI_BIOS_START_g2 7340032 -#define FLASH_PXE_BIOS_START_g2 7864320 - -#define FLASH_REDBOOT_START_g3 262144 -#define FLASH_PHY_FW_START_g3 1310720 -#define FLASH_iSCSI_PRIMARY_IMAGE_START_g3 2097152 -#define FLASH_iSCSI_BACKUP_IMAGE_START_g3 4194304 -#define FLASH_FCoE_PRIMARY_IMAGE_START_g3 6291456 -#define FLASH_FCoE_BACKUP_IMAGE_START_g3 8388608 -#define FLASH_iSCSI_BIOS_START_g3 12582912 -#define FLASH_PXE_BIOS_START_g3 13107200 -#define FLASH_FCoE_BIOS_START_g3 13631488 -#define FLASH_NCSI_START_g3 15990784 - -#define IMAGE_NCSI 16 -#define IMAGE_OPTION_ROM_PXE 32 -#define IMAGE_OPTION_ROM_FCoE 33 -#define IMAGE_OPTION_ROM_ISCSI 34 -#define IMAGE_FLASHISM_JUMPVECTOR 48 -#define IMAGE_FIRMWARE_iSCSI 160 -#define IMAGE_FIRMWARE_FCoE 162 -#define IMAGE_FIRMWARE_BACKUP_iSCSI 176 -#define IMAGE_FIRMWARE_BACKUP_FCoE 178 -#define IMAGE_FIRMWARE_PHY 192 -#define IMAGE_REDBOOT_DIR 208 -#define IMAGE_REDBOOT_CONFIG 209 -#define IMAGE_UFI_DIR 210 -#define IMAGE_BOOT_CODE 224 +/* Optypes of each component in the UFI */ +enum { + OPTYPE_ISCSI_ACTIVE = 0, + OPTYPE_REDBOOT = 1, + OPTYPE_BIOS = 2, + OPTYPE_PXE_BIOS = 3, + OPTYPE_OFFSET_SPECIFIED = 7, + OPTYPE_FCOE_BIOS = 8, + OPTYPE_ISCSI_BACKUP = 9, + OPTYPE_FCOE_FW_ACTIVE = 10, + OPTYPE_FCOE_FW_BACKUP = 11, + OPTYPE_NCSI_FW = 13, + OPTYPE_REDBOOT_DIR = 18, + OPTYPE_REDBOOT_CONFIG = 19, + OPTYPE_SH_PHY_FW = 21, + OPTYPE_FLASHISM_JUMPVECTOR = 22, + OPTYPE_UFI_DIR = 23, + OPTYPE_PHY_FW = 99 +}; + +/* Maximum sizes of components in BE2 FW UFI */ +enum { + BE2_BIOS_COMP_MAX_SIZE = 0x40000, + BE2_REDBOOT_COMP_MAX_SIZE = 0x40000, + BE2_COMP_MAX_SIZE = 0x140000 +}; + +/* Maximum sizes of components in BE3 FW UFI */ +enum { + BE3_NCSI_COMP_MAX_SIZE = 0x40000, + BE3_PHY_FW_COMP_MAX_SIZE = 0x40000, + BE3_BIOS_COMP_MAX_SIZE = 0x80000, + BE3_REDBOOT_COMP_MAX_SIZE = 0x100000, + BE3_COMP_MAX_SIZE = 0x200000 +}; + +/* Offsets for components in BE2 FW UFI */ +enum { + BE2_REDBOOT_START = 0x8000, + BE2_FCOE_BIOS_START = 0x80000, + BE2_ISCSI_PRIMARY_IMAGE_START = 0x100000, + BE2_ISCSI_BACKUP_IMAGE_START = 0x240000, + BE2_FCOE_PRIMARY_IMAGE_START = 0x380000, + BE2_FCOE_BACKUP_IMAGE_START = 0x4c0000, + BE2_ISCSI_BIOS_START = 0x700000, + BE2_PXE_BIOS_START = 0x780000 +}; + +/* Offsets for components in BE3 FW UFI */ +enum { + BE3_REDBOOT_START = 0x40000, + BE3_PHY_FW_START = 0x140000, + BE3_ISCSI_PRIMARY_IMAGE_START = 0x200000, + BE3_ISCSI_BACKUP_IMAGE_START = 0x400000, + BE3_FCOE_PRIMARY_IMAGE_START = 0x600000, + BE3_FCOE_BACKUP_IMAGE_START = 0x800000, + BE3_ISCSI_BIOS_START = 0xc00000, + BE3_PXE_BIOS_START = 0xc80000, + BE3_FCOE_BIOS_START = 0xd00000, + BE3_NCSI_START = 0xf40000 +}; + +/* Component entry types */ +enum { + IMAGE_NCSI = 0x10, + IMAGE_OPTION_ROM_PXE = 0x20, + IMAGE_OPTION_ROM_FCOE = 0x21, + IMAGE_OPTION_ROM_ISCSI = 0x22, + IMAGE_FLASHISM_JUMPVECTOR = 0x30, + IMAGE_FIRMWARE_ISCSI = 0xa0, + IMAGE_FIRMWARE_FCOE = 0xa2, + IMAGE_FIRMWARE_BACKUP_ISCSI = 0xb0, + IMAGE_FIRMWARE_BACKUP_FCOE = 0xb2, + IMAGE_FIRMWARE_PHY = 0xc0, + IMAGE_REDBOOT_DIR = 0xd0, + IMAGE_REDBOOT_CONFIG = 0xd1, + IMAGE_UFI_DIR = 0xd2, + IMAGE_BOOT_CODE = 0xe2 +}; struct controller_id { u32 vendor; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 2f76cbeab1e49..0bb6e5a29f8d8 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4616,45 +4616,45 @@ static int be_flash_BEx(struct be_adapter *adapter, const u8 *p; struct flash_comp gen3_flash_types[] = { - { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE, - FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_iSCSI}, - { FLASH_REDBOOT_START_g3, OPTYPE_REDBOOT, - FLASH_REDBOOT_IMAGE_MAX_SIZE_g3, IMAGE_BOOT_CODE}, - { FLASH_iSCSI_BIOS_START_g3, OPTYPE_BIOS, - FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_ISCSI}, - { FLASH_PXE_BIOS_START_g3, OPTYPE_PXE_BIOS, - FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_PXE}, - { FLASH_FCoE_BIOS_START_g3, OPTYPE_FCOE_BIOS, - FLASH_BIOS_IMAGE_MAX_SIZE_g3, IMAGE_OPTION_ROM_FCoE}, - { FLASH_iSCSI_BACKUP_IMAGE_START_g3, OPTYPE_ISCSI_BACKUP, - FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_iSCSI}, - { FLASH_FCoE_PRIMARY_IMAGE_START_g3, OPTYPE_FCOE_FW_ACTIVE, - FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_FCoE}, - { FLASH_FCoE_BACKUP_IMAGE_START_g3, OPTYPE_FCOE_FW_BACKUP, - FLASH_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_BACKUP_FCoE}, - { FLASH_NCSI_START_g3, OPTYPE_NCSI_FW, - FLASH_NCSI_IMAGE_MAX_SIZE_g3, IMAGE_NCSI}, - { FLASH_PHY_FW_START_g3, OPTYPE_PHY_FW, - FLASH_PHY_FW_IMAGE_MAX_SIZE_g3, IMAGE_FIRMWARE_PHY} + { BE3_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE, + BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI}, + { BE3_REDBOOT_START, OPTYPE_REDBOOT, + BE3_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE}, + { BE3_ISCSI_BIOS_START, OPTYPE_BIOS, + BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI}, + { BE3_PXE_BIOS_START, OPTYPE_PXE_BIOS, + BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE}, + { BE3_FCOE_BIOS_START, OPTYPE_FCOE_BIOS, + BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE}, + { BE3_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP, + BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI}, + { BE3_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE, + BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE}, + { BE3_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP, + BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE}, + { BE3_NCSI_START, OPTYPE_NCSI_FW, + BE3_NCSI_COMP_MAX_SIZE, IMAGE_NCSI}, + { BE3_PHY_FW_START, OPTYPE_PHY_FW, + BE3_PHY_FW_COMP_MAX_SIZE, IMAGE_FIRMWARE_PHY} }; struct flash_comp gen2_flash_types[] = { - { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, OPTYPE_ISCSI_ACTIVE, - FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_iSCSI}, - { FLASH_REDBOOT_START_g2, OPTYPE_REDBOOT, - FLASH_REDBOOT_IMAGE_MAX_SIZE_g2, IMAGE_BOOT_CODE}, - { FLASH_iSCSI_BIOS_START_g2, OPTYPE_BIOS, - FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_ISCSI}, - { FLASH_PXE_BIOS_START_g2, OPTYPE_PXE_BIOS, - FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_PXE}, - { FLASH_FCoE_BIOS_START_g2, OPTYPE_FCOE_BIOS, - FLASH_BIOS_IMAGE_MAX_SIZE_g2, IMAGE_OPTION_ROM_FCoE}, - { FLASH_iSCSI_BACKUP_IMAGE_START_g2, OPTYPE_ISCSI_BACKUP, - FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_iSCSI}, - { FLASH_FCoE_PRIMARY_IMAGE_START_g2, OPTYPE_FCOE_FW_ACTIVE, - FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_FCoE}, - { FLASH_FCoE_BACKUP_IMAGE_START_g2, OPTYPE_FCOE_FW_BACKUP, - FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_FCoE} + { BE2_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE, + BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI}, + { BE2_REDBOOT_START, OPTYPE_REDBOOT, + BE2_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE}, + { BE2_ISCSI_BIOS_START, OPTYPE_BIOS, + BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI}, + { BE2_PXE_BIOS_START, OPTYPE_PXE_BIOS, + BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE}, + { BE2_FCOE_BIOS_START, OPTYPE_FCOE_BIOS, + BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE}, + { BE2_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP, + BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI}, + { BE2_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE, + BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE}, + { BE2_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP, + BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE} }; if (BE3_chip(adapter)) { @@ -4729,7 +4729,7 @@ static u16 be_get_img_optype(struct flash_section_entry fsec_entry) return img_optype; switch (img_type) { - case IMAGE_FIRMWARE_iSCSI: + case IMAGE_FIRMWARE_ISCSI: img_optype = OPTYPE_ISCSI_ACTIVE; break; case IMAGE_BOOT_CODE: @@ -4741,10 +4741,10 @@ static u16 be_get_img_optype(struct flash_section_entry fsec_entry) case IMAGE_OPTION_ROM_PXE: img_optype = OPTYPE_PXE_BIOS; break; - case IMAGE_OPTION_ROM_FCoE: + case IMAGE_OPTION_ROM_FCOE: img_optype = OPTYPE_FCOE_BIOS; break; - case IMAGE_FIRMWARE_BACKUP_iSCSI: + case IMAGE_FIRMWARE_BACKUP_ISCSI: img_optype = OPTYPE_ISCSI_BACKUP; break; case IMAGE_NCSI: From a23113b5f6db9804da185bab4137dfad5dab9dc8 Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Wed, 30 Dec 2015 01:28:59 -0500 Subject: [PATCH 04/10] be2net: move FW flash cmd code to be_cmds.c All code relating to FW cmds is in be_cmds.[ch] excepting FW flash cmd related code. This patch moves these routines from be_main.c to be_cmds.c Signed-off-by: Suresh Reddy Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 583 +++++++++++++++++++- drivers/net/ethernet/emulex/benet/be_cmds.h | 15 +- drivers/net/ethernet/emulex/benet/be_main.c | 564 ------------------- 3 files changed, 578 insertions(+), 584 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 8083eca608087..da3b39873470f 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -2291,10 +2291,11 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, return status; } -int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, - u32 data_size, u32 data_offset, - const char *obj_name, u32 *data_written, - u8 *change_status, u8 *addn_status) +static int lancer_cmd_write_object(struct be_adapter *adapter, + struct be_dma_mem *cmd, u32 data_size, + u32 data_offset, const char *obj_name, + u32 *data_written, u8 *change_status, + u8 *addn_status) { struct be_mcc_wrb *wrb; struct lancer_cmd_req_write_object *req; @@ -2410,7 +2411,8 @@ int be_cmd_query_sfp_info(struct be_adapter *adapter) return status; } -int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name) +static int lancer_cmd_delete_object(struct be_adapter *adapter, + const char *obj_name) { struct lancer_cmd_req_delete_object *req; struct be_mcc_wrb *wrb; @@ -2485,9 +2487,9 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, return status; } -int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, - u32 flash_type, u32 flash_opcode, u32 img_offset, - u32 buf_size) +static int be_cmd_write_flashrom(struct be_adapter *adapter, + struct be_dma_mem *cmd, u32 flash_type, + u32 flash_opcode, u32 img_offset, u32 buf_size) { struct be_mcc_wrb *wrb; struct be_cmd_write_flashrom *req; @@ -2533,8 +2535,8 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, return status; } -int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, - u16 img_optype, u32 img_offset, u32 crc_offset) +static int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, + u16 img_optype, u32 img_offset, u32 crc_offset) { struct be_cmd_read_flash_crc *req; struct be_mcc_wrb *wrb; @@ -2571,6 +2573,567 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, return status; } +static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; + +static bool phy_flashing_required(struct be_adapter *adapter) +{ + return (adapter->phy.phy_type == PHY_TYPE_TN_8022 && + adapter->phy.interface_type == PHY_TYPE_BASET_10GB); +} + +static bool is_comp_in_ufi(struct be_adapter *adapter, + struct flash_section_info *fsec, int type) +{ + int i = 0, img_type = 0; + struct flash_section_info_g2 *fsec_g2 = NULL; + + if (BE2_chip(adapter)) + fsec_g2 = (struct flash_section_info_g2 *)fsec; + + for (i = 0; i < MAX_FLASH_COMP; i++) { + if (fsec_g2) + img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type); + else + img_type = le32_to_cpu(fsec->fsec_entry[i].type); + + if (img_type == type) + return true; + } + return false; +} + +static struct flash_section_info *get_fsec_info(struct be_adapter *adapter, + int header_size, + const struct firmware *fw) +{ + struct flash_section_info *fsec = NULL; + const u8 *p = fw->data; + + p += header_size; + while (p < (fw->data + fw->size)) { + fsec = (struct flash_section_info *)p; + if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) + return fsec; + p += 32; + } + return NULL; +} + +static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p, + u32 img_offset, u32 img_size, int hdr_size, + u16 img_optype, bool *crc_match) +{ + u32 crc_offset; + int status; + u8 crc[4]; + + status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_offset, + img_size - 4); + if (status) + return status; + + crc_offset = hdr_size + img_offset + img_size - 4; + + /* Skip flashing, if crc of flashed region matches */ + if (!memcmp(crc, p + crc_offset, 4)) + *crc_match = true; + else + *crc_match = false; + + return status; +} + +static int be_flash(struct be_adapter *adapter, const u8 *img, + struct be_dma_mem *flash_cmd, int optype, int img_size, + u32 img_offset) +{ + u32 flash_op, num_bytes, total_bytes = img_size, bytes_sent = 0; + struct be_cmd_write_flashrom *req = flash_cmd->va; + int status; + + while (total_bytes) { + num_bytes = min_t(u32, 32 * 1024, total_bytes); + + total_bytes -= num_bytes; + + if (!total_bytes) { + if (optype == OPTYPE_PHY_FW) + flash_op = FLASHROM_OPER_PHY_FLASH; + else + flash_op = FLASHROM_OPER_FLASH; + } else { + if (optype == OPTYPE_PHY_FW) + flash_op = FLASHROM_OPER_PHY_SAVE; + else + flash_op = FLASHROM_OPER_SAVE; + } + + memcpy(req->data_buf, img, num_bytes); + img += num_bytes; + status = be_cmd_write_flashrom(adapter, flash_cmd, optype, + flash_op, img_offset + + bytes_sent, num_bytes); + if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST && + optype == OPTYPE_PHY_FW) + break; + else if (status) + return status; + + bytes_sent += num_bytes; + } + return 0; +} + +/* For BE2, BE3 and BE3-R */ +static int be_flash_BEx(struct be_adapter *adapter, + const struct firmware *fw, + struct be_dma_mem *flash_cmd, int num_of_images) +{ + int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); + struct device *dev = &adapter->pdev->dev; + struct flash_section_info *fsec = NULL; + int status, i, filehdr_size, num_comp; + const struct flash_comp *pflashcomp; + bool crc_match; + const u8 *p; + + struct flash_comp gen3_flash_types[] = { + { BE3_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE, + BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI}, + { BE3_REDBOOT_START, OPTYPE_REDBOOT, + BE3_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE}, + { BE3_ISCSI_BIOS_START, OPTYPE_BIOS, + BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI}, + { BE3_PXE_BIOS_START, OPTYPE_PXE_BIOS, + BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE}, + { BE3_FCOE_BIOS_START, OPTYPE_FCOE_BIOS, + BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE}, + { BE3_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP, + BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI}, + { BE3_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE, + BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE}, + { BE3_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP, + BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE}, + { BE3_NCSI_START, OPTYPE_NCSI_FW, + BE3_NCSI_COMP_MAX_SIZE, IMAGE_NCSI}, + { BE3_PHY_FW_START, OPTYPE_PHY_FW, + BE3_PHY_FW_COMP_MAX_SIZE, IMAGE_FIRMWARE_PHY} + }; + + struct flash_comp gen2_flash_types[] = { + { BE2_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE, + BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI}, + { BE2_REDBOOT_START, OPTYPE_REDBOOT, + BE2_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE}, + { BE2_ISCSI_BIOS_START, OPTYPE_BIOS, + BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI}, + { BE2_PXE_BIOS_START, OPTYPE_PXE_BIOS, + BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE}, + { BE2_FCOE_BIOS_START, OPTYPE_FCOE_BIOS, + BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE}, + { BE2_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP, + BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI}, + { BE2_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE, + BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE}, + { BE2_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP, + BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE} + }; + + if (BE3_chip(adapter)) { + pflashcomp = gen3_flash_types; + filehdr_size = sizeof(struct flash_file_hdr_g3); + num_comp = ARRAY_SIZE(gen3_flash_types); + } else { + pflashcomp = gen2_flash_types; + filehdr_size = sizeof(struct flash_file_hdr_g2); + num_comp = ARRAY_SIZE(gen2_flash_types); + img_hdrs_size = 0; + } + + /* Get flash section info*/ + fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); + if (!fsec) { + dev_err(dev, "Invalid Cookie. FW image may be corrupted\n"); + return -1; + } + for (i = 0; i < num_comp; i++) { + if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type)) + continue; + + if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) && + memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) + continue; + + if (pflashcomp[i].optype == OPTYPE_PHY_FW && + !phy_flashing_required(adapter)) + continue; + + if (pflashcomp[i].optype == OPTYPE_REDBOOT) { + status = be_check_flash_crc(adapter, fw->data, + pflashcomp[i].offset, + pflashcomp[i].size, + filehdr_size + + img_hdrs_size, + OPTYPE_REDBOOT, &crc_match); + if (status) { + dev_err(dev, + "Could not get CRC for 0x%x region\n", + pflashcomp[i].optype); + continue; + } + + if (crc_match) + continue; + } + + p = fw->data + filehdr_size + pflashcomp[i].offset + + img_hdrs_size; + if (p + pflashcomp[i].size > fw->data + fw->size) + return -1; + + status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype, + pflashcomp[i].size, 0); + if (status) { + dev_err(dev, "Flashing section type 0x%x failed\n", + pflashcomp[i].img_type); + return status; + } + } + return 0; +} + +static u16 be_get_img_optype(struct flash_section_entry fsec_entry) +{ + u32 img_type = le32_to_cpu(fsec_entry.type); + u16 img_optype = le16_to_cpu(fsec_entry.optype); + + if (img_optype != 0xFFFF) + return img_optype; + + switch (img_type) { + case IMAGE_FIRMWARE_ISCSI: + img_optype = OPTYPE_ISCSI_ACTIVE; + break; + case IMAGE_BOOT_CODE: + img_optype = OPTYPE_REDBOOT; + break; + case IMAGE_OPTION_ROM_ISCSI: + img_optype = OPTYPE_BIOS; + break; + case IMAGE_OPTION_ROM_PXE: + img_optype = OPTYPE_PXE_BIOS; + break; + case IMAGE_OPTION_ROM_FCOE: + img_optype = OPTYPE_FCOE_BIOS; + break; + case IMAGE_FIRMWARE_BACKUP_ISCSI: + img_optype = OPTYPE_ISCSI_BACKUP; + break; + case IMAGE_NCSI: + img_optype = OPTYPE_NCSI_FW; + break; + case IMAGE_FLASHISM_JUMPVECTOR: + img_optype = OPTYPE_FLASHISM_JUMPVECTOR; + break; + case IMAGE_FIRMWARE_PHY: + img_optype = OPTYPE_SH_PHY_FW; + break; + case IMAGE_REDBOOT_DIR: + img_optype = OPTYPE_REDBOOT_DIR; + break; + case IMAGE_REDBOOT_CONFIG: + img_optype = OPTYPE_REDBOOT_CONFIG; + break; + case IMAGE_UFI_DIR: + img_optype = OPTYPE_UFI_DIR; + break; + default: + break; + } + + return img_optype; +} + +static int be_flash_skyhawk(struct be_adapter *adapter, + const struct firmware *fw, + struct be_dma_mem *flash_cmd, int num_of_images) +{ + int img_hdrs_size = num_of_images * sizeof(struct image_hdr); + bool crc_match, old_fw_img, flash_offset_support = true; + struct device *dev = &adapter->pdev->dev; + struct flash_section_info *fsec = NULL; + u32 img_offset, img_size, img_type; + u16 img_optype, flash_optype; + int status, i, filehdr_size; + const u8 *p; + + filehdr_size = sizeof(struct flash_file_hdr_g3); + fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); + if (!fsec) { + dev_err(dev, "Invalid Cookie. FW image may be corrupted\n"); + return -EINVAL; + } + +retry_flash: + for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) { + img_offset = le32_to_cpu(fsec->fsec_entry[i].offset); + img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size); + img_type = le32_to_cpu(fsec->fsec_entry[i].type); + img_optype = be_get_img_optype(fsec->fsec_entry[i]); + old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF; + + if (img_optype == 0xFFFF) + continue; + + if (flash_offset_support) + flash_optype = OPTYPE_OFFSET_SPECIFIED; + else + flash_optype = img_optype; + + /* Don't bother verifying CRC if an old FW image is being + * flashed + */ + if (old_fw_img) + goto flash; + + status = be_check_flash_crc(adapter, fw->data, img_offset, + img_size, filehdr_size + + img_hdrs_size, flash_optype, + &crc_match); + if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST || + base_status(status) == MCC_STATUS_ILLEGAL_FIELD) { + /* The current FW image on the card does not support + * OFFSET based flashing. Retry using older mechanism + * of OPTYPE based flashing + */ + if (flash_optype == OPTYPE_OFFSET_SPECIFIED) { + flash_offset_support = false; + goto retry_flash; + } + + /* The current FW image on the card does not recognize + * the new FLASH op_type. The FW download is partially + * complete. Reboot the server now to enable FW image + * to recognize the new FLASH op_type. To complete the + * remaining process, download the same FW again after + * the reboot. + */ + dev_err(dev, "Flash incomplete. Reset the server\n"); + dev_err(dev, "Download FW image again after reset\n"); + return -EAGAIN; + } else if (status) { + dev_err(dev, "Could not get CRC for 0x%x region\n", + img_optype); + return -EFAULT; + } + + if (crc_match) + continue; + +flash: + p = fw->data + filehdr_size + img_offset + img_hdrs_size; + if (p + img_size > fw->data + fw->size) + return -1; + + status = be_flash(adapter, p, flash_cmd, flash_optype, img_size, + img_offset); + + /* The current FW image on the card does not support OFFSET + * based flashing. Retry using older mechanism of OPTYPE based + * flashing + */ + if (base_status(status) == MCC_STATUS_ILLEGAL_FIELD && + flash_optype == OPTYPE_OFFSET_SPECIFIED) { + flash_offset_support = false; + goto retry_flash; + } + + /* For old FW images ignore ILLEGAL_FIELD error or errors on + * UFI_DIR region + */ + if (old_fw_img && + (base_status(status) == MCC_STATUS_ILLEGAL_FIELD || + (img_optype == OPTYPE_UFI_DIR && + base_status(status) == MCC_STATUS_FAILED))) { + continue; + } else if (status) { + dev_err(dev, "Flashing section type 0x%x failed\n", + img_type); + return -EFAULT; + } + } + return 0; +} + +int lancer_fw_download(struct be_adapter *adapter, + const struct firmware *fw) +{ + struct device *dev = &adapter->pdev->dev; + struct be_dma_mem flash_cmd; + const u8 *data_ptr = NULL; + u8 *dest_image_ptr = NULL; + size_t image_size = 0; + u32 chunk_size = 0; + u32 data_written = 0; + u32 offset = 0; + int status = 0; + u8 add_status = 0; + u8 change_status; + + if (!IS_ALIGNED(fw->size, sizeof(u32))) { + dev_err(dev, "FW image size should be multiple of 4\n"); + return -EINVAL; + } + + flash_cmd.size = sizeof(struct lancer_cmd_req_write_object) + + LANCER_FW_DOWNLOAD_CHUNK; + flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, + &flash_cmd.dma, GFP_KERNEL); + if (!flash_cmd.va) + return -ENOMEM; + + dest_image_ptr = flash_cmd.va + + sizeof(struct lancer_cmd_req_write_object); + image_size = fw->size; + data_ptr = fw->data; + + while (image_size) { + chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK); + + /* Copy the image chunk content. */ + memcpy(dest_image_ptr, data_ptr, chunk_size); + + status = lancer_cmd_write_object(adapter, &flash_cmd, + chunk_size, offset, + LANCER_FW_DOWNLOAD_LOCATION, + &data_written, &change_status, + &add_status); + if (status) + break; + + offset += data_written; + data_ptr += data_written; + image_size -= data_written; + } + + if (!status) { + /* Commit the FW written */ + status = lancer_cmd_write_object(adapter, &flash_cmd, + 0, offset, + LANCER_FW_DOWNLOAD_LOCATION, + &data_written, &change_status, + &add_status); + } + + dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma); + if (status) { + dev_err(dev, "Firmware load error\n"); + return be_cmd_status(status); + } + + dev_info(dev, "Firmware flashed successfully\n"); + + if (change_status == LANCER_FW_RESET_NEEDED) { + dev_info(dev, "Resetting adapter to activate new FW\n"); + status = lancer_physdev_ctrl(adapter, + PHYSDEV_CONTROL_FW_RESET_MASK); + if (status) { + dev_err(dev, "Adapter busy, could not reset FW\n"); + dev_err(dev, "Reboot server to activate new FW\n"); + } + } else if (change_status != LANCER_NO_RESET_NEEDED) { + dev_info(dev, "Reboot server to activate new FW\n"); + } + + return 0; +} + +/* Check if the flash image file is compatible with the adapter that + * is being flashed. + */ +static bool be_check_ufi_compatibility(struct be_adapter *adapter, + struct flash_file_hdr_g3 *fhdr) +{ + if (!fhdr) { + dev_err(&adapter->pdev->dev, "Invalid FW UFI file"); + return false; + } + + /* First letter of the build version is used to identify + * which chip this image file is meant for. + */ + switch (fhdr->build[0]) { + case BLD_STR_UFI_TYPE_SH: + if (!skyhawk_chip(adapter)) + return false; + break; + case BLD_STR_UFI_TYPE_BE3: + if (!BE3_chip(adapter)) + return false; + break; + case BLD_STR_UFI_TYPE_BE2: + if (!BE2_chip(adapter)) + return false; + break; + default: + return false; + } + + /* In BE3 FW images the "asic_type_rev" field doesn't track the + * asic_rev of the chips it is compatible with. + * When asic_type_rev is 0 the image is compatible only with + * pre-BE3-R chips (asic_rev < 0x10) + */ + if (BEx_chip(adapter) && fhdr->asic_type_rev == 0) + return adapter->asic_rev < 0x10; + else + return (fhdr->asic_type_rev >= adapter->asic_rev); +} + +int be_fw_download(struct be_adapter *adapter, const struct firmware *fw) +{ + struct device *dev = &adapter->pdev->dev; + struct flash_file_hdr_g3 *fhdr3; + struct image_hdr *img_hdr_ptr; + int status = 0, i, num_imgs; + struct be_dma_mem flash_cmd; + + fhdr3 = (struct flash_file_hdr_g3 *)fw->data; + if (!be_check_ufi_compatibility(adapter, fhdr3)) { + dev_err(dev, "Flash image is not compatible with adapter\n"); + return -EINVAL; + } + + flash_cmd.size = sizeof(struct be_cmd_write_flashrom); + flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, &flash_cmd.dma, + GFP_KERNEL); + if (!flash_cmd.va) + return -ENOMEM; + + num_imgs = le32_to_cpu(fhdr3->num_imgs); + for (i = 0; i < num_imgs; i++) { + img_hdr_ptr = (struct image_hdr *)(fw->data + + (sizeof(struct flash_file_hdr_g3) + + i * sizeof(struct image_hdr))); + if (!BE2_chip(adapter) && + le32_to_cpu(img_hdr_ptr->imageid) != 1) + continue; + + if (skyhawk_chip(adapter)) + status = be_flash_skyhawk(adapter, fw, &flash_cmd, + num_imgs); + else + status = be_flash_BEx(adapter, fw, &flash_cmd, + num_imgs); + } + + dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma); + if (!status) + dev_info(dev, "Firmware flashed successfully\n"); + + return status; +} + int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, struct be_dma_mem *nonemb_cmd) { diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 8c6b606f0e909..4b0ca994d6c38 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -1411,6 +1411,9 @@ struct be_cmd_read_flash_crc { } __packed; /**************** Lancer Firmware Flash ************/ +#define LANCER_FW_DOWNLOAD_CHUNK (32 * 1024) +#define LANCER_FW_DOWNLOAD_LOCATION "/prg" + struct amap_lancer_write_obj_context { u8 write_length[24]; u8 reserved1[7]; @@ -2339,19 +2342,11 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter, u8 page_num, u8 *data); int be_cmd_query_cable_type(struct be_adapter *adapter); int be_cmd_query_sfp_info(struct be_adapter *adapter); -int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, - u32 flash_oper, u32 flash_opcode, u32 img_offset, - u32 buf_size); -int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, - u32 data_size, u32 data_offset, - const char *obj_name, u32 *data_written, - u8 *change_status, u8 *addn_status); int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 data_size, u32 data_offset, const char *obj_name, u32 *data_read, u32 *eof, u8 *addn_status); -int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name); -int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, - u16 img_optype, u32 img_offset, u32 crc_offset); +int lancer_fw_download(struct be_adapter *adapter, const struct firmware *fw); +int be_fw_download(struct be_adapter *adapter, const struct firmware *fw); int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, struct be_dma_mem *nonemb_cmd); int be_cmd_fw_init(struct be_adapter *adapter); diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 0bb6e5a29f8d8..646b02136b0e7 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4490,570 +4490,6 @@ static void be_netpoll(struct net_device *netdev) } #endif -static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; - -static bool phy_flashing_required(struct be_adapter *adapter) -{ - return (adapter->phy.phy_type == PHY_TYPE_TN_8022 && - adapter->phy.interface_type == PHY_TYPE_BASET_10GB); -} - -static bool is_comp_in_ufi(struct be_adapter *adapter, - struct flash_section_info *fsec, int type) -{ - int i = 0, img_type = 0; - struct flash_section_info_g2 *fsec_g2 = NULL; - - if (BE2_chip(adapter)) - fsec_g2 = (struct flash_section_info_g2 *)fsec; - - for (i = 0; i < MAX_FLASH_COMP; i++) { - if (fsec_g2) - img_type = le32_to_cpu(fsec_g2->fsec_entry[i].type); - else - img_type = le32_to_cpu(fsec->fsec_entry[i].type); - - if (img_type == type) - return true; - } - return false; - -} - -static struct flash_section_info *get_fsec_info(struct be_adapter *adapter, - int header_size, - const struct firmware *fw) -{ - struct flash_section_info *fsec = NULL; - const u8 *p = fw->data; - - p += header_size; - while (p < (fw->data + fw->size)) { - fsec = (struct flash_section_info *)p; - if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) - return fsec; - p += 32; - } - return NULL; -} - -static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p, - u32 img_offset, u32 img_size, int hdr_size, - u16 img_optype, bool *crc_match) -{ - u32 crc_offset; - int status; - u8 crc[4]; - - status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_offset, - img_size - 4); - if (status) - return status; - - crc_offset = hdr_size + img_offset + img_size - 4; - - /* Skip flashing, if crc of flashed region matches */ - if (!memcmp(crc, p + crc_offset, 4)) - *crc_match = true; - else - *crc_match = false; - - return status; -} - -static int be_flash(struct be_adapter *adapter, const u8 *img, - struct be_dma_mem *flash_cmd, int optype, int img_size, - u32 img_offset) -{ - u32 flash_op, num_bytes, total_bytes = img_size, bytes_sent = 0; - struct be_cmd_write_flashrom *req = flash_cmd->va; - int status; - - while (total_bytes) { - num_bytes = min_t(u32, 32*1024, total_bytes); - - total_bytes -= num_bytes; - - if (!total_bytes) { - if (optype == OPTYPE_PHY_FW) - flash_op = FLASHROM_OPER_PHY_FLASH; - else - flash_op = FLASHROM_OPER_FLASH; - } else { - if (optype == OPTYPE_PHY_FW) - flash_op = FLASHROM_OPER_PHY_SAVE; - else - flash_op = FLASHROM_OPER_SAVE; - } - - memcpy(req->data_buf, img, num_bytes); - img += num_bytes; - status = be_cmd_write_flashrom(adapter, flash_cmd, optype, - flash_op, img_offset + - bytes_sent, num_bytes); - if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST && - optype == OPTYPE_PHY_FW) - break; - else if (status) - return status; - - bytes_sent += num_bytes; - } - return 0; -} - -/* For BE2, BE3 and BE3-R */ -static int be_flash_BEx(struct be_adapter *adapter, - const struct firmware *fw, - struct be_dma_mem *flash_cmd, int num_of_images) -{ - int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); - struct device *dev = &adapter->pdev->dev; - struct flash_section_info *fsec = NULL; - int status, i, filehdr_size, num_comp; - const struct flash_comp *pflashcomp; - bool crc_match; - const u8 *p; - - struct flash_comp gen3_flash_types[] = { - { BE3_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE, - BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI}, - { BE3_REDBOOT_START, OPTYPE_REDBOOT, - BE3_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE}, - { BE3_ISCSI_BIOS_START, OPTYPE_BIOS, - BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI}, - { BE3_PXE_BIOS_START, OPTYPE_PXE_BIOS, - BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE}, - { BE3_FCOE_BIOS_START, OPTYPE_FCOE_BIOS, - BE3_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE}, - { BE3_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP, - BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI}, - { BE3_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE, - BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE}, - { BE3_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP, - BE3_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE}, - { BE3_NCSI_START, OPTYPE_NCSI_FW, - BE3_NCSI_COMP_MAX_SIZE, IMAGE_NCSI}, - { BE3_PHY_FW_START, OPTYPE_PHY_FW, - BE3_PHY_FW_COMP_MAX_SIZE, IMAGE_FIRMWARE_PHY} - }; - - struct flash_comp gen2_flash_types[] = { - { BE2_ISCSI_PRIMARY_IMAGE_START, OPTYPE_ISCSI_ACTIVE, - BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_ISCSI}, - { BE2_REDBOOT_START, OPTYPE_REDBOOT, - BE2_REDBOOT_COMP_MAX_SIZE, IMAGE_BOOT_CODE}, - { BE2_ISCSI_BIOS_START, OPTYPE_BIOS, - BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_ISCSI}, - { BE2_PXE_BIOS_START, OPTYPE_PXE_BIOS, - BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_PXE}, - { BE2_FCOE_BIOS_START, OPTYPE_FCOE_BIOS, - BE2_BIOS_COMP_MAX_SIZE, IMAGE_OPTION_ROM_FCOE}, - { BE2_ISCSI_BACKUP_IMAGE_START, OPTYPE_ISCSI_BACKUP, - BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_ISCSI}, - { BE2_FCOE_PRIMARY_IMAGE_START, OPTYPE_FCOE_FW_ACTIVE, - BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_FCOE}, - { BE2_FCOE_BACKUP_IMAGE_START, OPTYPE_FCOE_FW_BACKUP, - BE2_COMP_MAX_SIZE, IMAGE_FIRMWARE_BACKUP_FCOE} - }; - - if (BE3_chip(adapter)) { - pflashcomp = gen3_flash_types; - filehdr_size = sizeof(struct flash_file_hdr_g3); - num_comp = ARRAY_SIZE(gen3_flash_types); - } else { - pflashcomp = gen2_flash_types; - filehdr_size = sizeof(struct flash_file_hdr_g2); - num_comp = ARRAY_SIZE(gen2_flash_types); - img_hdrs_size = 0; - } - - /* Get flash section info*/ - fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); - if (!fsec) { - dev_err(dev, "Invalid Cookie. FW image may be corrupted\n"); - return -1; - } - for (i = 0; i < num_comp; i++) { - if (!is_comp_in_ufi(adapter, fsec, pflashcomp[i].img_type)) - continue; - - if ((pflashcomp[i].optype == OPTYPE_NCSI_FW) && - memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) - continue; - - if (pflashcomp[i].optype == OPTYPE_PHY_FW && - !phy_flashing_required(adapter)) - continue; - - if (pflashcomp[i].optype == OPTYPE_REDBOOT) { - status = be_check_flash_crc(adapter, fw->data, - pflashcomp[i].offset, - pflashcomp[i].size, - filehdr_size + - img_hdrs_size, - OPTYPE_REDBOOT, &crc_match); - if (status) { - dev_err(dev, - "Could not get CRC for 0x%x region\n", - pflashcomp[i].optype); - continue; - } - - if (crc_match) - continue; - } - - p = fw->data + filehdr_size + pflashcomp[i].offset + - img_hdrs_size; - if (p + pflashcomp[i].size > fw->data + fw->size) - return -1; - - status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype, - pflashcomp[i].size, 0); - if (status) { - dev_err(dev, "Flashing section type 0x%x failed\n", - pflashcomp[i].img_type); - return status; - } - } - return 0; -} - -static u16 be_get_img_optype(struct flash_section_entry fsec_entry) -{ - u32 img_type = le32_to_cpu(fsec_entry.type); - u16 img_optype = le16_to_cpu(fsec_entry.optype); - - if (img_optype != 0xFFFF) - return img_optype; - - switch (img_type) { - case IMAGE_FIRMWARE_ISCSI: - img_optype = OPTYPE_ISCSI_ACTIVE; - break; - case IMAGE_BOOT_CODE: - img_optype = OPTYPE_REDBOOT; - break; - case IMAGE_OPTION_ROM_ISCSI: - img_optype = OPTYPE_BIOS; - break; - case IMAGE_OPTION_ROM_PXE: - img_optype = OPTYPE_PXE_BIOS; - break; - case IMAGE_OPTION_ROM_FCOE: - img_optype = OPTYPE_FCOE_BIOS; - break; - case IMAGE_FIRMWARE_BACKUP_ISCSI: - img_optype = OPTYPE_ISCSI_BACKUP; - break; - case IMAGE_NCSI: - img_optype = OPTYPE_NCSI_FW; - break; - case IMAGE_FLASHISM_JUMPVECTOR: - img_optype = OPTYPE_FLASHISM_JUMPVECTOR; - break; - case IMAGE_FIRMWARE_PHY: - img_optype = OPTYPE_SH_PHY_FW; - break; - case IMAGE_REDBOOT_DIR: - img_optype = OPTYPE_REDBOOT_DIR; - break; - case IMAGE_REDBOOT_CONFIG: - img_optype = OPTYPE_REDBOOT_CONFIG; - break; - case IMAGE_UFI_DIR: - img_optype = OPTYPE_UFI_DIR; - break; - default: - break; - } - - return img_optype; -} - -static int be_flash_skyhawk(struct be_adapter *adapter, - const struct firmware *fw, - struct be_dma_mem *flash_cmd, int num_of_images) -{ - int img_hdrs_size = num_of_images * sizeof(struct image_hdr); - bool crc_match, old_fw_img, flash_offset_support = true; - struct device *dev = &adapter->pdev->dev; - struct flash_section_info *fsec = NULL; - u32 img_offset, img_size, img_type; - u16 img_optype, flash_optype; - int status, i, filehdr_size; - const u8 *p; - - filehdr_size = sizeof(struct flash_file_hdr_g3); - fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); - if (!fsec) { - dev_err(dev, "Invalid Cookie. FW image may be corrupted\n"); - return -EINVAL; - } - -retry_flash: - for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) { - img_offset = le32_to_cpu(fsec->fsec_entry[i].offset); - img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size); - img_type = le32_to_cpu(fsec->fsec_entry[i].type); - img_optype = be_get_img_optype(fsec->fsec_entry[i]); - old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF; - - if (img_optype == 0xFFFF) - continue; - - if (flash_offset_support) - flash_optype = OPTYPE_OFFSET_SPECIFIED; - else - flash_optype = img_optype; - - /* Don't bother verifying CRC if an old FW image is being - * flashed - */ - if (old_fw_img) - goto flash; - - status = be_check_flash_crc(adapter, fw->data, img_offset, - img_size, filehdr_size + - img_hdrs_size, flash_optype, - &crc_match); - if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST || - base_status(status) == MCC_STATUS_ILLEGAL_FIELD) { - /* The current FW image on the card does not support - * OFFSET based flashing. Retry using older mechanism - * of OPTYPE based flashing - */ - if (flash_optype == OPTYPE_OFFSET_SPECIFIED) { - flash_offset_support = false; - goto retry_flash; - } - - /* The current FW image on the card does not recognize - * the new FLASH op_type. The FW download is partially - * complete. Reboot the server now to enable FW image - * to recognize the new FLASH op_type. To complete the - * remaining process, download the same FW again after - * the reboot. - */ - dev_err(dev, "Flash incomplete. Reset the server\n"); - dev_err(dev, "Download FW image again after reset\n"); - return -EAGAIN; - } else if (status) { - dev_err(dev, "Could not get CRC for 0x%x region\n", - img_optype); - return -EFAULT; - } - - if (crc_match) - continue; - -flash: - p = fw->data + filehdr_size + img_offset + img_hdrs_size; - if (p + img_size > fw->data + fw->size) - return -1; - - status = be_flash(adapter, p, flash_cmd, flash_optype, img_size, - img_offset); - - /* The current FW image on the card does not support OFFSET - * based flashing. Retry using older mechanism of OPTYPE based - * flashing - */ - if (base_status(status) == MCC_STATUS_ILLEGAL_FIELD && - flash_optype == OPTYPE_OFFSET_SPECIFIED) { - flash_offset_support = false; - goto retry_flash; - } - - /* For old FW images ignore ILLEGAL_FIELD error or errors on - * UFI_DIR region - */ - if (old_fw_img && - (base_status(status) == MCC_STATUS_ILLEGAL_FIELD || - (img_optype == OPTYPE_UFI_DIR && - base_status(status) == MCC_STATUS_FAILED))) { - continue; - } else if (status) { - dev_err(dev, "Flashing section type 0x%x failed\n", - img_type); - return -EFAULT; - } - } - return 0; -} - -static int lancer_fw_download(struct be_adapter *adapter, - const struct firmware *fw) -{ -#define LANCER_FW_DOWNLOAD_CHUNK (32 * 1024) -#define LANCER_FW_DOWNLOAD_LOCATION "/prg" - struct device *dev = &adapter->pdev->dev; - struct be_dma_mem flash_cmd; - const u8 *data_ptr = NULL; - u8 *dest_image_ptr = NULL; - size_t image_size = 0; - u32 chunk_size = 0; - u32 data_written = 0; - u32 offset = 0; - int status = 0; - u8 add_status = 0; - u8 change_status; - - if (!IS_ALIGNED(fw->size, sizeof(u32))) { - dev_err(dev, "FW image size should be multiple of 4\n"); - return -EINVAL; - } - - flash_cmd.size = sizeof(struct lancer_cmd_req_write_object) - + LANCER_FW_DOWNLOAD_CHUNK; - flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, - &flash_cmd.dma, GFP_KERNEL); - if (!flash_cmd.va) - return -ENOMEM; - - dest_image_ptr = flash_cmd.va + - sizeof(struct lancer_cmd_req_write_object); - image_size = fw->size; - data_ptr = fw->data; - - while (image_size) { - chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK); - - /* Copy the image chunk content. */ - memcpy(dest_image_ptr, data_ptr, chunk_size); - - status = lancer_cmd_write_object(adapter, &flash_cmd, - chunk_size, offset, - LANCER_FW_DOWNLOAD_LOCATION, - &data_written, &change_status, - &add_status); - if (status) - break; - - offset += data_written; - data_ptr += data_written; - image_size -= data_written; - } - - if (!status) { - /* Commit the FW written */ - status = lancer_cmd_write_object(adapter, &flash_cmd, - 0, offset, - LANCER_FW_DOWNLOAD_LOCATION, - &data_written, &change_status, - &add_status); - } - - dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma); - if (status) { - dev_err(dev, "Firmware load error\n"); - return be_cmd_status(status); - } - - dev_info(dev, "Firmware flashed successfully\n"); - - if (change_status == LANCER_FW_RESET_NEEDED) { - dev_info(dev, "Resetting adapter to activate new FW\n"); - status = lancer_physdev_ctrl(adapter, - PHYSDEV_CONTROL_FW_RESET_MASK); - if (status) { - dev_err(dev, "Adapter busy, could not reset FW\n"); - dev_err(dev, "Reboot server to activate new FW\n"); - } - } else if (change_status != LANCER_NO_RESET_NEEDED) { - dev_info(dev, "Reboot server to activate new FW\n"); - } - - return 0; -} - -/* Check if the flash image file is compatible with the adapter that - * is being flashed. - */ -static bool be_check_ufi_compatibility(struct be_adapter *adapter, - struct flash_file_hdr_g3 *fhdr) -{ - if (!fhdr) { - dev_err(&adapter->pdev->dev, "Invalid FW UFI file"); - return false; - } - - /* First letter of the build version is used to identify - * which chip this image file is meant for. - */ - switch (fhdr->build[0]) { - case BLD_STR_UFI_TYPE_SH: - if (!skyhawk_chip(adapter)) - return false; - break; - case BLD_STR_UFI_TYPE_BE3: - if (!BE3_chip(adapter)) - return false; - break; - case BLD_STR_UFI_TYPE_BE2: - if (!BE2_chip(adapter)) - return false; - break; - default: - return false; - } - - /* In BE3 FW images the "asic_type_rev" field doesn't track the - * asic_rev of the chips it is compatible with. - * When asic_type_rev is 0 the image is compatible only with - * pre-BE3-R chips (asic_rev < 0x10) - */ - if (BEx_chip(adapter) && fhdr->asic_type_rev == 0) - return adapter->asic_rev < 0x10; - else - return (fhdr->asic_type_rev >= adapter->asic_rev); -} - -static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) -{ - struct device *dev = &adapter->pdev->dev; - struct flash_file_hdr_g3 *fhdr3; - struct image_hdr *img_hdr_ptr; - int status = 0, i, num_imgs; - struct be_dma_mem flash_cmd; - - fhdr3 = (struct flash_file_hdr_g3 *)fw->data; - if (!be_check_ufi_compatibility(adapter, fhdr3)) { - dev_err(dev, "Flash image is not compatible with adapter\n"); - return -EINVAL; - } - - flash_cmd.size = sizeof(struct be_cmd_write_flashrom); - flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, &flash_cmd.dma, - GFP_KERNEL); - if (!flash_cmd.va) - return -ENOMEM; - - num_imgs = le32_to_cpu(fhdr3->num_imgs); - for (i = 0; i < num_imgs; i++) { - img_hdr_ptr = (struct image_hdr *)(fw->data + - (sizeof(struct flash_file_hdr_g3) + - i * sizeof(struct image_hdr))); - if (!BE2_chip(adapter) && - le32_to_cpu(img_hdr_ptr->imageid) != 1) - continue; - - if (skyhawk_chip(adapter)) - status = be_flash_skyhawk(adapter, fw, &flash_cmd, - num_imgs); - else - status = be_flash_BEx(adapter, fw, &flash_cmd, - num_imgs); - } - - dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma); - if (!status) - dev_info(dev, "Firmware flashed successfully\n"); - - return status; -} - int be_load_fw(struct be_adapter *adapter, u8 *fw_file) { const struct firmware *fw; From 6b525782820f49079a0848f72d7a379f0c101cf8 Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Wed, 30 Dec 2015 01:29:00 -0500 Subject: [PATCH 05/10] be2net: log digital signature errors while flashing FW image (based on a jumper setting on the adapter.) In this mode, the FW image when flashed is authenticated with a digital signature. This patch logs appropriate error messages and return a status to ethtool when errors relating to FW image authentication occur. Signed-off-by: Suresh Reddy Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be_cmds.c | 14 +++++++++++++- drivers/net/ethernet/emulex/benet/be_cmds.h | 4 +++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index da3b39873470f..451f9eaa27a24 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -2959,7 +2959,19 @@ static int be_flash_skyhawk(struct be_adapter *adapter, } else if (status) { dev_err(dev, "Flashing section type 0x%x failed\n", img_type); - return -EFAULT; + + switch (addl_status(status)) { + case MCC_ADDL_STATUS_MISSING_SIGNATURE: + dev_err(dev, + "Digital signature missing in FW\n"); + return -EINVAL; + case MCC_ADDL_STATUS_INVALID_SIGNATURE: + dev_err(dev, + "Invalid digital signature in FW\n"); + return -EINVAL; + default: + return -EFAULT; + } } } return 0; diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 4b0ca994d6c38..16415cad12980 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -66,7 +66,9 @@ enum mcc_addl_status { MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES = 0x16, MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH = 0x4d, MCC_ADDL_STATUS_TOO_MANY_INTERFACES = 0x4a, - MCC_ADDL_STATUS_INSUFFICIENT_VLANS = 0xab + MCC_ADDL_STATUS_INSUFFICIENT_VLANS = 0xab, + MCC_ADDL_STATUS_INVALID_SIGNATURE = 0x56, + MCC_ADDL_STATUS_MISSING_SIGNATURE = 0x57 }; #define CQE_BASE_STATUS_MASK 0xFFFF From fdf81bfb7aab307146cdc33c1d741db324572ca3 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 30 Dec 2015 01:29:01 -0500 Subject: [PATCH 06/10] be2net: remove a line of code that has no effect This patch removes a line of code that changes adapter->recommended_prio value followed by yet another assignment. Also, the variable is used to store the vlan priority value that is already shifted to the PCP bits position in the vlan tag format. Hence, the name of this variable is changed to recommended_prio_bits. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 2 +- drivers/net/ethernet/emulex/benet/be_cmds.c | 3 +-- drivers/net/ethernet/emulex/benet/be_main.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index d463563e1f703..93e5eab20e028 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -521,7 +521,7 @@ struct be_adapter { struct be_drv_stats drv_stats; struct be_aic_obj aic_obj[MAX_EVT_QS]; u8 vlan_prio_bmap; /* Available Priority BitMap */ - u16 recommended_prio; /* Recommended Priority */ + u16 recommended_prio_bits;/* Recommended Priority bits in vlan tag */ struct be_dma_mem rx_filter; /* Cmd DMA mem for rx-filter */ struct be_dma_mem stats_cmd; diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 451f9eaa27a24..7c0e7ff4679f3 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -308,8 +308,7 @@ static void be_async_grp5_cos_priority_process(struct be_adapter *adapter, if (evt->valid) { adapter->vlan_prio_bmap = evt->available_priority_bmap; - adapter->recommended_prio &= ~VLAN_PRIO_MASK; - adapter->recommended_prio = + adapter->recommended_prio_bits = evt->reco_default_priority << VLAN_PRIO_SHIFT; } } diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 646b02136b0e7..c9f9d4b7e6af4 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -729,7 +729,7 @@ static inline u16 be_get_tx_vlan_tag(struct be_adapter *adapter, /* If vlan priority provided by OS is NOT in available bmap */ if (!(adapter->vlan_prio_bmap & (1 << vlan_prio))) vlan_tag = (vlan_tag & ~VLAN_PRIO_MASK) | - adapter->recommended_prio; + adapter->recommended_prio_bits; return vlan_tag; } From 04e888de2d72b587f81a18e42cb9af2c020ef63b Mon Sep 17 00:00:00 2001 From: Venkat Duvvuru Date: Wed, 30 Dec 2015 01:29:02 -0500 Subject: [PATCH 07/10] be2net: remove unused error variables eeh_error, fw_timeout, hw_error variables in the be_adapter structure are not used anymore. An earlier patch that introduced adapter->err_flags to store this information missed removing these variables. Signed-off-by: Venkat Duvvuru Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 93e5eab20e028..0af32f15007c6 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -547,10 +547,6 @@ struct be_adapter { u32 beacon_state; /* for set_phys_id */ - bool eeh_error; - bool fw_timeout; - bool hw_error; - u32 port_num; char port_name; u8 mc_type; From 980df249bdab2adc8522d2178bfffceba79c5e6b Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Wed, 30 Dec 2015 01:29:03 -0500 Subject: [PATCH 08/10] be2net: fix port-res desc query of GET_PROFILE_CONFIG FW cmd Commit 72ef3a88fa8e ("be2net: set pci_func_num while issuing GET_PROFILE_CONFIG cmd") passed a specific pf_num while issuing a GET_PROFILE_CONFIG cmd as FW returns descriptors for all functions when pf_num is zero. But, when pf_num is set to a non-zero value, FW does not return the Port resource descriptor. This patch fixes this by setting pf_num to 0 while issuing the query cmd and adds code to pick the correct NIC resource descriptor from the list of descriptors returned by FW. Fixes: 72ef3a88fa8e ("be2net: set pci_func_num while issuing GET_PROFILE_CONFIG cmd") Signed-off-by: Suresh Reddy Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 4 +- drivers/net/ethernet/emulex/benet/be_cmds.c | 85 +++++++++++---------- drivers/net/ethernet/emulex/benet/be_cmds.h | 11 +-- drivers/net/ethernet/emulex/benet/be_main.c | 16 +++- 4 files changed, 63 insertions(+), 53 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 0af32f15007c6..66988f4312f90 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -570,6 +570,8 @@ struct be_adapter { struct be_resources pool_res; /* resources available for the port */ struct be_resources res; /* resources available for the func */ u16 num_vfs; /* Number of VFs provisioned by PF */ + u8 pf_num; /* Numbering used by FW, starts at 0 */ + u8 vf_num; /* Numbering used by FW, starts at 1 */ u8 virtfn; struct be_vf_cfg *vf_cfg; bool be3_native; @@ -587,8 +589,6 @@ struct be_adapter { u32 msg_enable; int be_get_temp_freq; struct be_hwmon hwmon_info; - u8 pf_number; - u8 pci_func_num; struct rss_info rss_info; /* Filters for packets that need to be sent to BMC */ u32 bmc_filt_mask; diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 7c0e7ff4679f3..b92ee06555c5f 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -3466,7 +3466,6 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter) if (!status) { attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr); adapter->hba_port_num = attribs->hba_attribs.phy_port; - adapter->pci_func_num = attribs->pci_func_num; serial_num = attribs->hba_attribs.controller_serial_number; for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++) adapter->serial_num[i] = le32_to_cpu(serial_num[i]) & @@ -4149,14 +4148,16 @@ int be_cmd_query_port_name(struct be_adapter *adapter) return status; } -/* Descriptor type */ -enum { - FUNC_DESC = 1, - VFT_DESC = 2 -}; - +/* When more than 1 NIC descriptor is present in the descriptor list, + * the caller must specify the pf_num to obtain the NIC descriptor + * corresponding to its pci function. + * get_vft must be true when the caller wants the VF-template desc of the + * PF-pool. + * The pf_num should be set to PF_NUM_IGNORE when the caller knows + * that only it's NIC descriptor is present in the descriptor list. + */ static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count, - int desc_type) + bool get_vft, u8 pf_num) { struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; struct be_nic_res_desc *nic; @@ -4166,40 +4167,42 @@ static struct be_nic_res_desc *be_get_nic_desc(u8 *buf, u32 desc_count, if (hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V0 || hdr->desc_type == NIC_RESOURCE_DESC_TYPE_V1) { nic = (struct be_nic_res_desc *)hdr; - if (desc_type == FUNC_DESC || - (desc_type == VFT_DESC && - nic->flags & (1 << VFT_SHIFT))) + + if ((pf_num == PF_NUM_IGNORE || + nic->pf_num == pf_num) && + (!get_vft || nic->flags & BIT(VFT_SHIFT))) return nic; } - hdr->desc_len = hdr->desc_len ? : RESOURCE_DESC_SIZE_V0; hdr = (void *)hdr + hdr->desc_len; } return NULL; } -static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count) +static struct be_nic_res_desc *be_get_vft_desc(u8 *buf, u32 desc_count, + u8 pf_num) { - return be_get_nic_desc(buf, desc_count, VFT_DESC); + return be_get_nic_desc(buf, desc_count, true, pf_num); } -static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count) +static struct be_nic_res_desc *be_get_func_nic_desc(u8 *buf, u32 desc_count, + u8 pf_num) { - return be_get_nic_desc(buf, desc_count, FUNC_DESC); + return be_get_nic_desc(buf, desc_count, false, pf_num); } -static struct be_pcie_res_desc *be_get_pcie_desc(u8 devfn, u8 *buf, - u32 desc_count) +static struct be_pcie_res_desc *be_get_pcie_desc(u8 *buf, u32 desc_count, + u8 pf_num) { struct be_res_desc_hdr *hdr = (struct be_res_desc_hdr *)buf; struct be_pcie_res_desc *pcie; int i; for (i = 0; i < desc_count; i++) { - if ((hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 || - hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1)) { - pcie = (struct be_pcie_res_desc *)hdr; - if (pcie->pf_num == devfn) + if (hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V0 || + hdr->desc_type == PCIE_RESOURCE_DESC_TYPE_V1) { + pcie = (struct be_pcie_res_desc *)hdr; + if (pcie->pf_num == pf_num) return pcie; } @@ -4284,13 +4287,23 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res) u32 desc_count = le32_to_cpu(resp->desc_count); struct be_nic_res_desc *desc; - desc = be_get_func_nic_desc(resp->func_param, desc_count); + /* GET_FUNC_CONFIG returns resource descriptors of the + * current function only. So, pf_num should be set to + * PF_NUM_IGNORE. + */ + desc = be_get_func_nic_desc(resp->func_param, desc_count, + PF_NUM_IGNORE); if (!desc) { status = -EINVAL; goto err; } - adapter->pf_number = desc->pf_num; - be_copy_nic_desc(res, desc); + + /* Store pf_num & vf_num for later use in GET_PROFILE_CONFIG */ + adapter->pf_num = desc->pf_num; + adapter->vf_num = desc->vf_num; + + if (res) + be_copy_nic_desc(res, desc); } err: mutex_unlock(&adapter->mbox_lock); @@ -4300,10 +4313,7 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res) return status; } -/* Will use MBOX only if MCCQ has not been created - * non-zero domain => a PF is querying this on behalf of a VF - * zero domain => a PF or a VF is querying this for itself - */ +/* Will use MBOX only if MCCQ has not been created */ int be_cmd_get_profile_config(struct be_adapter *adapter, struct be_resources *res, u8 query, u8 domain) { @@ -4333,12 +4343,7 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, if (!lancer_chip(adapter)) req->hdr.version = 1; req->type = ACTIVE_PROFILE_TYPE; - /* When a function is querying profile information relating to - * itself hdr.pf_number must be set to it's pci_func_num + 1 - */ req->hdr.domain = domain; - if (domain == 0) - req->hdr.pf_num = adapter->pci_func_num + 1; /* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the * descriptors with all bits set to "1" for the fields which can be @@ -4354,8 +4359,8 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, resp = cmd.va; desc_count = le16_to_cpu(resp->desc_count); - pcie = be_get_pcie_desc(adapter->pdev->devfn, resp->func_param, - desc_count); + pcie = be_get_pcie_desc(resp->func_param, desc_count, + adapter->pf_num); if (pcie) res->max_vfs = le16_to_cpu(pcie->num_vfs); @@ -4363,11 +4368,13 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, if (port) adapter->mc_type = port->mc_type; - nic = be_get_func_nic_desc(resp->func_param, desc_count); + nic = be_get_func_nic_desc(resp->func_param, desc_count, + adapter->pf_num); if (nic) be_copy_nic_desc(res, nic); - vf_res = be_get_vft_desc(resp->func_param, desc_count); + vf_res = be_get_vft_desc(resp->func_param, desc_count, + adapter->pf_num); if (vf_res) res->vf_if_cap_flags = vf_res->cap_flags; err: @@ -4457,7 +4464,7 @@ int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed, return be_cmd_set_qos(adapter, max_rate / 10, domain); be_reset_nic_desc(&nic_desc); - nic_desc.pf_num = adapter->pf_number; + nic_desc.pf_num = adapter->pf_num; nic_desc.vf_num = domain; nic_desc.bw_min = 0; if (lancer_chip(adapter)) { diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 16415cad12980..50981700cdb0d 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -291,9 +291,7 @@ struct be_cmd_req_hdr { u32 timeout; /* dword 1 */ u32 request_length; /* dword 2 */ u8 version; /* dword 3 */ - u8 rsvd1; /* dword 3 */ - u8 pf_num; /* dword 3 */ - u8 rsvd2; /* dword 3 */ + u8 rsvd[3]; /* dword 3 */ }; #define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ @@ -1676,11 +1674,7 @@ struct mgmt_hba_attribs { struct mgmt_controller_attrib { struct mgmt_hba_attribs hba_attribs; - u32 rsvd0[2]; - u16 rsvd1; - u8 pci_func_num; - u8 rsvd2; - u32 rsvd3[7]; + u32 rsvd0[10]; } __packed; struct be_cmd_req_cntl_attribs { @@ -2105,6 +2099,7 @@ struct be_port_res_desc { #define NV_TYPE_VXLAN 3 #define SOCVID_SHIFT 2 /* Strip outer vlan */ #define RCVID_SHIFT 4 /* Report vlan */ +#define PF_NUM_IGNORE 255 u8 nv_flags; u8 rsvd2; __le16 nv_port; /* vxlan/gre port */ diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index c9f9d4b7e6af4..7039870a4e436 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4204,6 +4204,10 @@ static int be_get_config(struct be_adapter *adapter) int status, level; u16 profile_id; + status = be_cmd_get_cntl_attributes(adapter); + if (status) + return status; + status = be_cmd_query_fw_cfg(adapter); if (status) return status; @@ -4402,10 +4406,14 @@ static int be_setup(struct be_adapter *adapter) if (!lancer_chip(adapter)) be_cmd_req_native_mode(adapter); - /* Need to invoke this cmd first to get the PCI Function Number */ - status = be_cmd_get_cntl_attributes(adapter); - if (status) - return status; + /* invoke this cmd first to get pf_num and vf_num which are needed + * for issuing profile related cmds + */ + if (!BEx_chip(adapter)) { + status = be_cmd_get_func_config(adapter, NULL); + if (status) + return status; + } if (!BE2_chip(adapter) && be_physfn(adapter)) be_alloc_sriov_res(adapter); From fd7ff6f06a4eda894e309bf21c6f11fc86f08841 Mon Sep 17 00:00:00 2001 From: Venkat Duvvuru Date: Wed, 30 Dec 2015 01:29:04 -0500 Subject: [PATCH 09/10] be2net: support ethtool get-dump option This patch adds support for ethtool's --get-dump option in be2net, to retrieve FW dump. In the past when this option was not yet available, this feature was supported via the --register-dump option as a workaround. This patch removes support for FW-dump via --register-dump option as it is now available via --get-dump option. Even though the "ethtool --register-dump" cmd which used to work earlier, will now fail with ENOTSUPP error, we feel it is not an issue as this is used only for diagnostics purpose. Signed-off-by: Venkat Duvvuru Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 1 + drivers/net/ethernet/emulex/benet/be_cmds.c | 38 +++------ drivers/net/ethernet/emulex/benet/be_cmds.h | 4 +- .../net/ethernet/emulex/benet/be_ethtool.c | 82 ++++++++++++------- drivers/net/ethernet/emulex/benet/be_main.c | 3 + 5 files changed, 71 insertions(+), 57 deletions(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 66988f4312f90..8b8212fda632b 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -592,6 +592,7 @@ struct be_adapter { struct rss_info rss_info; /* Filters for packets that need to be sent to BMC */ u32 bmc_filt_mask; + u32 fat_dump_len; u16 serial_num[CNTL_SERIAL_NUM_WORDS]; }; diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index b92ee06555c5f..b63d8ad2e1157 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1712,49 +1712,40 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter) } /* Uses synchronous mcc */ -int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size) +int be_cmd_get_fat_dump_len(struct be_adapter *adapter, u32 *dump_size) { - struct be_mcc_wrb *wrb; + struct be_mcc_wrb wrb = {0}; struct be_cmd_req_get_fat *req; int status; - spin_lock_bh(&adapter->mcc_lock); - - wrb = wrb_from_mccq(adapter); - if (!wrb) { - status = -EBUSY; - goto err; - } - req = embedded_payload(wrb); + req = embedded_payload(&wrb); be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, - OPCODE_COMMON_MANAGE_FAT, sizeof(*req), wrb, - NULL); + OPCODE_COMMON_MANAGE_FAT, sizeof(*req), + &wrb, NULL); req->fat_operation = cpu_to_le32(QUERY_FAT); - status = be_mcc_notify_wait(adapter); + status = be_cmd_notify_wait(adapter, &wrb); if (!status) { - struct be_cmd_resp_get_fat *resp = embedded_payload(wrb); + struct be_cmd_resp_get_fat *resp = embedded_payload(&wrb); - if (log_size && resp->log_size) - *log_size = le32_to_cpu(resp->log_size) - + if (dump_size && resp->log_size) + *dump_size = le32_to_cpu(resp->log_size) - sizeof(u32); } -err: - spin_unlock_bh(&adapter->mcc_lock); return status; } -int be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf) +int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf) { struct be_dma_mem get_fat_cmd; struct be_mcc_wrb *wrb; struct be_cmd_req_get_fat *req; u32 offset = 0, total_size, buf_size, log_offset = sizeof(u32), payload_len; - int status = 0; + int status; if (buf_len == 0) - return -EIO; + return 0; total_size = buf_len; @@ -1762,11 +1753,8 @@ int be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf) get_fat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, get_fat_cmd.size, &get_fat_cmd.dma, GFP_ATOMIC); - if (!get_fat_cmd.va) { - dev_err(&adapter->pdev->dev, - "Memory allocation failure while reading FAT data\n"); + if (!get_fat_cmd.va) return -ENOMEM; - } spin_lock_bh(&adapter->mcc_lock); diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 50981700cdb0d..241819b36ca72 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -2365,9 +2365,9 @@ int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, void be_detect_error(struct be_adapter *adapter); int be_cmd_get_die_temperature(struct be_adapter *adapter); int be_cmd_get_cntl_attributes(struct be_adapter *adapter); +int be_cmd_get_fat_dump_len(struct be_adapter *adapter, u32 *dump_size); +int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf); int be_cmd_req_native_mode(struct be_adapter *adapter); -int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size); -int be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf); int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, u32 domain); int be_cmd_set_fn_privileges(struct be_adapter *adapter, u32 privileges, diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index d2a5baf019ab8..a19ac441336f7 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -250,6 +250,19 @@ static u32 lancer_cmd_get_file_len(struct be_adapter *adapter, u8 *file_name) return data_read; } +static int be_get_dump_len(struct be_adapter *adapter) +{ + u32 dump_size = 0; + + if (lancer_chip(adapter)) + dump_size = lancer_cmd_get_file_len(adapter, + LANCER_FW_DUMP_FILE); + else + dump_size = adapter->fat_dump_len; + + return dump_size; +} + static int lancer_cmd_read_file(struct be_adapter *adapter, u8 *file_name, u32 buf_len, void *buf) { @@ -291,37 +304,18 @@ static int lancer_cmd_read_file(struct be_adapter *adapter, u8 *file_name, return status; } -static int be_get_reg_len(struct net_device *netdev) +static int be_read_dump_data(struct be_adapter *adapter, u32 dump_len, + void *buf) { - struct be_adapter *adapter = netdev_priv(netdev); - u32 log_size = 0; - - if (!check_privilege(adapter, MAX_PRIVILEGES)) - return 0; - - if (be_physfn(adapter)) { - if (lancer_chip(adapter)) - log_size = lancer_cmd_get_file_len(adapter, - LANCER_FW_DUMP_FILE); - else - be_cmd_get_reg_len(adapter, &log_size); - } - return log_size; -} + int status = 0; -static void -be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf) -{ - struct be_adapter *adapter = netdev_priv(netdev); + if (lancer_chip(adapter)) + status = lancer_cmd_read_file(adapter, LANCER_FW_DUMP_FILE, + dump_len, buf); + else + status = be_cmd_get_fat_dump(adapter, dump_len, buf); - if (be_physfn(adapter)) { - memset(buf, 0, regs->len); - if (lancer_chip(adapter)) - lancer_cmd_read_file(adapter, LANCER_FW_DUMP_FILE, - regs->len, buf); - else - be_cmd_get_regs(adapter, regs->len, buf); - } + return status; } static int be_get_coalesce(struct net_device *netdev, @@ -914,6 +908,34 @@ static int be_do_flash(struct net_device *netdev, struct ethtool_flash *efl) return be_load_fw(adapter, efl->data); } +static int +be_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + if (!check_privilege(adapter, MAX_PRIVILEGES)) + return -EOPNOTSUPP; + + dump->len = be_get_dump_len(adapter); + dump->version = 1; + dump->flag = 0x1; /* FW dump is enabled */ + return 0; +} + +static int +be_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, + void *buf) +{ + struct be_adapter *adapter = netdev_priv(netdev); + int status; + + if (!check_privilege(adapter, MAX_PRIVILEGES)) + return -EOPNOTSUPP; + + status = be_read_dump_data(adapter, dump->len, buf); + return be_cmd_status(status); +} + static int be_get_eeprom_len(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); @@ -1311,8 +1333,6 @@ const struct ethtool_ops be_ethtool_ops = { .set_msglevel = be_set_msg_level, .get_sset_count = be_get_sset_count, .get_ethtool_stats = be_get_ethtool_stats, - .get_regs_len = be_get_reg_len, - .get_regs = be_get_regs, .flash_device = be_do_flash, .self_test = be_self_test, .get_rxnfc = be_get_rxnfc, @@ -1321,6 +1341,8 @@ const struct ethtool_ops be_ethtool_ops = { .get_rxfh_key_size = be_get_rxfh_key_size, .get_rxfh = be_get_rxfh, .set_rxfh = be_set_rxfh, + .get_dump_flag = be_get_dump_flag, + .get_dump_data = be_get_dump_data, .get_channels = be_get_channels, .set_channels = be_set_channels, .get_module_info = be_get_module_info, diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 7039870a4e436..00059afad81c7 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -4212,6 +4212,9 @@ static int be_get_config(struct be_adapter *adapter) if (status) return status; + if (!lancer_chip(adapter) && be_physfn(adapter)) + be_cmd_get_fat_dump_len(adapter, &adapter->fat_dump_len); + if (BEx_chip(adapter)) { level = be_cmd_get_fw_log_level(adapter); adapter->msg_enable = From ab07ead53327ba574b84547a9c403fabab9e5a64 Mon Sep 17 00:00:00 2001 From: Suresh Reddy Date: Wed, 30 Dec 2015 01:29:05 -0500 Subject: [PATCH 10/10] be2net: bump up the driver version to 11.0.0.0 Signed-off-by: Suresh Reddy Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/ethernet/emulex/benet/be.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 8b8212fda632b..22bf7afe53116 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -37,7 +37,7 @@ #include "be_hw.h" #include "be_roce.h" -#define DRV_VER "10.6.0.3" +#define DRV_VER "11.0.0.0" #define DRV_NAME "be2net" #define BE_NAME "Emulex BladeEngine2" #define BE3_NAME "Emulex BladeEngine3"