tree-wide: fix assorted typos all over the place
[safe/jmp/linux-2.6] / drivers / net / benet / be_main.c
index 45507d8..02a0908 100644 (file)
@@ -117,30 +117,25 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped)
        iowrite32(val, adapter->db + DB_CQ_OFFSET);
 }
 
-
 static int be_mac_addr_set(struct net_device *netdev, void *p)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
        struct sockaddr *addr = p;
        int status = 0;
 
-       if (netif_running(netdev)) {
-               status = be_cmd_pmac_del(adapter, adapter->if_handle,
-                               adapter->pmac_id);
-               if (status)
-                       return status;
-
-               status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
-                               adapter->if_handle, &adapter->pmac_id);
-       }
+       status = be_cmd_pmac_del(adapter, adapter->if_handle, adapter->pmac_id);
+       if (status)
+               return status;
 
+       status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
+                       adapter->if_handle, &adapter->pmac_id);
        if (!status)
                memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 
        return status;
 }
 
-static void netdev_stats_update(struct be_adapter *adapter)
+void netdev_stats_update(struct be_adapter *adapter)
 {
        struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va);
        struct be_rxf_stats *rxf_stats = &hw_stats->rxf;
@@ -202,7 +197,7 @@ static void netdev_stats_update(struct be_adapter *adapter)
        /* no space available in linux */
        dev_stats->tx_dropped = 0;
 
-       dev_stats->multicast = port_stats->tx_multicastframes;
+       dev_stats->multicast = port_stats->rx_multicast_frames;
        dev_stats->collisions = 0;
 
        /* detailed tx_errors */
@@ -390,15 +385,19 @@ static int make_tx_wrbs(struct be_adapter *adapter,
        struct be_eth_wrb *wrb;
        struct be_eth_hdr_wrb *hdr;
 
-       atomic_add(wrb_cnt, &txq->used);
        hdr = queue_head_node(txq);
+       atomic_add(wrb_cnt, &txq->used);
        queue_head_inc(txq);
 
+       if (skb_dma_map(&pdev->dev, skb, DMA_TO_DEVICE)) {
+               dev_err(&pdev->dev, "TX DMA mapping failed\n");
+               return 0;
+       }
+
        if (skb->len > skb->data_len) {
                int len = skb->len - skb->data_len;
-               busaddr = pci_map_single(pdev, skb->data, len,
-                                        PCI_DMA_TODEVICE);
                wrb = queue_head_node(txq);
+               busaddr = skb_shinfo(skb)->dma_head;
                wrb_fill(wrb, busaddr, len);
                be_dws_cpu_to_le(wrb, sizeof(*wrb));
                queue_head_inc(txq);
@@ -408,9 +407,8 @@ static int make_tx_wrbs(struct be_adapter *adapter,
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                struct skb_frag_struct *frag =
                        &skb_shinfo(skb)->frags[i];
-               busaddr = pci_map_page(pdev, frag->page,
-                                       frag->page_offset,
-                                       frag->size, PCI_DMA_TODEVICE);
+
+               busaddr = skb_shinfo(skb)->dma_maps[i];
                wrb = queue_head_node(txq);
                wrb_fill(wrb, busaddr, frag->size);
                be_dws_cpu_to_le(wrb, sizeof(*wrb));
@@ -432,7 +430,8 @@ static int make_tx_wrbs(struct be_adapter *adapter,
        return copied;
 }
 
-static int be_xmit(struct sk_buff *skb, struct net_device *netdev)
+static netdev_tx_t be_xmit(struct sk_buff *skb,
+                       struct net_device *netdev)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
        struct be_tx_obj *tx_obj = &adapter->tx_obj;
@@ -444,23 +443,28 @@ static int be_xmit(struct sk_buff *skb, struct net_device *netdev)
        wrb_cnt = wrb_cnt_for_skb(skb, &dummy_wrb);
 
        copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb);
+       if (copied) {
+               /* record the sent skb in the sent_skb table */
+               BUG_ON(tx_obj->sent_skb_list[start]);
+               tx_obj->sent_skb_list[start] = skb;
+
+               /* Ensure txq has space for the next skb; Else stop the queue
+                * *BEFORE* ringing the tx doorbell, so that we serialze the
+                * tx compls of the current transmit which'll wake up the queue
+                */
+               if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >=
+                                                               txq->len) {
+                       netif_stop_queue(netdev);
+                       stopped = true;
+               }
 
-       /* record the sent skb in the sent_skb table */
-       BUG_ON(tx_obj->sent_skb_list[start]);
-       tx_obj->sent_skb_list[start] = skb;
+               be_txq_notify(adapter, txq->id, wrb_cnt);
 
-       /* Ensure that txq has space for the next skb; Else stop the queue
-        * *BEFORE* ringing the tx doorbell, so that we serialze the
-        * tx compls of the current transmit which'll wake up the queue
-        */
-       if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >= txq->len) {
-               netif_stop_queue(netdev);
-               stopped = true;
+               be_tx_stats_update(adapter, wrb_cnt, copied, stopped);
+       } else {
+               txq->head = start;
+               dev_kfree_skb_any(skb);
        }
-
-       be_txq_notify(adapter, txq->id, wrb_cnt);
-
-       be_tx_stats_update(adapter, wrb_cnt, copied, stopped);
        return NETDEV_TX_OK;
 }
 
@@ -485,11 +489,11 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu)
  * program them in BE.  If more than BE_NUM_VLANS_SUPPORTED are configured,
  * set the BE in promiscuous VLAN mode.
  */
-static void be_vid_config(struct net_device *netdev)
+static int be_vid_config(struct be_adapter *adapter)
 {
-       struct be_adapter *adapter = netdev_priv(netdev);
        u16 vtag[BE_NUM_VLANS_SUPPORTED];
        u16 ntags = 0, i;
+       int status;
 
        if (adapter->num_vlans <= BE_NUM_VLANS_SUPPORTED)  {
                /* Construct VLAN Table to give to HW */
@@ -499,12 +503,13 @@ static void be_vid_config(struct net_device *netdev)
                                ntags++;
                        }
                }
-               be_cmd_vlan_config(adapter, adapter->if_handle,
-                       vtag, ntags, 1, 0);
+               status = be_cmd_vlan_config(adapter, adapter->if_handle,
+                                       vtag, ntags, 1, 0);
        } else {
-               be_cmd_vlan_config(adapter, adapter->if_handle,
-                       NULL, 0, 1, 1);
+               status = be_cmd_vlan_config(adapter, adapter->if_handle,
+                                       NULL, 0, 1, 1);
        }
+       return status;
 }
 
 static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp)
@@ -527,7 +532,7 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid)
        adapter->num_vlans++;
        adapter->vlan_tag[vid] = 1;
 
-       be_vid_config(netdev);
+       be_vid_config(adapter);
 }
 
 static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
@@ -538,7 +543,7 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid)
        adapter->vlan_tag[vid] = 0;
 
        vlan_group_set_device(adapter->vlan_grp, vid, NULL);
-       be_vid_config(netdev);
+       be_vid_config(adapter);
 }
 
 static void be_set_multicast_list(struct net_device *netdev)
@@ -742,9 +747,16 @@ static void be_rx_compl_process(struct be_adapter *adapter,
                        struct be_eth_rx_compl *rxcp)
 {
        struct sk_buff *skb;
-       u32 vtp, vid;
+       u32 vlanf, vid;
+       u8 vtm;
+
+       vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
+       vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
 
-       vtp = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
+       /* vlanf could be wrongly set in some cards.
+        * ignore if vtm is not set */
+       if ((adapter->cap == 0x400) && !vtm)
+               vlanf = 0;
 
        skb = netdev_alloc_skb(adapter->netdev, BE_HDR_LEN + NET_IP_ALIGN);
        if (!skb) {
@@ -767,7 +779,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
        skb->protocol = eth_type_trans(skb, adapter->netdev);
        skb->dev = adapter->netdev;
 
-       if (vtp) {
+       if (vlanf) {
                if (!adapter->vlan_grp || adapter->num_vlans == 0) {
                        kfree_skb(skb);
                        return;
@@ -779,8 +791,6 @@ static void be_rx_compl_process(struct be_adapter *adapter,
                netif_receive_skb(skb);
        }
 
-       adapter->netdev->last_rx = jiffies;
-
        return;
 }
 
@@ -794,11 +804,18 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
        struct be_eq_obj *eq_obj =  &adapter->rx_eq;
        u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
        u16 i, rxq_idx = 0, vid, j;
+       u8 vtm;
 
        num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
        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);
+       vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
+
+       /* vlanf could be wrongly set in some cards.
+        * ignore if vtm is not set */
+       if ((adapter->cap == 0x400) && !vtm)
+               vlanf = 0;
 
        skb = napi_get_frags(&eq_obj->napi);
        if (!skb) {
@@ -964,10 +981,8 @@ static struct be_eth_tx_compl *be_tx_compl_get(struct be_queue_info *tx_cq)
 static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index)
 {
        struct be_queue_info *txq = &adapter->tx_obj.q;
-       struct be_eth_wrb *wrb;
        struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list;
        struct sk_buff *sent_skb;
-       u64 busaddr;
        u16 cur_index, num_wrbs = 0;
 
        cur_index = txq->tail;
@@ -977,19 +992,12 @@ static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index)
 
        do {
                cur_index = txq->tail;
-               wrb = queue_tail_node(txq);
-               be_dws_le_to_cpu(wrb, sizeof(*wrb));
-               busaddr = ((u64)wrb->frag_pa_hi << 32) | (u64)wrb->frag_pa_lo;
-               if (busaddr != 0) {
-                       pci_unmap_single(adapter->pdev, busaddr,
-                               wrb->frag_len, PCI_DMA_TODEVICE);
-               }
                num_wrbs++;
                queue_tail_inc(txq);
        } while (cur_index != last_index);
 
        atomic_sub(num_wrbs, &txq->used);
-
+       skb_dma_unmap(&adapter->pdev->dev, sent_skb, DMA_TO_DEVICE);
        kfree_skb(sent_skb);
 }
 
@@ -1308,6 +1316,12 @@ rx_eq_free:
        return rc;
 }
 
+/* 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)
+{
+       return eq_id - 8 * be_pci_func(adapter);
+}
+
 static irqreturn_t be_intx(int irq, void *dev)
 {
        struct be_adapter *adapter = dev;
@@ -1444,12 +1458,8 @@ static void be_worker(struct work_struct *work)
 {
        struct be_adapter *adapter =
                container_of(work, struct be_adapter, work.work);
-       int status;
 
-       /* Get Stats */
-       status = be_cmd_get_stats(adapter, &adapter->stats.cmd);
-       if (!status)
-               netdev_stats_update(adapter);
+       be_cmd_get_stats(adapter, &adapter->stats.cmd);
 
        /* Set EQ delay */
        be_rx_eqd_update(adapter);
@@ -1481,31 +1491,44 @@ static void be_msix_enable(struct be_adapter *adapter)
 
 static inline int be_msix_vec_get(struct be_adapter *adapter, u32 eq_id)
 {
-       return adapter->msix_entries[eq_id - 8 * be_pci_func(adapter)].vector;
+       return adapter->msix_entries[
+                       be_evt_bit_get(adapter, eq_id)].vector;
 }
 
-static int be_msix_register(struct be_adapter *adapter)
+static int be_request_irq(struct be_adapter *adapter,
+               struct be_eq_obj *eq_obj,
+               void *handler, char *desc)
 {
        struct net_device *netdev = adapter->netdev;
-       struct be_eq_obj *tx_eq = &adapter->tx_eq;
-       struct be_eq_obj *rx_eq = &adapter->rx_eq;
-       int status, vec;
+       int vec;
+
+       sprintf(eq_obj->desc, "%s-%s", netdev->name, desc);
+       vec = be_msix_vec_get(adapter, eq_obj->q.id);
+       return request_irq(vec, handler, 0, eq_obj->desc, adapter);
+}
 
-       sprintf(tx_eq->desc, "%s-tx", netdev->name);
-       vec = be_msix_vec_get(adapter, tx_eq->q.id);
-       status = request_irq(vec, be_msix_tx_mcc, 0, tx_eq->desc, adapter);
+static void be_free_irq(struct be_adapter *adapter, struct be_eq_obj *eq_obj)
+{
+       int vec = be_msix_vec_get(adapter, eq_obj->q.id);
+       free_irq(vec, adapter);
+}
+
+static int be_msix_register(struct be_adapter *adapter)
+{
+       int status;
+
+       status = be_request_irq(adapter, &adapter->tx_eq, be_msix_tx_mcc, "tx");
        if (status)
                goto err;
 
-       sprintf(rx_eq->desc, "%s-rx", netdev->name);
-       vec = be_msix_vec_get(adapter, rx_eq->q.id);
-       status = request_irq(vec, be_msix_rx, 0, rx_eq->desc, adapter);
-       if (status) { /* Free TX IRQ */
-               vec = be_msix_vec_get(adapter, tx_eq->q.id);
-               free_irq(vec, adapter);
-               goto err;
-       }
+       status = be_request_irq(adapter, &adapter->rx_eq, be_msix_rx, "rx");
+       if (status)
+               goto free_tx_irq;
+
        return 0;
+
+free_tx_irq:
+       be_free_irq(adapter, &adapter->tx_eq);
 err:
        dev_warn(&adapter->pdev->dev,
                "MSIX Request IRQ failed - err %d\n", status);
@@ -1542,7 +1565,6 @@ done:
 static void be_irq_unregister(struct be_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
-       int vec;
 
        if (!adapter->isr_registered)
                return;
@@ -1554,10 +1576,8 @@ static void be_irq_unregister(struct be_adapter *adapter)
        }
 
        /* MSIx */
-       vec = be_msix_vec_get(adapter, adapter->tx_eq.q.id);
-       free_irq(vec, adapter);
-       vec = be_msix_vec_get(adapter, adapter->rx_eq.q.id);
-       free_irq(vec, adapter);
+       be_free_irq(adapter, &adapter->tx_eq);
+       be_free_irq(adapter, &adapter->rx_eq);
 done:
        adapter->isr_registered = false;
        return;
@@ -1600,23 +1620,21 @@ static int be_open(struct net_device *netdev)
 static int be_setup(struct be_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
-       u32 if_flags;
+       u32 cap_flags, en_flags;
        int status;
 
-       if_flags = BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PROMISCUOUS |
-               BE_IF_FLAGS_MCAST_PROMISCUOUS | BE_IF_FLAGS_UNTAGGED |
-               BE_IF_FLAGS_PASS_L3L4_ERRORS;
-       status = be_cmd_if_create(adapter, if_flags, netdev->dev_addr,
-                       false/* pmac_invalid */, &adapter->if_handle,
-                       &adapter->pmac_id);
-       if (status != 0)
-               goto do_none;
+       cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+                       BE_IF_FLAGS_MCAST_PROMISCUOUS |
+                       BE_IF_FLAGS_PROMISCUOUS |
+                       BE_IF_FLAGS_PASS_L3L4_ERRORS;
+       en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+                       BE_IF_FLAGS_PASS_L3L4_ERRORS;
 
-       be_vid_config(netdev);
-
-       status = be_cmd_set_flow_control(adapter, true, true);
+       status = be_cmd_if_create(adapter, cap_flags, en_flags,
+                       netdev->dev_addr, false/* pmac_invalid */,
+                       &adapter->if_handle, &adapter->pmac_id);
        if (status != 0)
-               goto if_destroy;
+               goto do_none;
 
        status = be_tx_queues_create(adapter);
        if (status != 0)
@@ -1630,8 +1648,17 @@ static int be_setup(struct be_adapter *adapter)
        if (status != 0)
                goto rx_qs_destroy;
 
+       status = be_vid_config(adapter);
+       if (status != 0)
+               goto mccqs_destroy;
+
+       status = be_cmd_set_flow_control(adapter, true, true);
+       if (status != 0)
+               goto mccqs_destroy;
        return 0;
 
+mccqs_destroy:
+       be_mcc_queues_destroy(adapter);
 rx_qs_destroy:
        be_rx_queues_destroy(adapter);
 tx_qs_destroy:
@@ -1644,12 +1671,12 @@ do_none:
 
 static int be_clear(struct be_adapter *adapter)
 {
+       be_mcc_queues_destroy(adapter);
        be_rx_queues_destroy(adapter);
        be_tx_queues_destroy(adapter);
 
        be_cmd_if_destroy(adapter, adapter->if_handle);
 
-       be_mcc_queues_destroy(adapter);
        return 0;
 }
 
@@ -1689,6 +1716,173 @@ static int be_close(struct net_device *netdev)
        return 0;
 }
 
+#define FW_FILE_HDR_SIGN       "ServerEngines Corp. "
+char flash_cookie[2][16] =     {"*** SE FLAS",
+                               "H DIRECTORY *** "};
+static int be_flash_image(struct be_adapter *adapter,
+                       const struct firmware *fw,
+                       struct be_dma_mem *flash_cmd, u32 flash_type)
+{
+       int status;
+       u32 flash_op, image_offset = 0, total_bytes, image_size = 0;
+       int num_bytes;
+       const u8 *p = fw->data;
+       struct be_cmd_write_flashrom *req = flash_cmd->va;
+
+       switch (flash_type) {
+       case FLASHROM_TYPE_ISCSI_ACTIVE:
+               image_offset = FLASH_iSCSI_PRIMARY_IMAGE_START;
+               image_size = FLASH_IMAGE_MAX_SIZE;
+               break;
+       case FLASHROM_TYPE_ISCSI_BACKUP:
+               image_offset = FLASH_iSCSI_BACKUP_IMAGE_START;
+               image_size = FLASH_IMAGE_MAX_SIZE;
+               break;
+       case FLASHROM_TYPE_FCOE_FW_ACTIVE:
+               image_offset = FLASH_FCoE_PRIMARY_IMAGE_START;
+               image_size = FLASH_IMAGE_MAX_SIZE;
+               break;
+       case FLASHROM_TYPE_FCOE_FW_BACKUP:
+               image_offset = FLASH_FCoE_BACKUP_IMAGE_START;
+               image_size = FLASH_IMAGE_MAX_SIZE;
+               break;
+       case FLASHROM_TYPE_BIOS:
+               image_offset = FLASH_iSCSI_BIOS_START;
+               image_size = FLASH_BIOS_IMAGE_MAX_SIZE;
+               break;
+       case FLASHROM_TYPE_FCOE_BIOS:
+               image_offset = FLASH_FCoE_BIOS_START;
+               image_size = FLASH_BIOS_IMAGE_MAX_SIZE;
+               break;
+       case FLASHROM_TYPE_PXE_BIOS:
+               image_offset = FLASH_PXE_BIOS_START;
+               image_size = FLASH_BIOS_IMAGE_MAX_SIZE;
+               break;
+       default:
+               return 0;
+       }
+
+       p += sizeof(struct flash_file_hdr) + image_offset;
+       if (p + image_size > fw->data + fw->size)
+               return -1;
+
+       total_bytes = image_size;
+
+       while (total_bytes) {
+               if (total_bytes > 32*1024)
+                       num_bytes = 32*1024;
+               else
+                       num_bytes = total_bytes;
+               total_bytes -= num_bytes;
+
+               if (!total_bytes)
+                       flash_op = FLASHROM_OPER_FLASH;
+               else
+                       flash_op = FLASHROM_OPER_SAVE;
+               memcpy(req->params.data_buf, p, num_bytes);
+               p += num_bytes;
+               status = be_cmd_write_flashrom(adapter, flash_cmd,
+                               flash_type, flash_op, num_bytes);
+               if (status) {
+                       dev_err(&adapter->pdev->dev,
+                       "cmd to write to flash rom failed. type/op %d/%d\n",
+                       flash_type, flash_op);
+                       return -1;
+               }
+               yield();
+       }
+
+       return 0;
+}
+
+int be_load_fw(struct be_adapter *adapter, u8 *func)
+{
+       char fw_file[ETHTOOL_FLASH_MAX_FILENAME];
+       const struct firmware *fw;
+       struct flash_file_hdr *fhdr;
+       struct flash_section_info *fsec = NULL;
+       struct be_dma_mem flash_cmd;
+       int status;
+       const u8 *p;
+       bool entry_found = false;
+       int flash_type;
+       char fw_ver[FW_VER_LEN];
+       char fw_cfg;
+
+       status = be_cmd_get_fw_ver(adapter, fw_ver);
+       if (status)
+               return status;
+
+       fw_cfg = *(fw_ver + 2);
+       if (fw_cfg == '0')
+               fw_cfg = '1';
+       strcpy(fw_file, func);
+
+       status = request_firmware(&fw, fw_file, &adapter->pdev->dev);
+       if (status)
+               goto fw_exit;
+
+       p = fw->data;
+       fhdr = (struct flash_file_hdr *) p;
+       if (memcmp(fhdr->sign, FW_FILE_HDR_SIGN, strlen(FW_FILE_HDR_SIGN))) {
+               dev_err(&adapter->pdev->dev,
+                       "Firmware(%s) load error (signature did not match)\n",
+                               fw_file);
+               status = -1;
+               goto fw_exit;
+       }
+
+       dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file);
+
+       p += sizeof(struct flash_file_hdr);
+       while (p < (fw->data + fw->size)) {
+               fsec = (struct flash_section_info *)p;
+               if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) {
+                       entry_found = true;
+                       break;
+               }
+               p += 32;
+       }
+
+       if (!entry_found) {
+               status = -1;
+               dev_err(&adapter->pdev->dev,
+                       "Flash cookie not found in firmware image\n");
+               goto fw_exit;
+       }
+
+       flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
+       flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size,
+                                       &flash_cmd.dma);
+       if (!flash_cmd.va) {
+               status = -ENOMEM;
+               dev_err(&adapter->pdev->dev,
+                       "Memory allocation failure while flashing\n");
+               goto fw_exit;
+       }
+
+       for (flash_type = FLASHROM_TYPE_ISCSI_ACTIVE;
+               flash_type <= FLASHROM_TYPE_FCOE_FW_BACKUP; flash_type++) {
+               status = be_flash_image(adapter, fw, &flash_cmd,
+                               flash_type);
+               if (status)
+                       break;
+       }
+
+       pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va,
+                               flash_cmd.dma);
+       if (status) {
+               dev_err(&adapter->pdev->dev, "Firmware load error\n");
+               goto fw_exit;
+       }
+
+       dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n");
+
+fw_exit:
+       release_firmware(fw);
+       return status;
+}
+
 static struct net_device_ops be_netdev_ops = {
        .ndo_open               = be_open,
        .ndo_stop               = be_close,
@@ -1708,13 +1902,15 @@ static void be_netdev_init(struct net_device *netdev)
        struct be_adapter *adapter = netdev_priv(netdev);
 
        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_IP_CSUM |
-               NETIF_F_IPV6_CSUM | NETIF_F_GRO;
+               NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM |
+               NETIF_F_GRO;
 
        netdev->flags |= IFF_MULTICAST;
 
        adapter->rx_csum = true;
 
+       netif_set_gso_max_size(netdev, 65535);
+
        BE_SET_NETDEV_OPS(netdev, &be_netdev_ops);
 
        SET_ETHTOOL_OPS(netdev, &be_ethtool_ops);
@@ -1862,11 +2058,16 @@ static int be_hw_up(struct be_adapter *adapter)
        if (status)
                return status;
 
+       status = be_cmd_reset_function(adapter);
+       if (status)
+               return status;
+
        status = be_cmd_get_fw_ver(adapter, adapter->fw_ver);
        if (status)
                return status;
 
-       status = be_cmd_query_fw_cfg(adapter, &adapter->port_num);
+       status = be_cmd_query_fw_cfg(adapter,
+                               &adapter->port_num, &adapter->cap);
        return status;
 }
 
@@ -1914,10 +2115,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
        if (status)
                goto free_netdev;
 
-       status = be_cmd_reset_function(adapter);
-       if (status)
-               goto ctrl_clean;
-
        status = be_stats_init(adapter);
        if (status)
                goto ctrl_clean;