blob: f9db78697e2b57bcfef24aa6b9916e99be77c650 [file] [log] [blame]
Ron Mercerc4e84bd2008-09-18 11:56:28 -04001#include "qlge.h"
2
Ron Mercera2e809b2009-02-26 10:08:33 +00003int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data)
Ron Mercerc4e84bd2008-09-18 11:56:28 -04004{
5 int status;
6 /* wait for reg to come ready */
7 status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR);
8 if (status)
9 goto exit;
10 /* set up for reg read */
11 ql_write32(qdev, PROC_ADDR, reg | PROC_ADDR_R);
12 /* wait for reg to come ready */
13 status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR);
14 if (status)
15 goto exit;
16 /* get the data */
17 *data = ql_read32(qdev, PROC_DATA);
18exit:
19 return status;
20}
21
Ron Mercera2e809b2009-02-26 10:08:33 +000022int ql_write_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 data)
23{
24 int status = 0;
25 /* wait for reg to come ready */
26 status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR);
27 if (status)
28 goto exit;
29 /* write the data to the data reg */
30 ql_write32(qdev, PROC_DATA, data);
31 /* trigger the write */
32 ql_write32(qdev, PROC_ADDR, reg);
33 /* wait for reg to come ready */
34 status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR);
35 if (status)
36 goto exit;
37exit:
38 return status;
39}
40
41int ql_soft_reset_mpi_risc(struct ql_adapter *qdev)
42{
43 int status;
44 status = ql_write_mpi_reg(qdev, 0x00001010, 1);
45 return status;
46}
47
Hannes Eder2f22d222008-12-26 00:04:53 -080048static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp)
Ron Mercerc4e84bd2008-09-18 11:56:28 -040049{
50 int i, status;
51
52 status = ql_sem_spinlock(qdev, SEM_PROC_REG_MASK);
53 if (status)
54 return -EBUSY;
55 for (i = 0; i < mbcp->out_count; i++) {
56 status =
Ron Mercera2e809b2009-02-26 10:08:33 +000057 ql_read_mpi_reg(qdev, qdev->mailbox_out + i,
Ron Mercerc4e84bd2008-09-18 11:56:28 -040058 &mbcp->mbox_out[i]);
59 if (status) {
60 QPRINTK(qdev, DRV, ERR, "Failed mailbox read.\n");
61 break;
62 }
63 }
64 ql_sem_unlock(qdev, SEM_PROC_REG_MASK); /* does flush too */
65 return status;
66}
67
68static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp)
69{
70 mbcp->out_count = 2;
71
72 if (ql_get_mb_sts(qdev, mbcp))
73 goto exit;
74
75 qdev->link_status = mbcp->mbox_out[1];
76 QPRINTK(qdev, DRV, ERR, "Link Up.\n");
77 QPRINTK(qdev, DRV, INFO, "Link Status = 0x%.08x.\n", mbcp->mbox_out[1]);
78 if (!netif_carrier_ok(qdev->ndev)) {
79 QPRINTK(qdev, LINK, INFO, "Link is Up.\n");
80 netif_carrier_on(qdev->ndev);
81 netif_wake_queue(qdev->ndev);
82 }
83exit:
84 /* Clear the MPI firmware status. */
85 ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
86}
87
88static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp)
89{
90 mbcp->out_count = 3;
91
92 if (ql_get_mb_sts(qdev, mbcp)) {
93 QPRINTK(qdev, DRV, ERR, "Firmware did not initialize!\n");
94 goto exit;
95 }
96
97 if (netif_carrier_ok(qdev->ndev)) {
98 QPRINTK(qdev, LINK, INFO, "Link is Down.\n");
99 netif_carrier_off(qdev->ndev);
100 netif_stop_queue(qdev->ndev);
101 }
102 QPRINTK(qdev, DRV, ERR, "Link Down.\n");
103 QPRINTK(qdev, DRV, ERR, "Link Status = 0x%.08x.\n", mbcp->mbox_out[1]);
104exit:
105 /* Clear the MPI firmware status. */
106 ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
107}
108
109static void ql_init_fw_done(struct ql_adapter *qdev, struct mbox_params *mbcp)
110{
111 mbcp->out_count = 2;
112
113 if (ql_get_mb_sts(qdev, mbcp)) {
114 QPRINTK(qdev, DRV, ERR, "Firmware did not initialize!\n");
115 goto exit;
116 }
117 QPRINTK(qdev, DRV, ERR, "Firmware initialized!\n");
118 QPRINTK(qdev, DRV, ERR, "Firmware status = 0x%.08x.\n",
119 mbcp->mbox_out[0]);
120 QPRINTK(qdev, DRV, ERR, "Firmware Revision = 0x%.08x.\n",
121 mbcp->mbox_out[1]);
122exit:
123 /* Clear the MPI firmware status. */
124 ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
125}
126
127void ql_mpi_work(struct work_struct *work)
128{
129 struct ql_adapter *qdev =
130 container_of(work, struct ql_adapter, mpi_work.work);
131 struct mbox_params mbc;
132 struct mbox_params *mbcp = &mbc;
133 mbcp->out_count = 1;
134
135 while (ql_read32(qdev, STS) & STS_PI) {
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
142 switch (mbcp->mbox_out[0]) {
143 case AEN_LINK_UP:
144 ql_link_up(qdev, mbcp);
145 break;
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 }
164 ql_enable_completion_interrupt(qdev, 0);
165}
166
167void ql_mpi_reset_work(struct work_struct *work)
168{
169 struct ql_adapter *qdev =
170 container_of(work, struct ql_adapter, mpi_reset_work.work);
Ron Mercera2e809b2009-02-26 10:08:33 +0000171 ql_soft_reset_mpi_risc(qdev);
Ron Mercerc4e84bd2008-09-18 11:56:28 -0400172}