Commit 9612de92 authored by Emil Tantilov's avatar Emil Tantilov Committed by Jeff Kirsher

ixgbe: add support for Dell CEM

This patch adds support for Dell CEM (Comprehensive Embedded Management)).
This consists of informing the management firmware of the driver version
during probe on 82599 and X540 HW.
Signed-off-by: default avatarEmil Tantilov <emil.s.tantilov@intel.com>
Tested-by: default avatarEvan Swanson <evan.swanson@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent fb5475ff
...@@ -1316,6 +1316,7 @@ static struct ixgbe_mac_operations mac_ops_82598 = { ...@@ -1316,6 +1316,7 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
.clear_vfta = &ixgbe_clear_vfta_82598, .clear_vfta = &ixgbe_clear_vfta_82598,
.set_vfta = &ixgbe_set_vfta_82598, .set_vfta = &ixgbe_set_vfta_82598,
.fc_enable = &ixgbe_fc_enable_82598, .fc_enable = &ixgbe_fc_enable_82598,
.set_fw_drv_ver = NULL,
.acquire_swfw_sync = &ixgbe_acquire_swfw_sync, .acquire_swfw_sync = &ixgbe_acquire_swfw_sync,
.release_swfw_sync = &ixgbe_release_swfw_sync, .release_swfw_sync = &ixgbe_release_swfw_sync,
}; };
......
...@@ -2126,6 +2126,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = { ...@@ -2126,6 +2126,7 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
.clear_vfta = &ixgbe_clear_vfta_generic, .clear_vfta = &ixgbe_clear_vfta_generic,
.set_vfta = &ixgbe_set_vfta_generic, .set_vfta = &ixgbe_set_vfta_generic,
.fc_enable = &ixgbe_fc_enable_generic, .fc_enable = &ixgbe_fc_enable_generic,
.set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic,
.init_uta_tables = &ixgbe_init_uta_tables_generic, .init_uta_tables = &ixgbe_init_uta_tables_generic,
.setup_sfp = &ixgbe_setup_sfp_modules_82599, .setup_sfp = &ixgbe_setup_sfp_modules_82599,
.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing,
......
...@@ -3333,3 +3333,177 @@ void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, ...@@ -3333,3 +3333,177 @@ void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw,
IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0); IXGBE_WRITE_REG(hw, IXGBE_TXPBTHRESH(i), 0);
} }
} }
/**
* ixgbe_calculate_checksum - Calculate checksum for buffer
* @buffer: pointer to EEPROM
* @length: size of EEPROM to calculate a checksum for
* Calculates the checksum for some buffer on a specified length. The
* checksum calculated is returned.
**/
static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
{
u32 i;
u8 sum = 0;
if (!buffer)
return 0;
for (i = 0; i < length; i++)
sum += buffer[i];
return (u8) (0 - sum);
}
/**
* ixgbe_host_interface_command - Issue command to manageability block
* @hw: pointer to the HW structure
* @buffer: contains the command to write and where the return status will
* be placed
* @lenght: lenght of buffer, must be multiple of 4 bytes
*
* Communicates with the manageability block. On success return 0
* else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
**/
static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
u32 length)
{
u32 hicr, i;
u32 hdr_size = sizeof(struct ixgbe_hic_hdr);
u8 buf_len, dword_len;
s32 ret_val = 0;
if (length == 0 || length & 0x3 ||
length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
hw_dbg(hw, "Buffer length failure.\n");
ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
goto out;
}
/* Check that the host interface is enabled. */
hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
if ((hicr & IXGBE_HICR_EN) == 0) {
hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n");
ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
goto out;
}
/* Calculate length in DWORDs */
dword_len = length >> 2;
/*
* The device driver writes the relevant command block
* into the ram area.
*/
for (i = 0; i < dword_len; i++)
IXGBE_WRITE_REG_ARRAY(hw, IXGBE_FLEX_MNG,
i, *((u32 *)buffer + i));
/* Setting this bit tells the ARC that a new command is pending. */
IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C);
for (i = 0; i < IXGBE_HI_COMMAND_TIMEOUT; i++) {
hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
if (!(hicr & IXGBE_HICR_C))
break;
usleep_range(1000, 2000);
}
/* Check command successful completion. */
if (i == IXGBE_HI_COMMAND_TIMEOUT ||
(!(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))) {
hw_dbg(hw, "Command has failed with no status valid.\n");
ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
goto out;
}
/* Calculate length in DWORDs */
dword_len = hdr_size >> 2;
/* first pull in the header so we know the buffer length */
for (i = 0; i < dword_len; i++)
*((u32 *)buffer + i) =
IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
/* If there is any thing in data position pull it in */
buf_len = ((struct ixgbe_hic_hdr *)buffer)->buf_len;
if (buf_len == 0)
goto out;
if (length < (buf_len + hdr_size)) {
hw_dbg(hw, "Buffer not large enough for reply message.\n");
ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
goto out;
}
/* Calculate length in DWORDs, add one for odd lengths */
dword_len = (buf_len + 1) >> 2;
/* Pull in the rest of the buffer (i is where we left off)*/
for (; i < buf_len; i++)
*((u32 *)buffer + i) =
IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG, i);
out:
return ret_val;
}
/**
* ixgbe_set_fw_drv_ver_generic - Sends driver version to firmware
* @hw: pointer to the HW structure
* @maj: driver version major number
* @min: driver version minor number
* @build: driver version build number
* @sub: driver version sub build number
*
* Sends driver version number to firmware through the manageability
* block. On success return 0
* else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
* semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
**/
s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
u8 build, u8 sub)
{
struct ixgbe_hic_drv_info fw_cmd;
int i;
s32 ret_val = 0;
if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM) != 0) {
ret_val = IXGBE_ERR_SWFW_SYNC;
goto out;
}
fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN;
fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
fw_cmd.port_num = (u8)hw->bus.func;
fw_cmd.ver_maj = maj;
fw_cmd.ver_min = min;
fw_cmd.ver_build = build;
fw_cmd.ver_sub = sub;
fw_cmd.hdr.checksum = 0;
fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
(FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
fw_cmd.pad = 0;
fw_cmd.pad2 = 0;
for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
ret_val = ixgbe_host_interface_command(hw, (u8 *)&fw_cmd,
sizeof(fw_cmd));
if (ret_val != 0)
continue;
if (fw_cmd.hdr.cmd_or_resp.ret_status ==
FW_CEM_RESP_STATUS_SUCCESS)
ret_val = 0;
else
ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
break;
}
hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
out:
return ret_val;
}
...@@ -99,6 +99,8 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index); ...@@ -99,6 +99,8 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf); void ixgbe_set_mac_anti_spoofing(struct ixgbe_hw *hw, bool enable, int pf);
void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf); void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf);
s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps); s32 ixgbe_get_device_caps_generic(struct ixgbe_hw *hw, u16 *device_caps);
s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
u8 build, u8 ver);
void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb, void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
u32 headroom, int strategy); u32 headroom, int strategy);
......
...@@ -7674,6 +7674,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, ...@@ -7674,6 +7674,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
ixgbe_vf_configuration(pdev, (i | 0x10000000)); ixgbe_vf_configuration(pdev, (i | 0x10000000));
} }
/* Inform firmware of driver version */
if (hw->mac.ops.set_fw_drv_ver)
hw->mac.ops.set_fw_drv_ver(hw, MAJ, MIN, BUILD, KFIX);
/* add san mac addr to netdev */ /* add san mac addr to netdev */
ixgbe_add_sanmac_netdev(netdev); ixgbe_add_sanmac_netdev(netdev);
......
...@@ -707,6 +707,13 @@ ...@@ -707,6 +707,13 @@
#define IXGBE_HFDR 0x15FE8 #define IXGBE_HFDR 0x15FE8
#define IXGBE_FLEX_MNG 0x15800 /* 0x15800 - 0x15EFC */ #define IXGBE_FLEX_MNG 0x15800 /* 0x15800 - 0x15EFC */
#define IXGBE_HICR_EN 0x01 /* Enable bit - RO */
/* Driver sets this bit when done to put command in RAM */
#define IXGBE_HICR_C 0x02
#define IXGBE_HICR_SV 0x04 /* Status Validity */
#define IXGBE_HICR_FW_RESET_ENABLE 0x40
#define IXGBE_HICR_FW_RESET 0x80
/* PCI-E registers */ /* PCI-E registers */
#define IXGBE_GCR 0x11000 #define IXGBE_GCR 0x11000
#define IXGBE_GTV 0x11004 #define IXGBE_GTV 0x11004
...@@ -2124,6 +2131,41 @@ enum ixgbe_fdir_pballoc_type { ...@@ -2124,6 +2131,41 @@ enum ixgbe_fdir_pballoc_type {
#define IXGBE_FDIR_INIT_DONE_POLL 10 #define IXGBE_FDIR_INIT_DONE_POLL 10
#define IXGBE_FDIRCMD_CMD_POLL 10 #define IXGBE_FDIRCMD_CMD_POLL 10
/* Manageablility Host Interface defines */
#define IXGBE_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Num of bytes in range */
#define IXGBE_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Num of dwords in range */
#define IXGBE_HI_COMMAND_TIMEOUT 500 /* Process HI command limit */
/* CEM Support */
#define FW_CEM_HDR_LEN 0x4
#define FW_CEM_CMD_DRIVER_INFO 0xDD
#define FW_CEM_CMD_DRIVER_INFO_LEN 0x5
#define FW_CEM_CMD_RESERVED 0X0
#define FW_CEM_MAX_RETRIES 3
#define FW_CEM_RESP_STATUS_SUCCESS 0x1
/* Host Interface Command Structures */
struct ixgbe_hic_hdr {
u8 cmd;
u8 buf_len;
union {
u8 cmd_resv;
u8 ret_status;
} cmd_or_resp;
u8 checksum;
};
struct ixgbe_hic_drv_info {
struct ixgbe_hic_hdr hdr;
u8 port_num;
u8 ver_sub;
u8 ver_build;
u8 ver_min;
u8 ver_maj;
u8 pad; /* end spacing to ensure length is mult. of dword */
u16 pad2; /* end spacing to ensure length is mult. of dword2 */
};
/* Transmit Descriptor - Advanced */ /* Transmit Descriptor - Advanced */
union ixgbe_adv_tx_desc { union ixgbe_adv_tx_desc {
struct { struct {
...@@ -2663,6 +2705,9 @@ struct ixgbe_mac_operations { ...@@ -2663,6 +2705,9 @@ struct ixgbe_mac_operations {
/* Flow Control */ /* Flow Control */
s32 (*fc_enable)(struct ixgbe_hw *, s32); s32 (*fc_enable)(struct ixgbe_hw *, s32);
/* Manageability interface */
s32 (*set_fw_drv_ver)(struct ixgbe_hw *, u8, u8, u8, u8);
}; };
struct ixgbe_phy_operations { struct ixgbe_phy_operations {
...@@ -2832,6 +2877,7 @@ struct ixgbe_info { ...@@ -2832,6 +2877,7 @@ struct ixgbe_info {
#define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE -30 #define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE -30
#define IXGBE_ERR_PBA_SECTION -31 #define IXGBE_ERR_PBA_SECTION -31
#define IXGBE_ERR_INVALID_ARGUMENT -32 #define IXGBE_ERR_INVALID_ARGUMENT -32
#define IXGBE_ERR_HOST_INTERFACE_COMMAND -33
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF #define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
#endif /* _IXGBE_TYPE_H_ */ #endif /* _IXGBE_TYPE_H_ */
...@@ -894,6 +894,7 @@ static struct ixgbe_mac_operations mac_ops_X540 = { ...@@ -894,6 +894,7 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
.clear_vfta = &ixgbe_clear_vfta_generic, .clear_vfta = &ixgbe_clear_vfta_generic,
.set_vfta = &ixgbe_set_vfta_generic, .set_vfta = &ixgbe_set_vfta_generic,
.fc_enable = &ixgbe_fc_enable_generic, .fc_enable = &ixgbe_fc_enable_generic,
.set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic,
.init_uta_tables = &ixgbe_init_uta_tables_generic, .init_uta_tables = &ixgbe_init_uta_tables_generic,
.setup_sfp = NULL, .setup_sfp = NULL,
.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, .set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment