diff options
-rw-r--r-- | drivers/net/qlge/qlge.h | 3 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 4 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_mpi.c | 143 |
3 files changed, 149 insertions, 1 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 6f9fd24bf384..9918106f2a53 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h | |||
@@ -1499,6 +1499,7 @@ struct ql_adapter { | |||
1499 | struct delayed_work mpi_reset_work; | 1499 | struct delayed_work mpi_reset_work; |
1500 | struct delayed_work mpi_work; | 1500 | struct delayed_work mpi_work; |
1501 | struct delayed_work mpi_port_cfg_work; | 1501 | struct delayed_work mpi_port_cfg_work; |
1502 | struct delayed_work mpi_idc_work; | ||
1502 | struct completion ide_completion; | 1503 | struct completion ide_completion; |
1503 | struct nic_operations *nic_ops; | 1504 | struct nic_operations *nic_ops; |
1504 | u16 device_id; | 1505 | u16 device_id; |
@@ -1574,8 +1575,10 @@ void ql_queue_asic_error(struct ql_adapter *qdev); | |||
1574 | u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr); | 1575 | u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr); |
1575 | void ql_set_ethtool_ops(struct net_device *ndev); | 1576 | void ql_set_ethtool_ops(struct net_device *ndev); |
1576 | int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data); | 1577 | int ql_read_xgmac_reg64(struct ql_adapter *qdev, u32 reg, u64 *data); |
1578 | void ql_mpi_idc_work(struct work_struct *work); | ||
1577 | void ql_mpi_port_cfg_work(struct work_struct *work); | 1579 | void ql_mpi_port_cfg_work(struct work_struct *work); |
1578 | int ql_mb_get_fw_state(struct ql_adapter *qdev); | 1580 | int ql_mb_get_fw_state(struct ql_adapter *qdev); |
1581 | int ql_cam_route_initialize(struct ql_adapter *qdev); | ||
1579 | 1582 | ||
1580 | #if 1 | 1583 | #if 1 |
1581 | #define QL_ALL_DUMP | 1584 | #define QL_ALL_DUMP |
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 7c1ce5765759..d800ff40b32b 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c | |||
@@ -3014,7 +3014,7 @@ exit: | |||
3014 | return status; | 3014 | return status; |
3015 | } | 3015 | } |
3016 | 3016 | ||
3017 | static int ql_cam_route_initialize(struct ql_adapter *qdev) | 3017 | int ql_cam_route_initialize(struct ql_adapter *qdev) |
3018 | { | 3018 | { |
3019 | int status; | 3019 | int status; |
3020 | 3020 | ||
@@ -3195,6 +3195,7 @@ static int ql_adapter_down(struct ql_adapter *qdev) | |||
3195 | cancel_delayed_work_sync(&qdev->asic_reset_work); | 3195 | cancel_delayed_work_sync(&qdev->asic_reset_work); |
3196 | cancel_delayed_work_sync(&qdev->mpi_reset_work); | 3196 | cancel_delayed_work_sync(&qdev->mpi_reset_work); |
3197 | cancel_delayed_work_sync(&qdev->mpi_work); | 3197 | cancel_delayed_work_sync(&qdev->mpi_work); |
3198 | cancel_delayed_work_sync(&qdev->mpi_idc_work); | ||
3198 | cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); | 3199 | cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); |
3199 | 3200 | ||
3200 | /* The default queue at index 0 is always processed in | 3201 | /* The default queue at index 0 is always processed in |
@@ -3782,6 +3783,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, | |||
3782 | INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work); | 3783 | INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work); |
3783 | INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); | 3784 | INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); |
3784 | INIT_DELAYED_WORK(&qdev->mpi_port_cfg_work, ql_mpi_port_cfg_work); | 3785 | INIT_DELAYED_WORK(&qdev->mpi_port_cfg_work, ql_mpi_port_cfg_work); |
3786 | INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work); | ||
3785 | mutex_init(&qdev->mpi_mutex); | 3787 | mutex_init(&qdev->mpi_mutex); |
3786 | init_completion(&qdev->ide_completion); | 3788 | init_completion(&qdev->ide_completion); |
3787 | 3789 | ||
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 3b4b494387aa..9f1fe542e271 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c | |||
@@ -138,6 +138,40 @@ end: | |||
138 | return status; | 138 | return status; |
139 | } | 139 | } |
140 | 140 | ||
141 | /* We are being asked by firmware to accept | ||
142 | * a change to the port. This is only | ||
143 | * a change to max frame sizes (Tx/Rx), pause | ||
144 | * paramters, or loopback mode. We wake up a worker | ||
145 | * to handler processing this since a mailbox command | ||
146 | * will need to be sent to ACK the request. | ||
147 | */ | ||
148 | static int ql_idc_req_aen(struct ql_adapter *qdev) | ||
149 | { | ||
150 | int status; | ||
151 | struct mbox_params *mbcp = &qdev->idc_mbc; | ||
152 | |||
153 | QPRINTK(qdev, DRV, ERR, "Enter!\n"); | ||
154 | /* Get the status data and start up a thread to | ||
155 | * handle the request. | ||
156 | */ | ||
157 | mbcp = &qdev->idc_mbc; | ||
158 | mbcp->out_count = 4; | ||
159 | status = ql_get_mb_sts(qdev, mbcp); | ||
160 | if (status) { | ||
161 | QPRINTK(qdev, DRV, ERR, | ||
162 | "Could not read MPI, resetting ASIC!\n"); | ||
163 | ql_queue_asic_error(qdev); | ||
164 | } else { | ||
165 | /* Begin polled mode early so | ||
166 | * we don't get another interrupt | ||
167 | * when we leave mpi_worker. | ||
168 | */ | ||
169 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | ||
170 | queue_delayed_work(qdev->workqueue, &qdev->mpi_idc_work, 0); | ||
171 | } | ||
172 | return status; | ||
173 | } | ||
174 | |||
141 | /* Process an inter-device event completion. | 175 | /* Process an inter-device event completion. |
142 | * If good, signal the caller's completion. | 176 | * If good, signal the caller's completion. |
143 | */ | 177 | */ |
@@ -175,6 +209,35 @@ static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp) | |||
175 | qdev->link_status = mbcp->mbox_out[1]; | 209 | qdev->link_status = mbcp->mbox_out[1]; |
176 | QPRINTK(qdev, DRV, ERR, "Link Up.\n"); | 210 | QPRINTK(qdev, DRV, ERR, "Link Up.\n"); |
177 | 211 | ||
212 | /* If we're coming back from an IDC event | ||
213 | * then set up the CAM and frame routing. | ||
214 | */ | ||
215 | if (test_bit(QL_CAM_RT_SET, &qdev->flags)) { | ||
216 | status = ql_cam_route_initialize(qdev); | ||
217 | if (status) { | ||
218 | QPRINTK(qdev, IFUP, ERR, | ||
219 | "Failed to init CAM/Routing tables.\n"); | ||
220 | return; | ||
221 | } else | ||
222 | clear_bit(QL_CAM_RT_SET, &qdev->flags); | ||
223 | } | ||
224 | |||
225 | /* Queue up a worker to check the frame | ||
226 | * size information, and fix it if it's not | ||
227 | * to our liking. | ||
228 | */ | ||
229 | if (!test_bit(QL_PORT_CFG, &qdev->flags)) { | ||
230 | QPRINTK(qdev, DRV, ERR, "Queue Port Config Worker!\n"); | ||
231 | set_bit(QL_PORT_CFG, &qdev->flags); | ||
232 | /* Begin polled mode early so | ||
233 | * we don't get another interrupt | ||
234 | * when we leave mpi_worker dpc. | ||
235 | */ | ||
236 | ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); | ||
237 | queue_delayed_work(qdev->workqueue, | ||
238 | &qdev->mpi_port_cfg_work, 0); | ||
239 | } | ||
240 | |||
178 | netif_carrier_on(qdev->ndev); | 241 | netif_carrier_on(qdev->ndev); |
179 | } | 242 | } |
180 | 243 | ||
@@ -283,6 +346,15 @@ static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp) | |||
283 | status = ql_get_mb_sts(qdev, mbcp); | 346 | status = ql_get_mb_sts(qdev, mbcp); |
284 | return status; | 347 | return status; |
285 | 348 | ||
349 | /* We are being asked by firmware to accept | ||
350 | * a change to the port. This is only | ||
351 | * a change to max frame sizes (Tx/Rx), pause | ||
352 | * paramters, or loopback mode. | ||
353 | */ | ||
354 | case AEN_IDC_REQ: | ||
355 | status = ql_idc_req_aen(qdev); | ||
356 | break; | ||
357 | |||
286 | /* Process and inbound IDC event. | 358 | /* Process and inbound IDC event. |
287 | * This will happen when we're trying to | 359 | * This will happen when we're trying to |
288 | * change tx/rx max frame size, change pause | 360 | * change tx/rx max frame size, change pause |
@@ -451,6 +523,38 @@ int ql_mb_get_fw_state(struct ql_adapter *qdev) | |||
451 | return status; | 523 | return status; |
452 | } | 524 | } |
453 | 525 | ||
526 | /* Send and ACK mailbox command to the firmware to | ||
527 | * let it continue with the change. | ||
528 | */ | ||
529 | int ql_mb_idc_ack(struct ql_adapter *qdev) | ||
530 | { | ||
531 | struct mbox_params mbc; | ||
532 | struct mbox_params *mbcp = &mbc; | ||
533 | int status = 0; | ||
534 | |||
535 | memset(mbcp, 0, sizeof(struct mbox_params)); | ||
536 | |||
537 | mbcp->in_count = 5; | ||
538 | mbcp->out_count = 1; | ||
539 | |||
540 | mbcp->mbox_in[0] = MB_CMD_IDC_ACK; | ||
541 | mbcp->mbox_in[1] = qdev->idc_mbc.mbox_out[1]; | ||
542 | mbcp->mbox_in[2] = qdev->idc_mbc.mbox_out[2]; | ||
543 | mbcp->mbox_in[3] = qdev->idc_mbc.mbox_out[3]; | ||
544 | mbcp->mbox_in[4] = qdev->idc_mbc.mbox_out[4]; | ||
545 | |||
546 | status = ql_mailbox_command(qdev, mbcp); | ||
547 | if (status) | ||
548 | return status; | ||
549 | |||
550 | if (mbcp->mbox_out[0] != MB_CMD_STS_GOOD) { | ||
551 | QPRINTK(qdev, DRV, ERR, | ||
552 | "Failed IDC ACK send.\n"); | ||
553 | status = -EIO; | ||
554 | } | ||
555 | return status; | ||
556 | } | ||
557 | |||
454 | /* Get link settings and maximum frame size settings | 558 | /* Get link settings and maximum frame size settings |
455 | * for the current port. | 559 | * for the current port. |
456 | * Most likely will block. | 560 | * Most likely will block. |
@@ -627,6 +731,44 @@ err: | |||
627 | goto end; | 731 | goto end; |
628 | } | 732 | } |
629 | 733 | ||
734 | /* Process an inter-device request. This is issues by | ||
735 | * the firmware in response to another function requesting | ||
736 | * a change to the port. We set a flag to indicate a change | ||
737 | * has been made and then send a mailbox command ACKing | ||
738 | * the change request. | ||
739 | */ | ||
740 | void ql_mpi_idc_work(struct work_struct *work) | ||
741 | { | ||
742 | struct ql_adapter *qdev = | ||
743 | container_of(work, struct ql_adapter, mpi_idc_work.work); | ||
744 | int status; | ||
745 | struct mbox_params *mbcp = &qdev->idc_mbc; | ||
746 | u32 aen; | ||
747 | |||
748 | aen = mbcp->mbox_out[1] >> 16; | ||
749 | |||
750 | switch (aen) { | ||
751 | default: | ||
752 | QPRINTK(qdev, DRV, ERR, | ||
753 | "Bug: Unhandled IDC action.\n"); | ||
754 | break; | ||
755 | case MB_CMD_PORT_RESET: | ||
756 | case MB_CMD_SET_PORT_CFG: | ||
757 | case MB_CMD_STOP_FW: | ||
758 | netif_carrier_off(qdev->ndev); | ||
759 | /* Signal the resulting link up AEN | ||
760 | * that the frame routing and mac addr | ||
761 | * needs to be set. | ||
762 | * */ | ||
763 | set_bit(QL_CAM_RT_SET, &qdev->flags); | ||
764 | status = ql_mb_idc_ack(qdev); | ||
765 | if (status) { | ||
766 | QPRINTK(qdev, DRV, ERR, | ||
767 | "Bug: No pending IDC!\n"); | ||
768 | } | ||
769 | } | ||
770 | } | ||
771 | |||
630 | void ql_mpi_work(struct work_struct *work) | 772 | void ql_mpi_work(struct work_struct *work) |
631 | { | 773 | { |
632 | struct ql_adapter *qdev = | 774 | struct ql_adapter *qdev = |
@@ -652,5 +794,6 @@ void ql_mpi_reset_work(struct work_struct *work) | |||
652 | container_of(work, struct ql_adapter, mpi_reset_work.work); | 794 | container_of(work, struct ql_adapter, mpi_reset_work.work); |
653 | cancel_delayed_work_sync(&qdev->mpi_work); | 795 | cancel_delayed_work_sync(&qdev->mpi_work); |
654 | cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); | 796 | cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); |
797 | cancel_delayed_work_sync(&qdev->mpi_idc_work); | ||
655 | ql_soft_reset_mpi_risc(qdev); | 798 | ql_soft_reset_mpi_risc(qdev); |
656 | } | 799 | } |