Commit 5c510811 authored by Somnath Kotur's avatar Somnath Kotur Committed by David S. Miller

be2net: Implement initiate FW dump feature for Lancer

Added code to initiate FW dump via ethtool. Driver checks if the previous dump
has been cleared before initiating the dump. It doesn't initiate the dump
if it is not cleared.
Signed-off-by: default avatarKalesh AP <kalesh.purayil@emulex.com>
Signed-off-by: default avatarSomnath Kotur <somnath.kotur@emulex.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 28a19fe6
...@@ -332,6 +332,9 @@ enum vf_state { ...@@ -332,6 +332,9 @@ enum vf_state {
#define BE_VF_UC_PMAC_COUNT 2 #define BE_VF_UC_PMAC_COUNT 2
#define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11) #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11)
/* Ethtool set_dump flags */
#define LANCER_INITIATE_FW_DUMP 0x1
struct phy_info { struct phy_info {
u8 transceiver; u8 transceiver;
u8 autoneg; u8 autoneg;
......
...@@ -3255,6 +3255,72 @@ int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg, ...@@ -3255,6 +3255,72 @@ int be_cmd_get_if_id(struct be_adapter *adapter, struct be_vf_cfg *vf_cfg,
return status; return status;
} }
static int lancer_wait_idle(struct be_adapter *adapter)
{
#define SLIPORT_IDLE_TIMEOUT 30
u32 reg_val;
int status = 0, i;
for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
break;
ssleep(1);
}
if (i == SLIPORT_IDLE_TIMEOUT)
status = -1;
return status;
}
int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask)
{
int status = 0;
status = lancer_wait_idle(adapter);
if (status)
return status;
iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET);
return status;
}
/* Routine to check whether dump image is present or not */
bool dump_present(struct be_adapter *adapter)
{
u32 sliport_status = 0;
sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
return !!(sliport_status & SLIPORT_STATUS_DIP_MASK);
}
int lancer_initiate_dump(struct be_adapter *adapter)
{
int status;
/* give firmware reset and diagnostic dump */
status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
PHYSDEV_CONTROL_DD_MASK);
if (status < 0) {
dev_err(&adapter->pdev->dev, "Firmware reset failed\n");
return status;
}
status = lancer_wait_idle(adapter);
if (status)
return status;
if (!dump_present(adapter)) {
dev_err(&adapter->pdev->dev, "Dump image not present\n");
return -1;
}
return 0;
}
/* Uses sync mcc */ /* Uses sync mcc */
int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
{ {
......
...@@ -1937,6 +1937,9 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, ...@@ -1937,6 +1937,9 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
struct be_dma_mem *cmd, struct be_dma_mem *cmd,
struct be_fat_conf_params *cfgs); struct be_fat_conf_params *cfgs);
extern int lancer_wait_ready(struct be_adapter *adapter); extern int lancer_wait_ready(struct be_adapter *adapter);
extern int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask);
extern int lancer_initiate_dump(struct be_adapter *adapter);
extern bool dump_present(struct be_adapter *adapter);
extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter); extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name); extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
extern int be_cmd_get_func_config(struct be_adapter *adapter); extern int be_cmd_get_func_config(struct be_adapter *adapter);
......
...@@ -669,6 +669,34 @@ be_set_phys_id(struct net_device *netdev, ...@@ -669,6 +669,34 @@ be_set_phys_id(struct net_device *netdev,
return 0; return 0;
} }
static int be_set_dump(struct net_device *netdev, struct ethtool_dump *dump)
{
struct be_adapter *adapter = netdev_priv(netdev);
struct device *dev = &adapter->pdev->dev;
int status;
if (!lancer_chip(adapter)) {
dev_err(dev, "FW dump not supported\n");
return -EOPNOTSUPP;
}
if (dump_present(adapter)) {
dev_err(dev, "Previous dump not cleared, not forcing dump\n");
return 0;
}
switch (dump->flag) {
case LANCER_INITIATE_FW_DUMP:
status = lancer_initiate_dump(adapter);
if (!status)
dev_info(dev, "F/w dump initiated successfully\n");
break;
default:
dev_err(dev, "Invalid dump level: 0x%x\n", dump->flag);
return -EINVAL;
}
return status;
}
static void static void
be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
...@@ -1106,6 +1134,7 @@ const struct ethtool_ops be_ethtool_ops = { ...@@ -1106,6 +1134,7 @@ const struct ethtool_ops be_ethtool_ops = {
.set_pauseparam = be_set_pauseparam, .set_pauseparam = be_set_pauseparam,
.get_strings = be_get_stat_strings, .get_strings = be_get_stat_strings,
.set_phys_id = be_set_phys_id, .set_phys_id = be_set_phys_id,
.set_dump = be_set_dump,
.get_msglevel = be_get_msg_level, .get_msglevel = be_get_msg_level,
.set_msglevel = be_set_msg_level, .set_msglevel = be_set_msg_level,
.get_sset_count = be_get_sset_count, .get_sset_count = be_get_sset_count,
......
...@@ -53,10 +53,12 @@ ...@@ -53,10 +53,12 @@
#define PHYSDEV_CONTROL_OFFSET 0x414 #define PHYSDEV_CONTROL_OFFSET 0x414
#define SLIPORT_STATUS_ERR_MASK 0x80000000 #define SLIPORT_STATUS_ERR_MASK 0x80000000
#define SLIPORT_STATUS_DIP_MASK 0x02000000
#define SLIPORT_STATUS_RN_MASK 0x01000000 #define SLIPORT_STATUS_RN_MASK 0x01000000
#define SLIPORT_STATUS_RDY_MASK 0x00800000 #define SLIPORT_STATUS_RDY_MASK 0x00800000
#define SLI_PORT_CONTROL_IP_MASK 0x08000000 #define SLI_PORT_CONTROL_IP_MASK 0x08000000
#define PHYSDEV_CONTROL_FW_RESET_MASK 0x00000002 #define PHYSDEV_CONTROL_FW_RESET_MASK 0x00000002
#define PHYSDEV_CONTROL_DD_MASK 0x00000004
#define PHYSDEV_CONTROL_INP_MASK 0x40000000 #define PHYSDEV_CONTROL_INP_MASK 0x40000000
#define SLIPORT_ERROR_NO_RESOURCE1 0x2 #define SLIPORT_ERROR_NO_RESOURCE1 0x2
......
...@@ -3551,40 +3551,6 @@ static int be_flash_skyhawk(struct be_adapter *adapter, ...@@ -3551,40 +3551,6 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
return 0; return 0;
} }
static int lancer_wait_idle(struct be_adapter *adapter)
{
#define SLIPORT_IDLE_TIMEOUT 30
u32 reg_val;
int status = 0, i;
for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
break;
ssleep(1);
}
if (i == SLIPORT_IDLE_TIMEOUT)
status = -1;
return status;
}
static int lancer_fw_reset(struct be_adapter *adapter)
{
int status = 0;
status = lancer_wait_idle(adapter);
if (status)
return status;
iowrite32(PHYSDEV_CONTROL_FW_RESET_MASK, adapter->db +
PHYSDEV_CONTROL_OFFSET);
return status;
}
static int lancer_fw_download(struct be_adapter *adapter, static int lancer_fw_download(struct be_adapter *adapter,
const struct firmware *fw) const struct firmware *fw)
{ {
...@@ -3662,7 +3628,8 @@ static int lancer_fw_download(struct be_adapter *adapter, ...@@ -3662,7 +3628,8 @@ static int lancer_fw_download(struct be_adapter *adapter,
} }
if (change_status == LANCER_FW_RESET_NEEDED) { if (change_status == LANCER_FW_RESET_NEEDED) {
status = lancer_fw_reset(adapter); status = lancer_physdev_ctrl(adapter,
PHYSDEV_CONTROL_FW_RESET_MASK);
if (status) { if (status) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Adapter busy for FW reset.\n" "Adapter busy for FW reset.\n"
......
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