netxen: add new board types
[safe/jmp/linux-2.6] / drivers / net / netxen / netxen_nic_hw.c
index fde8c6f..d0c6935 100644 (file)
@@ -280,80 +280,6 @@ static unsigned crb_hub_agt[64] =
        0,
 };
 
-struct netxen_recv_crb recv_crb_registers[] = {
-       /*
-        * Instance 0.
-        */
-       {
-               /* crb_rcv_producer: */
-               {
-                       NETXEN_NIC_REG(0x100),
-                       /* Jumbo frames */
-                       NETXEN_NIC_REG(0x110),
-                       /* LRO */
-                       NETXEN_NIC_REG(0x120)
-               },
-               /* crb_sts_consumer: */
-               NETXEN_NIC_REG(0x138),
-       },
-       /*
-        * Instance 1,
-        */
-       {
-               /* crb_rcv_producer: */
-               {
-                       NETXEN_NIC_REG(0x144),
-                       /* Jumbo frames */
-                       NETXEN_NIC_REG(0x154),
-                       /* LRO */
-                       NETXEN_NIC_REG(0x164)
-               },
-               /* crb_sts_consumer: */
-               NETXEN_NIC_REG(0x17c),
-       },
-       /*
-        * Instance 2,
-        */
-       {
-               /* crb_rcv_producer: */
-               {
-                       NETXEN_NIC_REG(0x1d8),
-                       /* Jumbo frames */
-                       NETXEN_NIC_REG(0x1f8),
-                       /* LRO */
-                       NETXEN_NIC_REG(0x208)
-               },
-               /* crb_sts_consumer: */
-               NETXEN_NIC_REG(0x220),
-       },
-       /*
-        * Instance 3,
-        */
-       {
-               /* crb_rcv_producer: */
-               {
-                       NETXEN_NIC_REG(0x22c),
-                       /* Jumbo frames */
-                       NETXEN_NIC_REG(0x23c),
-                       /* LRO */
-                       NETXEN_NIC_REG(0x24c)
-               },
-               /* crb_sts_consumer: */
-               NETXEN_NIC_REG(0x264),
-       },
-};
-
-static u64 ctx_addr_sig_regs[][3] = {
-       {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)},
-       {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)},
-       {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)},
-       {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)}
-};
-#define CRB_CTX_ADDR_REG_LO(FUNC_ID)           (ctx_addr_sig_regs[FUNC_ID][0])
-#define CRB_CTX_ADDR_REG_HI(FUNC_ID)           (ctx_addr_sig_regs[FUNC_ID][2])
-#define CRB_CTX_SIGNATURE_REG(FUNC_ID)         (ctx_addr_sig_regs[FUNC_ID][1])
-
-
 /*  PCI Windowing for DDR regions.  */
 
 #define ADDR_IN_RANGE(addr, low, high) \
@@ -368,10 +294,6 @@ static u64 ctx_addr_sig_regs[][3] = {
 #define NETXEN_NIU_HDRSIZE     (0x1 << 6)
 #define NETXEN_NIU_TLRSIZE     (0x1 << 5)
 
-#define lower32(x)             ((u32)((x) & 0xffffffff))
-#define upper32(x)                     \
-       ((u32)(((unsigned long long)(x) >> 32) & 0xffffffff))
-
 #define NETXEN_NIC_ZERO_PAUSE_ADDR     0ULL
 #define NETXEN_NIC_UNIT_PAUSE_ADDR     0x200ULL
 #define NETXEN_NIC_EPG_PAUSE_ADDR1     0x2200010000c28001ULL
@@ -392,8 +314,10 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)
 
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 
-       if (adapter->macaddr_set)
-               adapter->macaddr_set(adapter, addr->sa_data);
+       /* For P3, MAC addr is not set in NIU */
+       if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
+               if (adapter->macaddr_set)
+                       adapter->macaddr_set(adapter, addr->sa_data);
 
        return 0;
 }
@@ -483,10 +407,7 @@ netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
        return 0;
 }
 
-/*
- * netxen_nic_set_multi - Multicast
- */
-void netxen_nic_set_multi(struct net_device *netdev)
+void netxen_p2_nic_set_multi(struct net_device *netdev)
 {
        struct netxen_adapter *adapter = netdev_priv(netdev);
        struct dev_mc_list *mc_ptr;
@@ -534,211 +455,227 @@ void netxen_nic_set_multi(struct net_device *netdev)
                netxen_nic_set_mcast_addr(adapter, index, null_addr);
 }
 
-/*
- * netxen_nic_change_mtu - Change the Maximum Transfer Unit
- * @returns 0 on success, negative on failure
- */
-int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
+static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
+               u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list)
 {
-       struct netxen_adapter *adapter = netdev_priv(netdev);
-       int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE;
+       nx_mac_list_t *cur, *prev;
+
+       /* if in del_list, move it to adapter->mac_list */
+       for (cur = *del_list, prev = NULL; cur;) {
+               if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
+                       if (prev == NULL)
+                               *del_list = cur->next;
+                       else
+                               prev->next = cur->next;
+                       cur->next = adapter->mac_list;
+                       adapter->mac_list = cur;
+                       return 0;
+               }
+               prev = cur;
+               cur = cur->next;
+       }
 
-       if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) {
-               printk(KERN_ERR "%s: %s %d is not supported.\n",
-                      netxen_nic_driver_name, netdev->name, mtu);
+       /* make sure to add each mac address only once */
+       for (cur = adapter->mac_list; cur; cur = cur->next) {
+               if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
+                       return 0;
+       }
+       /* not in del_list, create new entry and add to add_list */
+       cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL);
+       if (cur == NULL) {
+               printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may"
+                               "not work properly from now.\n", __func__);
+               return -1;
+       }
+
+       memcpy(cur->mac_addr, addr, ETH_ALEN);
+       cur->next = *add_list;
+       *add_list = cur;
+       return 0;
+}
+
+static int
+netxen_send_cmd_descs(struct netxen_adapter *adapter,
+               struct cmd_desc_type0 *cmd_desc_arr, int nr_elements)
+{
+       uint32_t i, producer;
+       struct netxen_cmd_buffer *pbuf;
+       struct cmd_desc_type0 *cmd_desc;
+
+       if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) {
+               printk(KERN_WARNING "%s: Too many command descriptors in a "
+                             "request\n", __func__);
                return -EINVAL;
        }
 
-       if (adapter->set_mtu)
-               adapter->set_mtu(adapter, mtu);
-       netdev->mtu = mtu;
+       i = 0;
+
+       producer = adapter->cmd_producer;
+       do {
+               cmd_desc = &cmd_desc_arr[i];
+
+               pbuf = &adapter->cmd_buf_arr[producer];
+               pbuf->mss = 0;
+               pbuf->total_length = 0;
+               pbuf->skb = NULL;
+               pbuf->cmd = 0;
+               pbuf->frag_count = 0;
+               pbuf->port = 0;
+
+               /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
+               memcpy(&adapter->ahw.cmd_desc_head[producer],
+                       &cmd_desc_arr[i], sizeof(struct cmd_desc_type0));
+
+               producer = get_next_index(producer,
+                               adapter->max_tx_desc_count);
+               i++;
+
+       } while (i != nr_elements);
+
+       adapter->cmd_producer = producer;
+
+       /* write producer index to start the xmit */
+
+       netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
 
        return 0;
 }
 
-/*
- * check if the firmware has been downloaded and ready to run  and
- * setup the address for the descriptors in the adapter
- */
-int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
+#define NIC_REQUEST            0x14
+#define NETXEN_MAC_EVENT       0x1
+
+static int nx_p3_sre_macaddr_change(struct net_device *dev,
+               u8 *addr, unsigned op)
 {
-       struct netxen_hardware_context *hw = &adapter->ahw;
-       u32 state = 0;
-       void *addr;
-       int err = 0;
-       int ctx, ring;
-       struct netxen_recv_context *recv_ctx;
-       struct netxen_rcv_desc_ctx *rcv_desc;
-       int func_id = adapter->portnum;
-
-       err = netxen_receive_peg_ready(adapter);
-       if (err) {
-               printk(KERN_ERR "Rcv Peg initialization not complete:%x.\n",
-                               state);
-               return err;
-       }
-       adapter->intr_scheme = adapter->pci_read_normalize(adapter,
-                       CRB_NIC_CAPABILITIES_FW);
-       adapter->msi_mode = adapter->pci_read_normalize(adapter,
-                       CRB_NIC_MSI_MODE_FW);
-
-       addr = pci_alloc_consistent(adapter->pdev,
-                           sizeof(struct netxen_ring_ctx) + sizeof(uint32_t),
-                           &adapter->ctx_desc_phys_addr);
-
-       if (addr == NULL) {
-               DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
-               err = -ENOMEM;
-               return err;
-       }
-       memset(addr, 0, sizeof(struct netxen_ring_ctx));
-       adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
-       adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
-       adapter->ctx_desc->cmd_consumer_offset =
-           cpu_to_le64(adapter->ctx_desc_phys_addr +
-                       sizeof(struct netxen_ring_ctx));
-       adapter->cmd_consumer = (__le32 *) (((char *)addr) +
-                                             sizeof(struct netxen_ring_ctx));
-
-       addr = pci_alloc_consistent(adapter->pdev,
-                           sizeof(struct cmd_desc_type0) *
-                           adapter->max_tx_desc_count,
-                           &hw->cmd_desc_phys_addr);
-
-       if (addr == NULL) {
-               DPRINTK(ERR, "bad return from pci_alloc_consistent\n");
-               netxen_free_hw_resources(adapter);
-               return -ENOMEM;
-       }
-
-       adapter->ctx_desc->cmd_ring_addr =
-               cpu_to_le64(hw->cmd_desc_phys_addr);
-       adapter->ctx_desc->cmd_ring_size =
-               cpu_to_le32(adapter->max_tx_desc_count);
-
-       hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;
-
-       for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-               recv_ctx = &adapter->recv_ctx[ctx];
-
-               for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-                       rcv_desc = &recv_ctx->rcv_desc[ring];
-                       addr = pci_alloc_consistent(adapter->pdev,
-                                           RCV_DESC_RINGSIZE,
-                                           &rcv_desc->phys_addr);
-                       if (addr == NULL) {
-                               DPRINTK(ERR, "bad return from "
-                                       "pci_alloc_consistent\n");
-                               netxen_free_hw_resources(adapter);
-                               err = -ENOMEM;
-                               return err;
-                       }
-                       rcv_desc->desc_head = (struct rcv_desc *)addr;
-                       adapter->ctx_desc->rcv_ctx[ring].rcv_ring_addr =
-                           cpu_to_le64(rcv_desc->phys_addr);
-                       adapter->ctx_desc->rcv_ctx[ring].rcv_ring_size =
-                           cpu_to_le32(rcv_desc->max_rx_desc_count);
-                       rcv_desc->crb_rcv_producer =
-                                   recv_crb_registers[adapter->portnum].
-                                   crb_rcv_producer[ring];
-               }
+       struct netxen_adapter *adapter = (struct netxen_adapter *)dev->priv;
+       nx_nic_req_t req;
+       nx_mac_req_t mac_req;
+       int rv;
 
-               addr = pci_alloc_consistent(adapter->pdev, STATUS_DESC_RINGSIZE,
-                                   &recv_ctx->rcv_status_desc_phys_addr);
-               if (addr == NULL) {
-                       DPRINTK(ERR, "bad return from"
-                               " pci_alloc_consistent\n");
-                       netxen_free_hw_resources(adapter);
-                       err = -ENOMEM;
-                       return err;
-               }
-               recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;
-               adapter->ctx_desc->sts_ring_addr =
-                   cpu_to_le64(recv_ctx->rcv_status_desc_phys_addr);
-               adapter->ctx_desc->sts_ring_size =
-                   cpu_to_le32(adapter->max_rx_desc_count);
-               recv_ctx->crb_sts_consumer =
-                       recv_crb_registers[adapter->portnum].crb_sts_consumer;
-
-       }
-       /* Window = 1 */
-
-       adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_LO(func_id),
-                       lower32(adapter->ctx_desc_phys_addr));
-       adapter->pci_write_normalize(adapter, CRB_CTX_ADDR_REG_HI(func_id),
-                       upper32(adapter->ctx_desc_phys_addr));
-       adapter->pci_write_normalize(adapter, CRB_CTX_SIGNATURE_REG(func_id),
-                       NETXEN_CTX_SIGNATURE | func_id);
-       return err;
+       memset(&req, 0, sizeof(nx_nic_req_t));
+       req.qhdr |= (NIC_REQUEST << 23);
+       req.req_hdr |= NETXEN_MAC_EVENT;
+       req.req_hdr |= ((u64)adapter->portnum << 16);
+       mac_req.op = op;
+       memcpy(&mac_req.mac_addr, addr, 6);
+       req.words[0] = cpu_to_le64(*(u64 *)&mac_req);
+
+       rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+       if (rv != 0) {
+               printk(KERN_ERR "ERROR. Could not send mac update\n");
+               return rv;
+       }
+
+       return 0;
 }
 
-void netxen_free_hw_resources(struct netxen_adapter *adapter)
+void netxen_p3_nic_set_multi(struct net_device *netdev)
 {
-       struct netxen_recv_context *recv_ctx;
-       struct netxen_rcv_desc_ctx *rcv_desc;
-       int ctx, ring;
-
-       if (adapter->ctx_desc != NULL) {
-               pci_free_consistent(adapter->pdev,
-                                   sizeof(struct netxen_ring_ctx) +
-                                   sizeof(uint32_t),
-                                   adapter->ctx_desc,
-                                   adapter->ctx_desc_phys_addr);
-               adapter->ctx_desc = NULL;
-       }
-
-       if (adapter->ahw.cmd_desc_head != NULL) {
-               pci_free_consistent(adapter->pdev,
-                                   sizeof(struct cmd_desc_type0) *
-                                   adapter->max_tx_desc_count,
-                                   adapter->ahw.cmd_desc_head,
-                                   adapter->ahw.cmd_desc_phys_addr);
-               adapter->ahw.cmd_desc_head = NULL;
-       }
-
-       for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
-               recv_ctx = &adapter->recv_ctx[ctx];
-               for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
-                       rcv_desc = &recv_ctx->rcv_desc[ring];
-
-                       if (rcv_desc->desc_head != NULL) {
-                               pci_free_consistent(adapter->pdev,
-                                                   RCV_DESC_RINGSIZE,
-                                                   rcv_desc->desc_head,
-                                                   rcv_desc->phys_addr);
-                               rcv_desc->desc_head = NULL;
-                       }
-               }
+       struct netxen_adapter *adapter = netdev_priv(netdev);
+       nx_mac_list_t *cur, *next, *del_list, *add_list = NULL;
+       struct dev_mc_list *mc_ptr;
+       u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+       adapter->set_promisc(adapter, NETXEN_NIU_PROMISC_MODE);
+
+       /*
+        * Programming mac addresses will automaticly enabling L2 filtering.
+        * HW will replace timestamp with L2 conid when L2 filtering is
+        * enabled. This causes problem for LSA. Do not enabling L2 filtering
+        * until that problem is fixed.
+        */
+       if ((netdev->flags & IFF_PROMISC) ||
+                       (netdev->mc_count > adapter->max_mc_count))
+               return;
 
-               if (recv_ctx->rcv_status_desc_head != NULL) {
-                       pci_free_consistent(adapter->pdev,
-                                           STATUS_DESC_RINGSIZE,
-                                           recv_ctx->rcv_status_desc_head,
-                                           recv_ctx->
-                                           rcv_status_desc_phys_addr);
-                       recv_ctx->rcv_status_desc_head = NULL;
+       del_list = adapter->mac_list;
+       adapter->mac_list = NULL;
+
+       nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list);
+       if (netdev->mc_count > 0) {
+               nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list);
+               for (mc_ptr = netdev->mc_list; mc_ptr;
+                    mc_ptr = mc_ptr->next) {
+                       nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr,
+                                         &add_list, &del_list);
                }
        }
+       for (cur = del_list; cur;) {
+               nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL);
+               next = cur->next;
+               kfree(cur);
+               cur = next;
+       }
+       for (cur = add_list; cur;) {
+               nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD);
+               next = cur->next;
+               cur->next = adapter->mac_list;
+               adapter->mac_list = cur;
+               cur = next;
+       }
 }
 
-void netxen_tso_check(struct netxen_adapter *adapter,
-                     struct cmd_desc_type0 *desc, struct sk_buff *skb)
+#define        NETXEN_CONFIG_INTR_COALESCE     3
+
+/*
+ * Send the interrupt coalescing parameter set by ethtool to the card.
+ */
+int netxen_config_intr_coalesce(struct netxen_adapter *adapter)
 {
-       if (desc->mss) {
-               desc->total_hdr_length = (sizeof(struct ethhdr) +
-                                         ip_hdrlen(skb) + tcp_hdrlen(skb));
-               netxen_set_cmd_desc_opcode(desc, TX_TCP_LSO);
-       } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
-                       netxen_set_cmd_desc_opcode(desc, TX_TCP_PKT);
-               } else if (ip_hdr(skb)->protocol == IPPROTO_UDP) {
-                       netxen_set_cmd_desc_opcode(desc, TX_UDP_PKT);
-               } else {
-                       return;
-               }
+       nx_nic_req_t req;
+       int rv;
+
+       memset(&req, 0, sizeof(nx_nic_req_t));
+
+       req.qhdr |= (NIC_REQUEST << 23);
+       req.req_hdr |= NETXEN_CONFIG_INTR_COALESCE;
+       req.req_hdr |= ((u64)adapter->portnum << 16);
+
+       memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal));
+
+       rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
+       if (rv != 0) {
+               printk(KERN_ERR "ERROR. Could not send "
+                       "interrupt coalescing parameters\n");
        }
-       desc->tcp_hdr_offset = skb_transport_offset(skb);
-       desc->ip_hdr_offset = skb_network_offset(skb);
+
+       return rv;
+}
+
+/*
+ * netxen_nic_change_mtu - Change the Maximum Transfer Unit
+ * @returns 0 on success, negative on failure
+ */
+
+#define MTU_FUDGE_FACTOR       100
+
+int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
+{
+       struct netxen_adapter *adapter = netdev_priv(netdev);
+       int max_mtu;
+
+       if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+               max_mtu = P3_MAX_MTU;
+       else
+               max_mtu = P2_MAX_MTU;
+
+       if (mtu > max_mtu) {
+               printk(KERN_ERR "%s: mtu > %d bytes unsupported\n",
+                               netdev->name, max_mtu);
+               return -EINVAL;
+       }
+
+       if (adapter->set_mtu)
+               adapter->set_mtu(adapter, mtu);
+       netdev->mtu = mtu;
+
+       mtu += MTU_FUDGE_FACTOR;
+       if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+               nx_fw_cmd_set_mtu(adapter, mtu);
+       else if (adapter->set_mtu)
+               adapter->set_mtu(adapter, mtu);
+
+       return 0;
 }
 
 int netxen_is_flash_supported(struct netxen_adapter *adapter)
@@ -2079,6 +2016,8 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
        case NETXEN_BRDTYPE_P3_10G_CX4_LP:
        case NETXEN_BRDTYPE_P3_IMEZ:
        case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
+       case NETXEN_BRDTYPE_P3_10G_SFP_CT:
+       case NETXEN_BRDTYPE_P3_10G_SFP_QT:
        case NETXEN_BRDTYPE_P3_10G_XFP:
        case NETXEN_BRDTYPE_P3_10000_BASE_T:
 
@@ -2097,6 +2036,7 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
        default:
                printk("%s: Unknown(%x)\n", netxen_nic_driver_name,
                       boardinfo->board_type);
+               rv = -ENODEV;
                break;
        }
 
@@ -2125,11 +2065,6 @@ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
        return 0;
 }
 
-void netxen_nic_init_niu_gb(struct netxen_adapter *adapter)
-{
-       netxen_niu_gbe_init_port(adapter, adapter->physical_port);
-}
-
 void
 netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
                unsigned long off, int data)
@@ -2142,12 +2077,22 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
        __u32 status;
        __u32 autoneg;
        __u32 mode;
+       __u32 port_mode;
 
        netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode);
        if (netxen_get_niu_enable_ge(mode)) {   /* Gb 10/100/1000 Mbps mode */
+
+               adapter->hw_read_wx(adapter,
+                               NETXEN_PORT_MODE_ADDR, &port_mode, 4);
+               if (port_mode == NETXEN_PORT_MODE_802_3_AP) {
+                       adapter->link_speed   = SPEED_1000;
+                       adapter->link_duplex  = DUPLEX_FULL;
+                       adapter->link_autoneg = AUTONEG_DISABLE;
+                       return;
+               }
+
                if (adapter->phy_read
-                   && adapter->
-                   phy_read(adapter,
+                   && adapter->phy_read(adapter,
                             NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
                             &status) == 0) {
                        if (netxen_get_phy_link(status)) {
@@ -2177,8 +2122,7 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter)
                                        break;
                                }
                                if (adapter->phy_read
-                                   && adapter->
-                                   phy_read(adapter,
+                                   && adapter->phy_read(adapter,
                                             NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
                                             &autoneg) != 0)
                                        adapter->link_autoneg = autoneg;
@@ -2236,16 +2180,12 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter)
                                fw_minor, fw_build);
        }
 
-       if (fw_major != _NETXEN_NIC_LINUX_MAJOR) {
+       if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) <
+                       NETXEN_VERSION_CODE(3, 4, 216)) {
                adapter->driver_mismatch = 1;
-       }
-       if (fw_minor != _NETXEN_NIC_LINUX_MINOR &&
-                       fw_minor != (_NETXEN_NIC_LINUX_MINOR + 1)) {
-               adapter->driver_mismatch = 1;
-       }
-       if (adapter->driver_mismatch) {
-               printk(KERN_ERR "%s: driver and firmware version mismatch\n",
-                               adapter->netdev->name);
+               printk(KERN_ERR "%s: firmware version %d.%d.%d unsupported\n",
+                               netxen_nic_driver_name,
+                               fw_major, fw_minor, fw_build);
                return;
        }
 }