aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic/qlcnic_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_init.c')
-rw-r--r--drivers/net/qlcnic/qlcnic_init.c156
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
571static int 573static int
572qlcnic_set_product_offs(struct qlcnic_adapter *adapter) 574qlcnic_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
596static int
597qlcnic_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
631static int
632qlcnic_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
665static int
666qlcnic_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
586nomn: 688nomn:
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
717static int
718qlcnic_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
615static 747static
@@ -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
721int 853int
@@ -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}