Skip to content

Commit

Permalink
qlge: Move firmware event handler.
Browse files Browse the repository at this point in the history
This is not a logical change but rather a move of the inbound firmware event
handler into it's own function as it will later be called by the outbound
path.
The addition of the mutex is to create exclusive access to the mailbox
commands between inbound and outbound handling.

Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ron Mercer authored and David S. Miller committed Feb 27, 2009
1 parent a2e809b commit 125844e
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 28 deletions.
1 change: 1 addition & 0 deletions drivers/net/qlge/qlge.h
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,7 @@ struct ql_adapter {

u32 mailbox_in;
u32 mailbox_out;
struct mutex mpi_mutex;

int tx_ring_size;
int rx_ring_size;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/qlge/qlge_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3659,6 +3659,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work);
INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work);
INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work);
mutex_init(&qdev->mpi_mutex);

if (!cards_found) {
dev_info(&pdev->dev, "%s\n", DRV_STRING);
Expand Down
88 changes: 60 additions & 28 deletions drivers/net/qlge/qlge_mpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,43 +124,75 @@ static void ql_init_fw_done(struct ql_adapter *qdev, struct mbox_params *mbcp)
ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
}

/* Process an async event and clear it unless it's an
* error condition.
* This can get called iteratively from the mpi_work thread
* when events arrive via an interrupt.
* It also gets called when a mailbox command is polling for
* it's completion. */
static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp)
{
int status;

/* Just get mailbox zero for now. */
mbcp->out_count = 1;
status = ql_get_mb_sts(qdev, mbcp);
if (status) {
QPRINTK(qdev, DRV, ERR,
"Could not read MPI, resetting ASIC!\n");
ql_queue_asic_error(qdev);
goto end;
}

switch (mbcp->mbox_out[0]) {

case AEN_LINK_UP:
ql_link_up(qdev, mbcp);
break;

case AEN_LINK_DOWN:
ql_link_down(qdev, mbcp);
break;

case AEN_FW_INIT_DONE:
ql_init_fw_done(qdev, mbcp);
break;

case MB_CMD_STS_GOOD:
break;

case AEN_FW_INIT_FAIL:
case AEN_SYS_ERR:
case MB_CMD_STS_ERR:
ql_queue_fw_error(qdev);
break;

default:
QPRINTK(qdev, DRV, ERR,
"Unsupported AE %.08x.\n", mbcp->mbox_out[0]);
/* Clear the MPI firmware status. */
}
end:
ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
return status;
}

void ql_mpi_work(struct work_struct *work)
{
struct ql_adapter *qdev =
container_of(work, struct ql_adapter, mpi_work.work);
struct mbox_params mbc;
struct mbox_params *mbcp = &mbc;
mbcp->out_count = 1;

while (ql_read32(qdev, STS) & STS_PI) {
if (ql_get_mb_sts(qdev, mbcp)) {
QPRINTK(qdev, DRV, ERR,
"Could not read MPI, resetting ASIC!\n");
ql_queue_asic_error(qdev);
}
mutex_lock(&qdev->mpi_mutex);

switch (mbcp->mbox_out[0]) {
case AEN_LINK_UP:
ql_link_up(qdev, mbcp);
break;
case AEN_LINK_DOWN:
ql_link_down(qdev, mbcp);
break;
case AEN_FW_INIT_DONE:
ql_init_fw_done(qdev, mbcp);
break;
case MB_CMD_STS_GOOD:
break;
case AEN_FW_INIT_FAIL:
case AEN_SYS_ERR:
case MB_CMD_STS_ERR:
ql_queue_fw_error(qdev);
default:
/* Clear the MPI firmware status. */
ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
break;
}
while (ql_read32(qdev, STS) & STS_PI) {
memset(mbcp, 0, sizeof(struct mbox_params));
mbcp->out_count = 1;
ql_mpi_handler(qdev, mbcp);
}

mutex_unlock(&qdev->mpi_mutex);
ql_enable_completion_interrupt(qdev, 0);
}

Expand Down

0 comments on commit 125844e

Please sign in to comment.