Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[pandora-kernel.git] / drivers / net / benet / be_main.c
index fd251b5..28a32a6 100644 (file)
@@ -41,6 +41,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
        { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) },
        { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },
        { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },
+       { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)},
        { 0 }
 };
 MODULE_DEVICE_TABLE(pci, be_dev_ids);
@@ -188,6 +189,8 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid,
 {
        u32 val = 0;
        val |= qid & DB_EQ_RING_ID_MASK;
+       val |= ((qid & DB_EQ_RING_ID_EXT_MASK) <<
+                       DB_EQ_RING_ID_EXT_MASK_SHIFT);
 
        if (adapter->eeh_err)
                return;
@@ -205,6 +208,8 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped)
 {
        u32 val = 0;
        val |= qid & DB_CQ_RING_ID_MASK;
+       val |= ((qid & DB_CQ_RING_ID_EXT_MASK) <<
+                       DB_CQ_RING_ID_EXT_MASK_SHIFT);
 
        if (adapter->eeh_err)
                return;
@@ -307,11 +312,9 @@ void be_link_status_update(struct be_adapter *adapter, bool link_up)
        if (adapter->link_up != link_up) {
                adapter->link_speed = -1;
                if (link_up) {
-                       netif_start_queue(netdev);
                        netif_carrier_on(netdev);
                        printk(KERN_INFO "%s: Link up\n", netdev->name);
                } else {
-                       netif_stop_queue(netdev);
                        netif_carrier_off(netdev);
                        printk(KERN_INFO "%s: Link down\n", netdev->name);
                }
@@ -404,7 +407,8 @@ static void be_tx_stats_update(struct be_adapter *adapter,
 }
 
 /* Determine number of WRB entries needed to xmit data in an skb */
-static u32 wrb_cnt_for_skb(struct sk_buff *skb, bool *dummy)
+static u32 wrb_cnt_for_skb(struct be_adapter *adapter, struct sk_buff *skb,
+                                                               bool *dummy)
 {
        int cnt = (skb->len > skb->data_len);
 
@@ -412,12 +416,13 @@ static u32 wrb_cnt_for_skb(struct sk_buff *skb, bool *dummy)
 
        /* to account for hdr wrb */
        cnt++;
-       if (cnt & 1) {
+       if (lancer_chip(adapter) || !(cnt & 1)) {
+               *dummy = false;
+       } else {
                /* add a dummy to make it an even num */
                cnt++;
                *dummy = true;
-       } else
-               *dummy = false;
+       }
        BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT);
        return cnt;
 }
@@ -443,8 +448,18 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
                AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso, hdr, 1);
                AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso_mss,
                        hdr, skb_shinfo(skb)->gso_size);
-               if (skb_is_gso_v6(skb))
+               if (skb_is_gso_v6(skb) && !lancer_chip(adapter))
                        AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1);
+               if (lancer_chip(adapter) && adapter->sli_family  ==
+                                                       LANCER_A0_SLI_FAMILY) {
+                       AMAP_SET_BITS(struct amap_eth_hdr_wrb, ipcs, hdr, 1);
+                       if (is_tcp_pkt(skb))
+                               AMAP_SET_BITS(struct amap_eth_hdr_wrb,
+                                                               tcpcs, hdr, 1);
+                       else if (is_udp_pkt(skb))
+                               AMAP_SET_BITS(struct amap_eth_hdr_wrb,
+                                                               udpcs, hdr, 1);
+               }
        } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                if (is_tcp_pkt(skb))
                        AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1);
@@ -566,7 +581,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb,
        u32 start = txq->head;
        bool dummy_wrb, stopped = false;
 
-       wrb_cnt = wrb_cnt_for_skb(skb, &dummy_wrb);
+       wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb);
 
        copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb);
        if (copied) {
@@ -894,11 +909,17 @@ static void be_rx_compl_discard(struct be_adapter *adapter,
        rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
        num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
 
-       for (i = 0; i < num_rcvd; i++) {
-               page_info = get_rx_page_info(adapter, rxo, rxq_idx);
-               put_page(page_info->page);
-               memset(page_info, 0, sizeof(*page_info));
-               index_inc(&rxq_idx, rxq->len);
+        /* Skip out-of-buffer compl(lancer) or flush compl(BE) */
+       if (likely(rxq_idx != rxo->last_frag_index && num_rcvd != 0)) {
+
+               rxo->last_frag_index = rxq_idx;
+
+               for (i = 0; i < num_rcvd; i++) {
+                       page_info = get_rx_page_info(adapter, rxo, rxq_idx);
+                       put_page(page_info->page);
+                       memset(page_info, 0, sizeof(*page_info));
+                       index_inc(&rxq_idx, rxq->len);
+               }
        }
 }
 
@@ -999,9 +1020,6 @@ static void be_rx_compl_process(struct be_adapter *adapter,
        u8 vtm;
 
        num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
-       /* Is it a flush compl that has no data */
-       if (unlikely(num_rcvd == 0))
-               return;
 
        skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN);
        if (unlikely(!skb)) {
@@ -1035,7 +1053,8 @@ static void be_rx_compl_process(struct be_adapter *adapter,
                        return;
                }
                vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp);
-               vid = swab16(vid);
+               if (!lancer_chip(adapter))
+                       vid = swab16(vid);
                vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, vid);
        } else {
                netif_receive_skb(skb);
@@ -1057,10 +1076,6 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
        u8 pkt_type;
 
        num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
-       /* Is it a flush compl that has no data */
-       if (unlikely(num_rcvd == 0))
-               return;
-
        pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
        vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
        rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
@@ -1113,7 +1128,8 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
                napi_gro_frags(&eq_obj->napi);
        } else {
                vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp);
-               vid = swab16(vid);
+               if (!lancer_chip(adapter))
+                       vid = swab16(vid);
 
                if (!adapter->vlan_grp || adapter->vlans_added == 0)
                        return;
@@ -1330,7 +1346,7 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo)
        while ((rxcp = be_rx_compl_get(rxo)) != NULL) {
                be_rx_compl_discard(adapter, rxo, rxcp);
                be_rx_compl_reset(rxcp);
-               be_cq_notify(adapter, rx_cq->id, true, 1);
+               be_cq_notify(adapter, rx_cq->id, false, 1);
        }
 
        /* Then free posted rx buffer that were not used */
@@ -1381,7 +1397,8 @@ static void be_tx_compl_clean(struct be_adapter *adapter)
                sent_skb = sent_skbs[txq->tail];
                end_idx = txq->tail;
                index_adv(&end_idx,
-                       wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len);
+                       wrb_cnt_for_skb(adapter, sent_skb, &dummy_wrb) - 1,
+                       txq->len);
                be_tx_compl_process(adapter, end_idx);
        }
 }
@@ -1476,7 +1493,9 @@ static int be_tx_queues_create(struct be_adapter *adapter)
        /* Ask BE to create Tx Event queue */
        if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd))
                goto tx_eq_free;
-       adapter->base_eq_id = adapter->tx_eq.q.id;
+
+       adapter->tx_eq.msix_vec_idx = adapter->msix_vec_next_idx++;
+
 
        /* Alloc TX eth compl queue */
        cq = &adapter->tx_obj.cq;
@@ -1554,6 +1573,9 @@ static int be_rx_queues_create(struct be_adapter *adapter)
        adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
        for_all_rx_queues(adapter, rxo, i) {
                rxo->adapter = adapter;
+               /* Init last_frag_index so that the frag index in the first
+                * completion will never match */
+               rxo->last_frag_index = 0xffff;
                rxo->rx_eq.max_eqd = BE_MAX_EQD;
                rxo->rx_eq.enable_aic = true;
 
@@ -1568,6 +1590,8 @@ static int be_rx_queues_create(struct be_adapter *adapter)
                if (rc)
                        goto err;
 
+               rxo->rx_eq.msix_vec_idx = adapter->msix_vec_next_idx++;
+
                /* CQ */
                cq = &rxo->cq;
                rc = be_queue_alloc(adapter, cq, RX_CQ_LEN,
@@ -1578,7 +1602,6 @@ static int be_rx_queues_create(struct be_adapter *adapter)
                rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3);
                if (rc)
                        goto err;
-
                /* Rx Q */
                q = &rxo->q;
                rc = be_queue_alloc(adapter, q, RX_Q_LEN,
@@ -1611,29 +1634,45 @@ err:
        return -1;
 }
 
-/* There are 8 evt ids per func. Retruns the evt id's bit number */
-static inline int be_evt_bit_get(struct be_adapter *adapter, u32 eq_id)
+static bool event_peek(struct be_eq_obj *eq_obj)
 {
-       return eq_id - adapter->base_eq_id;
+       struct be_eq_entry *eqe = queue_tail_node(&eq_obj->q);
+       if (!eqe->evt)
+               return false;
+       else
+               return true;
 }
 
 static irqreturn_t be_intx(int irq, void *dev)
 {
        struct be_adapter *adapter = dev;
        struct be_rx_obj *rxo;
-       int isr, i;
+       int isr, i, tx = 0 , rx = 0;
+
+       if (lancer_chip(adapter)) {
+               if (event_peek(&adapter->tx_eq))
+                       tx = event_handle(adapter, &adapter->tx_eq);
+               for_all_rx_queues(adapter, rxo, i) {
+                       if (event_peek(&rxo->rx_eq))
+                               rx |= event_handle(adapter, &rxo->rx_eq);
+               }
 
-       isr = ioread32(adapter->csr + CEV_ISR0_OFFSET +
-               (adapter->tx_eq.q.id/ 8) * CEV_ISR_SIZE);
-       if (!isr)
-               return IRQ_NONE;
+               if (!(tx || rx))
+                       return IRQ_NONE;
 
-       if ((1 << be_evt_bit_get(adapter, adapter->tx_eq.q.id) & isr))
-               event_handle(adapter, &adapter->tx_eq);
+       } else {
+               isr = ioread32(adapter->csr + CEV_ISR0_OFFSET +
+                       (adapter->tx_eq.q.id / 8) * CEV_ISR_SIZE);
+               if (!isr)
+                       return IRQ_NONE;
 
-       for_all_rx_queues(adapter, rxo, i) {
-               if ((1 << be_evt_bit_get(adapter, rxo->rx_eq.q.id) & isr))
-                       event_handle(adapter, &rxo->rx_eq);
+               if ((1 << adapter->tx_eq.msix_vec_idx & isr))
+                       event_handle(adapter, &adapter->tx_eq);
+
+               for_all_rx_queues(adapter, rxo, i) {
+                       if ((1 << rxo->rx_eq.msix_vec_idx & isr))
+                               event_handle(adapter, &rxo->rx_eq);
+               }
        }
 
        return IRQ_HANDLED;
@@ -1658,10 +1697,9 @@ static irqreturn_t be_msix_tx_mcc(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
-static inline bool do_gro(struct be_adapter *adapter, struct be_rx_obj *rxo,
-                       struct be_eth_rx_compl *rxcp)
+static inline bool do_gro(struct be_rx_obj *rxo,
+                       struct be_eth_rx_compl *rxcp, u8 err)
 {
-       int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp);
        int tcp_frame = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp);
 
        if (err)
@@ -1678,6 +1716,8 @@ static int be_poll_rx(struct napi_struct *napi, int budget)
        struct be_queue_info *rx_cq = &rxo->cq;
        struct be_eth_rx_compl *rxcp;
        u32 work_done;
+       u16 frag_index, num_rcvd;
+       u8 err;
 
        rxo->stats.rx_polls++;
        for (work_done = 0; work_done < budget; work_done++) {
@@ -1685,10 +1725,22 @@ static int be_poll_rx(struct napi_struct *napi, int budget)
                if (!rxcp)
                        break;
 
-               if (do_gro(adapter, rxo, rxcp))
-                       be_rx_compl_process_gro(adapter, rxo, rxcp);
-               else
-                       be_rx_compl_process(adapter, rxo, rxcp);
+               err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp);
+               frag_index = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx,
+                                                               rxcp);
+               num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags,
+                                                               rxcp);
+
+               /* Skip out-of-buffer compl(lancer) or flush compl(BE) */
+               if (likely(frag_index != rxo->last_frag_index &&
+                               num_rcvd != 0)) {
+                       rxo->last_frag_index = frag_index;
+
+                       if (do_gro(rxo, rxcp, err))
+                               be_rx_compl_process_gro(adapter, rxo, rxcp);
+                       else
+                               be_rx_compl_process(adapter, rxo, rxcp);
+               }
 
                be_rx_compl_reset(rxcp);
        }
@@ -1830,8 +1882,7 @@ static void be_worker(struct work_struct *work)
                        be_post_rx_frags(rxo);
                }
        }
-
-       if (!adapter->ue_detected)
+       if (!adapter->ue_detected && !lancer_chip(adapter))
                be_detect_dump_ue(adapter);
 
 reschedule:
@@ -1910,10 +1961,10 @@ static void be_sriov_disable(struct be_adapter *adapter)
 #endif
 }
 
-static inline int be_msix_vec_get(struct be_adapter *adapter, u32 eq_id)
+static inline int be_msix_vec_get(struct be_adapter *adapter,
+                                       struct be_eq_obj *eq_obj)
 {
-       return adapter->msix_entries[
-                       be_evt_bit_get(adapter, eq_id)].vector;
+       return adapter->msix_entries[eq_obj->msix_vec_idx].vector;
 }
 
 static int be_request_irq(struct be_adapter *adapter,
@@ -1924,14 +1975,14 @@ static int be_request_irq(struct be_adapter *adapter,
        int vec;
 
        sprintf(eq_obj->desc, "%s-%s", netdev->name, desc);
-       vec = be_msix_vec_get(adapter, eq_obj->q.id);
+       vec = be_msix_vec_get(adapter, eq_obj);
        return request_irq(vec, handler, 0, eq_obj->desc, context);
 }
 
 static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj,
                        void *context)
 {
-       int vec = be_msix_vec_get(adapter, eq_obj->q.id);
+       int vec = be_msix_vec_get(adapter, eq_obj);
        free_irq(vec, context);
 }
 
@@ -2036,14 +2087,15 @@ static int be_close(struct net_device *netdev)
        netif_carrier_off(netdev);
        adapter->link_up = false;
 
-       be_intr_set(adapter, false);
+       if (!lancer_chip(adapter))
+               be_intr_set(adapter, false);
 
        if (adapter->msix_enabled) {
-               vec = be_msix_vec_get(adapter, tx_eq->q.id);
+               vec = be_msix_vec_get(adapter, tx_eq);
                synchronize_irq(vec);
 
                for_all_rx_queues(adapter, rxo, i) {
-                       vec = be_msix_vec_get(adapter, rxo->rx_eq.q.id);
+                       vec = be_msix_vec_get(adapter, &rxo->rx_eq);
                        synchronize_irq(vec);
                }
        } else {
@@ -2082,7 +2134,8 @@ static int be_open(struct net_device *netdev)
 
        be_irq_register(adapter);
 
-       be_intr_set(adapter, true);
+       if (!lancer_chip(adapter))
+               be_intr_set(adapter, true);
 
        /* The evt queues are created in unarmed state; arm them */
        for_all_rx_queues(adapter, rxo, i) {
@@ -2343,10 +2396,10 @@ static int be_flash_data(struct be_adapter *adapter,
        int num_bytes;
        const u8 *p = fw->data;
        struct be_cmd_write_flashrom *req = flash_cmd->va;
-       struct flash_comp *pflashcomp;
+       const struct flash_comp *pflashcomp;
        int num_comp;
 
-       struct flash_comp gen3_flash_types[9] = {
+       static const struct flash_comp gen3_flash_types[9] = {
                { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE,
                        FLASH_IMAGE_MAX_SIZE_g3},
                { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT,
@@ -2366,7 +2419,7 @@ static int be_flash_data(struct be_adapter *adapter,
                { FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW,
                        FLASH_NCSI_IMAGE_MAX_SIZE_g3}
        };
-       struct flash_comp gen2_flash_types[8] = {
+       static const struct flash_comp gen2_flash_types[8] = {
                { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE,
                        FLASH_IMAGE_MAX_SIZE_g2},
                { FLASH_REDBOOT_START_g2, IMG_TYPE_REDBOOT,
@@ -2388,11 +2441,11 @@ static int be_flash_data(struct be_adapter *adapter,
        if (adapter->generation == BE_GEN3) {
                pflashcomp = gen3_flash_types;
                filehdr_size = sizeof(struct flash_file_hdr_g3);
-               num_comp = 9;
+               num_comp = ARRAY_SIZE(gen3_flash_types);
        } else {
                pflashcomp = gen2_flash_types;
                filehdr_size = sizeof(struct flash_file_hdr_g2);
-               num_comp = 8;
+               num_comp = ARRAY_SIZE(gen2_flash_types);
        }
        for (i = 0; i < num_comp; i++) {
                if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) &&
@@ -2543,10 +2596,15 @@ static void be_netdev_init(struct net_device *netdev)
        int i;
 
        netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO |
-               NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM |
+               NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
+               NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                NETIF_F_GRO | NETIF_F_TSO6;
 
-       netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_CSUM;
+       netdev->vlan_features |= NETIF_F_SG | NETIF_F_TSO |
+               NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+
+       if (lancer_chip(adapter))
+               netdev->vlan_features |= NETIF_F_TSO6;
 
        netdev->flags |= IFF_MULTICAST;
 
@@ -2568,8 +2626,6 @@ static void be_netdev_init(struct net_device *netdev)
 
        netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx_mcc,
                BE_NAPI_WEIGHT);
-
-       netif_stop_queue(netdev);
 }
 
 static void be_unmap_pci_bars(struct be_adapter *adapter)
@@ -2587,6 +2643,15 @@ static int be_map_pci_bars(struct be_adapter *adapter)
        u8 __iomem *addr;
        int pcicfg_reg, db_reg;
 
+       if (lancer_chip(adapter)) {
+               addr = ioremap_nocache(pci_resource_start(adapter->pdev, 0),
+                       pci_resource_len(adapter->pdev, 0));
+               if (addr == NULL)
+                       return -ENOMEM;
+               adapter->db = addr;
+               return 0;
+       }
+
        if (be_physfn(adapter)) {
                addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2),
                                pci_resource_len(adapter->pdev, 2));
@@ -2783,6 +2848,44 @@ static int be_get_config(struct be_adapter *adapter)
        return 0;
 }
 
+static int be_dev_family_check(struct be_adapter *adapter)
+{
+       struct pci_dev *pdev = adapter->pdev;
+       u32 sli_intf = 0, if_type;
+
+       switch (pdev->device) {
+       case BE_DEVICE_ID1:
+       case OC_DEVICE_ID1:
+               adapter->generation = BE_GEN2;
+               break;
+       case BE_DEVICE_ID2:
+       case OC_DEVICE_ID2:
+               adapter->generation = BE_GEN3;
+               break;
+       case OC_DEVICE_ID3:
+               pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+               if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
+                                               SLI_INTF_IF_TYPE_SHIFT;
+
+               if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
+                       if_type != 0x02) {
+                       dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
+                       return -EINVAL;
+               }
+               if (num_vfs > 0) {
+                       dev_err(&pdev->dev, "VFs not supported\n");
+                       return -EINVAL;
+               }
+               adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
+                                        SLI_INTF_FAMILY_SHIFT);
+               adapter->generation = BE_GEN3;
+               break;
+       default:
+               adapter->generation = 0;
+       }
+       return 0;
+}
+
 static int __devinit be_probe(struct pci_dev *pdev,
                        const struct pci_device_id *pdev_id)
 {
@@ -2805,22 +2908,13 @@ static int __devinit be_probe(struct pci_dev *pdev,
                goto rel_reg;
        }
        adapter = netdev_priv(netdev);
-
-       switch (pdev->device) {
-       case BE_DEVICE_ID1:
-       case OC_DEVICE_ID1:
-               adapter->generation = BE_GEN2;
-               break;
-       case BE_DEVICE_ID2:
-       case OC_DEVICE_ID2:
-               adapter->generation = BE_GEN3;
-               break;
-       default:
-               adapter->generation = 0;
-       }
-
        adapter->pdev = pdev;
        pci_set_drvdata(pdev, adapter);
+
+       status = be_dev_family_check(adapter);
+       if (status)
+               goto free_netdev;
+
        adapter->netdev = netdev;
        SET_NETDEV_DEV(netdev, &pdev->dev);
 
@@ -2895,7 +2989,7 @@ ctrl_clean:
        be_ctrl_cleanup(adapter);
 free_netdev:
        be_sriov_disable(adapter);
-       free_netdev(adapter->netdev);
+       free_netdev(netdev);
        pci_set_drvdata(pdev, NULL);
 rel_reg:
        pci_release_regions(pdev);