Skip to content

Commit

Permalink
be2net: Add error handling for Lancer
Browse files Browse the repository at this point in the history
Detect error in Lancer by polling a HW register and
recover from this error if it is recoverable.

Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Padmanabh Ratnakar authored and David S. Miller committed Nov 26, 2011
1 parent 3bb62f4 commit d8110f6
Showing 1 changed file with 106 additions and 49 deletions.
155 changes: 106 additions & 49 deletions drivers/net/ethernet/emulex/benet/be_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2044,52 +2044,6 @@ void be_detect_dump_ue(struct be_adapter *adapter)
}
}

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;

be_detect_dump_ue(adapter);

/* when interrupts are not yet enabled, just reap any pending
* mcc completions */
if (!netif_running(adapter->netdev)) {
int mcc_compl, status = 0;

mcc_compl = be_process_mcc(adapter, &status);

if (mcc_compl) {
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
}

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);
}

for_all_rx_queues(adapter, rxo, i) {
be_rx_eqd_update(adapter, rxo);

if (rxo->rx_post_starved) {
rxo->rx_post_starved = false;
be_post_rx_frags(rxo, GFP_KERNEL);
}
}

reschedule:
adapter->work_counter++;
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
}

static void be_msix_disable(struct be_adapter *adapter)
{
if (msix_enabled(adapter)) {
Expand Down Expand Up @@ -3328,7 +3282,7 @@ static int be_dev_family_check(struct be_adapter *adapter)

static int lancer_wait_ready(struct be_adapter *adapter)
{
#define SLIPORT_READY_TIMEOUT 500
#define SLIPORT_READY_TIMEOUT 30
u32 sliport_status;
int status = 0, i;

Expand All @@ -3337,7 +3291,7 @@ static int lancer_wait_ready(struct be_adapter *adapter)
if (sliport_status & SLIPORT_STATUS_RDY_MASK)
break;

msleep(20);
msleep(1000);
}

if (i == SLIPORT_READY_TIMEOUT)
Expand Down Expand Up @@ -3374,6 +3328,104 @@ static int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
return status;
}

static void lancer_test_and_recover_fn_err(struct be_adapter *adapter)
{
int status;
u32 sliport_status;

if (adapter->eeh_err || adapter->ue_detected)
return;

sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);

if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
dev_err(&adapter->pdev->dev,
"Adapter in error state."
"Trying to recover.\n");

status = lancer_test_and_set_rdy_state(adapter);
if (status)
goto err;

netif_device_detach(adapter->netdev);

if (netif_running(adapter->netdev))
be_close(adapter->netdev);

be_clear(adapter);

adapter->fw_timeout = false;

status = be_setup(adapter);
if (status)
goto err;

if (netif_running(adapter->netdev)) {
status = be_open(adapter->netdev);
if (status)
goto err;
}

netif_device_attach(adapter->netdev);

dev_err(&adapter->pdev->dev,
"Adapter error recovery succeeded\n");
}
return;
err:
dev_err(&adapter->pdev->dev,
"Adapter error recovery failed\n");
}

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;

if (lancer_chip(adapter))
lancer_test_and_recover_fn_err(adapter);

be_detect_dump_ue(adapter);

/* when interrupts are not yet enabled, just reap any pending
* mcc completions */
if (!netif_running(adapter->netdev)) {
int mcc_compl, status = 0;

mcc_compl = be_process_mcc(adapter, &status);

if (mcc_compl) {
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
}

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);
}

for_all_rx_queues(adapter, rxo, i) {
be_rx_eqd_update(adapter, rxo);

if (rxo->rx_post_starved) {
rxo->rx_post_starved = false;
be_post_rx_frags(rxo, GFP_KERNEL);
}
}

reschedule:
adapter->work_counter++;
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
}

static int __devinit be_probe(struct pci_dev *pdev,
const struct pci_device_id *pdev_id)
{
Expand Down Expand Up @@ -3426,7 +3478,12 @@ static int __devinit be_probe(struct pci_dev *pdev,
goto disable_sriov;

if (lancer_chip(adapter)) {
status = lancer_test_and_set_rdy_state(adapter);
status = lancer_wait_ready(adapter);
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(&pdev->dev, "Adapter in non recoverable error\n");
goto ctrl_clean;
Expand Down

0 comments on commit d8110f6

Please sign in to comment.