1004b26b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2aa43c215SJeff Kirsher /*
3aa43c215SJeff Kirsher * QLogic qlcnic NIC Driver
4577ae39dSJitendra Kalsaria * Copyright (c) 2009-2013 QLogic Corporation
5aa43c215SJeff Kirsher */
6aa43c215SJeff Kirsher
7aa43c215SJeff Kirsher #include "qlcnic.h"
8a15ebd37SHimanshu Madhani #include "qlcnic_hw.h"
9aa43c215SJeff Kirsher
10aa43c215SJeff Kirsher struct crb_addr_pair {
11aa43c215SJeff Kirsher u32 addr;
12aa43c215SJeff Kirsher u32 data;
13aa43c215SJeff Kirsher };
14aa43c215SJeff Kirsher
15aa43c215SJeff Kirsher #define QLCNIC_MAX_CRB_XFORM 60
16aa43c215SJeff Kirsher static unsigned int crb_addr_xform[QLCNIC_MAX_CRB_XFORM];
17aa43c215SJeff Kirsher
18aa43c215SJeff Kirsher #define crb_addr_transform(name) \
19aa43c215SJeff Kirsher (crb_addr_xform[QLCNIC_HW_PX_MAP_CRB_##name] = \
20aa43c215SJeff Kirsher QLCNIC_HW_CRB_HUB_AGT_ADR_##name << 20)
21aa43c215SJeff Kirsher
22aa43c215SJeff Kirsher #define QLCNIC_ADDR_ERROR (0xffffffff)
23aa43c215SJeff Kirsher
24aa43c215SJeff Kirsher static int
25aa43c215SJeff Kirsher qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter);
26aa43c215SJeff Kirsher
crb_addr_transform_setup(void)27aa43c215SJeff Kirsher static void crb_addr_transform_setup(void)
28aa43c215SJeff Kirsher {
29aa43c215SJeff Kirsher crb_addr_transform(XDMA);
30aa43c215SJeff Kirsher crb_addr_transform(TIMR);
31aa43c215SJeff Kirsher crb_addr_transform(SRE);
32aa43c215SJeff Kirsher crb_addr_transform(SQN3);
33aa43c215SJeff Kirsher crb_addr_transform(SQN2);
34aa43c215SJeff Kirsher crb_addr_transform(SQN1);
35aa43c215SJeff Kirsher crb_addr_transform(SQN0);
36aa43c215SJeff Kirsher crb_addr_transform(SQS3);
37aa43c215SJeff Kirsher crb_addr_transform(SQS2);
38aa43c215SJeff Kirsher crb_addr_transform(SQS1);
39aa43c215SJeff Kirsher crb_addr_transform(SQS0);
40aa43c215SJeff Kirsher crb_addr_transform(RPMX7);
41aa43c215SJeff Kirsher crb_addr_transform(RPMX6);
42aa43c215SJeff Kirsher crb_addr_transform(RPMX5);
43aa43c215SJeff Kirsher crb_addr_transform(RPMX4);
44aa43c215SJeff Kirsher crb_addr_transform(RPMX3);
45aa43c215SJeff Kirsher crb_addr_transform(RPMX2);
46aa43c215SJeff Kirsher crb_addr_transform(RPMX1);
47aa43c215SJeff Kirsher crb_addr_transform(RPMX0);
48aa43c215SJeff Kirsher crb_addr_transform(ROMUSB);
49aa43c215SJeff Kirsher crb_addr_transform(SN);
50aa43c215SJeff Kirsher crb_addr_transform(QMN);
51aa43c215SJeff Kirsher crb_addr_transform(QMS);
52aa43c215SJeff Kirsher crb_addr_transform(PGNI);
53aa43c215SJeff Kirsher crb_addr_transform(PGND);
54aa43c215SJeff Kirsher crb_addr_transform(PGN3);
55aa43c215SJeff Kirsher crb_addr_transform(PGN2);
56aa43c215SJeff Kirsher crb_addr_transform(PGN1);
57aa43c215SJeff Kirsher crb_addr_transform(PGN0);
58aa43c215SJeff Kirsher crb_addr_transform(PGSI);
59aa43c215SJeff Kirsher crb_addr_transform(PGSD);
60aa43c215SJeff Kirsher crb_addr_transform(PGS3);
61aa43c215SJeff Kirsher crb_addr_transform(PGS2);
62aa43c215SJeff Kirsher crb_addr_transform(PGS1);
63aa43c215SJeff Kirsher crb_addr_transform(PGS0);
64aa43c215SJeff Kirsher crb_addr_transform(PS);
65aa43c215SJeff Kirsher crb_addr_transform(PH);
66aa43c215SJeff Kirsher crb_addr_transform(NIU);
67aa43c215SJeff Kirsher crb_addr_transform(I2Q);
68aa43c215SJeff Kirsher crb_addr_transform(EG);
69aa43c215SJeff Kirsher crb_addr_transform(MN);
70aa43c215SJeff Kirsher crb_addr_transform(MS);
71aa43c215SJeff Kirsher crb_addr_transform(CAS2);
72aa43c215SJeff Kirsher crb_addr_transform(CAS1);
73aa43c215SJeff Kirsher crb_addr_transform(CAS0);
74aa43c215SJeff Kirsher crb_addr_transform(CAM);
75aa43c215SJeff Kirsher crb_addr_transform(C2C1);
76aa43c215SJeff Kirsher crb_addr_transform(C2C0);
77aa43c215SJeff Kirsher crb_addr_transform(SMB);
78aa43c215SJeff Kirsher crb_addr_transform(OCM0);
79aa43c215SJeff Kirsher crb_addr_transform(I2C0);
80aa43c215SJeff Kirsher }
81aa43c215SJeff Kirsher
qlcnic_release_rx_buffers(struct qlcnic_adapter * adapter)82aa43c215SJeff Kirsher void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter)
83aa43c215SJeff Kirsher {
84aa43c215SJeff Kirsher struct qlcnic_recv_context *recv_ctx;
85aa43c215SJeff Kirsher struct qlcnic_host_rds_ring *rds_ring;
86aa43c215SJeff Kirsher struct qlcnic_rx_buffer *rx_buf;
87aa43c215SJeff Kirsher int i, ring;
88aa43c215SJeff Kirsher
89aa43c215SJeff Kirsher recv_ctx = adapter->recv_ctx;
90aa43c215SJeff Kirsher for (ring = 0; ring < adapter->max_rds_rings; ring++) {
91aa43c215SJeff Kirsher rds_ring = &recv_ctx->rds_rings[ring];
92aa43c215SJeff Kirsher for (i = 0; i < rds_ring->num_desc; ++i) {
93aa43c215SJeff Kirsher rx_buf = &(rds_ring->rx_buf_arr[i]);
94aa43c215SJeff Kirsher if (rx_buf->skb == NULL)
95aa43c215SJeff Kirsher continue;
96aa43c215SJeff Kirsher
97*a14e3904SChristophe JAILLET dma_unmap_single(&adapter->pdev->dev, rx_buf->dma,
98*a14e3904SChristophe JAILLET rds_ring->dma_size, DMA_FROM_DEVICE);
99aa43c215SJeff Kirsher
100aa43c215SJeff Kirsher dev_kfree_skb_any(rx_buf->skb);
101aa43c215SJeff Kirsher }
102aa43c215SJeff Kirsher }
103aa43c215SJeff Kirsher }
104aa43c215SJeff Kirsher
qlcnic_reset_rx_buffers_list(struct qlcnic_adapter * adapter)105aa43c215SJeff Kirsher void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter)
106aa43c215SJeff Kirsher {
107aa43c215SJeff Kirsher struct qlcnic_recv_context *recv_ctx;
108aa43c215SJeff Kirsher struct qlcnic_host_rds_ring *rds_ring;
109aa43c215SJeff Kirsher struct qlcnic_rx_buffer *rx_buf;
110aa43c215SJeff Kirsher int i, ring;
111aa43c215SJeff Kirsher
112aa43c215SJeff Kirsher recv_ctx = adapter->recv_ctx;
113aa43c215SJeff Kirsher for (ring = 0; ring < adapter->max_rds_rings; ring++) {
114aa43c215SJeff Kirsher rds_ring = &recv_ctx->rds_rings[ring];
115aa43c215SJeff Kirsher
116aa43c215SJeff Kirsher INIT_LIST_HEAD(&rds_ring->free_list);
117aa43c215SJeff Kirsher
118aa43c215SJeff Kirsher rx_buf = rds_ring->rx_buf_arr;
119aa43c215SJeff Kirsher for (i = 0; i < rds_ring->num_desc; i++) {
120aa43c215SJeff Kirsher list_add_tail(&rx_buf->list,
121aa43c215SJeff Kirsher &rds_ring->free_list);
122aa43c215SJeff Kirsher rx_buf++;
123aa43c215SJeff Kirsher }
124aa43c215SJeff Kirsher }
125aa43c215SJeff Kirsher }
126aa43c215SJeff Kirsher
qlcnic_release_tx_buffers(struct qlcnic_adapter * adapter,struct qlcnic_host_tx_ring * tx_ring)127012ec812SHimanshu Madhani void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter,
128012ec812SHimanshu Madhani struct qlcnic_host_tx_ring *tx_ring)
129aa43c215SJeff Kirsher {
130aa43c215SJeff Kirsher struct qlcnic_cmd_buffer *cmd_buf;
131aa43c215SJeff Kirsher struct qlcnic_skb_frag *buffrag;
132aa43c215SJeff Kirsher int i, j;
133aa43c215SJeff Kirsher
134a02bdd42SShahed Shaikh spin_lock(&tx_ring->tx_clean_lock);
135a02bdd42SShahed Shaikh
136aa43c215SJeff Kirsher cmd_buf = tx_ring->cmd_buf_arr;
137aa43c215SJeff Kirsher for (i = 0; i < tx_ring->num_desc; i++) {
138aa43c215SJeff Kirsher buffrag = cmd_buf->frag_array;
139aa43c215SJeff Kirsher if (buffrag->dma) {
140*a14e3904SChristophe JAILLET dma_unmap_single(&adapter->pdev->dev, buffrag->dma,
141*a14e3904SChristophe JAILLET buffrag->length, DMA_TO_DEVICE);
142aa43c215SJeff Kirsher buffrag->dma = 0ULL;
143aa43c215SJeff Kirsher }
144b662eca0SJitendra Kalsaria for (j = 1; j < cmd_buf->frag_count; j++) {
145aa43c215SJeff Kirsher buffrag++;
146aa43c215SJeff Kirsher if (buffrag->dma) {
147*a14e3904SChristophe JAILLET dma_unmap_page(&adapter->pdev->dev,
148*a14e3904SChristophe JAILLET buffrag->dma, buffrag->length,
149*a14e3904SChristophe JAILLET DMA_TO_DEVICE);
150aa43c215SJeff Kirsher buffrag->dma = 0ULL;
151aa43c215SJeff Kirsher }
152aa43c215SJeff Kirsher }
153aa43c215SJeff Kirsher if (cmd_buf->skb) {
154aa43c215SJeff Kirsher dev_kfree_skb_any(cmd_buf->skb);
155aa43c215SJeff Kirsher cmd_buf->skb = NULL;
156aa43c215SJeff Kirsher }
157aa43c215SJeff Kirsher cmd_buf++;
158aa43c215SJeff Kirsher }
159a02bdd42SShahed Shaikh
160a02bdd42SShahed Shaikh spin_unlock(&tx_ring->tx_clean_lock);
161aa43c215SJeff Kirsher }
162aa43c215SJeff Kirsher
qlcnic_free_sw_resources(struct qlcnic_adapter * adapter)163aa43c215SJeff Kirsher void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter)
164aa43c215SJeff Kirsher {
165aa43c215SJeff Kirsher struct qlcnic_recv_context *recv_ctx;
166aa43c215SJeff Kirsher struct qlcnic_host_rds_ring *rds_ring;
167aa43c215SJeff Kirsher int ring;
168aa43c215SJeff Kirsher
169aa43c215SJeff Kirsher recv_ctx = adapter->recv_ctx;
170aa43c215SJeff Kirsher
171aa43c215SJeff Kirsher if (recv_ctx->rds_rings == NULL)
1724be41e92SSony Chacko return;
173aa43c215SJeff Kirsher
174aa43c215SJeff Kirsher for (ring = 0; ring < adapter->max_rds_rings; ring++) {
175aa43c215SJeff Kirsher rds_ring = &recv_ctx->rds_rings[ring];
176aa43c215SJeff Kirsher vfree(rds_ring->rx_buf_arr);
177aa43c215SJeff Kirsher rds_ring->rx_buf_arr = NULL;
178aa43c215SJeff Kirsher }
179aa43c215SJeff Kirsher kfree(recv_ctx->rds_rings);
180aa43c215SJeff Kirsher }
181aa43c215SJeff Kirsher
qlcnic_alloc_sw_resources(struct qlcnic_adapter * adapter)182aa43c215SJeff Kirsher int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
183aa43c215SJeff Kirsher {
184aa43c215SJeff Kirsher struct qlcnic_recv_context *recv_ctx;
185aa43c215SJeff Kirsher struct qlcnic_host_rds_ring *rds_ring;
186aa43c215SJeff Kirsher struct qlcnic_host_sds_ring *sds_ring;
187aa43c215SJeff Kirsher struct qlcnic_rx_buffer *rx_buf;
188b2adaca9SJoe Perches int ring, i;
189aa43c215SJeff Kirsher
190aa43c215SJeff Kirsher recv_ctx = adapter->recv_ctx;
191aa43c215SJeff Kirsher
192b2adaca9SJoe Perches rds_ring = kcalloc(adapter->max_rds_rings,
193b2adaca9SJoe Perches sizeof(struct qlcnic_host_rds_ring), GFP_KERNEL);
194b2adaca9SJoe Perches if (rds_ring == NULL)
195aa43c215SJeff Kirsher goto err_out;
196b2adaca9SJoe Perches
197aa43c215SJeff Kirsher recv_ctx->rds_rings = rds_ring;
198aa43c215SJeff Kirsher
199aa43c215SJeff Kirsher for (ring = 0; ring < adapter->max_rds_rings; ring++) {
200aa43c215SJeff Kirsher rds_ring = &recv_ctx->rds_rings[ring];
201aa43c215SJeff Kirsher switch (ring) {
202aa43c215SJeff Kirsher case RCV_RING_NORMAL:
203aa43c215SJeff Kirsher rds_ring->num_desc = adapter->num_rxd;
204aa43c215SJeff Kirsher rds_ring->dma_size = QLCNIC_P3P_RX_BUF_MAX_LEN;
205aa43c215SJeff Kirsher rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN;
206aa43c215SJeff Kirsher break;
207aa43c215SJeff Kirsher
208aa43c215SJeff Kirsher case RCV_RING_JUMBO:
209aa43c215SJeff Kirsher rds_ring->num_desc = adapter->num_jumbo_rxd;
210aa43c215SJeff Kirsher rds_ring->dma_size =
211aa43c215SJeff Kirsher QLCNIC_P3P_RX_JUMBO_BUF_MAX_LEN;
212aa43c215SJeff Kirsher
21379788450SSony Chacko if (adapter->ahw->capabilities &
21479788450SSony Chacko QLCNIC_FW_CAPABILITY_HW_LRO)
215aa43c215SJeff Kirsher rds_ring->dma_size += QLCNIC_LRO_BUFFER_EXTRA;
216aa43c215SJeff Kirsher
217aa43c215SJeff Kirsher rds_ring->skb_size =
218aa43c215SJeff Kirsher rds_ring->dma_size + NET_IP_ALIGN;
219aa43c215SJeff Kirsher break;
220aa43c215SJeff Kirsher }
221aa43c215SJeff Kirsher rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring));
222b2adaca9SJoe Perches if (rds_ring->rx_buf_arr == NULL)
223aa43c215SJeff Kirsher goto err_out;
2244be41e92SSony Chacko
225aa43c215SJeff Kirsher INIT_LIST_HEAD(&rds_ring->free_list);
226aa43c215SJeff Kirsher /*
227aa43c215SJeff Kirsher * Now go through all of them, set reference handles
228aa43c215SJeff Kirsher * and put them in the queues.
229aa43c215SJeff Kirsher */
230aa43c215SJeff Kirsher rx_buf = rds_ring->rx_buf_arr;
231aa43c215SJeff Kirsher for (i = 0; i < rds_ring->num_desc; i++) {
232aa43c215SJeff Kirsher list_add_tail(&rx_buf->list,
233aa43c215SJeff Kirsher &rds_ring->free_list);
234aa43c215SJeff Kirsher rx_buf->ref_handle = i;
235aa43c215SJeff Kirsher rx_buf++;
236aa43c215SJeff Kirsher }
237aa43c215SJeff Kirsher spin_lock_init(&rds_ring->lock);
238aa43c215SJeff Kirsher }
239aa43c215SJeff Kirsher
24034e8c406SHimanshu Madhani for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
241aa43c215SJeff Kirsher sds_ring = &recv_ctx->sds_rings[ring];
242aa43c215SJeff Kirsher sds_ring->irq = adapter->msix_entries[ring].vector;
243aa43c215SJeff Kirsher sds_ring->adapter = adapter;
244aa43c215SJeff Kirsher sds_ring->num_desc = adapter->num_rxd;
245012ec812SHimanshu Madhani if (qlcnic_82xx_check(adapter)) {
246c2c5e3a0SHimanshu Madhani if (qlcnic_check_multi_tx(adapter) &&
247c2c5e3a0SHimanshu Madhani !adapter->ahw->diag_test)
248012ec812SHimanshu Madhani sds_ring->tx_ring = &adapter->tx_ring[ring];
249012ec812SHimanshu Madhani else
250012ec812SHimanshu Madhani sds_ring->tx_ring = &adapter->tx_ring[0];
251012ec812SHimanshu Madhani }
252aa43c215SJeff Kirsher for (i = 0; i < NUM_RCV_DESC_RINGS; i++)
253aa43c215SJeff Kirsher INIT_LIST_HEAD(&sds_ring->free_list[i]);
254aa43c215SJeff Kirsher }
255aa43c215SJeff Kirsher
256aa43c215SJeff Kirsher return 0;
257aa43c215SJeff Kirsher
258aa43c215SJeff Kirsher err_out:
259aa43c215SJeff Kirsher qlcnic_free_sw_resources(adapter);
260aa43c215SJeff Kirsher return -ENOMEM;
261aa43c215SJeff Kirsher }
262aa43c215SJeff Kirsher
263aa43c215SJeff Kirsher /*
264aa43c215SJeff Kirsher * Utility to translate from internal Phantom CRB address
265aa43c215SJeff Kirsher * to external PCI CRB address.
266aa43c215SJeff Kirsher */
qlcnic_decode_crb_addr(u32 addr)267aa43c215SJeff Kirsher static u32 qlcnic_decode_crb_addr(u32 addr)
268aa43c215SJeff Kirsher {
269aa43c215SJeff Kirsher int i;
270aa43c215SJeff Kirsher u32 base_addr, offset, pci_base;
271aa43c215SJeff Kirsher
272aa43c215SJeff Kirsher crb_addr_transform_setup();
273aa43c215SJeff Kirsher
274aa43c215SJeff Kirsher pci_base = QLCNIC_ADDR_ERROR;
275aa43c215SJeff Kirsher base_addr = addr & 0xfff00000;
276aa43c215SJeff Kirsher offset = addr & 0x000fffff;
277aa43c215SJeff Kirsher
278aa43c215SJeff Kirsher for (i = 0; i < QLCNIC_MAX_CRB_XFORM; i++) {
279aa43c215SJeff Kirsher if (crb_addr_xform[i] == base_addr) {
280aa43c215SJeff Kirsher pci_base = i << 20;
281aa43c215SJeff Kirsher break;
282aa43c215SJeff Kirsher }
283aa43c215SJeff Kirsher }
284aa43c215SJeff Kirsher if (pci_base == QLCNIC_ADDR_ERROR)
285aa43c215SJeff Kirsher return pci_base;
286aa43c215SJeff Kirsher else
287aa43c215SJeff Kirsher return pci_base + offset;
288aa43c215SJeff Kirsher }
289aa43c215SJeff Kirsher
290aa43c215SJeff Kirsher #define QLCNIC_MAX_ROM_WAIT_USEC 100
291aa43c215SJeff Kirsher
qlcnic_wait_rom_done(struct qlcnic_adapter * adapter)292aa43c215SJeff Kirsher static int qlcnic_wait_rom_done(struct qlcnic_adapter *adapter)
293aa43c215SJeff Kirsher {
294aa43c215SJeff Kirsher long timeout = 0;
295aa43c215SJeff Kirsher long done = 0;
2964bd8e738SHimanshu Madhani int err = 0;
297aa43c215SJeff Kirsher
298aa43c215SJeff Kirsher cond_resched();
299aa43c215SJeff Kirsher while (done == 0) {
3004bd8e738SHimanshu Madhani done = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_STATUS, &err);
301aa43c215SJeff Kirsher done &= 2;
302aa43c215SJeff Kirsher if (++timeout >= QLCNIC_MAX_ROM_WAIT_USEC) {
303aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
304aa43c215SJeff Kirsher "Timeout reached waiting for rom done");
305aa43c215SJeff Kirsher return -EIO;
306aa43c215SJeff Kirsher }
307aa43c215SJeff Kirsher udelay(1);
308aa43c215SJeff Kirsher }
309aa43c215SJeff Kirsher return 0;
310aa43c215SJeff Kirsher }
311aa43c215SJeff Kirsher
do_rom_fast_read(struct qlcnic_adapter * adapter,u32 addr,u32 * valp)312aa43c215SJeff Kirsher static int do_rom_fast_read(struct qlcnic_adapter *adapter,
313aa43c215SJeff Kirsher u32 addr, u32 *valp)
314aa43c215SJeff Kirsher {
3154bd8e738SHimanshu Madhani int err = 0;
3164bd8e738SHimanshu Madhani
317aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ADDRESS, addr);
318aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
319aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ABYTE_CNT, 3);
320aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_ROMUSB_ROM_INSTR_OPCODE, 0xb);
321aa43c215SJeff Kirsher if (qlcnic_wait_rom_done(adapter)) {
322aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev, "Error waiting for rom done\n");
323aa43c215SJeff Kirsher return -EIO;
324aa43c215SJeff Kirsher }
325aa43c215SJeff Kirsher /* reset abyte_cnt and dummy_byte_cnt */
326aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_ROMUSB_ROM_ABYTE_CNT, 0);
327aa43c215SJeff Kirsher udelay(10);
328aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT, 0);
329aa43c215SJeff Kirsher
3304bd8e738SHimanshu Madhani *valp = QLCRD32(adapter, QLCNIC_ROMUSB_ROM_RDATA, &err);
3314bd8e738SHimanshu Madhani if (err == -EIO)
3324bd8e738SHimanshu Madhani return err;
333aa43c215SJeff Kirsher return 0;
334aa43c215SJeff Kirsher }
335aa43c215SJeff Kirsher
do_rom_fast_read_words(struct qlcnic_adapter * adapter,int addr,u8 * bytes,size_t size)336aa43c215SJeff Kirsher static int do_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr,
337aa43c215SJeff Kirsher u8 *bytes, size_t size)
338aa43c215SJeff Kirsher {
339aa43c215SJeff Kirsher int addridx;
340aa43c215SJeff Kirsher int ret = 0;
341aa43c215SJeff Kirsher
342aa43c215SJeff Kirsher for (addridx = addr; addridx < (addr + size); addridx += 4) {
343aa43c215SJeff Kirsher int v;
344aa43c215SJeff Kirsher ret = do_rom_fast_read(adapter, addridx, &v);
345aa43c215SJeff Kirsher if (ret != 0)
346aa43c215SJeff Kirsher break;
347aa43c215SJeff Kirsher *(__le32 *)bytes = cpu_to_le32(v);
348aa43c215SJeff Kirsher bytes += 4;
349aa43c215SJeff Kirsher }
350aa43c215SJeff Kirsher
351aa43c215SJeff Kirsher return ret;
352aa43c215SJeff Kirsher }
353aa43c215SJeff Kirsher
354aa43c215SJeff Kirsher int
qlcnic_rom_fast_read_words(struct qlcnic_adapter * adapter,int addr,u8 * bytes,size_t size)355aa43c215SJeff Kirsher qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr,
356aa43c215SJeff Kirsher u8 *bytes, size_t size)
357aa43c215SJeff Kirsher {
358aa43c215SJeff Kirsher int ret;
359aa43c215SJeff Kirsher
360aa43c215SJeff Kirsher ret = qlcnic_rom_lock(adapter);
361aa43c215SJeff Kirsher if (ret < 0)
362aa43c215SJeff Kirsher return ret;
363aa43c215SJeff Kirsher
364aa43c215SJeff Kirsher ret = do_rom_fast_read_words(adapter, addr, bytes, size);
365aa43c215SJeff Kirsher
366aa43c215SJeff Kirsher qlcnic_rom_unlock(adapter);
367aa43c215SJeff Kirsher return ret;
368aa43c215SJeff Kirsher }
369aa43c215SJeff Kirsher
qlcnic_rom_fast_read(struct qlcnic_adapter * adapter,u32 addr,u32 * valp)370aa43c215SJeff Kirsher int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, u32 addr, u32 *valp)
371aa43c215SJeff Kirsher {
372aa43c215SJeff Kirsher int ret;
373aa43c215SJeff Kirsher
374aa43c215SJeff Kirsher if (qlcnic_rom_lock(adapter) != 0)
375aa43c215SJeff Kirsher return -EIO;
376aa43c215SJeff Kirsher
377aa43c215SJeff Kirsher ret = do_rom_fast_read(adapter, addr, valp);
378aa43c215SJeff Kirsher qlcnic_rom_unlock(adapter);
379aa43c215SJeff Kirsher return ret;
380aa43c215SJeff Kirsher }
381aa43c215SJeff Kirsher
qlcnic_pinit_from_rom(struct qlcnic_adapter * adapter)382aa43c215SJeff Kirsher int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
383aa43c215SJeff Kirsher {
3844bd8e738SHimanshu Madhani int addr, err = 0;
385aa43c215SJeff Kirsher int i, n, init_delay;
386aa43c215SJeff Kirsher struct crb_addr_pair *buf;
387aa43c215SJeff Kirsher unsigned offset;
3884bd8e738SHimanshu Madhani u32 off, val;
389aa43c215SJeff Kirsher struct pci_dev *pdev = adapter->pdev;
390aa43c215SJeff Kirsher
391a15ebd37SHimanshu Madhani QLC_SHARED_REG_WR32(adapter, QLCNIC_CMDPEG_STATE, 0);
392a15ebd37SHimanshu Madhani QLC_SHARED_REG_WR32(adapter, QLCNIC_RCVPEG_STATE, 0);
393aa43c215SJeff Kirsher
39468233c58SSony Chacko /* Halt all the indiviual PEGs and other blocks */
39568233c58SSony Chacko /* disable all I2Q */
39668233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x10, 0x0);
39768233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x14, 0x0);
39868233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x18, 0x0);
39968233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x1c, 0x0);
40068233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x20, 0x0);
40168233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_I2Q + 0x24, 0x0);
40268233c58SSony Chacko
40368233c58SSony Chacko /* disable all niu interrupts */
40468233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_NIU + 0x40, 0xff);
40568233c58SSony Chacko /* disable xge rx/tx */
40668233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_NIU + 0x70000, 0x00);
40768233c58SSony Chacko /* disable xg1 rx/tx */
40868233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_NIU + 0x80000, 0x00);
40968233c58SSony Chacko /* disable sideband mac */
41068233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_NIU + 0x90000, 0x00);
41168233c58SSony Chacko /* disable ap0 mac */
41268233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_NIU + 0xa0000, 0x00);
41368233c58SSony Chacko /* disable ap1 mac */
41468233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_NIU + 0xb0000, 0x00);
41568233c58SSony Chacko
41668233c58SSony Chacko /* halt sre */
4174bd8e738SHimanshu Madhani val = QLCRD32(adapter, QLCNIC_CRB_SRE + 0x1000, &err);
4184bd8e738SHimanshu Madhani if (err == -EIO)
4194bd8e738SHimanshu Madhani return err;
42068233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_SRE + 0x1000, val & (~(0x1)));
42168233c58SSony Chacko
42268233c58SSony Chacko /* halt epg */
42368233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_EPG + 0x1300, 0x1);
42468233c58SSony Chacko
42568233c58SSony Chacko /* halt timers */
42668233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x0, 0x0);
42768233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x8, 0x0);
42868233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x10, 0x0);
42968233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x18, 0x0);
43068233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x100, 0x0);
43168233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_TIMER + 0x200, 0x0);
43268233c58SSony Chacko /* halt pegs */
43368233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c, 1);
43468233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c, 1);
43568233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c, 1);
43668233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c, 1);
43768233c58SSony Chacko QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c, 1);
43868233c58SSony Chacko msleep(20);
43968233c58SSony Chacko
44068233c58SSony Chacko /* big hammer don't reset CAM block on reset */
44168233c58SSony Chacko QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff);
442aa43c215SJeff Kirsher
443aa43c215SJeff Kirsher /* Init HW CRB block */
444aa43c215SJeff Kirsher if (qlcnic_rom_fast_read(adapter, 0, &n) != 0 || (n != 0xcafecafe) ||
445aa43c215SJeff Kirsher qlcnic_rom_fast_read(adapter, 4, &n) != 0) {
446aa43c215SJeff Kirsher dev_err(&pdev->dev, "ERROR Reading crb_init area: val:%x\n", n);
447aa43c215SJeff Kirsher return -EIO;
448aa43c215SJeff Kirsher }
449aa43c215SJeff Kirsher offset = n & 0xffffU;
450aa43c215SJeff Kirsher n = (n >> 16) & 0xffffU;
451aa43c215SJeff Kirsher
452aa43c215SJeff Kirsher if (n >= 1024) {
453aa43c215SJeff Kirsher dev_err(&pdev->dev, "QLOGIC card flash not initialized.\n");
454aa43c215SJeff Kirsher return -EIO;
455aa43c215SJeff Kirsher }
456aa43c215SJeff Kirsher
457aa43c215SJeff Kirsher buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
458b2adaca9SJoe Perches if (buf == NULL)
459aa43c215SJeff Kirsher return -ENOMEM;
460aa43c215SJeff Kirsher
461aa43c215SJeff Kirsher for (i = 0; i < n; i++) {
462aa43c215SJeff Kirsher if (qlcnic_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 ||
463aa43c215SJeff Kirsher qlcnic_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) {
464aa43c215SJeff Kirsher kfree(buf);
465aa43c215SJeff Kirsher return -EIO;
466aa43c215SJeff Kirsher }
467aa43c215SJeff Kirsher
468aa43c215SJeff Kirsher buf[i].addr = addr;
469aa43c215SJeff Kirsher buf[i].data = val;
470aa43c215SJeff Kirsher }
471aa43c215SJeff Kirsher
472aa43c215SJeff Kirsher for (i = 0; i < n; i++) {
473aa43c215SJeff Kirsher
474aa43c215SJeff Kirsher off = qlcnic_decode_crb_addr(buf[i].addr);
475aa43c215SJeff Kirsher if (off == QLCNIC_ADDR_ERROR) {
476aa43c215SJeff Kirsher dev_err(&pdev->dev, "CRB init value out of range %x\n",
477aa43c215SJeff Kirsher buf[i].addr);
478aa43c215SJeff Kirsher continue;
479aa43c215SJeff Kirsher }
480aa43c215SJeff Kirsher off += QLCNIC_PCI_CRBSPACE;
481aa43c215SJeff Kirsher
482aa43c215SJeff Kirsher if (off & 1)
483aa43c215SJeff Kirsher continue;
484aa43c215SJeff Kirsher
485aa43c215SJeff Kirsher /* skipping cold reboot MAGIC */
486aa43c215SJeff Kirsher if (off == QLCNIC_CAM_RAM(0x1fc))
487aa43c215SJeff Kirsher continue;
488aa43c215SJeff Kirsher if (off == (QLCNIC_CRB_I2C0 + 0x1c))
489aa43c215SJeff Kirsher continue;
490aa43c215SJeff Kirsher if (off == (ROMUSB_GLB + 0xbc)) /* do not reset PCI */
491aa43c215SJeff Kirsher continue;
492aa43c215SJeff Kirsher if (off == (ROMUSB_GLB + 0xa8))
493aa43c215SJeff Kirsher continue;
494aa43c215SJeff Kirsher if (off == (ROMUSB_GLB + 0xc8)) /* core clock */
495aa43c215SJeff Kirsher continue;
496aa43c215SJeff Kirsher if (off == (ROMUSB_GLB + 0x24)) /* MN clock */
497aa43c215SJeff Kirsher continue;
498aa43c215SJeff Kirsher if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */
499aa43c215SJeff Kirsher continue;
500aa43c215SJeff Kirsher if ((off & 0x0ff00000) == QLCNIC_CRB_DDR_NET)
501aa43c215SJeff Kirsher continue;
502aa43c215SJeff Kirsher /* skip the function enable register */
503aa43c215SJeff Kirsher if (off == QLCNIC_PCIE_REG(PCIE_SETUP_FUNCTION))
504aa43c215SJeff Kirsher continue;
505aa43c215SJeff Kirsher if (off == QLCNIC_PCIE_REG(PCIE_SETUP_FUNCTION2))
506aa43c215SJeff Kirsher continue;
507aa43c215SJeff Kirsher if ((off & 0x0ff00000) == QLCNIC_CRB_SMB)
508aa43c215SJeff Kirsher continue;
509aa43c215SJeff Kirsher
510aa43c215SJeff Kirsher init_delay = 1;
511aa43c215SJeff Kirsher /* After writing this register, HW needs time for CRB */
512aa43c215SJeff Kirsher /* to quiet down (else crb_window returns 0xffffffff) */
513aa43c215SJeff Kirsher if (off == QLCNIC_ROMUSB_GLB_SW_RESET)
514aa43c215SJeff Kirsher init_delay = 1000;
515aa43c215SJeff Kirsher
516aa43c215SJeff Kirsher QLCWR32(adapter, off, buf[i].data);
517aa43c215SJeff Kirsher
518aa43c215SJeff Kirsher msleep(init_delay);
519aa43c215SJeff Kirsher }
520aa43c215SJeff Kirsher kfree(buf);
521aa43c215SJeff Kirsher
522aa43c215SJeff Kirsher /* Initialize protocol process engine */
523aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0xec, 0x1e);
524aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_D + 0x4c, 8);
525aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_I + 0x4c, 8);
526aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x8, 0);
527aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0xc, 0);
528aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x8, 0);
529aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_1 + 0xc, 0);
530aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x8, 0);
531aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_2 + 0xc, 0);
532aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x8, 0);
533aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_3 + 0xc, 0);
534aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x8, 0);
535aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0xc, 0);
536c1b2037fSJitendra Kalsaria usleep_range(1000, 1500);
53768233c58SSony Chacko
538a15ebd37SHimanshu Madhani QLC_SHARED_REG_WR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0);
539a15ebd37SHimanshu Madhani QLC_SHARED_REG_WR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0);
54068233c58SSony Chacko
541aa43c215SJeff Kirsher return 0;
542aa43c215SJeff Kirsher }
543aa43c215SJeff Kirsher
qlcnic_cmd_peg_ready(struct qlcnic_adapter * adapter)544aa43c215SJeff Kirsher static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter)
545aa43c215SJeff Kirsher {
546aa43c215SJeff Kirsher u32 val;
547aa43c215SJeff Kirsher int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;
548aa43c215SJeff Kirsher
549aa43c215SJeff Kirsher do {
550a15ebd37SHimanshu Madhani val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CMDPEG_STATE);
551aa43c215SJeff Kirsher
552aa43c215SJeff Kirsher switch (val) {
553aa43c215SJeff Kirsher case PHAN_INITIALIZE_COMPLETE:
554aa43c215SJeff Kirsher case PHAN_INITIALIZE_ACK:
555aa43c215SJeff Kirsher return 0;
556aa43c215SJeff Kirsher case PHAN_INITIALIZE_FAILED:
557aa43c215SJeff Kirsher goto out_err;
558aa43c215SJeff Kirsher default:
559aa43c215SJeff Kirsher break;
560aa43c215SJeff Kirsher }
561aa43c215SJeff Kirsher
562aa43c215SJeff Kirsher msleep(QLCNIC_CMDPEG_CHECK_DELAY);
563aa43c215SJeff Kirsher
564aa43c215SJeff Kirsher } while (--retries);
565aa43c215SJeff Kirsher
566a15ebd37SHimanshu Madhani QLC_SHARED_REG_WR32(adapter, QLCNIC_CMDPEG_STATE,
567a15ebd37SHimanshu Madhani PHAN_INITIALIZE_FAILED);
568aa43c215SJeff Kirsher
569aa43c215SJeff Kirsher out_err:
570aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev, "Command Peg initialization not "
571aa43c215SJeff Kirsher "complete, state: 0x%x.\n", val);
572aa43c215SJeff Kirsher return -EIO;
573aa43c215SJeff Kirsher }
574aa43c215SJeff Kirsher
575aa43c215SJeff Kirsher static int
qlcnic_receive_peg_ready(struct qlcnic_adapter * adapter)576aa43c215SJeff Kirsher qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter)
577aa43c215SJeff Kirsher {
578aa43c215SJeff Kirsher u32 val;
579aa43c215SJeff Kirsher int retries = QLCNIC_RCVPEG_CHECK_RETRY_COUNT;
580aa43c215SJeff Kirsher
581aa43c215SJeff Kirsher do {
582a15ebd37SHimanshu Madhani val = QLC_SHARED_REG_RD32(adapter, QLCNIC_RCVPEG_STATE);
583aa43c215SJeff Kirsher
584aa43c215SJeff Kirsher if (val == PHAN_PEG_RCV_INITIALIZED)
585aa43c215SJeff Kirsher return 0;
586aa43c215SJeff Kirsher
587aa43c215SJeff Kirsher msleep(QLCNIC_RCVPEG_CHECK_DELAY);
588aa43c215SJeff Kirsher
589aa43c215SJeff Kirsher } while (--retries);
590aa43c215SJeff Kirsher
591f6849d01SColin Ian King dev_err(&adapter->pdev->dev, "Receive Peg initialization not complete, state: 0x%x.\n",
592f6849d01SColin Ian King val);
593aa43c215SJeff Kirsher return -EIO;
594aa43c215SJeff Kirsher }
595aa43c215SJeff Kirsher
596aa43c215SJeff Kirsher int
qlcnic_check_fw_status(struct qlcnic_adapter * adapter)597aa43c215SJeff Kirsher qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
598aa43c215SJeff Kirsher {
599aa43c215SJeff Kirsher int err;
600aa43c215SJeff Kirsher
601aa43c215SJeff Kirsher err = qlcnic_cmd_peg_ready(adapter);
602aa43c215SJeff Kirsher if (err)
603aa43c215SJeff Kirsher return err;
604aa43c215SJeff Kirsher
605aa43c215SJeff Kirsher err = qlcnic_receive_peg_ready(adapter);
606aa43c215SJeff Kirsher if (err)
607aa43c215SJeff Kirsher return err;
608aa43c215SJeff Kirsher
609a15ebd37SHimanshu Madhani QLC_SHARED_REG_WR32(adapter, QLCNIC_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
610aa43c215SJeff Kirsher
611aa43c215SJeff Kirsher return err;
612aa43c215SJeff Kirsher }
613aa43c215SJeff Kirsher
614aa43c215SJeff Kirsher int
qlcnic_setup_idc_param(struct qlcnic_adapter * adapter)615aa43c215SJeff Kirsher qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
616aa43c215SJeff Kirsher
617aa43c215SJeff Kirsher int timeo;
618aa43c215SJeff Kirsher u32 val;
619aa43c215SJeff Kirsher
620a15ebd37SHimanshu Madhani val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_PARTITION_INFO);
621aa43c215SJeff Kirsher val = QLC_DEV_GET_DRV(val, adapter->portnum);
622aa43c215SJeff Kirsher if ((val & 0x3) != QLCNIC_TYPE_NIC) {
623aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
624aa43c215SJeff Kirsher "Not an Ethernet NIC func=%u\n", val);
625aa43c215SJeff Kirsher return -EIO;
626aa43c215SJeff Kirsher }
62779788450SSony Chacko adapter->ahw->physical_port = (val >> 2);
628aa43c215SJeff Kirsher if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo))
629aa43c215SJeff Kirsher timeo = QLCNIC_INIT_TIMEOUT_SECS;
630aa43c215SJeff Kirsher
631aa43c215SJeff Kirsher adapter->dev_init_timeo = timeo;
632aa43c215SJeff Kirsher
633aa43c215SJeff Kirsher if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DRV_RESET_TIMEOUT, &timeo))
634aa43c215SJeff Kirsher timeo = QLCNIC_RESET_TIMEOUT_SECS;
635aa43c215SJeff Kirsher
636aa43c215SJeff Kirsher adapter->reset_ack_timeo = timeo;
637aa43c215SJeff Kirsher
638aa43c215SJeff Kirsher return 0;
639aa43c215SJeff Kirsher }
640aa43c215SJeff Kirsher
qlcnic_get_flt_entry(struct qlcnic_adapter * adapter,u8 region,struct qlcnic_flt_entry * region_entry)641aa43c215SJeff Kirsher static int qlcnic_get_flt_entry(struct qlcnic_adapter *adapter, u8 region,
642aa43c215SJeff Kirsher struct qlcnic_flt_entry *region_entry)
643aa43c215SJeff Kirsher {
644aa43c215SJeff Kirsher struct qlcnic_flt_header flt_hdr;
645aa43c215SJeff Kirsher struct qlcnic_flt_entry *flt_entry;
646aa43c215SJeff Kirsher int i = 0, ret;
647aa43c215SJeff Kirsher u32 entry_size;
648aa43c215SJeff Kirsher
649aa43c215SJeff Kirsher memset(region_entry, 0, sizeof(struct qlcnic_flt_entry));
650aa43c215SJeff Kirsher ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION,
651aa43c215SJeff Kirsher (u8 *)&flt_hdr,
652aa43c215SJeff Kirsher sizeof(struct qlcnic_flt_header));
653aa43c215SJeff Kirsher if (ret) {
654aa43c215SJeff Kirsher dev_warn(&adapter->pdev->dev,
655aa43c215SJeff Kirsher "error reading flash layout header\n");
656aa43c215SJeff Kirsher return -EIO;
657aa43c215SJeff Kirsher }
658aa43c215SJeff Kirsher
659aa43c215SJeff Kirsher entry_size = flt_hdr.len - sizeof(struct qlcnic_flt_header);
660a15ebd37SHimanshu Madhani flt_entry = vzalloc(entry_size);
661b2adaca9SJoe Perches if (flt_entry == NULL)
662aa43c215SJeff Kirsher return -EIO;
663aa43c215SJeff Kirsher
664aa43c215SJeff Kirsher ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION +
665aa43c215SJeff Kirsher sizeof(struct qlcnic_flt_header),
666aa43c215SJeff Kirsher (u8 *)flt_entry, entry_size);
667aa43c215SJeff Kirsher if (ret) {
668aa43c215SJeff Kirsher dev_warn(&adapter->pdev->dev,
669aa43c215SJeff Kirsher "error reading flash layout entries\n");
670aa43c215SJeff Kirsher goto err_out;
671aa43c215SJeff Kirsher }
672aa43c215SJeff Kirsher
673aa43c215SJeff Kirsher while (i < (entry_size/sizeof(struct qlcnic_flt_entry))) {
674aa43c215SJeff Kirsher if (flt_entry[i].region == region)
675aa43c215SJeff Kirsher break;
676aa43c215SJeff Kirsher i++;
677aa43c215SJeff Kirsher }
678aa43c215SJeff Kirsher if (i >= (entry_size/sizeof(struct qlcnic_flt_entry))) {
679aa43c215SJeff Kirsher dev_warn(&adapter->pdev->dev,
680aa43c215SJeff Kirsher "region=%x not found in %d regions\n", region, i);
681aa43c215SJeff Kirsher ret = -EIO;
682aa43c215SJeff Kirsher goto err_out;
683aa43c215SJeff Kirsher }
684aa43c215SJeff Kirsher memcpy(region_entry, &flt_entry[i], sizeof(struct qlcnic_flt_entry));
685aa43c215SJeff Kirsher
686aa43c215SJeff Kirsher err_out:
687aa43c215SJeff Kirsher vfree(flt_entry);
688aa43c215SJeff Kirsher return ret;
689aa43c215SJeff Kirsher }
690aa43c215SJeff Kirsher
691aa43c215SJeff Kirsher int
qlcnic_check_flash_fw_ver(struct qlcnic_adapter * adapter)692aa43c215SJeff Kirsher qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter)
693aa43c215SJeff Kirsher {
694aa43c215SJeff Kirsher struct qlcnic_flt_entry fw_entry;
695aa43c215SJeff Kirsher u32 ver = -1, min_ver;
696aa43c215SJeff Kirsher int ret;
697aa43c215SJeff Kirsher
698a2050c7eSSritej Velaga if (adapter->ahw->revision_id == QLCNIC_P3P_C0)
699a2050c7eSSritej Velaga ret = qlcnic_get_flt_entry(adapter, QLCNIC_C0_FW_IMAGE_REGION,
700a2050c7eSSritej Velaga &fw_entry);
701a2050c7eSSritej Velaga else
702a2050c7eSSritej Velaga ret = qlcnic_get_flt_entry(adapter, QLCNIC_B0_FW_IMAGE_REGION,
703a2050c7eSSritej Velaga &fw_entry);
704a2050c7eSSritej Velaga
705aa43c215SJeff Kirsher if (!ret)
706aa43c215SJeff Kirsher /* 0-4:-signature, 4-8:-fw version */
707aa43c215SJeff Kirsher qlcnic_rom_fast_read(adapter, fw_entry.start_addr + 4,
708aa43c215SJeff Kirsher (int *)&ver);
709aa43c215SJeff Kirsher else
710aa43c215SJeff Kirsher qlcnic_rom_fast_read(adapter, QLCNIC_FW_VERSION_OFFSET,
711aa43c215SJeff Kirsher (int *)&ver);
712aa43c215SJeff Kirsher
713aa43c215SJeff Kirsher ver = QLCNIC_DECODE_VERSION(ver);
714aa43c215SJeff Kirsher min_ver = QLCNIC_MIN_FW_VERSION;
715aa43c215SJeff Kirsher
716aa43c215SJeff Kirsher if (ver < min_ver) {
717aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
718aa43c215SJeff Kirsher "firmware version %d.%d.%d unsupported."
719aa43c215SJeff Kirsher "Min supported version %d.%d.%d\n",
720aa43c215SJeff Kirsher _major(ver), _minor(ver), _build(ver),
721aa43c215SJeff Kirsher _major(min_ver), _minor(min_ver), _build(min_ver));
722aa43c215SJeff Kirsher return -EINVAL;
723aa43c215SJeff Kirsher }
724aa43c215SJeff Kirsher
725aa43c215SJeff Kirsher return 0;
726aa43c215SJeff Kirsher }
727aa43c215SJeff Kirsher
728aa43c215SJeff Kirsher static int
qlcnic_has_mn(struct qlcnic_adapter * adapter)729aa43c215SJeff Kirsher qlcnic_has_mn(struct qlcnic_adapter *adapter)
730aa43c215SJeff Kirsher {
7314bd8e738SHimanshu Madhani u32 capability = 0;
7324bd8e738SHimanshu Madhani int err = 0;
733aa43c215SJeff Kirsher
7344bd8e738SHimanshu Madhani capability = QLCRD32(adapter, QLCNIC_PEG_TUNE_CAPABILITY, &err);
7354bd8e738SHimanshu Madhani if (err == -EIO)
7364bd8e738SHimanshu Madhani return err;
737aa43c215SJeff Kirsher if (capability & QLCNIC_PEG_TUNE_MN_PRESENT)
738aa43c215SJeff Kirsher return 1;
739aa43c215SJeff Kirsher
740aa43c215SJeff Kirsher return 0;
741aa43c215SJeff Kirsher }
742aa43c215SJeff Kirsher
743aa43c215SJeff Kirsher static
qlcnic_get_table_desc(const u8 * unirom,int section)744aa43c215SJeff Kirsher struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section)
745aa43c215SJeff Kirsher {
74663507592SShahed Shaikh u32 i, entries;
747aa43c215SJeff Kirsher struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
74863507592SShahed Shaikh entries = le32_to_cpu(directory->num_entries);
749aa43c215SJeff Kirsher
750aa43c215SJeff Kirsher for (i = 0; i < entries; i++) {
751aa43c215SJeff Kirsher
75263507592SShahed Shaikh u32 offs = le32_to_cpu(directory->findex) +
75363507592SShahed Shaikh i * le32_to_cpu(directory->entry_size);
75463507592SShahed Shaikh u32 tab_type = le32_to_cpu(*((__le32 *)&unirom[offs] + 8));
755aa43c215SJeff Kirsher
756aa43c215SJeff Kirsher if (tab_type == section)
757aa43c215SJeff Kirsher return (struct uni_table_desc *) &unirom[offs];
758aa43c215SJeff Kirsher }
759aa43c215SJeff Kirsher
760aa43c215SJeff Kirsher return NULL;
761aa43c215SJeff Kirsher }
762aa43c215SJeff Kirsher
763aa43c215SJeff Kirsher #define FILEHEADER_SIZE (14 * 4)
764aa43c215SJeff Kirsher
765aa43c215SJeff Kirsher static int
qlcnic_validate_header(struct qlcnic_adapter * adapter)766aa43c215SJeff Kirsher qlcnic_validate_header(struct qlcnic_adapter *adapter)
767aa43c215SJeff Kirsher {
768aa43c215SJeff Kirsher const u8 *unirom = adapter->fw->data;
769aa43c215SJeff Kirsher struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
77063507592SShahed Shaikh u32 entries, entry_size, tab_size, fw_file_size;
77163507592SShahed Shaikh
77263507592SShahed Shaikh fw_file_size = adapter->fw->size;
773aa43c215SJeff Kirsher
774aa43c215SJeff Kirsher if (fw_file_size < FILEHEADER_SIZE)
775aa43c215SJeff Kirsher return -EINVAL;
776aa43c215SJeff Kirsher
77763507592SShahed Shaikh entries = le32_to_cpu(directory->num_entries);
77863507592SShahed Shaikh entry_size = le32_to_cpu(directory->entry_size);
77963507592SShahed Shaikh tab_size = le32_to_cpu(directory->findex) + (entries * entry_size);
780aa43c215SJeff Kirsher
781aa43c215SJeff Kirsher if (fw_file_size < tab_size)
782aa43c215SJeff Kirsher return -EINVAL;
783aa43c215SJeff Kirsher
784aa43c215SJeff Kirsher return 0;
785aa43c215SJeff Kirsher }
786aa43c215SJeff Kirsher
787aa43c215SJeff Kirsher static int
qlcnic_validate_bootld(struct qlcnic_adapter * adapter)788aa43c215SJeff Kirsher qlcnic_validate_bootld(struct qlcnic_adapter *adapter)
789aa43c215SJeff Kirsher {
790aa43c215SJeff Kirsher struct uni_table_desc *tab_desc;
791aa43c215SJeff Kirsher struct uni_data_desc *descr;
79263507592SShahed Shaikh u32 offs, tab_size, data_size, idx;
793aa43c215SJeff Kirsher const u8 *unirom = adapter->fw->data;
79463507592SShahed Shaikh __le32 temp;
795aa43c215SJeff Kirsher
79663507592SShahed Shaikh temp = *((__le32 *)&unirom[adapter->file_prd_off] +
79763507592SShahed Shaikh QLCNIC_UNI_BOOTLD_IDX_OFF);
79863507592SShahed Shaikh idx = le32_to_cpu(temp);
799aa43c215SJeff Kirsher tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD);
800aa43c215SJeff Kirsher
801aa43c215SJeff Kirsher if (!tab_desc)
802aa43c215SJeff Kirsher return -EINVAL;
803aa43c215SJeff Kirsher
80463507592SShahed Shaikh tab_size = le32_to_cpu(tab_desc->findex) +
80563507592SShahed Shaikh le32_to_cpu(tab_desc->entry_size) * (idx + 1);
806aa43c215SJeff Kirsher
807aa43c215SJeff Kirsher if (adapter->fw->size < tab_size)
808aa43c215SJeff Kirsher return -EINVAL;
809aa43c215SJeff Kirsher
81063507592SShahed Shaikh offs = le32_to_cpu(tab_desc->findex) +
81163507592SShahed Shaikh le32_to_cpu(tab_desc->entry_size) * idx;
812aa43c215SJeff Kirsher descr = (struct uni_data_desc *)&unirom[offs];
813aa43c215SJeff Kirsher
81463507592SShahed Shaikh data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size);
815aa43c215SJeff Kirsher
816aa43c215SJeff Kirsher if (adapter->fw->size < data_size)
817aa43c215SJeff Kirsher return -EINVAL;
818aa43c215SJeff Kirsher
819aa43c215SJeff Kirsher return 0;
820aa43c215SJeff Kirsher }
821aa43c215SJeff Kirsher
822aa43c215SJeff Kirsher static int
qlcnic_validate_fw(struct qlcnic_adapter * adapter)823aa43c215SJeff Kirsher qlcnic_validate_fw(struct qlcnic_adapter *adapter)
824aa43c215SJeff Kirsher {
825aa43c215SJeff Kirsher struct uni_table_desc *tab_desc;
826aa43c215SJeff Kirsher struct uni_data_desc *descr;
827aa43c215SJeff Kirsher const u8 *unirom = adapter->fw->data;
82863507592SShahed Shaikh u32 offs, tab_size, data_size, idx;
82963507592SShahed Shaikh __le32 temp;
830aa43c215SJeff Kirsher
83163507592SShahed Shaikh temp = *((__le32 *)&unirom[adapter->file_prd_off] +
83263507592SShahed Shaikh QLCNIC_UNI_FIRMWARE_IDX_OFF);
83363507592SShahed Shaikh idx = le32_to_cpu(temp);
834aa43c215SJeff Kirsher tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW);
835aa43c215SJeff Kirsher
836aa43c215SJeff Kirsher if (!tab_desc)
837aa43c215SJeff Kirsher return -EINVAL;
838aa43c215SJeff Kirsher
83963507592SShahed Shaikh tab_size = le32_to_cpu(tab_desc->findex) +
84063507592SShahed Shaikh le32_to_cpu(tab_desc->entry_size) * (idx + 1);
841aa43c215SJeff Kirsher
842aa43c215SJeff Kirsher if (adapter->fw->size < tab_size)
843aa43c215SJeff Kirsher return -EINVAL;
844aa43c215SJeff Kirsher
84563507592SShahed Shaikh offs = le32_to_cpu(tab_desc->findex) +
84663507592SShahed Shaikh le32_to_cpu(tab_desc->entry_size) * idx;
847aa43c215SJeff Kirsher descr = (struct uni_data_desc *)&unirom[offs];
84863507592SShahed Shaikh data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size);
849aa43c215SJeff Kirsher
850aa43c215SJeff Kirsher if (adapter->fw->size < data_size)
851aa43c215SJeff Kirsher return -EINVAL;
852aa43c215SJeff Kirsher
853aa43c215SJeff Kirsher return 0;
854aa43c215SJeff Kirsher }
855aa43c215SJeff Kirsher
856aa43c215SJeff Kirsher static int
qlcnic_validate_product_offs(struct qlcnic_adapter * adapter)857aa43c215SJeff Kirsher qlcnic_validate_product_offs(struct qlcnic_adapter *adapter)
858aa43c215SJeff Kirsher {
859aa43c215SJeff Kirsher struct uni_table_desc *ptab_descr;
860aa43c215SJeff Kirsher const u8 *unirom = adapter->fw->data;
861aa43c215SJeff Kirsher int mn_present = qlcnic_has_mn(adapter);
86263507592SShahed Shaikh u32 entries, entry_size, tab_size, i;
86363507592SShahed Shaikh __le32 temp;
864aa43c215SJeff Kirsher
865aa43c215SJeff Kirsher ptab_descr = qlcnic_get_table_desc(unirom,
866aa43c215SJeff Kirsher QLCNIC_UNI_DIR_SECT_PRODUCT_TBL);
867aa43c215SJeff Kirsher if (!ptab_descr)
868aa43c215SJeff Kirsher return -EINVAL;
869aa43c215SJeff Kirsher
87063507592SShahed Shaikh entries = le32_to_cpu(ptab_descr->num_entries);
87163507592SShahed Shaikh entry_size = le32_to_cpu(ptab_descr->entry_size);
87263507592SShahed Shaikh tab_size = le32_to_cpu(ptab_descr->findex) + (entries * entry_size);
873aa43c215SJeff Kirsher
874aa43c215SJeff Kirsher if (adapter->fw->size < tab_size)
875aa43c215SJeff Kirsher return -EINVAL;
876aa43c215SJeff Kirsher
877aa43c215SJeff Kirsher nomn:
878aa43c215SJeff Kirsher for (i = 0; i < entries; i++) {
879aa43c215SJeff Kirsher
88063507592SShahed Shaikh u32 flags, file_chiprev, offs;
881aa43c215SJeff Kirsher u8 chiprev = adapter->ahw->revision_id;
882aa43c215SJeff Kirsher u32 flagbit;
883aa43c215SJeff Kirsher
88463507592SShahed Shaikh offs = le32_to_cpu(ptab_descr->findex) +
88563507592SShahed Shaikh i * le32_to_cpu(ptab_descr->entry_size);
88663507592SShahed Shaikh temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_FLAGS_OFF);
88763507592SShahed Shaikh flags = le32_to_cpu(temp);
88863507592SShahed Shaikh temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_CHIP_REV_OFF);
88963507592SShahed Shaikh file_chiprev = le32_to_cpu(temp);
890aa43c215SJeff Kirsher
891aa43c215SJeff Kirsher flagbit = mn_present ? 1 : 2;
892aa43c215SJeff Kirsher
893aa43c215SJeff Kirsher if ((chiprev == file_chiprev) &&
894aa43c215SJeff Kirsher ((1ULL << flagbit) & flags)) {
895aa43c215SJeff Kirsher adapter->file_prd_off = offs;
896aa43c215SJeff Kirsher return 0;
897aa43c215SJeff Kirsher }
898aa43c215SJeff Kirsher }
899aa43c215SJeff Kirsher if (mn_present) {
900aa43c215SJeff Kirsher mn_present = 0;
901aa43c215SJeff Kirsher goto nomn;
902aa43c215SJeff Kirsher }
903aa43c215SJeff Kirsher return -EINVAL;
904aa43c215SJeff Kirsher }
905aa43c215SJeff Kirsher
906aa43c215SJeff Kirsher static int
qlcnic_validate_unified_romimage(struct qlcnic_adapter * adapter)907aa43c215SJeff Kirsher qlcnic_validate_unified_romimage(struct qlcnic_adapter *adapter)
908aa43c215SJeff Kirsher {
909aa43c215SJeff Kirsher if (qlcnic_validate_header(adapter)) {
910aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
911aa43c215SJeff Kirsher "unified image: header validation failed\n");
912aa43c215SJeff Kirsher return -EINVAL;
913aa43c215SJeff Kirsher }
914aa43c215SJeff Kirsher
915aa43c215SJeff Kirsher if (qlcnic_validate_product_offs(adapter)) {
916aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
917aa43c215SJeff Kirsher "unified image: product validation failed\n");
918aa43c215SJeff Kirsher return -EINVAL;
919aa43c215SJeff Kirsher }
920aa43c215SJeff Kirsher
921aa43c215SJeff Kirsher if (qlcnic_validate_bootld(adapter)) {
922aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
923aa43c215SJeff Kirsher "unified image: bootld validation failed\n");
924aa43c215SJeff Kirsher return -EINVAL;
925aa43c215SJeff Kirsher }
926aa43c215SJeff Kirsher
927aa43c215SJeff Kirsher if (qlcnic_validate_fw(adapter)) {
928aa43c215SJeff Kirsher dev_err(&adapter->pdev->dev,
929aa43c215SJeff Kirsher "unified image: firmware validation failed\n");
930aa43c215SJeff Kirsher return -EINVAL;
931aa43c215SJeff Kirsher }
932aa43c215SJeff Kirsher
933aa43c215SJeff Kirsher return 0;
934aa43c215SJeff Kirsher }
935aa43c215SJeff Kirsher
936aa43c215SJeff Kirsher static
qlcnic_get_data_desc(struct qlcnic_adapter * adapter,u32 section,u32 idx_offset)937aa43c215SJeff Kirsher struct uni_data_desc *qlcnic_get_data_desc(struct qlcnic_adapter *adapter,
938aa43c215SJeff Kirsher u32 section, u32 idx_offset)
939aa43c215SJeff Kirsher {
940aa43c215SJeff Kirsher const u8 *unirom = adapter->fw->data;
941aa43c215SJeff Kirsher struct uni_table_desc *tab_desc;
94263507592SShahed Shaikh u32 offs, idx;
94363507592SShahed Shaikh __le32 temp;
94463507592SShahed Shaikh
94563507592SShahed Shaikh temp = *((__le32 *)&unirom[adapter->file_prd_off] + idx_offset);
94663507592SShahed Shaikh idx = le32_to_cpu(temp);
947aa43c215SJeff Kirsher
948aa43c215SJeff Kirsher tab_desc = qlcnic_get_table_desc(unirom, section);
949aa43c215SJeff Kirsher
950aa43c215SJeff Kirsher if (tab_desc == NULL)
951aa43c215SJeff Kirsher return NULL;
952aa43c215SJeff Kirsher
95363507592SShahed Shaikh offs = le32_to_cpu(tab_desc->findex) +
95463507592SShahed Shaikh le32_to_cpu(tab_desc->entry_size) * idx;
955aa43c215SJeff Kirsher
956aa43c215SJeff Kirsher return (struct uni_data_desc *)&unirom[offs];
957aa43c215SJeff Kirsher }
958aa43c215SJeff Kirsher
959aa43c215SJeff Kirsher static u8 *
qlcnic_get_bootld_offs(struct qlcnic_adapter * adapter)960aa43c215SJeff Kirsher qlcnic_get_bootld_offs(struct qlcnic_adapter *adapter)
961aa43c215SJeff Kirsher {
962aa43c215SJeff Kirsher u32 offs = QLCNIC_BOOTLD_START;
96363507592SShahed Shaikh struct uni_data_desc *data_desc;
96463507592SShahed Shaikh
96563507592SShahed Shaikh data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_BOOTLD,
96663507592SShahed Shaikh QLCNIC_UNI_BOOTLD_IDX_OFF);
967aa43c215SJeff Kirsher
96879788450SSony Chacko if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
96963507592SShahed Shaikh offs = le32_to_cpu(data_desc->findex);
970aa43c215SJeff Kirsher
971aa43c215SJeff Kirsher return (u8 *)&adapter->fw->data[offs];
972aa43c215SJeff Kirsher }
973aa43c215SJeff Kirsher
974aa43c215SJeff Kirsher static u8 *
qlcnic_get_fw_offs(struct qlcnic_adapter * adapter)975aa43c215SJeff Kirsher qlcnic_get_fw_offs(struct qlcnic_adapter *adapter)
976aa43c215SJeff Kirsher {
977aa43c215SJeff Kirsher u32 offs = QLCNIC_IMAGE_START;
97863507592SShahed Shaikh struct uni_data_desc *data_desc;
979aa43c215SJeff Kirsher
98063507592SShahed Shaikh data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
98163507592SShahed Shaikh QLCNIC_UNI_FIRMWARE_IDX_OFF);
98279788450SSony Chacko if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
98363507592SShahed Shaikh offs = le32_to_cpu(data_desc->findex);
984aa43c215SJeff Kirsher
985aa43c215SJeff Kirsher return (u8 *)&adapter->fw->data[offs];
986aa43c215SJeff Kirsher }
987aa43c215SJeff Kirsher
qlcnic_get_fw_size(struct qlcnic_adapter * adapter)98863507592SShahed Shaikh static u32 qlcnic_get_fw_size(struct qlcnic_adapter *adapter)
989aa43c215SJeff Kirsher {
99063507592SShahed Shaikh struct uni_data_desc *data_desc;
99163507592SShahed Shaikh const u8 *unirom = adapter->fw->data;
99263507592SShahed Shaikh
99363507592SShahed Shaikh data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
99463507592SShahed Shaikh QLCNIC_UNI_FIRMWARE_IDX_OFF);
99563507592SShahed Shaikh
99679788450SSony Chacko if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
99763507592SShahed Shaikh return le32_to_cpu(data_desc->size);
998aa43c215SJeff Kirsher else
99963507592SShahed Shaikh return le32_to_cpu(*(__le32 *)&unirom[QLCNIC_FW_SIZE_OFFSET]);
1000aa43c215SJeff Kirsher }
1001aa43c215SJeff Kirsher
qlcnic_get_fw_version(struct qlcnic_adapter * adapter)100263507592SShahed Shaikh static u32 qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
1003aa43c215SJeff Kirsher {
1004aa43c215SJeff Kirsher struct uni_data_desc *fw_data_desc;
1005aa43c215SJeff Kirsher const struct firmware *fw = adapter->fw;
100663507592SShahed Shaikh u32 major, minor, sub;
100763507592SShahed Shaikh __le32 version_offset;
1008aa43c215SJeff Kirsher const u8 *ver_str;
1009aa43c215SJeff Kirsher int i, ret;
1010aa43c215SJeff Kirsher
101179788450SSony Chacko if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) {
101263507592SShahed Shaikh version_offset = *(__le32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET];
101363507592SShahed Shaikh return le32_to_cpu(version_offset);
101463507592SShahed Shaikh }
1015aa43c215SJeff Kirsher
1016aa43c215SJeff Kirsher fw_data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
1017aa43c215SJeff Kirsher QLCNIC_UNI_FIRMWARE_IDX_OFF);
101863507592SShahed Shaikh ver_str = fw->data + le32_to_cpu(fw_data_desc->findex) +
101963507592SShahed Shaikh le32_to_cpu(fw_data_desc->size) - 17;
1020aa43c215SJeff Kirsher
1021aa43c215SJeff Kirsher for (i = 0; i < 12; i++) {
1022aa43c215SJeff Kirsher if (!strncmp(&ver_str[i], "REV=", 4)) {
1023aa43c215SJeff Kirsher ret = sscanf(&ver_str[i+4], "%u.%u.%u ",
1024aa43c215SJeff Kirsher &major, &minor, &sub);
1025aa43c215SJeff Kirsher if (ret != 3)
1026aa43c215SJeff Kirsher return 0;
1027aa43c215SJeff Kirsher else
1028aa43c215SJeff Kirsher return major + (minor << 8) + (sub << 16);
1029aa43c215SJeff Kirsher }
1030aa43c215SJeff Kirsher }
1031aa43c215SJeff Kirsher
1032aa43c215SJeff Kirsher return 0;
1033aa43c215SJeff Kirsher }
1034aa43c215SJeff Kirsher
qlcnic_get_bios_version(struct qlcnic_adapter * adapter)103563507592SShahed Shaikh static u32 qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
1036aa43c215SJeff Kirsher {
1037aa43c215SJeff Kirsher const struct firmware *fw = adapter->fw;
103863507592SShahed Shaikh u32 bios_ver, prd_off = adapter->file_prd_off;
103963507592SShahed Shaikh u8 *version_offset;
104063507592SShahed Shaikh __le32 temp;
1041aa43c215SJeff Kirsher
104279788450SSony Chacko if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) {
104363507592SShahed Shaikh version_offset = (u8 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET];
104463507592SShahed Shaikh return le32_to_cpu(*(__le32 *)version_offset);
104563507592SShahed Shaikh }
1046aa43c215SJeff Kirsher
104763507592SShahed Shaikh temp = *((__le32 *)(&fw->data[prd_off]) + QLCNIC_UNI_BIOS_VERSION_OFF);
104863507592SShahed Shaikh bios_ver = le32_to_cpu(temp);
1049aa43c215SJeff Kirsher
1050aa43c215SJeff Kirsher return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24);
1051aa43c215SJeff Kirsher }
1052aa43c215SJeff Kirsher
qlcnic_rom_lock_recovery(struct qlcnic_adapter * adapter)1053aa43c215SJeff Kirsher static void qlcnic_rom_lock_recovery(struct qlcnic_adapter *adapter)
1054aa43c215SJeff Kirsher {
1055aa43c215SJeff Kirsher if (qlcnic_pcie_sem_lock(adapter, 2, QLCNIC_ROM_LOCK_ID))
1056aa43c215SJeff Kirsher dev_info(&adapter->pdev->dev, "Resetting rom_lock\n");
1057aa43c215SJeff Kirsher
1058aa43c215SJeff Kirsher qlcnic_pcie_sem_unlock(adapter, 2);
1059aa43c215SJeff Kirsher }
1060aa43c215SJeff Kirsher
1061aa43c215SJeff Kirsher static int
qlcnic_check_fw_hearbeat(struct qlcnic_adapter * adapter)1062aa43c215SJeff Kirsher qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter)
1063aa43c215SJeff Kirsher {
1064aa43c215SJeff Kirsher u32 heartbeat, ret = -EIO;
1065aa43c215SJeff Kirsher int retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;
1066aa43c215SJeff Kirsher
1067a15ebd37SHimanshu Madhani adapter->heartbeat = QLC_SHARED_REG_RD32(adapter,
1068a15ebd37SHimanshu Madhani QLCNIC_PEG_ALIVE_COUNTER);
1069aa43c215SJeff Kirsher
1070aa43c215SJeff Kirsher do {
1071aa43c215SJeff Kirsher msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
1072a15ebd37SHimanshu Madhani heartbeat = QLC_SHARED_REG_RD32(adapter,
1073a15ebd37SHimanshu Madhani QLCNIC_PEG_ALIVE_COUNTER);
1074aa43c215SJeff Kirsher if (heartbeat != adapter->heartbeat) {
1075aa43c215SJeff Kirsher ret = QLCNIC_RCODE_SUCCESS;
1076aa43c215SJeff Kirsher break;
1077aa43c215SJeff Kirsher }
1078aa43c215SJeff Kirsher } while (--retries);
1079aa43c215SJeff Kirsher
1080aa43c215SJeff Kirsher return ret;
1081aa43c215SJeff Kirsher }
1082aa43c215SJeff Kirsher
1083aa43c215SJeff Kirsher int
qlcnic_need_fw_reset(struct qlcnic_adapter * adapter)1084aa43c215SJeff Kirsher qlcnic_need_fw_reset(struct qlcnic_adapter *adapter)
1085aa43c215SJeff Kirsher {
1086aa43c215SJeff Kirsher if ((adapter->flags & QLCNIC_FW_HANG) ||
1087aa43c215SJeff Kirsher qlcnic_check_fw_hearbeat(adapter)) {
1088aa43c215SJeff Kirsher qlcnic_rom_lock_recovery(adapter);
1089aa43c215SJeff Kirsher return 1;
1090aa43c215SJeff Kirsher }
1091aa43c215SJeff Kirsher
1092aa43c215SJeff Kirsher if (adapter->need_fw_reset)
1093aa43c215SJeff Kirsher return 1;
1094aa43c215SJeff Kirsher
1095aa43c215SJeff Kirsher if (adapter->fw)
1096aa43c215SJeff Kirsher return 1;
1097aa43c215SJeff Kirsher
1098aa43c215SJeff Kirsher return 0;
1099aa43c215SJeff Kirsher }
1100aa43c215SJeff Kirsher
1101aa43c215SJeff Kirsher static const char *fw_name[] = {
1102aa43c215SJeff Kirsher QLCNIC_UNIFIED_ROMIMAGE_NAME,
1103aa43c215SJeff Kirsher QLCNIC_FLASH_ROMIMAGE_NAME,
1104aa43c215SJeff Kirsher };
1105aa43c215SJeff Kirsher
1106aa43c215SJeff Kirsher int
qlcnic_load_firmware(struct qlcnic_adapter * adapter)1107aa43c215SJeff Kirsher qlcnic_load_firmware(struct qlcnic_adapter *adapter)
1108aa43c215SJeff Kirsher {
110963507592SShahed Shaikh __le64 *ptr64;
1110aa43c215SJeff Kirsher u32 i, flashaddr, size;
1111aa43c215SJeff Kirsher const struct firmware *fw = adapter->fw;
1112aa43c215SJeff Kirsher struct pci_dev *pdev = adapter->pdev;
1113aa43c215SJeff Kirsher
1114aa43c215SJeff Kirsher dev_info(&pdev->dev, "loading firmware from %s\n",
111579788450SSony Chacko fw_name[adapter->ahw->fw_type]);
1116aa43c215SJeff Kirsher
1117aa43c215SJeff Kirsher if (fw) {
111863507592SShahed Shaikh u64 data;
1119aa43c215SJeff Kirsher
1120aa43c215SJeff Kirsher size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
1121aa43c215SJeff Kirsher
112263507592SShahed Shaikh ptr64 = (__le64 *)qlcnic_get_bootld_offs(adapter);
1123aa43c215SJeff Kirsher flashaddr = QLCNIC_BOOTLD_START;
1124aa43c215SJeff Kirsher
1125aa43c215SJeff Kirsher for (i = 0; i < size; i++) {
112663507592SShahed Shaikh data = le64_to_cpu(ptr64[i]);
1127aa43c215SJeff Kirsher
1128aa43c215SJeff Kirsher if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data))
1129aa43c215SJeff Kirsher return -EIO;
1130aa43c215SJeff Kirsher
1131aa43c215SJeff Kirsher flashaddr += 8;
1132aa43c215SJeff Kirsher }
1133aa43c215SJeff Kirsher
113463507592SShahed Shaikh size = qlcnic_get_fw_size(adapter) / 8;
1135aa43c215SJeff Kirsher
113663507592SShahed Shaikh ptr64 = (__le64 *)qlcnic_get_fw_offs(adapter);
1137aa43c215SJeff Kirsher flashaddr = QLCNIC_IMAGE_START;
1138aa43c215SJeff Kirsher
1139aa43c215SJeff Kirsher for (i = 0; i < size; i++) {
114063507592SShahed Shaikh data = le64_to_cpu(ptr64[i]);
1141aa43c215SJeff Kirsher
1142aa43c215SJeff Kirsher if (qlcnic_pci_mem_write_2M(adapter,
1143aa43c215SJeff Kirsher flashaddr, data))
1144aa43c215SJeff Kirsher return -EIO;
1145aa43c215SJeff Kirsher
1146aa43c215SJeff Kirsher flashaddr += 8;
1147aa43c215SJeff Kirsher }
1148aa43c215SJeff Kirsher
114963507592SShahed Shaikh size = qlcnic_get_fw_size(adapter) % 8;
1150aa43c215SJeff Kirsher if (size) {
115163507592SShahed Shaikh data = le64_to_cpu(ptr64[i]);
1152aa43c215SJeff Kirsher
1153aa43c215SJeff Kirsher if (qlcnic_pci_mem_write_2M(adapter,
1154aa43c215SJeff Kirsher flashaddr, data))
1155aa43c215SJeff Kirsher return -EIO;
1156aa43c215SJeff Kirsher }
1157aa43c215SJeff Kirsher
1158aa43c215SJeff Kirsher } else {
1159aa43c215SJeff Kirsher u64 data;
1160aa43c215SJeff Kirsher u32 hi, lo;
1161aa43c215SJeff Kirsher int ret;
1162aa43c215SJeff Kirsher struct qlcnic_flt_entry bootld_entry;
1163aa43c215SJeff Kirsher
1164aa43c215SJeff Kirsher ret = qlcnic_get_flt_entry(adapter, QLCNIC_BOOTLD_REGION,
1165aa43c215SJeff Kirsher &bootld_entry);
1166aa43c215SJeff Kirsher if (!ret) {
1167aa43c215SJeff Kirsher size = bootld_entry.size / 8;
1168aa43c215SJeff Kirsher flashaddr = bootld_entry.start_addr;
1169aa43c215SJeff Kirsher } else {
1170aa43c215SJeff Kirsher size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
1171aa43c215SJeff Kirsher flashaddr = QLCNIC_BOOTLD_START;
1172aa43c215SJeff Kirsher dev_info(&pdev->dev,
1173aa43c215SJeff Kirsher "using legacy method to get flash fw region");
1174aa43c215SJeff Kirsher }
1175aa43c215SJeff Kirsher
1176aa43c215SJeff Kirsher for (i = 0; i < size; i++) {
1177aa43c215SJeff Kirsher if (qlcnic_rom_fast_read(adapter,
1178aa43c215SJeff Kirsher flashaddr, (int *)&lo) != 0)
1179aa43c215SJeff Kirsher return -EIO;
1180aa43c215SJeff Kirsher if (qlcnic_rom_fast_read(adapter,
1181aa43c215SJeff Kirsher flashaddr + 4, (int *)&hi) != 0)
1182aa43c215SJeff Kirsher return -EIO;
1183aa43c215SJeff Kirsher
1184aa43c215SJeff Kirsher data = (((u64)hi << 32) | lo);
1185aa43c215SJeff Kirsher
1186aa43c215SJeff Kirsher if (qlcnic_pci_mem_write_2M(adapter,
1187aa43c215SJeff Kirsher flashaddr, data))
1188aa43c215SJeff Kirsher return -EIO;
1189aa43c215SJeff Kirsher
1190aa43c215SJeff Kirsher flashaddr += 8;
1191aa43c215SJeff Kirsher }
1192aa43c215SJeff Kirsher }
1193c1b2037fSJitendra Kalsaria usleep_range(1000, 1500);
1194aa43c215SJeff Kirsher
1195aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x18, 0x1020);
1196aa43c215SJeff Kirsher QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0x80001e);
1197aa43c215SJeff Kirsher return 0;
1198aa43c215SJeff Kirsher }
1199aa43c215SJeff Kirsher
1200aa43c215SJeff Kirsher static int
qlcnic_validate_firmware(struct qlcnic_adapter * adapter)1201aa43c215SJeff Kirsher qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
1202aa43c215SJeff Kirsher {
120363507592SShahed Shaikh u32 val;
1204aa43c215SJeff Kirsher u32 ver, bios, min_size;
1205aa43c215SJeff Kirsher struct pci_dev *pdev = adapter->pdev;
1206aa43c215SJeff Kirsher const struct firmware *fw = adapter->fw;
120779788450SSony Chacko u8 fw_type = adapter->ahw->fw_type;
1208aa43c215SJeff Kirsher
1209aa43c215SJeff Kirsher if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) {
1210aa43c215SJeff Kirsher if (qlcnic_validate_unified_romimage(adapter))
1211aa43c215SJeff Kirsher return -EINVAL;
1212aa43c215SJeff Kirsher
1213aa43c215SJeff Kirsher min_size = QLCNIC_UNI_FW_MIN_SIZE;
1214aa43c215SJeff Kirsher } else {
121563507592SShahed Shaikh val = le32_to_cpu(*(__le32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]);
121663507592SShahed Shaikh if (val != QLCNIC_BDINFO_MAGIC)
1217aa43c215SJeff Kirsher return -EINVAL;
1218aa43c215SJeff Kirsher
1219aa43c215SJeff Kirsher min_size = QLCNIC_FW_MIN_SIZE;
1220aa43c215SJeff Kirsher }
1221aa43c215SJeff Kirsher
1222aa43c215SJeff Kirsher if (fw->size < min_size)
1223aa43c215SJeff Kirsher return -EINVAL;
1224aa43c215SJeff Kirsher
1225aa43c215SJeff Kirsher val = qlcnic_get_fw_version(adapter);
1226aa43c215SJeff Kirsher ver = QLCNIC_DECODE_VERSION(val);
1227aa43c215SJeff Kirsher
1228aa43c215SJeff Kirsher if (ver < QLCNIC_MIN_FW_VERSION) {
1229aa43c215SJeff Kirsher dev_err(&pdev->dev,
1230aa43c215SJeff Kirsher "%s: firmware version %d.%d.%d unsupported\n",
1231aa43c215SJeff Kirsher fw_name[fw_type], _major(ver), _minor(ver), _build(ver));
1232aa43c215SJeff Kirsher return -EINVAL;
1233aa43c215SJeff Kirsher }
1234aa43c215SJeff Kirsher
1235aa43c215SJeff Kirsher val = qlcnic_get_bios_version(adapter);
1236aa43c215SJeff Kirsher qlcnic_rom_fast_read(adapter, QLCNIC_BIOS_VERSION_OFFSET, (int *)&bios);
123763507592SShahed Shaikh if (val != bios) {
1238aa43c215SJeff Kirsher dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
1239aa43c215SJeff Kirsher fw_name[fw_type]);
1240aa43c215SJeff Kirsher return -EINVAL;
1241aa43c215SJeff Kirsher }
1242aa43c215SJeff Kirsher
1243a15ebd37SHimanshu Madhani QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID, QLCNIC_BDINFO_MAGIC);
1244aa43c215SJeff Kirsher return 0;
1245aa43c215SJeff Kirsher }
1246aa43c215SJeff Kirsher
1247aa43c215SJeff Kirsher static void
qlcnic_get_next_fwtype(struct qlcnic_adapter * adapter)1248aa43c215SJeff Kirsher qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter)
1249aa43c215SJeff Kirsher {
1250aa43c215SJeff Kirsher u8 fw_type;
1251aa43c215SJeff Kirsher
125279788450SSony Chacko switch (adapter->ahw->fw_type) {
1253aa43c215SJeff Kirsher case QLCNIC_UNKNOWN_ROMIMAGE:
1254aa43c215SJeff Kirsher fw_type = QLCNIC_UNIFIED_ROMIMAGE;
1255aa43c215SJeff Kirsher break;
1256aa43c215SJeff Kirsher
1257aa43c215SJeff Kirsher case QLCNIC_UNIFIED_ROMIMAGE:
1258aa43c215SJeff Kirsher default:
1259aa43c215SJeff Kirsher fw_type = QLCNIC_FLASH_ROMIMAGE;
1260aa43c215SJeff Kirsher break;
1261aa43c215SJeff Kirsher }
1262aa43c215SJeff Kirsher
126379788450SSony Chacko adapter->ahw->fw_type = fw_type;
1264aa43c215SJeff Kirsher }
1265aa43c215SJeff Kirsher
1266aa43c215SJeff Kirsher
1267aa43c215SJeff Kirsher
qlcnic_request_firmware(struct qlcnic_adapter * adapter)1268aa43c215SJeff Kirsher void qlcnic_request_firmware(struct qlcnic_adapter *adapter)
1269aa43c215SJeff Kirsher {
1270aa43c215SJeff Kirsher struct pci_dev *pdev = adapter->pdev;
1271aa43c215SJeff Kirsher int rc;
1272aa43c215SJeff Kirsher
127379788450SSony Chacko adapter->ahw->fw_type = QLCNIC_UNKNOWN_ROMIMAGE;
1274aa43c215SJeff Kirsher
1275aa43c215SJeff Kirsher next:
1276aa43c215SJeff Kirsher qlcnic_get_next_fwtype(adapter);
1277aa43c215SJeff Kirsher
127879788450SSony Chacko if (adapter->ahw->fw_type == QLCNIC_FLASH_ROMIMAGE) {
1279aa43c215SJeff Kirsher adapter->fw = NULL;
1280aa43c215SJeff Kirsher } else {
1281aa43c215SJeff Kirsher rc = request_firmware(&adapter->fw,
128279788450SSony Chacko fw_name[adapter->ahw->fw_type],
128379788450SSony Chacko &pdev->dev);
1284aa43c215SJeff Kirsher if (rc != 0)
1285aa43c215SJeff Kirsher goto next;
1286aa43c215SJeff Kirsher
1287aa43c215SJeff Kirsher rc = qlcnic_validate_firmware(adapter);
1288aa43c215SJeff Kirsher if (rc != 0) {
1289aa43c215SJeff Kirsher release_firmware(adapter->fw);
1290c1b2037fSJitendra Kalsaria usleep_range(1000, 1500);
1291aa43c215SJeff Kirsher goto next;
1292aa43c215SJeff Kirsher }
1293aa43c215SJeff Kirsher }
1294aa43c215SJeff Kirsher }
1295aa43c215SJeff Kirsher
1296aa43c215SJeff Kirsher
1297aa43c215SJeff Kirsher void
qlcnic_release_firmware(struct qlcnic_adapter * adapter)1298aa43c215SJeff Kirsher qlcnic_release_firmware(struct qlcnic_adapter *adapter)
1299aa43c215SJeff Kirsher {
1300aa43c215SJeff Kirsher release_firmware(adapter->fw);
1301aa43c215SJeff Kirsher adapter->fw = NULL;
1302aa43c215SJeff Kirsher }
1303