]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/netxen/netxen_nic_main.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6-omap-h63xx.git] / drivers / net / netxen / netxen_nic_main.c
index 555b4596b0fe46ee703441069aa8c50a3d4f9343..1af47257ba821d9a06c7e37d1a2b77425d01327e 100644 (file)
@@ -135,20 +135,71 @@ static uint32_t msi_tgt_status[8] = {
 
 static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG;
 
-static inline void netxen_nic_disable_int(struct netxen_adapter *adapter)
+static inline void netxen_nic_disable_int(struct nx_host_sds_ring *sds_ring)
 {
-       adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0);
+       struct netxen_adapter *adapter = sds_ring->adapter;
+
+       adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0);
 }
 
-static inline void netxen_nic_enable_int(struct netxen_adapter *adapter)
+static inline void netxen_nic_enable_int(struct nx_host_sds_ring *sds_ring)
 {
-       adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1);
+       struct netxen_adapter *adapter = sds_ring->adapter;
+
+       adapter->pci_write_normalize(adapter, sds_ring->crb_intr_mask, 0x1);
 
        if (!NETXEN_IS_MSI_FAMILY(adapter))
                adapter->pci_write_immediate(adapter,
                                adapter->legacy_intr.tgt_mask_reg, 0xfbff);
 }
 
+static void
+netxen_napi_add(struct netxen_adapter *adapter, struct net_device *netdev)
+{
+       int ring;
+       struct nx_host_sds_ring *sds_ring;
+       struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+       if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
+               adapter->max_sds_rings = (num_online_cpus() >= 4) ? 4 : 2;
+       else
+               adapter->max_sds_rings = 1;
+
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               netif_napi_add(netdev, &sds_ring->napi,
+                               netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
+       }
+}
+
+static void
+netxen_napi_enable(struct netxen_adapter *adapter)
+{
+       int ring;
+       struct nx_host_sds_ring *sds_ring;
+       struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               napi_enable(&sds_ring->napi);
+               netxen_nic_enable_int(sds_ring);
+       }
+}
+
+static void
+netxen_napi_disable(struct netxen_adapter *adapter)
+{
+       int ring;
+       struct nx_host_sds_ring *sds_ring;
+       struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               netxen_nic_disable_int(sds_ring);
+               napi_disable(&sds_ring->napi);
+       }
+}
+
 static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id)
 {
        struct pci_dev *pdev = adapter->pdev;
@@ -212,64 +263,20 @@ nx_update_dma_mask(struct netxen_adapter *adapter)
 
 static void netxen_check_options(struct netxen_adapter *adapter)
 {
-       switch (adapter->ahw.board_type) {
-       case NETXEN_BRDTYPE_P3_HMEZ:
-       case NETXEN_BRDTYPE_P3_XG_LOM:
-       case NETXEN_BRDTYPE_P3_10G_CX4:
-       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_QT:
-       case NETXEN_BRDTYPE_P3_10G_SFP_CT:
-       case NETXEN_BRDTYPE_P3_10G_XFP:
-       case NETXEN_BRDTYPE_P3_10000_BASE_T:
-               adapter->msix_supported = !!use_msi_x;
-               adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
-               break;
-
-       case NETXEN_BRDTYPE_P2_SB31_10G:
-       case NETXEN_BRDTYPE_P2_SB31_10G_CX4:
-       case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ:
-       case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ:
-               adapter->msix_supported = 0;
-               adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
-               break;
-
-       case NETXEN_BRDTYPE_P3_REF_QG:
-       case NETXEN_BRDTYPE_P3_4_GB:
-       case NETXEN_BRDTYPE_P3_4_GB_MM:
-               adapter->msix_supported = !!use_msi_x;
-               adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
-               break;
+       if (adapter->ahw.port_type == NETXEN_NIC_XGBE)
+               adapter->num_rxd = MAX_RCV_DESCRIPTORS_10G;
+       else if (adapter->ahw.port_type == NETXEN_NIC_GBE)
+               adapter->num_rxd = MAX_RCV_DESCRIPTORS_1G;
 
-       case NETXEN_BRDTYPE_P2_SB35_4G:
-       case NETXEN_BRDTYPE_P2_SB31_2G:
-               adapter->msix_supported = 0;
-               adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
-               break;
-
-       case NETXEN_BRDTYPE_P3_10G_TP:
+       if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
                adapter->msix_supported = !!use_msi_x;
-               if (adapter->ahw.port_type == NETXEN_NIC_XGBE)
-                       adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_10G;
-               else
-                       adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
-               break;
-
-       default:
+       else
                adapter->msix_supported = 0;
-               adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS_1G;
 
-               printk(KERN_WARNING "Unknown board type(0x%x)\n",
-                               adapter->ahw.board_type);
-               break;
-       }
+       adapter->num_txd = MAX_CMD_DESCRIPTORS_HOST;
+       adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS;
+       adapter->num_lro_rxd = MAX_LRO_RCV_DESCRIPTORS;
 
-       adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS_HOST;
-       adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS;
-       adapter->max_lro_rx_desc_count = MAX_LRO_RCV_DESCRIPTORS;
-
-       adapter->max_possible_rss_rings = 1;
        return;
 }
 
@@ -399,9 +406,6 @@ netxen_read_mac_addr(struct netxen_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
 
-       if (netxen_is_flash_supported(adapter) != 0)
-               return -EIO;
-
        if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
                if (netxen_p3_get_mac_addr(adapter, &mac_addr) != 0)
                        return -EIO;
@@ -490,6 +494,7 @@ request_msi:
                        dev_info(&pdev->dev, "using msi interrupts\n");
                } else
                        dev_info(&pdev->dev, "using legacy interrupts\n");
+               adapter->msix_entries[0].vector = pdev->irq;
        }
 }
 
@@ -714,8 +719,12 @@ static int
 netxen_nic_request_irq(struct netxen_adapter *adapter)
 {
        irq_handler_t handler;
+       struct nx_host_sds_ring *sds_ring;
+       int err, ring;
+
        unsigned long flags = IRQF_SAMPLE_RANDOM;
        struct net_device *netdev = adapter->netdev;
+       struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
 
        if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) ||
                (adapter->intr_scheme != INTR_SCHEME_PERPORT)) {
@@ -736,8 +745,30 @@ netxen_nic_request_irq(struct netxen_adapter *adapter)
        }
        adapter->irq = netdev->irq;
 
-       return request_irq(adapter->irq, handler,
-                         flags, netdev->name, adapter);
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               sprintf(sds_ring->name, "%16s[%d]", netdev->name, ring);
+               err = request_irq(sds_ring->irq, handler,
+                                 flags, sds_ring->name, sds_ring);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+static void
+netxen_nic_free_irq(struct netxen_adapter *adapter)
+{
+       int ring;
+       struct nx_host_sds_ring *sds_ring;
+
+       struct netxen_recv_context *recv_ctx = &adapter->recv_ctx;
+
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               free_irq(sds_ring->irq, sds_ring);
+       }
 }
 
 static int
@@ -762,8 +793,10 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev)
        adapter->ahw.linkup = 0;
        mod_timer(&adapter->watchdog_timer, jiffies);
 
-       napi_enable(&adapter->napi);
-       netxen_nic_enable_int(adapter);
+       netxen_napi_enable(adapter);
+
+       if (adapter->max_sds_rings > 1)
+               netxen_config_rss(adapter, 1);
 
        return 0;
 }
@@ -773,13 +806,11 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
 {
        netif_carrier_off(netdev);
        netif_stop_queue(netdev);
-       napi_disable(&adapter->napi);
+       netxen_napi_disable(adapter);
 
        if (adapter->stop_port)
                adapter->stop_port(adapter);
 
-       netxen_nic_disable_int(adapter);
-
        netxen_release_tx_buffers(adapter);
 
        FLUSH_SCHEDULED_WORK();
@@ -793,6 +824,7 @@ netxen_nic_attach(struct netxen_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
        struct pci_dev *pdev = adapter->pdev;
        int err, ring;
+       struct nx_host_rds_ring *rds_ring;
 
        err = netxen_init_firmware(adapter);
        if (err != 0) {
@@ -831,8 +863,10 @@ netxen_nic_attach(struct netxen_adapter *adapter)
                netxen_nic_update_cmd_consumer(adapter, 0);
        }
 
-       for (ring = 0; ring < adapter->max_rds_rings; ring++)
-               netxen_post_rx_buffers(adapter, ring);
+       for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+               rds_ring = &adapter->recv_ctx.rds_rings[ring];
+               netxen_post_rx_buffers(adapter, ring, rds_ring);
+       }
 
        err = netxen_nic_request_irq(adapter);
        if (err) {
@@ -855,8 +889,7 @@ err_out_free_sw:
 static void
 netxen_nic_detach(struct netxen_adapter *adapter)
 {
-       if (adapter->irq)
-               free_irq(adapter->irq, adapter);
+       netxen_nic_free_irq(adapter);
 
        netxen_release_rx_buffers(adapter);
        netxen_free_hw_resources(adapter);
@@ -874,9 +907,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        int pci_func_id = PCI_FUNC(pdev->devfn);
        uint8_t revision_id;
 
-       if (pci_func_id == 0)
-               printk(KERN_INFO "%s\n", netxen_nic_driver_string);
-
        if (pdev->class != 0x020000) {
                printk(KERN_DEBUG "NetXen function %d, class %x will not "
                                "be enabled.\n",pci_func_id, pdev->class);
@@ -926,14 +956,12 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_out_free_netdev;
 
        rwlock_init(&adapter->adapter_lock);
+       spin_lock_init(&adapter->tx_clean_lock);
 
        err = netxen_setup_pci_map(adapter);
        if (err)
                goto err_out_free_netdev;
 
-       netif_napi_add(netdev, &adapter->napi,
-                       netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
-
        /* This will be reset for mezz cards  */
        adapter->portnum = pci_func_id;
        adapter->rx_csum = 1;
@@ -983,12 +1011,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                break;
        }
 
-       /*
-        * This call will setup various max rx/tx counts.
-        * It must be done before any buffer/ring allocations.
-        */
-       netxen_check_options(adapter);
-
        err = netxen_start_firmware(adapter);
        if (err)
                goto err_out_iounmap;
@@ -1008,16 +1030,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        adapter->physical_port = i;
        }
 
-       adapter->flags &= ~(NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED);
-
-       netxen_set_msix_bit(pdev, 0);
+       netxen_check_options(adapter);
 
        netxen_setup_intr(adapter);
 
-       if (adapter->flags & NETXEN_NIC_MSIX_ENABLED)
-               netdev->irq = adapter->msix_entries[0].vector;
-       else
-               netdev->irq = pdev->irq;
+       netdev->irq = adapter->msix_entries[0].vector;
+
+       netxen_napi_add(adapter, netdev);
 
        err = netxen_receive_peg_ready(adapter);
        if (err)
@@ -1307,7 +1326,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
        u32 producer, consumer;
        int frag_count, no_of_desc;
-       u32 num_txd = adapter->max_tx_desc_count;
+       u32 num_txd = adapter->num_txd;
        bool is_tso = false;
 
        frag_count = skb_shinfo(skb)->nr_frags + 1;
@@ -1571,13 +1590,11 @@ static void netxen_tx_timeout_task(struct work_struct *work)
        printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
               netxen_nic_driver_name, adapter->netdev->name);
 
-       netxen_nic_disable_int(adapter);
-       napi_disable(&adapter->napi);
+       netxen_napi_disable(adapter);
 
        adapter->netdev->trans_start = jiffies;
 
-       napi_enable(&adapter->napi);
-       netxen_nic_enable_int(adapter);
+       netxen_napi_enable(adapter);
        netif_wake_queue(adapter->netdev);
 }
 
@@ -1615,7 +1632,8 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
 
 static irqreturn_t netxen_intr(int irq, void *data)
 {
-       struct netxen_adapter *adapter = data;
+       struct nx_host_sds_ring *sds_ring = data;
+       struct netxen_adapter *adapter = sds_ring->adapter;
        u32 status = 0;
 
        status = adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
@@ -1646,7 +1664,7 @@ static irqreturn_t netxen_intr(int irq, void *data)
 
        /* clear interrupt */
        if (adapter->fw_major < 4)
-               netxen_nic_disable_int(adapter);
+               netxen_nic_disable_int(sds_ring);
 
        adapter->pci_write_immediate(adapter,
                        adapter->legacy_intr.tgt_status_reg,
@@ -1655,45 +1673,49 @@ static irqreturn_t netxen_intr(int irq, void *data)
        adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
        adapter->pci_read_immediate(adapter, ISR_INT_VECTOR);
 
-       napi_schedule(&adapter->napi);
+       napi_schedule(&sds_ring->napi);
 
        return IRQ_HANDLED;
 }
 
 static irqreturn_t netxen_msi_intr(int irq, void *data)
 {
-       struct netxen_adapter *adapter = data;
+       struct nx_host_sds_ring *sds_ring = data;
+       struct netxen_adapter *adapter = sds_ring->adapter;
 
        /* clear interrupt */
        adapter->pci_write_immediate(adapter,
                        msi_tgt_status[adapter->ahw.pci_func], 0xffffffff);
 
-       napi_schedule(&adapter->napi);
+       napi_schedule(&sds_ring->napi);
        return IRQ_HANDLED;
 }
 
 static irqreturn_t netxen_msix_intr(int irq, void *data)
 {
-       struct netxen_adapter *adapter = data;
+       struct nx_host_sds_ring *sds_ring = data;
 
-       napi_schedule(&adapter->napi);
+       napi_schedule(&sds_ring->napi);
        return IRQ_HANDLED;
 }
 
 static int netxen_nic_poll(struct napi_struct *napi, int budget)
 {
-       struct netxen_adapter *adapter =
-               container_of(napi, struct netxen_adapter, napi);
+       struct nx_host_sds_ring *sds_ring =
+               container_of(napi, struct nx_host_sds_ring, napi);
+
+       struct netxen_adapter *adapter = sds_ring->adapter;
+
        int tx_complete;
        int work_done;
 
        tx_complete = netxen_process_cmd_ring(adapter);
 
-       work_done = netxen_process_rcv_ring(adapter, budget);
+       work_done = netxen_process_rcv_ring(sds_ring, budget);
 
        if ((work_done < budget) && tx_complete) {
-               napi_complete(&adapter->napi);
-               netxen_nic_enable_int(adapter);
+               napi_complete(&sds_ring->napi);
+               netxen_nic_enable_int(sds_ring);
        }
 
        return work_done;
@@ -1722,6 +1744,8 @@ static struct pci_driver netxen_driver = {
 
 static int __init netxen_init_module(void)
 {
+       printk(KERN_INFO "%s\n", netxen_nic_driver_string);
+
        if ((netxen_workq = create_singlethread_workqueue("netxen")) == NULL)
                return -ENOMEM;