diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_init.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 267 |
1 files changed, 265 insertions, 2 deletions
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 00d0524fef13..f7bb8c90537c 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c | |||
@@ -277,6 +277,7 @@ unsigned long netxen_decode_crb_addr(unsigned long addr) | |||
277 | 277 | ||
278 | static long rom_max_timeout = 10000; | 278 | static long rom_max_timeout = 10000; |
279 | static long rom_lock_timeout = 1000000; | 279 | static long rom_lock_timeout = 1000000; |
280 | static long rom_write_timeout = 700; | ||
280 | 281 | ||
281 | static inline int rom_lock(struct netxen_adapter *adapter) | 282 | static inline int rom_lock(struct netxen_adapter *adapter) |
282 | { | 283 | { |
@@ -405,7 +406,7 @@ do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) | |||
405 | { | 406 | { |
406 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); | 407 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); |
407 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); | 408 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); |
408 | udelay(100); /* prevent bursting on CRB */ | 409 | udelay(70); /* prevent bursting on CRB */ |
409 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); | 410 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); |
410 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); | 411 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); |
411 | if (netxen_wait_rom_done(adapter)) { | 412 | if (netxen_wait_rom_done(adapter)) { |
@@ -414,13 +415,46 @@ do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) | |||
414 | } | 415 | } |
415 | /* reset abyte_cnt and dummy_byte_cnt */ | 416 | /* reset abyte_cnt and dummy_byte_cnt */ |
416 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); | 417 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); |
417 | udelay(100); /* prevent bursting on CRB */ | 418 | udelay(70); /* prevent bursting on CRB */ |
418 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); | 419 | netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); |
419 | 420 | ||
420 | *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA); | 421 | *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA); |
421 | return 0; | 422 | return 0; |
422 | } | 423 | } |
423 | 424 | ||
425 | static inline int | ||
426 | do_rom_fast_read_words(struct netxen_adapter *adapter, int addr, | ||
427 | u8 *bytes, size_t size) | ||
428 | { | ||
429 | int addridx; | ||
430 | int ret = 0; | ||
431 | |||
432 | for (addridx = addr; addridx < (addr + size); addridx += 4) { | ||
433 | ret = do_rom_fast_read(adapter, addridx, (int *)bytes); | ||
434 | if (ret != 0) | ||
435 | break; | ||
436 | bytes += 4; | ||
437 | } | ||
438 | |||
439 | return ret; | ||
440 | } | ||
441 | |||
442 | int | ||
443 | netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr, | ||
444 | u8 *bytes, size_t size) | ||
445 | { | ||
446 | int ret; | ||
447 | |||
448 | ret = rom_lock(adapter); | ||
449 | if (ret < 0) | ||
450 | return ret; | ||
451 | |||
452 | ret = do_rom_fast_read_words(adapter, addr, bytes, size); | ||
453 | |||
454 | netxen_rom_unlock(adapter); | ||
455 | return ret; | ||
456 | } | ||
457 | |||
424 | int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) | 458 | int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) |
425 | { | 459 | { |
426 | int ret; | 460 | int ret; |
@@ -444,6 +478,152 @@ int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data) | |||
444 | netxen_rom_unlock(adapter); | 478 | netxen_rom_unlock(adapter); |
445 | return ret; | 479 | return ret; |
446 | } | 480 | } |
481 | |||
482 | static inline int do_rom_fast_write_words(struct netxen_adapter *adapter, | ||
483 | int addr, u8 *bytes, size_t size) | ||
484 | { | ||
485 | int addridx = addr; | ||
486 | int ret = 0; | ||
487 | |||
488 | while (addridx < (addr + size)) { | ||
489 | int last_attempt = 0; | ||
490 | int timeout = 0; | ||
491 | int data; | ||
492 | |||
493 | data = *(u32*)bytes; | ||
494 | |||
495 | ret = do_rom_fast_write(adapter, addridx, data); | ||
496 | if (ret < 0) | ||
497 | return ret; | ||
498 | |||
499 | while(1) { | ||
500 | int data1; | ||
501 | |||
502 | do_rom_fast_read(adapter, addridx, &data1); | ||
503 | if (data1 == data) | ||
504 | break; | ||
505 | |||
506 | if (timeout++ >= rom_write_timeout) { | ||
507 | if (last_attempt++ < 4) { | ||
508 | ret = do_rom_fast_write(adapter, | ||
509 | addridx, data); | ||
510 | if (ret < 0) | ||
511 | return ret; | ||
512 | } | ||
513 | else { | ||
514 | printk(KERN_INFO "Data write did not " | ||
515 | "succeed at address 0x%x\n", addridx); | ||
516 | break; | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | |||
521 | bytes += 4; | ||
522 | addridx += 4; | ||
523 | } | ||
524 | |||
525 | return ret; | ||
526 | } | ||
527 | |||
528 | int netxen_rom_fast_write_words(struct netxen_adapter *adapter, int addr, | ||
529 | u8 *bytes, size_t size) | ||
530 | { | ||
531 | int ret = 0; | ||
532 | |||
533 | ret = rom_lock(adapter); | ||
534 | if (ret < 0) | ||
535 | return ret; | ||
536 | |||
537 | ret = do_rom_fast_write_words(adapter, addr, bytes, size); | ||
538 | netxen_rom_unlock(adapter); | ||
539 | |||
540 | return ret; | ||
541 | } | ||
542 | |||
543 | int netxen_rom_wrsr(struct netxen_adapter *adapter, int data) | ||
544 | { | ||
545 | int ret; | ||
546 | |||
547 | ret = netxen_rom_wren(adapter); | ||
548 | if (ret < 0) | ||
549 | return ret; | ||
550 | |||
551 | netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_ROM_WDATA, data); | ||
552 | netxen_crb_writelit_adapter(adapter, | ||
553 | NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0x1); | ||
554 | |||
555 | ret = netxen_wait_rom_done(adapter); | ||
556 | if (ret < 0) | ||
557 | return ret; | ||
558 | |||
559 | return netxen_rom_wip_poll(adapter); | ||
560 | } | ||
561 | |||
562 | int netxen_rom_rdsr(struct netxen_adapter *adapter) | ||
563 | { | ||
564 | int ret; | ||
565 | |||
566 | ret = rom_lock(adapter); | ||
567 | if (ret < 0) | ||
568 | return ret; | ||
569 | |||
570 | ret = netxen_do_rom_rdsr(adapter); | ||
571 | netxen_rom_unlock(adapter); | ||
572 | return ret; | ||
573 | } | ||
574 | |||
575 | int netxen_backup_crbinit(struct netxen_adapter *adapter) | ||
576 | { | ||
577 | int ret = FLASH_SUCCESS; | ||
578 | int val; | ||
579 | char *buffer = kmalloc(FLASH_SECTOR_SIZE, GFP_KERNEL); | ||
580 | |||
581 | if (!buffer) | ||
582 | return -ENOMEM; | ||
583 | /* unlock sector 63 */ | ||
584 | val = netxen_rom_rdsr(adapter); | ||
585 | val = val & 0xe3; | ||
586 | ret = netxen_rom_wrsr(adapter, val); | ||
587 | if (ret != FLASH_SUCCESS) | ||
588 | goto out_kfree; | ||
589 | |||
590 | ret = netxen_rom_wip_poll(adapter); | ||
591 | if (ret != FLASH_SUCCESS) | ||
592 | goto out_kfree; | ||
593 | |||
594 | /* copy sector 0 to sector 63 */ | ||
595 | ret = netxen_rom_fast_read_words(adapter, CRBINIT_START, | ||
596 | buffer, FLASH_SECTOR_SIZE); | ||
597 | if (ret != FLASH_SUCCESS) | ||
598 | goto out_kfree; | ||
599 | |||
600 | ret = netxen_rom_fast_write_words(adapter, FIXED_START, | ||
601 | buffer, FLASH_SECTOR_SIZE); | ||
602 | if (ret != FLASH_SUCCESS) | ||
603 | goto out_kfree; | ||
604 | |||
605 | /* lock sector 63 */ | ||
606 | val = netxen_rom_rdsr(adapter); | ||
607 | if (!(val & 0x8)) { | ||
608 | val |= (0x1 << 2); | ||
609 | /* lock sector 63 */ | ||
610 | if (netxen_rom_wrsr(adapter, val) == 0) { | ||
611 | ret = netxen_rom_wip_poll(adapter); | ||
612 | if (ret != FLASH_SUCCESS) | ||
613 | goto out_kfree; | ||
614 | |||
615 | /* lock SR writes */ | ||
616 | ret = netxen_rom_wip_poll(adapter); | ||
617 | if (ret != FLASH_SUCCESS) | ||
618 | goto out_kfree; | ||
619 | } | ||
620 | } | ||
621 | |||
622 | out_kfree: | ||
623 | kfree(buffer); | ||
624 | return ret; | ||
625 | } | ||
626 | |||
447 | int netxen_do_rom_se(struct netxen_adapter *adapter, int addr) | 627 | int netxen_do_rom_se(struct netxen_adapter *adapter, int addr) |
448 | { | 628 | { |
449 | netxen_rom_wren(adapter); | 629 | netxen_rom_wren(adapter); |
@@ -458,6 +638,27 @@ int netxen_do_rom_se(struct netxen_adapter *adapter, int addr) | |||
458 | return netxen_rom_wip_poll(adapter); | 638 | return netxen_rom_wip_poll(adapter); |
459 | } | 639 | } |
460 | 640 | ||
641 | void check_erased_flash(struct netxen_adapter *adapter, int addr) | ||
642 | { | ||
643 | int i; | ||
644 | int val; | ||
645 | int count = 0, erased_errors = 0; | ||
646 | int range; | ||
647 | |||
648 | range = (addr == USER_START) ? FIXED_START : addr + FLASH_SECTOR_SIZE; | ||
649 | |||
650 | for (i = addr; i < range; i += 4) { | ||
651 | netxen_rom_fast_read(adapter, i, &val); | ||
652 | if (val != 0xffffffff) | ||
653 | erased_errors++; | ||
654 | count++; | ||
655 | } | ||
656 | |||
657 | if (erased_errors) | ||
658 | printk(KERN_INFO "0x%x out of 0x%x words fail to be erased " | ||
659 | "for sector address: %x\n", erased_errors, count, addr); | ||
660 | } | ||
661 | |||
461 | int netxen_rom_se(struct netxen_adapter *adapter, int addr) | 662 | int netxen_rom_se(struct netxen_adapter *adapter, int addr) |
462 | { | 663 | { |
463 | int ret = 0; | 664 | int ret = 0; |
@@ -466,6 +667,68 @@ int netxen_rom_se(struct netxen_adapter *adapter, int addr) | |||
466 | } | 667 | } |
467 | ret = netxen_do_rom_se(adapter, addr); | 668 | ret = netxen_do_rom_se(adapter, addr); |
468 | netxen_rom_unlock(adapter); | 669 | netxen_rom_unlock(adapter); |
670 | msleep(30); | ||
671 | check_erased_flash(adapter, addr); | ||
672 | |||
673 | return ret; | ||
674 | } | ||
675 | |||
676 | int | ||
677 | netxen_flash_erase_sections(struct netxen_adapter *adapter, int start, int end) | ||
678 | { | ||
679 | int ret = FLASH_SUCCESS; | ||
680 | int i; | ||
681 | |||
682 | for (i = start; i < end; i++) { | ||
683 | ret = netxen_rom_se(adapter, i * FLASH_SECTOR_SIZE); | ||
684 | if (ret) | ||
685 | break; | ||
686 | ret = netxen_rom_wip_poll(adapter); | ||
687 | if (ret < 0) | ||
688 | return ret; | ||
689 | } | ||
690 | |||
691 | return ret; | ||
692 | } | ||
693 | |||
694 | int | ||
695 | netxen_flash_erase_secondary(struct netxen_adapter *adapter) | ||
696 | { | ||
697 | int ret = FLASH_SUCCESS; | ||
698 | int start, end; | ||
699 | |||
700 | start = SECONDARY_START / FLASH_SECTOR_SIZE; | ||
701 | end = USER_START / FLASH_SECTOR_SIZE; | ||
702 | ret = netxen_flash_erase_sections(adapter, start, end); | ||
703 | |||
704 | return ret; | ||
705 | } | ||
706 | |||
707 | int | ||
708 | netxen_flash_erase_primary(struct netxen_adapter *adapter) | ||
709 | { | ||
710 | int ret = FLASH_SUCCESS; | ||
711 | int start, end; | ||
712 | |||
713 | start = PRIMARY_START / FLASH_SECTOR_SIZE; | ||
714 | end = SECONDARY_START / FLASH_SECTOR_SIZE; | ||
715 | ret = netxen_flash_erase_sections(adapter, start, end); | ||
716 | |||
717 | return ret; | ||
718 | } | ||
719 | |||
720 | int netxen_flash_unlock(struct netxen_adapter *adapter) | ||
721 | { | ||
722 | int ret = 0; | ||
723 | |||
724 | ret = netxen_rom_wrsr(adapter, 0); | ||
725 | if (ret < 0) | ||
726 | return ret; | ||
727 | |||
728 | ret = netxen_rom_wren(adapter); | ||
729 | if (ret < 0) | ||
730 | return ret; | ||
731 | |||
469 | return ret; | 732 | return ret; |
470 | } | 733 | } |
471 | 734 | ||