aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRon Mercer <ron.mercer@qlogic.com>2009-02-26 05:08:34 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-27 01:28:08 -0500
commit125844eaff0e9600c92a753995564fd93c807f3c (patch)
tree5549acecb41c61bec9e2c471b1e3ef2d4b9e9d91 /drivers
parenta2e809bb1b2174af66bf9798444f7e90892f45a9 (diff)
qlge: Move firmware event handler.
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/qlge/qlge.h1
-rw-r--r--drivers/net/qlge/qlge_main.c1
-rw-r--r--drivers/net/qlge/qlge_mpi.c88
3 files changed, 62 insertions, 28 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index 8b3c37afe80a..2103fe6ff3a5 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -1407,6 +1407,7 @@ struct ql_adapter {
1407 1407
1408 u32 mailbox_in; 1408 u32 mailbox_in;
1409 u32 mailbox_out; 1409 u32 mailbox_out;
1410 struct mutex mpi_mutex;
1410 1411
1411 int tx_ring_size; 1412 int tx_ring_size;
1412 int rx_ring_size; 1413 int rx_ring_size;
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 655f3c4322e0..b144b6becfea 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -3659,6 +3659,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
3659 INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work); 3659 INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work);
3660 INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work); 3660 INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work);
3661 INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); 3661 INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work);
3662 mutex_init(&qdev->mpi_mutex);
3662 3663
3663 if (!cards_found) { 3664 if (!cards_found) {
3664 dev_info(&pdev->dev, "%s\n", DRV_STRING); 3665 dev_info(&pdev->dev, "%s\n", DRV_STRING);
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c
index f9db78697e2b..a4b810d0d3d1 100644
--- a/drivers/net/qlge/qlge_mpi.c
+++ b/drivers/net/qlge/qlge_mpi.c
@@ -124,43 +124,75 @@ exit:
124 ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT); 124 ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
125} 125}
126 126
127/* Process an async event and clear it unless it's an
128 * error condition.
129 * This can get called iteratively from the mpi_work thread
130 * when events arrive via an interrupt.
131 * It also gets called when a mailbox command is polling for
132 * it's completion. */
133static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp)
134{
135 int status;
136
137 /* Just get mailbox zero for now. */
138 mbcp->out_count = 1;
139 status = ql_get_mb_sts(qdev, mbcp);
140 if (status) {
141 QPRINTK(qdev, DRV, ERR,
142 "Could not read MPI, resetting ASIC!\n");
143 ql_queue_asic_error(qdev);
144 goto end;
145 }
146
147 switch (mbcp->mbox_out[0]) {
148
149 case AEN_LINK_UP:
150 ql_link_up(qdev, mbcp);
151 break;
152
153 case AEN_LINK_DOWN:
154 ql_link_down(qdev, mbcp);
155 break;
156
157 case AEN_FW_INIT_DONE:
158 ql_init_fw_done(qdev, mbcp);
159 break;
160
161 case MB_CMD_STS_GOOD:
162 break;
163
164 case AEN_FW_INIT_FAIL:
165 case AEN_SYS_ERR:
166 case MB_CMD_STS_ERR:
167 ql_queue_fw_error(qdev);
168 break;
169
170 default:
171 QPRINTK(qdev, DRV, ERR,
172 "Unsupported AE %.08x.\n", mbcp->mbox_out[0]);
173 /* Clear the MPI firmware status. */
174 }
175end:
176 ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
177 return status;
178}
179
127void ql_mpi_work(struct work_struct *work) 180void ql_mpi_work(struct work_struct *work)
128{ 181{
129 struct ql_adapter *qdev = 182 struct ql_adapter *qdev =
130 container_of(work, struct ql_adapter, mpi_work.work); 183 container_of(work, struct ql_adapter, mpi_work.work);
131 struct mbox_params mbc; 184 struct mbox_params mbc;
132 struct mbox_params *mbcp = &mbc; 185 struct mbox_params *mbcp = &mbc;
133 mbcp->out_count = 1;
134 186
135 while (ql_read32(qdev, STS) & STS_PI) { 187 mutex_lock(&qdev->mpi_mutex);
136 if (ql_get_mb_sts(qdev, mbcp)) {
137 QPRINTK(qdev, DRV, ERR,
138 "Could not read MPI, resetting ASIC!\n");
139 ql_queue_asic_error(qdev);
140 }
141 188
142 switch (mbcp->mbox_out[0]) { 189 while (ql_read32(qdev, STS) & STS_PI) {
143 case AEN_LINK_UP: 190 memset(mbcp, 0, sizeof(struct mbox_params));
144 ql_link_up(qdev, mbcp); 191 mbcp->out_count = 1;
145 break; 192 ql_mpi_handler(qdev, mbcp);
146 case AEN_LINK_DOWN:
147 ql_link_down(qdev, mbcp);
148 break;
149 case AEN_FW_INIT_DONE:
150 ql_init_fw_done(qdev, mbcp);
151 break;
152 case MB_CMD_STS_GOOD:
153 break;
154 case AEN_FW_INIT_FAIL:
155 case AEN_SYS_ERR:
156 case MB_CMD_STS_ERR:
157 ql_queue_fw_error(qdev);
158 default:
159 /* Clear the MPI firmware status. */
160 ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
161 break;
162 }
163 } 193 }
194
195 mutex_unlock(&qdev->mpi_mutex);
164 ql_enable_completion_interrupt(qdev, 0); 196 ql_enable_completion_interrupt(qdev, 0);
165} 197}
166 198