diff options
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_init.c')
-rw-r--r-- | drivers/net/qlcnic/qlcnic_init.c | 156 |
1 files changed, 146 insertions, 10 deletions
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index ea00ab4d4feb..7c34e4e29b3f 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c | |||
@@ -568,21 +568,123 @@ struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section) | |||
568 | return NULL; | 568 | return NULL; |
569 | } | 569 | } |
570 | 570 | ||
571 | #define FILEHEADER_SIZE (14 * 4) | ||
572 | |||
571 | static int | 573 | static int |
572 | qlcnic_set_product_offs(struct qlcnic_adapter *adapter) | 574 | qlcnic_validate_header(struct qlcnic_adapter *adapter) |
573 | { | 575 | { |
574 | struct uni_table_desc *ptab_descr; | ||
575 | const u8 *unirom = adapter->fw->data; | 576 | const u8 *unirom = adapter->fw->data; |
576 | u32 i; | 577 | struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0]; |
578 | __le32 fw_file_size = adapter->fw->size; | ||
577 | __le32 entries; | 579 | __le32 entries; |
580 | __le32 entry_size; | ||
581 | __le32 tab_size; | ||
582 | |||
583 | if (fw_file_size < FILEHEADER_SIZE) | ||
584 | return -EINVAL; | ||
585 | |||
586 | entries = cpu_to_le32(directory->num_entries); | ||
587 | entry_size = cpu_to_le32(directory->entry_size); | ||
588 | tab_size = cpu_to_le32(directory->findex) + (entries * entry_size); | ||
589 | |||
590 | if (fw_file_size < tab_size) | ||
591 | return -EINVAL; | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int | ||
597 | qlcnic_validate_bootld(struct qlcnic_adapter *adapter) | ||
598 | { | ||
599 | struct uni_table_desc *tab_desc; | ||
600 | struct uni_data_desc *descr; | ||
601 | const u8 *unirom = adapter->fw->data; | ||
602 | int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + | ||
603 | QLCNIC_UNI_BOOTLD_IDX_OFF)); | ||
604 | __le32 offs; | ||
605 | __le32 tab_size; | ||
606 | __le32 data_size; | ||
607 | |||
608 | tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD); | ||
609 | |||
610 | if (!tab_desc) | ||
611 | return -EINVAL; | ||
612 | |||
613 | tab_size = cpu_to_le32(tab_desc->findex) + | ||
614 | (cpu_to_le32(tab_desc->entry_size * (idx + 1))); | ||
615 | |||
616 | if (adapter->fw->size < tab_size) | ||
617 | return -EINVAL; | ||
618 | |||
619 | offs = cpu_to_le32(tab_desc->findex) + | ||
620 | (cpu_to_le32(tab_desc->entry_size) * (idx)); | ||
621 | descr = (struct uni_data_desc *)&unirom[offs]; | ||
622 | |||
623 | data_size = descr->findex + cpu_to_le32(descr->size); | ||
624 | |||
625 | if (adapter->fw->size < data_size) | ||
626 | return -EINVAL; | ||
627 | |||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static int | ||
632 | qlcnic_validate_fw(struct qlcnic_adapter *adapter) | ||
633 | { | ||
634 | struct uni_table_desc *tab_desc; | ||
635 | struct uni_data_desc *descr; | ||
636 | const u8 *unirom = adapter->fw->data; | ||
637 | int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + | ||
638 | QLCNIC_UNI_FIRMWARE_IDX_OFF)); | ||
639 | __le32 offs; | ||
640 | __le32 tab_size; | ||
641 | __le32 data_size; | ||
642 | |||
643 | tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW); | ||
644 | |||
645 | if (!tab_desc) | ||
646 | return -EINVAL; | ||
647 | |||
648 | tab_size = cpu_to_le32(tab_desc->findex) + | ||
649 | (cpu_to_le32(tab_desc->entry_size * (idx + 1))); | ||
650 | |||
651 | if (adapter->fw->size < tab_size) | ||
652 | return -EINVAL; | ||
653 | |||
654 | offs = cpu_to_le32(tab_desc->findex) + | ||
655 | (cpu_to_le32(tab_desc->entry_size) * (idx)); | ||
656 | descr = (struct uni_data_desc *)&unirom[offs]; | ||
657 | data_size = descr->findex + cpu_to_le32(descr->size); | ||
658 | |||
659 | if (adapter->fw->size < data_size) | ||
660 | return -EINVAL; | ||
661 | |||
662 | return 0; | ||
663 | } | ||
664 | |||
665 | static int | ||
666 | qlcnic_validate_product_offs(struct qlcnic_adapter *adapter) | ||
667 | { | ||
668 | struct uni_table_desc *ptab_descr; | ||
669 | const u8 *unirom = adapter->fw->data; | ||
578 | int mn_present = qlcnic_has_mn(adapter); | 670 | int mn_present = qlcnic_has_mn(adapter); |
671 | __le32 entries; | ||
672 | __le32 entry_size; | ||
673 | __le32 tab_size; | ||
674 | u32 i; | ||
579 | 675 | ||
580 | ptab_descr = qlcnic_get_table_desc(unirom, | 676 | ptab_descr = qlcnic_get_table_desc(unirom, |
581 | QLCNIC_UNI_DIR_SECT_PRODUCT_TBL); | 677 | QLCNIC_UNI_DIR_SECT_PRODUCT_TBL); |
582 | if (ptab_descr == NULL) | 678 | if (!ptab_descr) |
583 | return -1; | 679 | return -EINVAL; |
584 | 680 | ||
585 | entries = cpu_to_le32(ptab_descr->num_entries); | 681 | entries = cpu_to_le32(ptab_descr->num_entries); |
682 | entry_size = cpu_to_le32(ptab_descr->entry_size); | ||
683 | tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size); | ||
684 | |||
685 | if (adapter->fw->size < tab_size) | ||
686 | return -EINVAL; | ||
687 | |||
586 | nomn: | 688 | nomn: |
587 | for (i = 0; i < entries; i++) { | 689 | for (i = 0; i < entries; i++) { |
588 | 690 | ||
@@ -609,7 +711,37 @@ nomn: | |||
609 | mn_present = 0; | 711 | mn_present = 0; |
610 | goto nomn; | 712 | goto nomn; |
611 | } | 713 | } |
612 | return -1; | 714 | return -EINVAL; |
715 | } | ||
716 | |||
717 | static int | ||
718 | qlcnic_validate_unified_romimage(struct qlcnic_adapter *adapter) | ||
719 | { | ||
720 | if (qlcnic_validate_header(adapter)) { | ||
721 | dev_err(&adapter->pdev->dev, | ||
722 | "unified image: header validation failed\n"); | ||
723 | return -EINVAL; | ||
724 | } | ||
725 | |||
726 | if (qlcnic_validate_product_offs(adapter)) { | ||
727 | dev_err(&adapter->pdev->dev, | ||
728 | "unified image: product validation failed\n"); | ||
729 | return -EINVAL; | ||
730 | } | ||
731 | |||
732 | if (qlcnic_validate_bootld(adapter)) { | ||
733 | dev_err(&adapter->pdev->dev, | ||
734 | "unified image: bootld validation failed\n"); | ||
735 | return -EINVAL; | ||
736 | } | ||
737 | |||
738 | if (qlcnic_validate_fw(adapter)) { | ||
739 | dev_err(&adapter->pdev->dev, | ||
740 | "unified image: firmware validation failed\n"); | ||
741 | return -EINVAL; | ||
742 | } | ||
743 | |||
744 | return 0; | ||
613 | } | 745 | } |
614 | 746 | ||
615 | static | 747 | static |
@@ -715,7 +847,7 @@ qlcnic_get_bios_version(struct qlcnic_adapter *adapter) | |||
715 | bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off]) | 847 | bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off]) |
716 | + QLCNIC_UNI_BIOS_VERSION_OFF)); | 848 | + QLCNIC_UNI_BIOS_VERSION_OFF)); |
717 | 849 | ||
718 | return (bios_ver << 24) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24); | 850 | return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24); |
719 | } | 851 | } |
720 | 852 | ||
721 | int | 853 | int |
@@ -858,7 +990,7 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter) | |||
858 | u8 fw_type = adapter->fw_type; | 990 | u8 fw_type = adapter->fw_type; |
859 | 991 | ||
860 | if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) { | 992 | if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) { |
861 | if (qlcnic_set_product_offs(adapter)) | 993 | if (qlcnic_validate_unified_romimage(adapter)) |
862 | return -EINVAL; | 994 | return -EINVAL; |
863 | 995 | ||
864 | min_size = QLCNIC_UNI_FW_MIN_SIZE; | 996 | min_size = QLCNIC_UNI_FW_MIN_SIZE; |
@@ -1114,8 +1246,10 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, | |||
1114 | struct pci_dev *pdev = adapter->pdev; | 1246 | struct pci_dev *pdev = adapter->pdev; |
1115 | 1247 | ||
1116 | buffer->skb = dev_alloc_skb(rds_ring->skb_size); | 1248 | buffer->skb = dev_alloc_skb(rds_ring->skb_size); |
1117 | if (!buffer->skb) | 1249 | if (!buffer->skb) { |
1250 | adapter->stats.skb_alloc_failure++; | ||
1118 | return -ENOMEM; | 1251 | return -ENOMEM; |
1252 | } | ||
1119 | 1253 | ||
1120 | skb = buffer->skb; | 1254 | skb = buffer->skb; |
1121 | 1255 | ||
@@ -1289,7 +1423,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, | |||
1289 | netif_receive_skb(skb); | 1423 | netif_receive_skb(skb); |
1290 | 1424 | ||
1291 | adapter->stats.lro_pkts++; | 1425 | adapter->stats.lro_pkts++; |
1292 | adapter->stats.rxbytes += length; | 1426 | adapter->stats.lrobytes += length; |
1293 | 1427 | ||
1294 | return buffer; | 1428 | return buffer; |
1295 | } | 1429 | } |
@@ -1505,6 +1639,8 @@ qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, | |||
1505 | adapter->diag_cnt++; | 1639 | adapter->diag_cnt++; |
1506 | 1640 | ||
1507 | dev_kfree_skb_any(skb); | 1641 | dev_kfree_skb_any(skb); |
1642 | adapter->stats.rx_pkts++; | ||
1643 | adapter->stats.rxbytes += length; | ||
1508 | 1644 | ||
1509 | return buffer; | 1645 | return buffer; |
1510 | } | 1646 | } |