Commit | Line | Data |
---|---|---|
800f879a AT |
1 | /* |
2 | * Copyright 2010-2017 Intel Corporation. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License, version 2, | |
6 | * as published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | * General Public License for more details. | |
12 | * | |
13 | * Disclaimer: The codes contained in these modules may be specific to | |
14 | * the Intel Software Development Platform codenamed Knights Ferry, | |
15 | * and the Intel product codenamed Knights Corner, and are not backward | |
16 | * compatible with other Intel products. Additionally, Intel will NOT | |
17 | * support the codes or instruction set in future products. | |
18 | * | |
19 | * Intel offers no warranty of any kind regarding the code. This code is | |
20 | * licensed on an "AS IS" basis and Intel is not obligated to provide | |
21 | * any support, assistance, installation, training, or other services | |
22 | * of any kind. Intel is also not obligated to provide any updates, | |
23 | * enhancements or extensions. Intel specifically disclaims any warranty | |
24 | * of merchantability, non-infringement, fitness for any particular | |
25 | * purpose, and any other warranty. | |
26 | * | |
27 | * Further, Intel disclaims all liability of any kind, including but | |
28 | * not limited to liability for infringement of any proprietary rights, | |
29 | * relating to the use of the code, even if Intel is notified of the | |
30 | * possibility of such liability. Except as expressly stated in an Intel | |
31 | * license agreement provided with this code and agreed upon with Intel, | |
32 | * no license, express or implied, by estoppel or otherwise, to any | |
33 | * intellectual property rights is granted herein. | |
34 | */ | |
35 | ||
36 | /* code to send escape calls to uOS; meant to test the ring buffer */ | |
37 | ||
38 | #include "mic_common.h" | |
39 | #include "mic/mic_dma_lib.h" | |
40 | #include "mic/mic_dma_api.h" | |
41 | #include <mic/micscif.h> | |
42 | #include <mic/micscif_smpt.h> | |
43 | ||
44 | // constants defined for flash commands for setting PCI aperture | |
45 | #define RASMM_DEFAULT_OFFSET 0x4000000 | |
46 | #define RASMM_FLASH_SIZE 0x200000 | |
47 | #define MAX_CORE_INDEX 61 | |
48 | #define SKU_MEM_DIVIDE 4 | |
49 | #define SKU_LOW_MEM 0 | |
50 | #define SKU_HIGH_MEM 1 | |
51 | #define FREQ_2P4 0x630 | |
52 | #define FREQ_4P5 0x65A | |
53 | #define FREQ_5P0 0x664 | |
54 | #define FREQ_5P5 0x66E | |
55 | #define MASK_MEMFREQ 0xfff | |
56 | #define SHIFT_MEMFREQ 16 | |
57 | ||
58 | int | |
59 | mic_unpin_user_pages(struct page **pages, uint32_t nf_pages) | |
60 | { | |
61 | uint32_t j = 0; | |
62 | uint32_t status = 0; | |
63 | if (pages) { | |
64 | for (j = 0; j < nf_pages; j++) { | |
65 | if (pages[j]) { | |
66 | SetPageDirty(pages[j]); | |
e3dad721 | 67 | put_page(pages[j]); |
800f879a AT |
68 | } |
69 | } | |
70 | kfree(pages); | |
71 | } | |
72 | ||
73 | return status; | |
74 | } | |
75 | ||
76 | int | |
77 | mic_pin_user_pages (void *data, struct page **pages, uint32_t len, int32_t *nf_pages, int32_t nr_pages) | |
78 | { | |
79 | ||
80 | int32_t status = 0; | |
81 | ||
82 | ||
83 | if (!(pages)) { | |
84 | printk("%s Failed to allocate memory for pages\n", __func__); | |
85 | status = -ENOMEM; | |
86 | return status; | |
87 | ||
88 | } | |
89 | ||
90 | // pin the user pages; use semaphores on linux for doing the same | |
91 | down_read(¤t->mm->mmap_sem); | |
856bf072 AT |
92 | *nf_pages = (int32_t)get_user_pages((uint64_t)data, nr_pages, |
93 | (FOLL_WRITE | FOLL_FORCE), pages, NULL); | |
800f879a AT |
94 | up_read(¤t->mm->mmap_sem); |
95 | ||
96 | // compare if the no of final pages is equal to no of requested pages | |
97 | if ((*nf_pages) < nr_pages) { | |
98 | printk("%s failed to do _get_user_pages\n", __func__); | |
99 | status = -EFAULT; | |
100 | mic_unpin_user_pages(pages, *nf_pages); | |
101 | return status; | |
102 | } | |
103 | ||
104 | ||
105 | return status; | |
106 | ||
107 | } | |
108 | ||
109 | int | |
110 | send_flash_cmd(mic_ctx_t *mic_ctx, MIC_FLASH_CMD_TYPE type, void *data, uint32_t len) | |
111 | { | |
112 | int32_t status = 0; | |
113 | uint8_t *mmio_va = mic_ctx->mmio.va; | |
114 | sbox_scratch1_reg_t scratch1reg = {0}; | |
115 | sbox_scratch2_reg_t scratch2reg = {0}; | |
116 | uint32_t ret = 0; | |
117 | void *src; | |
118 | struct timeval t; | |
119 | struct flash_stat *statbuf = NULL; | |
120 | uint64_t temp; | |
121 | uint32_t i = 0; | |
122 | struct version_struct *verbuf = NULL; | |
123 | int32_t offset = 0; | |
124 | uint8_t cmddata = 0; | |
125 | ||
126 | scratch1reg.bits.status = FLASH_CMD_INVALID; | |
127 | switch (type) { | |
128 | case FLASH_CMD_READ: | |
129 | ||
130 | /* | |
131 | * image address = the upper 20 bits of the 32-bit of scracth2 register | |
132 | * is card side physical address where the flash image resides | |
133 | * program scratch2 register to notify the image address | |
134 | */ | |
135 | scratch2reg.bits.image_addr = RASMM_DEFAULT_OFFSET >> 12; | |
136 | SBOX_WRITE(scratch2reg.value, mmio_va, SBOX_SCRATCH2); | |
137 | ||
138 | /* set command */ | |
139 | scratch1reg.bits.command = FLASH_CMD_READ; | |
140 | SBOX_WRITE(scratch1reg.value, mmio_va, SBOX_SCRATCH1); | |
141 | ||
142 | mic_send_bootstrap_intr(mic_ctx); | |
143 | break; | |
144 | ||
145 | case FLASH_CMD_READ_DATA: | |
146 | ||
147 | /* | |
148 | * flash read_data command : set pci aperture to 128MB | |
149 | * read the value of scratch2 in a variable | |
150 | */ | |
151 | ret = SBOX_READ(mmio_va, SBOX_SCRATCH2); | |
152 | scratch2reg.value = ret; | |
153 | ||
154 | /* | |
155 | * convert physical to virtual address | |
156 | * image address = the upper 20 bits of the 32-bit KNC side physical | |
157 | * address where the flash image resides | |
158 | */ | |
159 | offset = scratch2reg.bits.image_addr << 12 ; | |
160 | if (len == 0) { | |
161 | status = -EINVAL; | |
162 | goto exit; | |
163 | } | |
164 | ||
165 | if (len > (mic_ctx->aper.len - offset)) { | |
166 | status = -EINVAL; | |
167 | goto exit; | |
168 | } | |
169 | src = mic_ctx->aper.va + offset; | |
170 | ||
171 | temp = copy_to_user(data, src, len); | |
172 | if (temp > 0) { | |
173 | printk("error while copy to user \n"); | |
174 | status = -EFAULT; | |
175 | goto exit; | |
176 | } | |
177 | break; | |
178 | ||
179 | case FLASH_CMD_ABORT: | |
180 | ||
181 | scratch1reg.bits.command = FLASH_CMD_ABORT; | |
182 | SBOX_WRITE(scratch1reg.value, mmio_va, SBOX_SCRATCH1); | |
183 | ||
184 | mic_send_bootstrap_intr(mic_ctx); | |
185 | break; | |
186 | ||
187 | case FLASH_CMD_VERSION: | |
188 | ||
189 | /* | |
190 | * image address = the upper 20 bits of the 32-bit of scracth2 register | |
191 | * is card side physical address where the flash image resides | |
192 | */ | |
193 | scratch2reg.bits.image_addr = RASMM_DEFAULT_OFFSET >> 12; | |
194 | SBOX_WRITE(scratch2reg.value, mmio_va, SBOX_SCRATCH2); | |
195 | ||
196 | /* | |
197 | * flash version command : similar to read_data command. | |
198 | * Instead of get_user_pages(), use kmalloc() as we are allocating | |
199 | * buffer of lesser size | |
200 | */ | |
201 | scratch1reg.bits.command = FLASH_CMD_VERSION; | |
202 | SBOX_WRITE(scratch1reg.value, mmio_va, SBOX_SCRATCH1); | |
203 | ||
204 | mic_send_bootstrap_intr(mic_ctx); | |
205 | ||
206 | /* poll for completion */ | |
207 | while(scratch1reg.bits.status != FLASH_CMD_COMPLETED) { | |
208 | ret = SBOX_READ(mmio_va, SBOX_SCRATCH1); | |
209 | scratch1reg.value = ret; | |
210 | msleep(1); | |
211 | i++; | |
212 | printk("Looping for status (time = %d ms)\n", i); | |
213 | if(i > 3000) { | |
214 | status = -ETIME; | |
215 | goto exit; | |
216 | } | |
217 | ||
218 | } | |
219 | ||
220 | src = mic_ctx->aper.va + RASMM_DEFAULT_OFFSET; | |
221 | ||
222 | if (len == 0) { | |
223 | status = -EINVAL; | |
224 | goto exit; | |
225 | } | |
226 | verbuf = kmalloc(len, GFP_KERNEL); | |
227 | if (!verbuf) { | |
228 | status = -ENOMEM; | |
229 | goto exit; | |
230 | } | |
231 | ||
232 | memcpy(verbuf, src, len); | |
233 | ||
234 | printk("header verbuf is : %x\n", verbuf->hdr_ver); | |
235 | printk("odm verbuf is : %x\n", verbuf->odm_ver); | |
236 | printk("uptd time bcd is : %llu\n", verbuf->upd_time_bcd); | |
237 | printk("updated verbuf is : %d\n", *((int*)(&verbuf->upd_ver))); | |
238 | printk("mfg time bcd is : %llu\n", verbuf->mfg_time_bcd); | |
239 | printk("mfg verbuf is : %d\n", *((int*)(&verbuf->mfg_ver))); | |
240 | ||
241 | temp = copy_to_user(data, verbuf, len); | |
242 | if(temp > 0) { | |
243 | printk("error while copy to user \n"); | |
244 | status = -EFAULT; | |
245 | if(verbuf) { | |
246 | kfree(verbuf); | |
247 | } | |
248 | goto exit; | |
249 | } | |
250 | ||
251 | if(verbuf) { | |
252 | kfree(verbuf); | |
253 | } | |
254 | ||
255 | break; | |
256 | ||
257 | case FLASH_CMD_WRITE: | |
258 | ||
259 | /* flash write command : pin user pages for the data buffer which contains | |
260 | * the image. | |
261 | * For the write command, we provide the offset for writing. | |
262 | * GTT is set to 64MB and offset = 0. | |
263 | */ | |
264 | if (len > (mic_ctx->aper.len - RASMM_DEFAULT_OFFSET)) { | |
265 | status = -EINVAL; | |
266 | goto exit; | |
267 | } | |
268 | src = mic_ctx->aper.va + RASMM_DEFAULT_OFFSET; | |
269 | if (len == 0) { | |
270 | status = -EINVAL; | |
271 | goto exit; | |
272 | } | |
273 | temp = copy_from_user(src, data, len); | |
274 | if (temp > 0) { | |
275 | printk("error while copying from user \n"); | |
276 | status = -EFAULT; | |
277 | goto exit; | |
278 | } | |
279 | ||
280 | /* image address = the upper 20 bits of the 32-bit KNC side physical | |
281 | * address where the flash image resides | |
282 | */ | |
283 | scratch2reg.bits.image_addr = RASMM_DEFAULT_OFFSET >> 12; | |
284 | SBOX_WRITE(scratch2reg.value, mmio_va, SBOX_SCRATCH2); | |
285 | ||
286 | scratch1reg.bits.command = FLASH_CMD_WRITE; | |
287 | SBOX_WRITE(scratch1reg.value, mmio_va, SBOX_SCRATCH1); | |
288 | ||
289 | mic_send_bootstrap_intr(mic_ctx); | |
290 | ; | |
291 | ||
292 | break; | |
293 | ||
294 | case RAS_CMD_CORE_DISABLE: | |
295 | case RAS_CMD_CORE_ENABLE: | |
296 | if (copy_from_user(&cmddata, data, sizeof(cmddata))) { | |
297 | status = -EFAULT; | |
298 | goto exit; | |
299 | } | |
300 | scratch1reg.bits.cmd_data = cmddata; | |
301 | if (cmddata > MAX_CORE_INDEX) { | |
302 | printk("Parameter given is greater than physical core index\n"); | |
303 | status = -EINVAL; | |
304 | goto exit; | |
305 | } | |
306 | ||
307 | case RAS_CMD: | |
308 | case RAS_CMD_INJECT_REPAIR: | |
309 | case RAS_CMD_ECC_DISABLE: | |
310 | case RAS_CMD_ECC_ENABLE: | |
311 | case RAS_CMD_EXIT: | |
312 | do_gettimeofday(&t); | |
313 | SBOX_WRITE(t.tv_sec, mmio_va, SBOX_SCRATCH3); | |
314 | scratch1reg.bits.command = type; | |
315 | SBOX_WRITE(scratch1reg.value, mmio_va, SBOX_SCRATCH1); | |
316 | ||
317 | mic_send_bootstrap_intr(mic_ctx); | |
318 | ||
319 | break; | |
320 | ||
321 | case FLASH_CMD_STATUS: | |
322 | ||
323 | /* status command : mmio read of SCRATCH1 register | |
324 | * The percentage completion is only updated on the | |
325 | * Flash Write function as currently implemented. | |
326 | * The other functions are expected to complete almost instantly | |
327 | */ | |
328 | if(len != sizeof(struct flash_stat)) { | |
329 | status = -EINVAL; | |
330 | goto exit; | |
331 | } | |
332 | if (len == 0) { | |
333 | status = -EINVAL; | |
334 | goto exit; | |
335 | } | |
336 | statbuf = kmalloc(len, GFP_KERNEL); | |
337 | if(!statbuf) { | |
338 | status = -ENOMEM; | |
339 | goto exit; | |
340 | } | |
341 | ||
342 | temp = SBOX_READ(mmio_va, SBOX_SCRATCH1); | |
343 | scratch1reg.value = (uint32_t)temp; | |
344 | ||
345 | statbuf->status = scratch1reg.bits.status; | |
346 | statbuf->percent = scratch1reg.bits.percent; | |
347 | statbuf->smc_status = scratch1reg.bits.smc_status; | |
348 | statbuf->cmd_data = scratch1reg.bits.cmd_data; | |
349 | statbuf->mm_debug = scratch1reg.bits.mm_debug; | |
350 | ||
351 | temp = copy_to_user(data, statbuf, len); | |
352 | if(temp > 0) { | |
353 | printk("Error copying data to user buffer\n"); | |
354 | status = -EFAULT; | |
355 | if(statbuf) { | |
356 | kfree(statbuf); | |
357 | } | |
358 | goto exit; | |
359 | } | |
360 | ||
361 | if(statbuf) { | |
362 | kfree(statbuf); | |
363 | } | |
364 | ||
365 | break; | |
366 | ||
367 | default: | |
368 | printk(KERN_ERR "Unknown command\n"); | |
369 | status = -EOPNOTSUPP; | |
370 | break; | |
371 | ||
372 | } | |
373 | ||
374 | exit : | |
375 | return status; | |
376 | } | |
377 | ||
378 | int get_cardside_mem(mic_ctx_t *mic_ctx, uint64_t start, uint64_t size, void *dest) | |
379 | { | |
380 | int32_t status = 0; | |
381 | uint64_t len; | |
382 | uint64_t dest_pa; | |
383 | struct dma_channel *ch = NULL; | |
384 | int flags = 0; | |
385 | int poll_cookie; | |
386 | int i, next_page; | |
387 | int j; | |
388 | uint64_t num_pages; | |
389 | uint64_t card_pa; | |
390 | int32_t nf_pages = 0; | |
391 | uint64_t nr_pages = 0; | |
392 | struct page **pages = NULL; | |
393 | void *pg_virt_add; | |
394 | unsigned long t = jiffies; | |
395 | int dma_ret = 0; | |
396 | card_pa = start; | |
397 | len = size; | |
398 | ||
399 | if (len % PAGE_SIZE) | |
400 | nr_pages = (len >> PAGE_SHIFT) + 1; | |
401 | else | |
402 | nr_pages = len >> PAGE_SHIFT; | |
403 | ||
404 | flags |= DO_DMA_POLLING; | |
405 | num_pages = len / PAGE_SIZE; | |
406 | next_page = 0; | |
407 | ||
408 | pages = kmalloc(nr_pages * sizeof(struct page*), GFP_KERNEL); | |
409 | if (!pages) | |
410 | return -ENOMEM; | |
411 | status = mic_pin_user_pages(dest, pages, (uint32_t)len, &nf_pages, (int32_t)nr_pages); | |
412 | ||
413 | if (status) | |
414 | goto exit; | |
415 | ||
416 | /* allocate_dma_channel should fail in 2 cases : 1. if it doesnt get dma channel | |
417 | * then it times out 2. there is no device present | |
418 | */ | |
419 | status = micpm_get_reference(mic_ctx, true); | |
420 | if (status) | |
421 | goto exit; | |
422 | ||
423 | while ((dma_ret = allocate_dma_channel(mic_ctx->dma_handle, &ch)) != 0) { | |
424 | if (dma_ret == -ENODEV) { | |
425 | printk("No device present\n"); | |
426 | status = -ENODEV; | |
427 | goto put_ref; | |
428 | } | |
429 | msleep(1); | |
430 | if (time_after(jiffies,t + NODE_ALIVE_TIMEOUT)) { | |
431 | printk("dma channel allocation error\n"); | |
432 | status = -EBUSY; | |
433 | goto put_ref; | |
434 | } | |
435 | } | |
436 | ||
437 | for(j = 0; j < num_pages; j++) { | |
438 | i = 0; | |
439 | pg_virt_add = lowmem_page_address(pages[j]); | |
440 | /* get card side address */ | |
441 | dest_pa = mic_ctx_map_single(mic_ctx, pg_virt_add, PAGE_SIZE); | |
442 | ||
443 | /* do dma and keep polling for completion */ | |
444 | poll_cookie = do_dma(ch, flags, card_pa + next_page, dest_pa, PAGE_SIZE, NULL); | |
445 | pr_debug("Poll cookie %d\n", poll_cookie); | |
446 | if (0 > poll_cookie) { | |
447 | printk("Error programming the dma descriptor\n"); | |
448 | status = poll_cookie; | |
449 | goto put_ref; | |
450 | } else if (-2 == poll_cookie) { | |
451 | printk( "Copy was done successfully, check for validity\n"); | |
452 | } else if(-1 != poll_cookie) { | |
453 | while (i < 10000 && 1 != poll_dma_completion(poll_cookie, ch)) { | |
454 | i++; | |
455 | } | |
456 | if (i == 10000) { | |
457 | printk("DMA timed out \n"); | |
458 | } else { | |
459 | pr_debug("DMA SUCCESS at %d\n", i); | |
460 | /* increment by PAGE_SIZE on DMA SUCCESS to transfer next page */ | |
461 | next_page = next_page + PAGE_SIZE; | |
462 | } | |
463 | } | |
464 | mic_ctx_unmap_single(mic_ctx, (dma_addr_t)dest_pa, PAGE_SIZE); | |
465 | } | |
466 | ||
467 | put_ref: | |
468 | micpm_put_reference(mic_ctx); | |
469 | exit: | |
470 | mic_unpin_user_pages(pages, nf_pages); | |
471 | if (ch) | |
472 | free_dma_channel(ch); | |
473 | return status; | |
474 | } | |
475 | ||
476 | /* SKU functions */ | |
477 | void | |
478 | sku_swap_list(struct list_head *in, struct list_head *out) | |
479 | { | |
480 | struct list_head *pos, *tmp; | |
481 | sku_info_t *node; | |
482 | list_for_each_safe(pos, tmp, in) { | |
483 | node = list_entry(pos, sku_info_t, sku); | |
484 | list_del(pos); | |
485 | list_add_tail(&node->sku, out); | |
486 | } | |
487 | } | |
488 | ||
489 | int | |
490 | sku_create_node(uint32_t fuserev_low, | |
491 | uint32_t fuserev_high, uint32_t mem_size, | |
492 | uint32_t mem_freq, char *sku_name, | |
493 | sku_info_t ** newnode) | |
494 | { | |
495 | sku_info_t *temp; | |
496 | ||
497 | temp = kmalloc(sizeof(sku_info_t), GFP_KERNEL); | |
498 | if (temp == NULL) | |
499 | return -ENOMEM; | |
500 | temp->fuserev_low = fuserev_low; | |
501 | temp->fuserev_high = fuserev_high; | |
502 | temp->memsize = mem_size; | |
503 | temp->memfreq = mem_freq; | |
504 | strncpy(temp->sku_name, sku_name, SKU_NAME_LEN - 1); | |
505 | temp->sku_name[SKU_NAME_LEN - 1] = '\0'; | |
506 | *newnode = temp; | |
507 | return 0; | |
508 | } | |
509 | ||
510 | void | |
511 | sku_destroy_table() | |
512 | { | |
513 | int i; | |
514 | sku_info_t *node; | |
515 | struct list_head *pos, *tmp; | |
516 | for (i = 0; i < MAX_DEV_IDS; i++) | |
517 | list_for_each_safe(pos, tmp, &mic_data.sku_table[i]) { | |
518 | node = list_entry(pos, sku_info_t, sku); | |
519 | list_del(pos); | |
520 | kfree(node); | |
521 | } | |
522 | } | |
523 | ||
524 | int | |
525 | sku_find(mic_ctx_t *mic_ctx, uint32_t device_id) | |
526 | { | |
527 | int ret = 0; | |
528 | uint32_t cnt = 0; | |
529 | sku_info_t *match, *newnode = NULL, *skunode; | |
530 | struct list_head skulist_memsize_in; | |
531 | struct list_head skulist_memfreq_in; | |
532 | struct list_head skulist_out; | |
533 | uint32_t fuse_rev, memsize, memfreq; | |
534 | struct list_head *pos, *tmp; | |
535 | const char *invalid = "INVALID SKU"; | |
536 | ||
537 | /* Use the LSB as index to the array of pointers to the SKU table*/ | |
538 | device_id = device_id & 0xf; | |
539 | ||
540 | if (device_id > MAX_DEV_IDS) { | |
541 | strncpy(mic_ctx->sku_name, invalid, SKU_NAME_LEN - 1); | |
542 | mic_ctx->sku_name[SKU_NAME_LEN - 1] = '\0'; | |
543 | return -EINVAL; | |
544 | } | |
545 | ||
546 | INIT_LIST_HEAD(&skulist_memsize_in); | |
547 | INIT_LIST_HEAD(&skulist_memfreq_in); | |
548 | INIT_LIST_HEAD(&skulist_out); | |
549 | ||
550 | /* Search by fuse_config_rev */ | |
551 | fuse_rev = SBOX_READ(mic_ctx->mmio.va, SBOX_SCRATCH7); | |
552 | fuse_rev = (fuse_rev >> SHIFT_FUSE_CONFIG_REV) & MASK_FUSE_CONFIG_REV; | |
553 | ||
554 | list_for_each_safe(pos, tmp, &mic_data.sku_table[device_id]) { | |
555 | match = list_entry(pos, sku_info_t, sku); | |
556 | if ((match->fuserev_low <= fuse_rev) && (match->fuserev_high >= fuse_rev)) { | |
557 | cnt++; | |
558 | ret = sku_create_node(match->fuserev_low, match->fuserev_high, | |
559 | match->memsize, match->memfreq, match->sku_name, &newnode); | |
560 | if (ret) { | |
561 | strncpy(mic_ctx->sku_name, invalid, SKU_NAME_LEN - 1); | |
562 | mic_ctx->sku_name[SKU_NAME_LEN - 1] = '\0'; | |
563 | goto cleanup; | |
564 | } | |
565 | list_add_tail(&newnode->sku, &skulist_out); | |
566 | } | |
567 | } | |
568 | /* If only one node is present, the match has been found */ | |
569 | if (cnt == 1) { | |
570 | strncpy(mic_ctx->sku_name, newnode->sku_name, SKU_NAME_LEN - 1); | |
571 | mic_ctx->sku_name[SKU_NAME_LEN - 1] = '\0'; | |
572 | goto cleanup; | |
573 | } | |
574 | ||
575 | sku_swap_list(&skulist_out, &skulist_memsize_in); | |
576 | /* Search by memsize */ | |
577 | memsize = SBOX_READ(mic_ctx->mmio.va, SBOX_SCRATCH0); | |
578 | memsize = (memsize >> SHIFT_MEMSIZE) & MASK_MEMSIZE; | |
579 | memsize = memsize >> 20; | |
580 | if (memsize > SKU_MEM_DIVIDE) | |
581 | memsize = SKU_HIGH_MEM; | |
582 | else | |
583 | memsize = SKU_LOW_MEM; | |
584 | ||
585 | cnt = 0; | |
586 | list_for_each_safe(pos, tmp, &skulist_memsize_in) { | |
587 | match = list_entry(pos, sku_info_t, sku); | |
588 | /* Use the MSB for comparison */ | |
589 | /* Assumption - From the latest documentation, a particular | |
590 | * combination of device id and fuse_rev can either have memory | |
591 | * <=4GB (SKU_LOW_MEM) or > 4GB (SKU_HIGH_MEM) | |
592 | */ | |
593 | if (memsize == match->memsize) { | |
594 | cnt++; | |
595 | ret = sku_create_node(match->fuserev_low, match->fuserev_high, | |
596 | match->memsize, match->memfreq, match->sku_name, &newnode); | |
597 | if (ret) { | |
598 | strncpy(mic_ctx->sku_name, invalid, SKU_NAME_LEN - 1); | |
599 | mic_ctx->sku_name[SKU_NAME_LEN - 1] = '\0'; | |
600 | goto cleanup; | |
601 | } | |
602 | list_add_tail(&newnode->sku, &skulist_out); | |
603 | } | |
604 | ||
605 | } | |
606 | list_for_each_safe(pos, tmp, &skulist_memsize_in) { | |
607 | skunode = list_entry(pos, sku_info_t, sku); | |
608 | list_del(pos); | |
609 | kfree(skunode); | |
610 | } | |
611 | if (cnt == 1) { | |
612 | strncpy(mic_ctx->sku_name, newnode->sku_name, SKU_NAME_LEN - 1); | |
613 | mic_ctx->sku_name[SKU_NAME_LEN - 1] = '\0'; | |
614 | goto cleanup; | |
615 | } | |
616 | ||
617 | sku_swap_list(&skulist_out, &skulist_memfreq_in); | |
618 | /* Search by memfreq */ | |
619 | memfreq = SBOX_READ(mic_ctx->mmio.va, SBOX_SCRATCH9); | |
620 | memfreq = (memfreq >> SHIFT_MEMFREQ) & MASK_MEMFREQ; | |
621 | ||
622 | cnt = 0; | |
623 | list_for_each_safe(pos, tmp, &skulist_memfreq_in) { | |
624 | match = list_entry(pos, sku_info_t, sku); | |
625 | if (memfreq == match->memfreq) { | |
626 | cnt++; | |
627 | ret = sku_create_node(match->fuserev_low, match->fuserev_high, | |
628 | match->memsize, match->memfreq, match->sku_name, &newnode); | |
629 | if (ret) { | |
630 | strncpy(mic_ctx->sku_name, invalid, SKU_NAME_LEN - 1); | |
631 | mic_ctx->sku_name[SKU_NAME_LEN - 1] = '\0'; | |
632 | goto cleanup; | |
633 | } | |
634 | list_add_tail(&newnode->sku, &skulist_out); | |
635 | } | |
636 | ||
637 | } | |
638 | list_for_each_safe(pos, tmp, &skulist_memfreq_in) { | |
639 | skunode = list_entry(pos, sku_info_t, sku); | |
640 | list_del(pos); | |
641 | kfree(skunode); | |
642 | } | |
643 | if (cnt == 1) { | |
644 | strncpy(mic_ctx->sku_name, newnode->sku_name, SKU_NAME_LEN - 1); | |
645 | mic_ctx->sku_name[SKU_NAME_LEN - 1] = '\0'; | |
646 | } else { | |
647 | strncpy(mic_ctx->sku_name, invalid, SKU_NAME_LEN - 1); | |
648 | mic_ctx->sku_name[SKU_NAME_LEN - 1] = '\0'; | |
649 | } | |
650 | ||
651 | ||
652 | cleanup: | |
653 | list_for_each_safe(pos, tmp, &skulist_out) { | |
654 | skunode = list_entry(pos, sku_info_t, sku); | |
655 | list_del(pos); | |
656 | kfree(skunode); | |
657 | } | |
658 | ||
659 | return ret; | |
660 | } | |
661 | ||
662 | ||
663 | int | |
664 | sku_build_table(void) | |
665 | { | |
666 | int i = 0; | |
667 | sku_info_t *newnode = NULL; | |
668 | ||
669 | for ( i = 0; i < MAX_DEV_IDS; i++) | |
670 | INIT_LIST_HEAD(&mic_data.sku_table[i]); | |
671 | ||
672 | /*2250*/ | |
673 | if (sku_create_node(0, 1, SKU_LOW_MEM, FREQ_2P4, "A0PO-SKU1", &newnode)) | |
674 | return -ENOMEM; | |
675 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
676 | ||
677 | if (sku_create_node(0, 1, SKU_HIGH_MEM, FREQ_2P4, "A0PO-SKU1", &newnode)) | |
678 | return -ENOMEM; | |
679 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
680 | ||
681 | if (sku_create_node(2, 3, SKU_LOW_MEM, FREQ_4P5,"ES1-SKU2", &newnode)) | |
682 | return -ENOMEM; | |
683 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
684 | ||
685 | if (sku_create_node(2, 3, SKU_HIGH_MEM, FREQ_4P5, "ES1-SKU2", &newnode)) | |
686 | return -ENOMEM; | |
687 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
688 | ||
689 | if (sku_create_node(4, 49, SKU_HIGH_MEM, FREQ_4P5, "ES1B-SKU2", &newnode)) | |
690 | return -ENOMEM; | |
691 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
692 | ||
693 | if (sku_create_node(50, 100, SKU_HIGH_MEM, FREQ_4P5, "B0PO-SKU2", &newnode)) | |
694 | return -ENOMEM; | |
695 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
696 | ||
697 | if (sku_create_node(101, 150, SKU_HIGH_MEM, FREQ_5P0, "ES2-P1640", &newnode)) | |
698 | return -ENOMEM; | |
699 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
700 | ||
701 | if (sku_create_node(153, 154, SKU_HIGH_MEM, FREQ_5P0, "B1PO-5110P", &newnode)) | |
702 | return -ENOMEM; | |
703 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
704 | ||
705 | if (sku_create_node(151, 152, SKU_HIGH_MEM, FREQ_5P0, "B1PO-P1640/D1650", &newnode)) | |
706 | return -ENOMEM; | |
707 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
708 | ||
709 | if (sku_create_node(156, 156, SKU_HIGH_MEM, FREQ_5P0, "B1PRQ-5110P", &newnode)) | |
710 | return -ENOMEM; | |
711 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
712 | ||
713 | if (sku_create_node(155, 155, SKU_HIGH_MEM, FREQ_5P0, "B1QS-5110P", &newnode)) | |
714 | return -ENOMEM; | |
715 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
716 | ||
717 | if (sku_create_node(157, 157, SKU_HIGH_MEM, FREQ_5P0, "B1PRQ-5110P", &newnode)) | |
718 | return -ENOMEM; | |
719 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
720 | ||
721 | if (sku_create_node(158, 250, SKU_HIGH_MEM, FREQ_5P0, "B1PRQ-5110P/5120D", &newnode)) | |
722 | return -ENOMEM; | |
723 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
724 | ||
725 | if (sku_create_node(251, 253, SKU_HIGH_MEM, FREQ_5P0, "C0-5110P", &newnode)) | |
726 | return -ENOMEM; | |
727 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
728 | ||
729 | if (sku_create_node(254, 255, SKU_HIGH_MEM, FREQ_5P0, "C0QS-5110P", &newnode)) | |
730 | return -ENOMEM; | |
731 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
732 | ||
733 | if (sku_create_node(251, 253, SKU_HIGH_MEM, FREQ_5P5, "C0-5120D", &newnode)) | |
734 | return -ENOMEM; | |
735 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
736 | ||
737 | if (sku_create_node(254, 255, SKU_HIGH_MEM, FREQ_5P5, "C0QS-5120D", &newnode)) | |
738 | return -ENOMEM; | |
739 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
740 | ||
741 | if (sku_create_node(256, 350, SKU_HIGH_MEM, FREQ_5P0, "C0PRQ-5110P/5140P", &newnode)) | |
742 | return -ENOMEM; | |
743 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
744 | ||
745 | if (sku_create_node(256, 350, SKU_HIGH_MEM, FREQ_5P5, "C0PRQ-5120D/5140D", &newnode)) | |
746 | return -ENOMEM; | |
747 | list_add_tail(&newnode->sku, &mic_data.sku_table[0]); | |
748 | ||
749 | /*2251*/ | |
750 | if (sku_create_node(0, 1, SKU_LOW_MEM, FREQ_2P4, "A0PO-SKU2", &newnode)) | |
751 | return -ENOMEM; | |
752 | list_add_tail(&newnode->sku, &mic_data.sku_table[1]); | |
753 | ||
754 | if (sku_create_node(0, 1, SKU_HIGH_MEM, FREQ_2P4, "A0PO-SKU2", &newnode)) | |
755 | return -ENOMEM; | |
756 | list_add_tail(&newnode->sku, &mic_data.sku_table[1]); | |
757 | ||
758 | /*2252*/ | |
759 | if (sku_create_node(0, 1, SKU_LOW_MEM, FREQ_2P4, "A0PO-SKU3", &newnode)) | |
760 | return -ENOMEM; | |
761 | list_add_tail(&newnode->sku, &mic_data.sku_table[2]); | |
762 | ||
763 | /*2253*/ | |
764 | if (sku_create_node(0, 1, SKU_LOW_MEM, FREQ_2P4, "A0PO-SKU4", &newnode)) | |
765 | return -ENOMEM; | |
766 | list_add_tail(&newnode->sku, &mic_data.sku_table[3]); | |
767 | ||
768 | if (sku_create_node(2, 3, SKU_LOW_MEM, FREQ_2P4, "ES1-SKU5", &newnode)) | |
769 | return -ENOMEM; | |
770 | list_add_tail(&newnode->sku, &mic_data.sku_table[3]); | |
771 | ||
772 | if (sku_create_node(4, 49, SKU_LOW_MEM, FREQ_2P4, "ES1B-SKU5", &newnode)) | |
773 | return -ENOMEM; | |
774 | list_add_tail(&newnode->sku, &mic_data.sku_table[3]); | |
775 | ||
776 | if (sku_create_node(50, 100, SKU_LOW_MEM, FREQ_4P5, "B0PO-SKU5", &newnode)) | |
777 | return -ENOMEM; | |
778 | list_add_tail(&newnode->sku, &mic_data.sku_table[3]); | |
779 | ||
780 | /*2254*/ | |
781 | ||
782 | /*2255*/ | |
783 | if (sku_create_node(0, 1, SKU_LOW_MEM, FREQ_2P4, "A0PO-SKUX", &newnode)) | |
784 | return -ENOMEM; | |
785 | list_add_tail(&newnode->sku, &mic_data.sku_table[5]); | |
786 | ||
787 | /*2256*/ | |
788 | if (sku_create_node(0, 1, SKU_LOW_MEM, FREQ_2P4, "A0PO-SKU5", &newnode)) | |
789 | return -ENOMEM; | |
790 | list_add_tail(&newnode->sku, &mic_data.sku_table[6]); | |
791 | ||
792 | /*2257*/ | |
793 | if (sku_create_node(0, 1, SKU_LOW_MEM, FREQ_2P4, "A0PO-SKUZ", &newnode)) | |
794 | return -ENOMEM; | |
795 | list_add_tail(&newnode->sku, &mic_data.sku_table[7]); | |
796 | ||
797 | /*2258*/ | |
798 | if (sku_create_node(2, 3, SKU_LOW_MEM, FREQ_4P5, "ES1-SKU1", &newnode)) | |
799 | return -ENOMEM; | |
800 | list_add_tail(&newnode->sku, &mic_data.sku_table[8]); | |
801 | if (sku_create_node(2, 3, SKU_HIGH_MEM, FREQ_4P5, "ES1-SKU1", &newnode)) | |
802 | return -ENOMEM; | |
803 | list_add_tail(&newnode->sku, &mic_data.sku_table[8]); | |
804 | if (sku_create_node(4, 49, SKU_HIGH_MEM, FREQ_5P5, "ES1B-SKU1", &newnode)) | |
805 | return -ENOMEM; | |
806 | list_add_tail(&newnode->sku, &mic_data.sku_table[8]); | |
807 | if (sku_create_node(50, 100, SKU_HIGH_MEM, FREQ_5P5, "B0PO-SKU1", &newnode)) | |
808 | return -ENOMEM; | |
809 | list_add_tail(&newnode->sku, &mic_data.sku_table[8]); | |
810 | ||
811 | /*2259*/ | |
812 | if (sku_create_node(2, 3, SKU_LOW_MEM, FREQ_4P5, "ES1-SKU3", &newnode)) | |
813 | return -ENOMEM; | |
814 | list_add_tail(&newnode->sku, &mic_data.sku_table[9]); | |
815 | ||
816 | if (sku_create_node(2, 3, SKU_HIGH_MEM, FREQ_4P5, "ES1-SKU3", &newnode)) | |
817 | return -ENOMEM; | |
818 | list_add_tail(&newnode->sku, &mic_data.sku_table[9]); | |
819 | ||
820 | /*225A*/ | |
821 | if (sku_create_node(2, 3, SKU_LOW_MEM, FREQ_4P5, "ES1-SKU4", &newnode)) | |
822 | return -ENOMEM; | |
823 | list_add_tail(&newnode->sku, &mic_data.sku_table[10]); | |
824 | ||
825 | if (sku_create_node(4, 49, SKU_LOW_MEM, FREQ_5P0, "ES1B-SKU4", &newnode)) | |
826 | return -ENOMEM; | |
827 | list_add_tail(&newnode->sku, &mic_data.sku_table[10]); | |
828 | ||
829 | if (sku_create_node(50, 100, SKU_LOW_MEM, FREQ_5P0, "B0PO-SKU4", &newnode)) | |
830 | return -ENOMEM; | |
831 | list_add_tail(&newnode->sku, &mic_data.sku_table[10]); | |
832 | ||
833 | if (sku_create_node(101, 150, SKU_LOW_MEM, FREQ_5P0, "ES2-SKU4", &newnode)) | |
834 | return -ENOMEM; | |
835 | list_add_tail(&newnode->sku, &mic_data.sku_table[10]); | |
836 | ||
837 | /*225B*/ | |
838 | if (sku_create_node(4, 49, SKU_HIGH_MEM, FREQ_5P5, "ES1B-SKU3cs", &newnode)) | |
839 | return -ENOMEM; | |
840 | list_add_tail(&newnode->sku, &mic_data.sku_table[11]); | |
841 | ||
842 | if (sku_create_node(4, 49, SKU_LOW_MEM, FREQ_5P5, "ES1B-SKU3ncs", &newnode)) | |
843 | return -ENOMEM; | |
844 | list_add_tail(&newnode->sku, &mic_data.sku_table[11]); | |
845 | ||
846 | if (sku_create_node(50, 100, SKU_HIGH_MEM, FREQ_5P5, "B0PO-SKU3cs", &newnode)) | |
847 | return -ENOMEM; | |
848 | list_add_tail(&newnode->sku, &mic_data.sku_table[11]); | |
849 | ||
850 | if (sku_create_node(50, 100, SKU_LOW_MEM, FREQ_5P5, "B0PO-SKU3ncs", &newnode)) | |
851 | return -ENOMEM; | |
852 | list_add_tail(&newnode->sku, &mic_data.sku_table[11]); | |
853 | ||
854 | /*225C*/ | |
855 | if (sku_create_node(101, 150, SKU_HIGH_MEM, FREQ_5P5, "ES2-P/A/X 1750", &newnode)) | |
856 | return -ENOMEM; | |
857 | list_add_tail(&newnode->sku, &mic_data.sku_table[12]); | |
858 | ||
859 | if (sku_create_node(153, 154, SKU_HIGH_MEM, FREQ_5P5, "B1PO-7110 P/A/X", &newnode)) | |
860 | return -ENOMEM; | |
861 | list_add_tail(&newnode->sku, &mic_data.sku_table[12]); | |
862 | ||
863 | if (sku_create_node(155, 155, SKU_HIGH_MEM, FREQ_5P5, "B1QS-7110 P/A/X", &newnode)) | |
864 | return -ENOMEM; | |
865 | list_add_tail(&newnode->sku, &mic_data.sku_table[12]); | |
866 | ||
867 | if (sku_create_node(151, 152, SKU_HIGH_MEM, FREQ_5P0, "B1PO-P/A 1750", &newnode)) | |
868 | return -ENOMEM; | |
869 | list_add_tail(&newnode->sku, &mic_data.sku_table[12]); | |
870 | ||
871 | if (sku_create_node(156, 156, SKU_HIGH_MEM, FREQ_5P5, "B1PRQ-7110 P/A/X", &newnode)) | |
872 | return -ENOMEM; | |
873 | list_add_tail(&newnode->sku, &mic_data.sku_table[12]); | |
874 | ||
875 | if (sku_create_node(157, 157, SKU_HIGH_MEM, FREQ_5P5, "B1PRQ-7110 P/A/X", &newnode)) | |
876 | return -ENOMEM; | |
877 | list_add_tail(&newnode->sku, &mic_data.sku_table[12]); | |
878 | ||
879 | if (sku_create_node(158, 202, SKU_HIGH_MEM, FREQ_5P5, "B1PRQ-7110 P/X", &newnode)) | |
880 | return -ENOMEM; | |
881 | list_add_tail(&newnode->sku, &mic_data.sku_table[12]); | |
882 | ||
883 | if (sku_create_node(203, 250, SKU_HIGH_MEM, FREQ_5P5, "B1PRQ-SE10 P/X", &newnode)) | |
884 | return -ENOMEM; | |
885 | list_add_tail(&newnode->sku, &mic_data.sku_table[12]); | |
886 | ||
887 | if (sku_create_node(251, 253, SKU_HIGH_MEM, FREQ_5P5, "C0-7120 P/A/X/D", &newnode)) | |
888 | return -ENOMEM; | |
889 | list_add_tail(&newnode->sku, &mic_data.sku_table[12]); | |
890 | ||
891 | if (sku_create_node(254, 255, SKU_HIGH_MEM, FREQ_5P5, "C0QS-7120 P/A/X/D", &newnode)) | |
892 | return -ENOMEM; | |
893 | list_add_tail(&newnode->sku, &mic_data.sku_table[12]); | |
894 | ||
895 | if (sku_create_node(256, 350, SKU_HIGH_MEM, FREQ_5P5, "C0PRQ-7120 P/A/X/D", &newnode)) | |
896 | return -ENOMEM; | |
897 | list_add_tail(&newnode->sku, &mic_data.sku_table[12]); | |
898 | ||
899 | /*225D*/ | |
900 | if (sku_create_node(101, 150, SKU_LOW_MEM, FREQ_5P0, "ES2-P1310", &newnode)) | |
901 | return -ENOMEM; | |
902 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
903 | ||
904 | if (sku_create_node(101, 150, SKU_HIGH_MEM, FREQ_5P0, "ES2-A1330", &newnode)) | |
905 | return -ENOMEM; | |
906 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
907 | ||
908 | if (sku_create_node(153, 154, SKU_LOW_MEM, FREQ_5P0, "B1PO-3110P", &newnode)) | |
909 | return -ENOMEM; | |
910 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
911 | ||
912 | if (sku_create_node(153, 154, SKU_HIGH_MEM, FREQ_5P0, "B1PO-3115A", &newnode)) | |
913 | return -ENOMEM; | |
914 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
915 | ||
916 | if (sku_create_node(157, 157, SKU_LOW_MEM, FREQ_5P0, "B1PRQ-3110P", &newnode)) | |
917 | return -ENOMEM; | |
918 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
919 | ||
920 | if (sku_create_node(157, 157, SKU_HIGH_MEM, FREQ_5P0, "B1PRQ-3115A", &newnode)) | |
921 | return -ENOMEM; | |
922 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
923 | ||
924 | if (sku_create_node(156, 156, SKU_LOW_MEM, FREQ_5P0, "B1PRQ-3110P", &newnode)) | |
925 | return -ENOMEM; | |
926 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
927 | ||
928 | if (sku_create_node(156, 156, SKU_HIGH_MEM, FREQ_5P0, "B1PRQ-3115A", &newnode)) | |
929 | return -ENOMEM; | |
930 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
931 | ||
932 | if (sku_create_node(155, 155, SKU_HIGH_MEM, FREQ_5P0, "B1QS-3115A", &newnode)) | |
933 | return -ENOMEM; | |
934 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
935 | ||
936 | if (sku_create_node(155, 155, SKU_LOW_MEM, FREQ_5P0, "B1QS-3110P", &newnode)) | |
937 | return -ENOMEM; | |
938 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
939 | ||
940 | if (sku_create_node(158, 250, SKU_HIGH_MEM, FREQ_5P0, "B1PRQ-3120P", &newnode)) | |
941 | return -ENOMEM; | |
942 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
943 | ||
944 | if (sku_create_node(251, 253, SKU_HIGH_MEM, FREQ_5P0, "C0-3120 P/A", &newnode)) | |
945 | return -ENOMEM; | |
946 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
947 | ||
948 | if (sku_create_node(254, 255, SKU_HIGH_MEM, FREQ_5P0, "C0QS-3120 P/A", &newnode)) | |
949 | return -ENOMEM; | |
950 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
951 | ||
952 | if (sku_create_node(256, 350, SKU_HIGH_MEM, FREQ_5P0, "C0PRQ-3120/3140 P/A", &newnode)) | |
953 | return -ENOMEM; | |
954 | list_add_tail(&newnode->sku, &mic_data.sku_table[13]); | |
955 | ||
956 | /*225E*/ | |
957 | if (sku_create_node(157, 157, SKU_HIGH_MEM, FREQ_5P0, "B1PRQ-31S1P", &newnode)) | |
958 | return -ENOMEM; | |
959 | list_add_tail(&newnode->sku, &mic_data.sku_table[14]); | |
960 | ||
961 | if (sku_create_node(158, 250, SKU_HIGH_MEM, FREQ_5P0, "B1PRQ-31S1P", &newnode)) | |
962 | return -ENOMEM; | |
963 | list_add_tail(&newnode->sku, &mic_data.sku_table[14]); | |
964 | ||
965 | if (sku_create_node(251, 253, SKU_HIGH_MEM, FREQ_5P0, "C0-31S1P", &newnode)) | |
966 | return -ENOMEM; | |
967 | list_add_tail(&newnode->sku, &mic_data.sku_table[14]); | |
968 | ||
969 | if (sku_create_node(254, 255, SKU_HIGH_MEM, FREQ_5P0, "C0QS-31S1P", &newnode)) | |
970 | return -ENOMEM; | |
971 | list_add_tail(&newnode->sku, &mic_data.sku_table[14]); | |
972 | ||
973 | if (sku_create_node(256, 350, SKU_HIGH_MEM, FREQ_5P0, "C0PRQ-31S1P", &newnode)) | |
974 | return -ENOMEM; | |
975 | list_add_tail(&newnode->sku, &mic_data.sku_table[14]); | |
976 | ||
977 | return 0; // Successed | |
978 | } |