diff options
-rw-r--r-- | drivers/net/qlge/qlge.h | 1 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 1 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_mpi.c | 88 |
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. */ | ||
133 | static 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 | } | ||
175 | end: | ||
176 | ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT); | ||
177 | return status; | ||
178 | } | ||
179 | |||
127 | void ql_mpi_work(struct work_struct *work) | 180 | void 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 | ||