summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSomnath Kotur <somnath.kotur@emulex.com>2013-05-30 02:52:23 +0000
committerDavid S. Miller <davem@davemloft.net>2013-05-31 17:25:43 -0700
commit5c510811547f88522b00623417b97d9fba85a06b (patch)
tree465b29d0e6ad0830297c582be08f4cf933597b2a
parent28a19fe60f4f31cbd349f8473f0483aa7500acf5 (diff)
downloadlwn-5c510811547f88522b00623417b97d9fba85a06b.tar.gz
lwn-5c510811547f88522b00623417b97d9fba85a06b.zip
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: Kalesh AP <kalesh.purayil@emulex.com> Signed-off-by: Somnath Kotur <somnath.kotur@emulex.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h3
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c66
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h3
-rw-r--r--drivers/net/ethernet/emulex/benet/be_ethtool.c29
-rw-r--r--drivers/net/ethernet/emulex/benet/be_hw.h2
-rw-r--r--drivers/net/ethernet/emulex/benet/be_main.c37
6 files changed, 105 insertions, 35 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index edce38bf83c9..fcc30a2d831b 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -332,6 +332,9 @@ enum vf_state {
#define BE_VF_UC_PMAC_COUNT 2
#define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11)
+/* Ethtool set_dump flags */
+#define LANCER_INITIATE_FW_DUMP 0x1
+
struct phy_info {
u8 transceiver;
u8 autoneg;
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index a236ecd27cf3..4d0ec3649a63 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -3255,6 +3255,72 @@ err:
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 */
int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
{
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 025bdb0d1764..5228d88c5a02 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1937,6 +1937,9 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
struct be_dma_mem *cmd,
struct be_fat_conf_params *cfgs);
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 be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
extern int be_cmd_get_func_config(struct be_adapter *adapter);
diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c
index f3ee07758198..4f8c941217cc 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -669,6 +669,34 @@ be_set_phys_id(struct net_device *netdev,
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
be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
@@ -1106,6 +1134,7 @@ const struct ethtool_ops be_ethtool_ops = {
.set_pauseparam = be_set_pauseparam,
.get_strings = be_get_stat_strings,
.set_phys_id = be_set_phys_id,
+ .set_dump = be_set_dump,
.get_msglevel = be_get_msg_level,
.set_msglevel = be_set_msg_level,
.get_sset_count = be_get_sset_count,
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h
index 3c1099b47f2a..0311d9bfe858 100644
--- a/drivers/net/ethernet/emulex/benet/be_hw.h
+++ b/drivers/net/ethernet/emulex/benet/be_hw.h
@@ -53,10 +53,12 @@
#define PHYSDEV_CONTROL_OFFSET 0x414
#define SLIPORT_STATUS_ERR_MASK 0x80000000
+#define SLIPORT_STATUS_DIP_MASK 0x02000000
#define SLIPORT_STATUS_RN_MASK 0x01000000
#define SLIPORT_STATUS_RDY_MASK 0x00800000
#define SLI_PORT_CONTROL_IP_MASK 0x08000000
#define PHYSDEV_CONTROL_FW_RESET_MASK 0x00000002
+#define PHYSDEV_CONTROL_DD_MASK 0x00000004
#define PHYSDEV_CONTROL_INP_MASK 0x40000000
#define SLIPORT_ERROR_NO_RESOURCE1 0x2
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 1140a86ff5ea..5d9044e4afe2 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -3551,40 +3551,6 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
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,
const struct firmware *fw)
{
@@ -3662,7 +3628,8 @@ static int lancer_fw_download(struct be_adapter *adapter,
}
if (change_status == LANCER_FW_RESET_NEEDED) {
- status = lancer_fw_reset(adapter);
+ status = lancer_physdev_ctrl(adapter,
+ PHYSDEV_CONTROL_FW_RESET_MASK);
if (status) {
dev_err(&adapter->pdev->dev,
"Adapter busy for FW reset.\n"