Commit 5e3d3189 authored by David S. Miller's avatar David S. Miller

Merge branch 'be2net-next'

Sathya Perla says:

====================
be2net: patch set

Hi Dave, the following patch set reduces code duplication
in probe/pci-resume/eeh-resume and remove/pci-suspend/eeh-error and UE-error
detect/recovery paths. New helper routines have been introduced for this
purpose. Pls apply this set to the net-next tree. Thanks!

Patch 1 refactors the alloc/free code of adapter struct's fields into
a new set of helper routines -- be_drv_init/cleanup().

Patch 2 gets rid of the be_get_initial_config() routine as be_get_config()
is the place holder for related code.

Patch 3 introduces a new helper routine be_func_init() to execute the
initialization code used in probe/pci-resume/eeh-resume to remove
code duplication.

Patch 4 introduces a wrapper for scheduling/canceling error detection
task on similar lines to the be_worker task.

Patch 5 refactors UE error detection and recovery code on similar lines
to EEH code. Cleaning up resources is done in the error detection routine
followed by error recovery.

Patch 6 gets rid of the lancer_test_and_set_rdy_state() routine as the
same code now available in be_func_init().

Patch 7 creates a new helper routine be_resume() for all the common code
in be_probe(), be_pci_resume() and be_eeh_resume(), to reduce code duplication.

Patch 8 creates a new helper routine be_cleanup() for all the common
cleanup code duplicated in the suspend/EEH err detection paths.

Patch 9 moves be_func_init() inside be_setup() as everytime be_setup()
is called, the driver will have to wait for the function/FW to be be
initialized.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b7853d73 f962f840
...@@ -376,6 +376,7 @@ enum vf_state { ...@@ -376,6 +376,7 @@ enum vf_state {
#define BE_FLAGS_VXLAN_OFFLOADS BIT(8) #define BE_FLAGS_VXLAN_OFFLOADS BIT(8)
#define BE_FLAGS_SETUP_DONE BIT(9) #define BE_FLAGS_SETUP_DONE BIT(9)
#define BE_FLAGS_EVT_INCOMPATIBLE_SFP BIT(10) #define BE_FLAGS_EVT_INCOMPATIBLE_SFP BIT(10)
#define BE_FLAGS_ERR_DETECTION_SCHEDULED BIT(11)
#define BE_UC_PMAC_COUNT 30 #define BE_UC_PMAC_COUNT 30
#define BE_VF_UC_PMAC_COUNT 2 #define BE_VF_UC_PMAC_COUNT 2
...@@ -501,7 +502,7 @@ struct be_adapter { ...@@ -501,7 +502,7 @@ struct be_adapter {
struct delayed_work work; struct delayed_work work;
u16 work_counter; u16 work_counter;
struct delayed_work func_recovery_work; struct delayed_work be_err_detection_work;
u32 flags; u32 flags;
u32 cmd_privileges; u32 cmd_privileges;
/* Ethtool knobs and info */ /* Ethtool knobs and info */
......
...@@ -635,73 +635,16 @@ static int lancer_wait_ready(struct be_adapter *adapter) ...@@ -635,73 +635,16 @@ static int lancer_wait_ready(struct be_adapter *adapter)
for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) { for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
if (sliport_status & SLIPORT_STATUS_RDY_MASK) if (sliport_status & SLIPORT_STATUS_RDY_MASK)
break; return 0;
msleep(1000);
}
if (i == SLIPORT_READY_TIMEOUT)
return sliport_status ? : -1;
return 0;
}
static bool lancer_provisioning_error(struct be_adapter *adapter)
{
u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0;
sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
sliport_err1 = ioread32(adapter->db + SLIPORT_ERROR1_OFFSET);
sliport_err2 = ioread32(adapter->db + SLIPORT_ERROR2_OFFSET);
if (sliport_err1 == SLIPORT_ERROR_NO_RESOURCE1 &&
sliport_err2 == SLIPORT_ERROR_NO_RESOURCE2)
return true;
}
return false;
}
int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
{
int status;
u32 sliport_status, err, reset_needed;
bool resource_error;
resource_error = lancer_provisioning_error(adapter); if (sliport_status & SLIPORT_STATUS_ERR_MASK &&
if (resource_error) !(sliport_status & SLIPORT_STATUS_RN_MASK))
return -EAGAIN; return -EIO;
status = lancer_wait_ready(adapter); msleep(1000);
if (!status) {
sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
err = sliport_status & SLIPORT_STATUS_ERR_MASK;
reset_needed = sliport_status & SLIPORT_STATUS_RN_MASK;
if (err && reset_needed) {
iowrite32(SLI_PORT_CONTROL_IP_MASK,
adapter->db + SLIPORT_CONTROL_OFFSET);
/* check if adapter has corrected the error */
status = lancer_wait_ready(adapter);
sliport_status = ioread32(adapter->db +
SLIPORT_STATUS_OFFSET);
sliport_status &= (SLIPORT_STATUS_ERR_MASK |
SLIPORT_STATUS_RN_MASK);
if (status || sliport_status)
status = -1;
} else if (err || reset_needed) {
status = -1;
}
} }
/* Stop error recovery if error is not recoverable.
* No resource error is temporary errors and will go away
* when PF provisions resources.
*/
resource_error = lancer_provisioning_error(adapter);
if (resource_error)
status = -EAGAIN;
return status; return sliport_status ? : -1;
} }
int be_fw_wait_ready(struct be_adapter *adapter) int be_fw_wait_ready(struct be_adapter *adapter)
...@@ -720,6 +663,10 @@ int be_fw_wait_ready(struct be_adapter *adapter) ...@@ -720,6 +663,10 @@ int be_fw_wait_ready(struct be_adapter *adapter)
} }
do { do {
/* There's no means to poll POST state on BE2/3 VFs */
if (BEx_chip(adapter) && be_virtfn(adapter))
return 0;
stage = be_POST_stage_get(adapter); stage = be_POST_stage_get(adapter);
if (stage == POST_STAGE_ARMFW_RDY) if (stage == POST_STAGE_ARMFW_RDY)
return 0; return 0;
...@@ -734,7 +681,7 @@ int be_fw_wait_ready(struct be_adapter *adapter) ...@@ -734,7 +681,7 @@ int be_fw_wait_ready(struct be_adapter *adapter)
err: err:
dev_err(dev, "POST timeout; stage=%#x\n", stage); dev_err(dev, "POST timeout; stage=%#x\n", stage);
return -1; return -ETIMEDOUT;
} }
static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb) static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
...@@ -2126,16 +2073,12 @@ int be_cmd_reset_function(struct be_adapter *adapter) ...@@ -2126,16 +2073,12 @@ int be_cmd_reset_function(struct be_adapter *adapter)
int status; int status;
if (lancer_chip(adapter)) { if (lancer_chip(adapter)) {
iowrite32(SLI_PORT_CONTROL_IP_MASK,
adapter->db + SLIPORT_CONTROL_OFFSET);
status = lancer_wait_ready(adapter); status = lancer_wait_ready(adapter);
if (!status) { if (status)
iowrite32(SLI_PORT_CONTROL_IP_MASK,
adapter->db + SLIPORT_CONTROL_OFFSET);
status = lancer_test_and_set_rdy_state(adapter);
}
if (status) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Adapter in non recoverable error\n"); "Adapter in non recoverable error\n");
}
return status; return status;
} }
......
...@@ -2844,12 +2844,12 @@ void be_detect_error(struct be_adapter *adapter) ...@@ -2844,12 +2844,12 @@ void be_detect_error(struct be_adapter *adapter)
sliport_err2 = ioread32(adapter->db + sliport_err2 = ioread32(adapter->db +
SLIPORT_ERROR2_OFFSET); SLIPORT_ERROR2_OFFSET);
adapter->hw_error = true; adapter->hw_error = true;
error_detected = true;
/* Do not log error messages if its a FW reset */ /* Do not log error messages if its a FW reset */
if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 && if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 &&
sliport_err2 == SLIPORT_ERROR_FW_RESET2) { sliport_err2 == SLIPORT_ERROR_FW_RESET2) {
dev_info(dev, "Firmware update in progress\n"); dev_info(dev, "Firmware update in progress\n");
} else { } else {
error_detected = true;
dev_err(dev, "Error detected in the card\n"); dev_err(dev, "Error detected in the card\n");
dev_err(dev, "ERR: sliport status 0x%x\n", dev_err(dev, "ERR: sliport status 0x%x\n",
sliport_status); sliport_status);
...@@ -3363,6 +3363,14 @@ static void be_cancel_worker(struct be_adapter *adapter) ...@@ -3363,6 +3363,14 @@ static void be_cancel_worker(struct be_adapter *adapter)
} }
} }
static void be_cancel_err_detection(struct be_adapter *adapter)
{
if (adapter->flags & BE_FLAGS_ERR_DETECTION_SCHEDULED) {
cancel_delayed_work_sync(&adapter->be_err_detection_work);
adapter->flags &= ~BE_FLAGS_ERR_DETECTION_SCHEDULED;
}
}
static void be_mac_clear(struct be_adapter *adapter) static void be_mac_clear(struct be_adapter *adapter)
{ {
if (adapter->pmac_id) { if (adapter->pmac_id) {
...@@ -3771,13 +3779,25 @@ static void be_sriov_config(struct be_adapter *adapter) ...@@ -3771,13 +3779,25 @@ static void be_sriov_config(struct be_adapter *adapter)
static int be_get_config(struct be_adapter *adapter) static int be_get_config(struct be_adapter *adapter)
{ {
int status, level;
u16 profile_id; u16 profile_id;
int status;
status = be_cmd_get_cntl_attributes(adapter);
if (status)
return status;
status = be_cmd_query_fw_cfg(adapter); status = be_cmd_query_fw_cfg(adapter);
if (status) if (status)
return status; return status;
if (BEx_chip(adapter)) {
level = be_cmd_get_fw_log_level(adapter);
adapter->msg_enable =
level <= FW_LOG_LEVEL_DEFAULT ? NETIF_MSG_HW : 0;
}
be_cmd_get_acpi_wol_cap(adapter);
be_cmd_query_port_name(adapter); be_cmd_query_port_name(adapter);
if (be_physfn(adapter)) { if (be_physfn(adapter)) {
...@@ -3835,6 +3855,13 @@ static void be_schedule_worker(struct be_adapter *adapter) ...@@ -3835,6 +3855,13 @@ static void be_schedule_worker(struct be_adapter *adapter)
adapter->flags |= BE_FLAGS_WORKER_SCHEDULED; adapter->flags |= BE_FLAGS_WORKER_SCHEDULED;
} }
static void be_schedule_err_detection(struct be_adapter *adapter)
{
schedule_delayed_work(&adapter->be_err_detection_work,
msecs_to_jiffies(1000));
adapter->flags |= BE_FLAGS_ERR_DETECTION_SCHEDULED;
}
static int be_setup_queues(struct be_adapter *adapter) static int be_setup_queues(struct be_adapter *adapter)
{ {
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
...@@ -3917,11 +3944,53 @@ static inline int fw_major_num(const char *fw_ver) ...@@ -3917,11 +3944,53 @@ static inline int fw_major_num(const char *fw_ver)
return fw_major; return fw_major;
} }
/* If any VFs are already enabled don't FLR the PF */
static bool be_reset_required(struct be_adapter *adapter)
{
return pci_num_vf(adapter->pdev) ? false : true;
}
/* Wait for the FW to be ready and perform the required initialization */
static int be_func_init(struct be_adapter *adapter)
{
int status;
status = be_fw_wait_ready(adapter);
if (status)
return status;
if (be_reset_required(adapter)) {
status = be_cmd_reset_function(adapter);
if (status)
return status;
/* Wait for interrupts to quiesce after an FLR */
msleep(100);
/* We can clear all errors when function reset succeeds */
be_clear_all_error(adapter);
}
/* Tell FW we're ready to fire cmds */
status = be_cmd_fw_init(adapter);
if (status)
return status;
/* Allow interrupts for other ULPs running on NIC function */
be_intr_set(adapter, true);
return 0;
}
static int be_setup(struct be_adapter *adapter) static int be_setup(struct be_adapter *adapter)
{ {
struct device *dev = &adapter->pdev->dev; struct device *dev = &adapter->pdev->dev;
int status; int status;
status = be_func_init(adapter);
if (status)
return status;
be_setup_init(adapter); be_setup_init(adapter);
if (!lancer_chip(adapter)) if (!lancer_chip(adapter))
...@@ -3967,8 +4036,6 @@ static int be_setup(struct be_adapter *adapter) ...@@ -3967,8 +4036,6 @@ static int be_setup(struct be_adapter *adapter)
be_set_rx_mode(adapter->netdev); be_set_rx_mode(adapter->netdev);
be_cmd_get_acpi_wol_cap(adapter);
status = be_cmd_set_flow_control(adapter, adapter->tx_fc, status = be_cmd_set_flow_control(adapter, adapter->tx_fc,
adapter->rx_fc); adapter->rx_fc);
if (status) if (status)
...@@ -4878,6 +4945,142 @@ static void be_netdev_init(struct net_device *netdev) ...@@ -4878,6 +4945,142 @@ static void be_netdev_init(struct net_device *netdev)
netdev->ethtool_ops = &be_ethtool_ops; netdev->ethtool_ops = &be_ethtool_ops;
} }
static void be_cleanup(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
rtnl_lock();
netif_device_detach(netdev);
if (netif_running(netdev))
be_close(netdev);
rtnl_unlock();
be_clear(adapter);
}
static int be_resume(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
int status;
status = be_setup(adapter);
if (status)
return status;
if (netif_running(netdev)) {
status = be_open(netdev);
if (status)
return status;
}
netif_device_attach(netdev);
return 0;
}
static int be_err_recover(struct be_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
int status;
status = be_resume(adapter);
if (status)
goto err;
dev_info(dev, "Adapter recovery successful\n");
return 0;
err:
if (be_physfn(adapter))
dev_err(dev, "Adapter recovery failed\n");
else
dev_err(dev, "Re-trying adapter recovery\n");
return status;
}
static void be_err_detection_task(struct work_struct *work)
{
struct be_adapter *adapter =
container_of(work, struct be_adapter,
be_err_detection_work.work);
int status = 0;
be_detect_error(adapter);
if (adapter->hw_error) {
be_cleanup(adapter);
/* As of now error recovery support is in Lancer only */
if (lancer_chip(adapter))
status = be_err_recover(adapter);
}
/* Always attempt recovery on VFs */
if (!status || be_virtfn(adapter))
be_schedule_err_detection(adapter);
}
static void be_log_sfp_info(struct be_adapter *adapter)
{
int status;
status = be_cmd_query_sfp_info(adapter);
if (!status) {
dev_err(&adapter->pdev->dev,
"Unqualified SFP+ detected on %c from %s part no: %s",
adapter->port_name, adapter->phy.vendor_name,
adapter->phy.vendor_pn);
}
adapter->flags &= ~BE_FLAGS_EVT_INCOMPATIBLE_SFP;
}
static void be_worker(struct work_struct *work)
{
struct be_adapter *adapter =
container_of(work, struct be_adapter, work.work);
struct be_rx_obj *rxo;
int i;
/* when interrupts are not yet enabled, just reap any pending
* mcc completions
*/
if (!netif_running(adapter->netdev)) {
local_bh_disable();
be_process_mcc(adapter);
local_bh_enable();
goto reschedule;
}
if (!adapter->stats_cmd_sent) {
if (lancer_chip(adapter))
lancer_cmd_get_pport_stats(adapter,
&adapter->stats_cmd);
else
be_cmd_get_stats(adapter, &adapter->stats_cmd);
}
if (be_physfn(adapter) &&
MODULO(adapter->work_counter, adapter->be_get_temp_freq) == 0)
be_cmd_get_die_temperature(adapter);
for_all_rx_queues(adapter, rxo, i) {
/* Replenish RX-queues starved due to memory
* allocation failures.
*/
if (rxo->rx_post_starved)
be_post_rx_frags(rxo, GFP_KERNEL, MAX_RX_POST);
}
be_eqd_update(adapter);
if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP)
be_log_sfp_info(adapter);
reschedule:
adapter->work_counter++;
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
}
static void be_unmap_pci_bars(struct be_adapter *adapter) static void be_unmap_pci_bars(struct be_adapter *adapter)
{ {
if (adapter->csr) if (adapter->csr)
...@@ -4909,6 +5112,12 @@ static int be_roce_map_pci_bars(struct be_adapter *adapter) ...@@ -4909,6 +5112,12 @@ static int be_roce_map_pci_bars(struct be_adapter *adapter)
static int be_map_pci_bars(struct be_adapter *adapter) static int be_map_pci_bars(struct be_adapter *adapter)
{ {
u8 __iomem *addr; u8 __iomem *addr;
u32 sli_intf;
pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
adapter->sli_family = (sli_intf & SLI_INTF_FAMILY_MASK) >>
SLI_INTF_FAMILY_SHIFT;
adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
if (BEx_chip(adapter) && be_physfn(adapter)) { if (BEx_chip(adapter) && be_physfn(adapter)) {
adapter->csr = pci_iomap(adapter->pdev, 2, 0); adapter->csr = pci_iomap(adapter->pdev, 2, 0);
...@@ -4930,109 +5139,94 @@ static int be_map_pci_bars(struct be_adapter *adapter) ...@@ -4930,109 +5139,94 @@ static int be_map_pci_bars(struct be_adapter *adapter)
return -ENOMEM; return -ENOMEM;
} }
static void be_ctrl_cleanup(struct be_adapter *adapter) static void be_drv_cleanup(struct be_adapter *adapter)
{ {
struct be_dma_mem *mem = &adapter->mbox_mem_alloced; struct be_dma_mem *mem = &adapter->mbox_mem_alloced;
struct device *dev = &adapter->pdev->dev;
be_unmap_pci_bars(adapter);
if (mem->va) if (mem->va)
dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va, dma_free_coherent(dev, mem->size, mem->va, mem->dma);
mem->dma);
mem = &adapter->rx_filter; mem = &adapter->rx_filter;
if (mem->va) if (mem->va)
dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va, dma_free_coherent(dev, mem->size, mem->va, mem->dma);
mem->dma);
mem = &adapter->stats_cmd;
if (mem->va)
dma_free_coherent(dev, mem->size, mem->va, mem->dma);
} }
static int be_ctrl_init(struct be_adapter *adapter) /* Allocate and initialize various fields in be_adapter struct */
static int be_drv_init(struct be_adapter *adapter)
{ {
struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced; struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced;
struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem; struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem;
struct be_dma_mem *rx_filter = &adapter->rx_filter; struct be_dma_mem *rx_filter = &adapter->rx_filter;
u32 sli_intf; struct be_dma_mem *stats_cmd = &adapter->stats_cmd;
int status; struct device *dev = &adapter->pdev->dev;
int status = 0;
pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
adapter->sli_family = (sli_intf & SLI_INTF_FAMILY_MASK) >>
SLI_INTF_FAMILY_SHIFT;
adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
status = be_map_pci_bars(adapter);
if (status)
goto done;
mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
mbox_mem_alloc->va = dma_alloc_coherent(&adapter->pdev->dev, mbox_mem_alloc->va = dma_alloc_coherent(dev, mbox_mem_alloc->size,
mbox_mem_alloc->size,
&mbox_mem_alloc->dma, &mbox_mem_alloc->dma,
GFP_KERNEL); GFP_KERNEL);
if (!mbox_mem_alloc->va) { if (!mbox_mem_alloc->va)
status = -ENOMEM; return -ENOMEM;
goto unmap_pci_bars;
}
mbox_mem_align->size = sizeof(struct be_mcc_mailbox); mbox_mem_align->size = sizeof(struct be_mcc_mailbox);
mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
rx_filter->size = sizeof(struct be_cmd_req_rx_filter); rx_filter->size = sizeof(struct be_cmd_req_rx_filter);
rx_filter->va = dma_zalloc_coherent(&adapter->pdev->dev, rx_filter->va = dma_zalloc_coherent(dev, rx_filter->size,
rx_filter->size, &rx_filter->dma, &rx_filter->dma, GFP_KERNEL);
GFP_KERNEL);
if (!rx_filter->va) { if (!rx_filter->va) {
status = -ENOMEM; status = -ENOMEM;
goto free_mbox; goto free_mbox;
} }
if (lancer_chip(adapter))
stats_cmd->size = sizeof(struct lancer_cmd_req_pport_stats);
else if (BE2_chip(adapter))
stats_cmd->size = sizeof(struct be_cmd_req_get_stats_v0);
else if (BE3_chip(adapter))
stats_cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
else
stats_cmd->size = sizeof(struct be_cmd_req_get_stats_v2);
stats_cmd->va = dma_zalloc_coherent(dev, stats_cmd->size,
&stats_cmd->dma, GFP_KERNEL);
if (!stats_cmd->va) {
status = -ENOMEM;
goto free_rx_filter;
}
mutex_init(&adapter->mbox_lock); mutex_init(&adapter->mbox_lock);
spin_lock_init(&adapter->mcc_lock); spin_lock_init(&adapter->mcc_lock);
spin_lock_init(&adapter->mcc_cq_lock); spin_lock_init(&adapter->mcc_cq_lock);
init_completion(&adapter->et_cmd_compl); init_completion(&adapter->et_cmd_compl);
pci_save_state(adapter->pdev);
return 0;
free_mbox: pci_save_state(adapter->pdev);
dma_free_coherent(&adapter->pdev->dev, mbox_mem_alloc->size,
mbox_mem_alloc->va, mbox_mem_alloc->dma);
unmap_pci_bars:
be_unmap_pci_bars(adapter);
done:
return status;
}
static void be_stats_cleanup(struct be_adapter *adapter)
{
struct be_dma_mem *cmd = &adapter->stats_cmd;
if (cmd->va) INIT_DELAYED_WORK(&adapter->work, be_worker);
dma_free_coherent(&adapter->pdev->dev, cmd->size, INIT_DELAYED_WORK(&adapter->be_err_detection_work,
cmd->va, cmd->dma); be_err_detection_task);
}
static int be_stats_init(struct be_adapter *adapter) adapter->rx_fc = true;
{ adapter->tx_fc = true;
struct be_dma_mem *cmd = &adapter->stats_cmd;
if (lancer_chip(adapter)) /* Must be a power of 2 or else MODULO will BUG_ON */
cmd->size = sizeof(struct lancer_cmd_req_pport_stats); adapter->be_get_temp_freq = 64;
else if (BE2_chip(adapter)) adapter->cfg_num_qs = netif_get_num_default_rss_queues();
cmd->size = sizeof(struct be_cmd_req_get_stats_v0);
else if (BE3_chip(adapter))
cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
else
/* ALL non-BE ASICs */
cmd->size = sizeof(struct be_cmd_req_get_stats_v2);
cmd->va = dma_zalloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma,
GFP_KERNEL);
if (!cmd->va)
return -ENOMEM;
return 0; return 0;
free_rx_filter:
dma_free_coherent(dev, rx_filter->size, rx_filter->va, rx_filter->dma);
free_mbox:
dma_free_coherent(dev, mbox_mem_alloc->size, mbox_mem_alloc->va,
mbox_mem_alloc->dma);
return status;
} }
static void be_remove(struct pci_dev *pdev) static void be_remove(struct pci_dev *pdev)
...@@ -5045,7 +5239,7 @@ static void be_remove(struct pci_dev *pdev) ...@@ -5045,7 +5239,7 @@ static void be_remove(struct pci_dev *pdev)
be_roce_dev_remove(adapter); be_roce_dev_remove(adapter);
be_intr_set(adapter, false); be_intr_set(adapter, false);
cancel_delayed_work_sync(&adapter->func_recovery_work); be_cancel_err_detection(adapter);
unregister_netdev(adapter->netdev); unregister_netdev(adapter->netdev);
...@@ -5054,9 +5248,8 @@ static void be_remove(struct pci_dev *pdev) ...@@ -5054,9 +5248,8 @@ static void be_remove(struct pci_dev *pdev)
/* tell fw we're done with firing cmds */ /* tell fw we're done with firing cmds */
be_cmd_fw_clean(adapter); be_cmd_fw_clean(adapter);
be_stats_cleanup(adapter); be_unmap_pci_bars(adapter);
be_drv_cleanup(adapter);
be_ctrl_cleanup(adapter);
pci_disable_pcie_error_reporting(pdev); pci_disable_pcie_error_reporting(pdev);
...@@ -5066,156 +5259,6 @@ static void be_remove(struct pci_dev *pdev) ...@@ -5066,156 +5259,6 @@ static void be_remove(struct pci_dev *pdev)
free_netdev(adapter->netdev); free_netdev(adapter->netdev);
} }
static int be_get_initial_config(struct be_adapter *adapter)
{
int status, level;
status = be_cmd_get_cntl_attributes(adapter);
if (status)
return status;
/* Must be a power of 2 or else MODULO will BUG_ON */
adapter->be_get_temp_freq = 64;
if (BEx_chip(adapter)) {
level = be_cmd_get_fw_log_level(adapter);
adapter->msg_enable =
level <= FW_LOG_LEVEL_DEFAULT ? NETIF_MSG_HW : 0;
}
adapter->cfg_num_qs = netif_get_num_default_rss_queues();
return 0;
}
static int lancer_recover_func(struct be_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
int status;
status = lancer_test_and_set_rdy_state(adapter);
if (status)
goto err;
if (netif_running(adapter->netdev))
be_close(adapter->netdev);
be_clear(adapter);
be_clear_all_error(adapter);
status = be_setup(adapter);
if (status)
goto err;
if (netif_running(adapter->netdev)) {
status = be_open(adapter->netdev);
if (status)
goto err;
}
dev_err(dev, "Adapter recovery successful\n");
return 0;
err:
if (status == -EAGAIN)
dev_err(dev, "Waiting for resource provisioning\n");
else
dev_err(dev, "Adapter recovery failed\n");
return status;
}
static void be_func_recovery_task(struct work_struct *work)
{
struct be_adapter *adapter =
container_of(work, struct be_adapter, func_recovery_work.work);
int status = 0;
be_detect_error(adapter);
if (adapter->hw_error && lancer_chip(adapter)) {
rtnl_lock();
netif_device_detach(adapter->netdev);
rtnl_unlock();
status = lancer_recover_func(adapter);
if (!status)
netif_device_attach(adapter->netdev);
}
/* In Lancer, for all errors other than provisioning error (-EAGAIN),
* no need to attempt further recovery.
*/
if (!status || status == -EAGAIN)
schedule_delayed_work(&adapter->func_recovery_work,
msecs_to_jiffies(1000));
}
static void be_log_sfp_info(struct be_adapter *adapter)
{
int status;
status = be_cmd_query_sfp_info(adapter);
if (!status) {
dev_err(&adapter->pdev->dev,
"Unqualified SFP+ detected on %c from %s part no: %s",
adapter->port_name, adapter->phy.vendor_name,
adapter->phy.vendor_pn);
}
adapter->flags &= ~BE_FLAGS_EVT_INCOMPATIBLE_SFP;
}
static void be_worker(struct work_struct *work)
{
struct be_adapter *adapter =
container_of(work, struct be_adapter, work.work);
struct be_rx_obj *rxo;
int i;
/* when interrupts are not yet enabled, just reap any pending
* mcc completions */
if (!netif_running(adapter->netdev)) {
local_bh_disable();
be_process_mcc(adapter);
local_bh_enable();
goto reschedule;
}
if (!adapter->stats_cmd_sent) {
if (lancer_chip(adapter))
lancer_cmd_get_pport_stats(adapter,
&adapter->stats_cmd);
else
be_cmd_get_stats(adapter, &adapter->stats_cmd);
}
if (be_physfn(adapter) &&
MODULO(adapter->work_counter, adapter->be_get_temp_freq) == 0)
be_cmd_get_die_temperature(adapter);
for_all_rx_queues(adapter, rxo, i) {
/* Replenish RX-queues starved due to memory
* allocation failures.
*/
if (rxo->rx_post_starved)
be_post_rx_frags(rxo, GFP_KERNEL, MAX_RX_POST);
}
be_eqd_update(adapter);
if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP)
be_log_sfp_info(adapter);
reschedule:
adapter->work_counter++;
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
}
/* If any VFs are already enabled don't FLR the PF */
static bool be_reset_required(struct be_adapter *adapter)
{
return pci_num_vf(adapter->pdev) ? false : true;
}
static char *mc_name(struct be_adapter *adapter) static char *mc_name(struct be_adapter *adapter)
{ {
char *str = ""; /* default */ char *str = ""; /* default */
...@@ -5314,50 +5357,17 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) ...@@ -5314,50 +5357,17 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
if (!status) if (!status)
dev_info(&pdev->dev, "PCIe error reporting enabled\n"); dev_info(&pdev->dev, "PCIe error reporting enabled\n");
status = be_ctrl_init(adapter); status = be_map_pci_bars(adapter);
if (status) if (status)
goto free_netdev; goto free_netdev;
/* sync up with fw's ready state */ status = be_drv_init(adapter);
if (be_physfn(adapter)) {
status = be_fw_wait_ready(adapter);
if (status)
goto ctrl_clean;
}
if (be_reset_required(adapter)) {
status = be_cmd_reset_function(adapter);
if (status)
goto ctrl_clean;
/* Wait for interrupts to quiesce after an FLR */
msleep(100);
}
/* Allow interrupts for other ULPs running on NIC function */
be_intr_set(adapter, true);
/* tell fw we're ready to fire cmds */
status = be_cmd_fw_init(adapter);
if (status)
goto ctrl_clean;
status = be_stats_init(adapter);
if (status) if (status)
goto ctrl_clean; goto unmap_bars;
status = be_get_initial_config(adapter);
if (status)
goto stats_clean;
INIT_DELAYED_WORK(&adapter->work, be_worker);
INIT_DELAYED_WORK(&adapter->func_recovery_work, be_func_recovery_task);
adapter->rx_fc = true;
adapter->tx_fc = true;
status = be_setup(adapter); status = be_setup(adapter);
if (status) if (status)
goto stats_clean; goto drv_cleanup;
be_netdev_init(netdev); be_netdev_init(netdev);
status = register_netdev(netdev); status = register_netdev(netdev);
...@@ -5366,8 +5376,7 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) ...@@ -5366,8 +5376,7 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
be_roce_dev_add(adapter); be_roce_dev_add(adapter);
schedule_delayed_work(&adapter->func_recovery_work, be_schedule_err_detection(adapter);
msecs_to_jiffies(1000));
dev_info(&pdev->dev, "%s: %s %s port %c\n", nic_name(pdev), dev_info(&pdev->dev, "%s: %s %s port %c\n", nic_name(pdev),
func_name(adapter), mc_name(adapter), adapter->port_name); func_name(adapter), mc_name(adapter), adapter->port_name);
...@@ -5376,10 +5385,10 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) ...@@ -5376,10 +5385,10 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
unsetup: unsetup:
be_clear(adapter); be_clear(adapter);
stats_clean: drv_cleanup:
be_stats_cleanup(adapter); be_drv_cleanup(adapter);
ctrl_clean: unmap_bars:
be_ctrl_cleanup(adapter); be_unmap_pci_bars(adapter);
free_netdev: free_netdev:
free_netdev(netdev); free_netdev(netdev);
rel_reg: rel_reg:
...@@ -5394,21 +5403,14 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) ...@@ -5394,21 +5403,14 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
static int be_suspend(struct pci_dev *pdev, pm_message_t state) static int be_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
struct be_adapter *adapter = pci_get_drvdata(pdev); struct be_adapter *adapter = pci_get_drvdata(pdev);
struct net_device *netdev = adapter->netdev;
if (adapter->wol_en) if (adapter->wol_en)
be_setup_wol(adapter, true); be_setup_wol(adapter, true);
be_intr_set(adapter, false); be_intr_set(adapter, false);
cancel_delayed_work_sync(&adapter->func_recovery_work); be_cancel_err_detection(adapter);
netif_device_detach(netdev); be_cleanup(adapter);
if (netif_running(netdev)) {
rtnl_lock();
be_close(netdev);
rtnl_unlock();
}
be_clear(adapter);
pci_save_state(pdev); pci_save_state(pdev);
pci_disable_device(pdev); pci_disable_device(pdev);
...@@ -5416,13 +5418,10 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -5416,13 +5418,10 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
return 0; return 0;
} }
static int be_resume(struct pci_dev *pdev) static int be_pci_resume(struct pci_dev *pdev)
{ {
int status = 0;
struct be_adapter *adapter = pci_get_drvdata(pdev); struct be_adapter *adapter = pci_get_drvdata(pdev);
struct net_device *netdev = adapter->netdev; int status = 0;
netif_device_detach(netdev);
status = pci_enable_device(pdev); status = pci_enable_device(pdev);
if (status) if (status)
...@@ -5431,30 +5430,11 @@ static int be_resume(struct pci_dev *pdev) ...@@ -5431,30 +5430,11 @@ static int be_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0); pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev); pci_restore_state(pdev);
status = be_fw_wait_ready(adapter); status = be_resume(adapter);
if (status) if (status)
return status; return status;
status = be_cmd_reset_function(adapter); be_schedule_err_detection(adapter);
if (status)
return status;
be_intr_set(adapter, true);
/* tell fw we're ready to fire cmds */
status = be_cmd_fw_init(adapter);
if (status)
return status;
be_setup(adapter);
if (netif_running(netdev)) {
rtnl_lock();
be_open(netdev);
rtnl_unlock();
}
schedule_delayed_work(&adapter->func_recovery_work,
msecs_to_jiffies(1000));
netif_device_attach(netdev);
if (adapter->wol_en) if (adapter->wol_en)
be_setup_wol(adapter, false); be_setup_wol(adapter, false);
...@@ -5474,7 +5454,7 @@ static void be_shutdown(struct pci_dev *pdev) ...@@ -5474,7 +5454,7 @@ static void be_shutdown(struct pci_dev *pdev)
be_roce_dev_shutdown(adapter); be_roce_dev_shutdown(adapter);
cancel_delayed_work_sync(&adapter->work); cancel_delayed_work_sync(&adapter->work);
cancel_delayed_work_sync(&adapter->func_recovery_work); be_cancel_err_detection(adapter);
netif_device_detach(adapter->netdev); netif_device_detach(adapter->netdev);
...@@ -5487,22 +5467,15 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, ...@@ -5487,22 +5467,15 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
pci_channel_state_t state) pci_channel_state_t state)
{ {
struct be_adapter *adapter = pci_get_drvdata(pdev); struct be_adapter *adapter = pci_get_drvdata(pdev);
struct net_device *netdev = adapter->netdev;
dev_err(&adapter->pdev->dev, "EEH error detected\n"); dev_err(&adapter->pdev->dev, "EEH error detected\n");
if (!adapter->eeh_error) { if (!adapter->eeh_error) {
adapter->eeh_error = true; adapter->eeh_error = true;
cancel_delayed_work_sync(&adapter->func_recovery_work); be_cancel_err_detection(adapter);
rtnl_lock(); be_cleanup(adapter);
netif_device_detach(netdev);
if (netif_running(netdev))
be_close(netdev);
rtnl_unlock();
be_clear(adapter);
} }
if (state == pci_channel_io_perm_failure) if (state == pci_channel_io_perm_failure)
...@@ -5553,40 +5526,16 @@ static void be_eeh_resume(struct pci_dev *pdev) ...@@ -5553,40 +5526,16 @@ static void be_eeh_resume(struct pci_dev *pdev)
{ {
int status = 0; int status = 0;
struct be_adapter *adapter = pci_get_drvdata(pdev); struct be_adapter *adapter = pci_get_drvdata(pdev);
struct net_device *netdev = adapter->netdev;
dev_info(&adapter->pdev->dev, "EEH resume\n"); dev_info(&adapter->pdev->dev, "EEH resume\n");
pci_save_state(pdev); pci_save_state(pdev);
status = be_cmd_reset_function(adapter); status = be_resume(adapter);
if (status) if (status)
goto err; goto err;
/* On some BE3 FW versions, after a HW reset, be_schedule_err_detection(adapter);
* interrupts will remain disabled for each function.
* So, explicitly enable interrupts
*/
be_intr_set(adapter, true);
/* tell fw we're ready to fire cmds */
status = be_cmd_fw_init(adapter);
if (status)
goto err;
status = be_setup(adapter);
if (status)
goto err;
if (netif_running(netdev)) {
status = be_open(netdev);
if (status)
goto err;
}
schedule_delayed_work(&adapter->func_recovery_work,
msecs_to_jiffies(1000));
netif_device_attach(netdev);
return; return;
err: err:
dev_err(&adapter->pdev->dev, "EEH resume failed\n"); dev_err(&adapter->pdev->dev, "EEH resume failed\n");
...@@ -5604,7 +5553,7 @@ static struct pci_driver be_driver = { ...@@ -5604,7 +5553,7 @@ static struct pci_driver be_driver = {
.probe = be_probe, .probe = be_probe,
.remove = be_remove, .remove = be_remove,
.suspend = be_suspend, .suspend = be_suspend,
.resume = be_resume, .resume = be_pci_resume,
.shutdown = be_shutdown, .shutdown = be_shutdown,
.err_handler = &be_eeh_handlers .err_handler = &be_eeh_handlers
}; };
......
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