aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/s2io-regs.h2
-rw-r--r--drivers/net/s2io.c93
-rw-r--r--drivers/net/s2io.h6
3 files changed, 98 insertions, 3 deletions
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h
index cfa267914476..83e3e47a9e3d 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/s2io-regs.h
@@ -220,7 +220,7 @@ struct XENA_dev_config {
220 u64 scheduled_int_ctrl; 220 u64 scheduled_int_ctrl;
221#define SCHED_INT_CTRL_TIMER_EN BIT(0) 221#define SCHED_INT_CTRL_TIMER_EN BIT(0)
222#define SCHED_INT_CTRL_ONE_SHOT BIT(1) 222#define SCHED_INT_CTRL_ONE_SHOT BIT(1)
223#define SCHED_INT_CTRL_INT2MSI TBD 223#define SCHED_INT_CTRL_INT2MSI(val) vBIT(val,10,6)
224#define SCHED_INT_PERIOD TBD 224#define SCHED_INT_PERIOD TBD
225 225
226 u64 txreqtimeout; 226 u64 txreqtimeout;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index dd012322cdbe..588938204e20 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -37,7 +37,7 @@
37 * tx_fifo_len: This too is an array of 8. Each element defines the number of 37 * tx_fifo_len: This too is an array of 8. Each element defines the number of
38 * Tx descriptors that can be associated with each corresponding FIFO. 38 * Tx descriptors that can be associated with each corresponding FIFO.
39 * intr_type: This defines the type of interrupt. The values can be 0(INTA), 39 * intr_type: This defines the type of interrupt. The values can be 0(INTA),
40 * 2(MSI_X). Default value is '0(INTA)' 40 * 2(MSI_X). Default value is '2(MSI_X)'
41 * lro: Specifies whether to enable Large Receive Offload (LRO) or not. 41 * lro: Specifies whether to enable Large Receive Offload (LRO) or not.
42 * Possible values '1' for enable '0' for disable. Default is '0' 42 * Possible values '1' for enable '0' for disable. Default is '0'
43 * lro_max_pkts: This parameter defines maximum number of packets can be 43 * lro_max_pkts: This parameter defines maximum number of packets can be
@@ -428,7 +428,7 @@ S2IO_PARM_INT(l3l4hdr_size, 128);
428/* Frequency of Rx desc syncs expressed as power of 2 */ 428/* Frequency of Rx desc syncs expressed as power of 2 */
429S2IO_PARM_INT(rxsync_frequency, 3); 429S2IO_PARM_INT(rxsync_frequency, 3);
430/* Interrupt type. Values can be 0(INTA), 2(MSI_X) */ 430/* Interrupt type. Values can be 0(INTA), 2(MSI_X) */
431S2IO_PARM_INT(intr_type, 0); 431S2IO_PARM_INT(intr_type, 2);
432/* Large receive offload feature */ 432/* Large receive offload feature */
433S2IO_PARM_INT(lro, 0); 433S2IO_PARM_INT(lro, 0);
434/* Max pkts to be aggregated by LRO at one time. If not specified, 434/* Max pkts to be aggregated by LRO at one time. If not specified,
@@ -3773,6 +3773,59 @@ static int s2io_enable_msi_x(struct s2io_nic *nic)
3773 return 0; 3773 return 0;
3774} 3774}
3775 3775
3776/* Handle software interrupt used during MSI(X) test */
3777static irqreturn_t __devinit s2io_test_intr(int irq, void *dev_id)
3778{
3779 struct s2io_nic *sp = dev_id;
3780
3781 sp->msi_detected = 1;
3782 wake_up(&sp->msi_wait);
3783
3784 return IRQ_HANDLED;
3785}
3786
3787/* Test interrupt path by forcing a a software IRQ */
3788static int __devinit s2io_test_msi(struct s2io_nic *sp)
3789{
3790 struct pci_dev *pdev = sp->pdev;
3791 struct XENA_dev_config __iomem *bar0 = sp->bar0;
3792 int err;
3793 u64 val64, saved64;
3794
3795 err = request_irq(sp->entries[1].vector, s2io_test_intr, 0,
3796 sp->name, sp);
3797 if (err) {
3798 DBG_PRINT(ERR_DBG, "%s: PCI %s: cannot assign irq %d\n",
3799 sp->dev->name, pci_name(pdev), pdev->irq);
3800 return err;
3801 }
3802
3803 init_waitqueue_head (&sp->msi_wait);
3804 sp->msi_detected = 0;
3805
3806 saved64 = val64 = readq(&bar0->scheduled_int_ctrl);
3807 val64 |= SCHED_INT_CTRL_ONE_SHOT;
3808 val64 |= SCHED_INT_CTRL_TIMER_EN;
3809 val64 |= SCHED_INT_CTRL_INT2MSI(1);
3810 writeq(val64, &bar0->scheduled_int_ctrl);
3811
3812 wait_event_timeout(sp->msi_wait, sp->msi_detected, HZ/10);
3813
3814 if (!sp->msi_detected) {
3815 /* MSI(X) test failed, go back to INTx mode */
3816 DBG_PRINT(ERR_DBG, "%s: PCI %s: No interrupt was generated"
3817 "using MSI(X) during test\n", sp->dev->name,
3818 pci_name(pdev));
3819
3820 err = -EOPNOTSUPP;
3821 }
3822
3823 free_irq(sp->entries[1].vector, sp);
3824
3825 writeq(saved64, &bar0->scheduled_int_ctrl);
3826
3827 return err;
3828}
3776/* ********************************************************* * 3829/* ********************************************************* *
3777 * Functions defined below concern the OS part of the driver * 3830 * Functions defined below concern the OS part of the driver *
3778 * ********************************************************* */ 3831 * ********************************************************* */
@@ -3803,6 +3856,42 @@ static int s2io_open(struct net_device *dev)
3803 3856
3804 napi_enable(&sp->napi); 3857 napi_enable(&sp->napi);
3805 3858
3859 if (sp->intr_type == MSI_X) {
3860 int ret = s2io_enable_msi_x(sp);
3861
3862 if (!ret) {
3863 u16 msi_control;
3864
3865 ret = s2io_test_msi(sp);
3866
3867 /* rollback MSI-X, will re-enable during add_isr() */
3868 kfree(sp->entries);
3869 sp->mac_control.stats_info->sw_stat.mem_freed +=
3870 (MAX_REQUESTED_MSI_X *
3871 sizeof(struct msix_entry));
3872 kfree(sp->s2io_entries);
3873 sp->mac_control.stats_info->sw_stat.mem_freed +=
3874 (MAX_REQUESTED_MSI_X *
3875 sizeof(struct s2io_msix_entry));
3876 sp->entries = NULL;
3877 sp->s2io_entries = NULL;
3878
3879 pci_read_config_word(sp->pdev, 0x42, &msi_control);
3880 msi_control &= 0xFFFE; /* Disable MSI */
3881 pci_write_config_word(sp->pdev, 0x42, msi_control);
3882
3883 pci_disable_msix(sp->pdev);
3884
3885 }
3886 if (ret) {
3887
3888 DBG_PRINT(ERR_DBG,
3889 "%s: MSI-X requested but failed to enable\n",
3890 dev->name);
3891 sp->intr_type = INTA;
3892 }
3893 }
3894
3806 /* Initialize H/W and enable interrupts */ 3895 /* Initialize H/W and enable interrupts */
3807 err = s2io_card_up(sp); 3896 err = s2io_card_up(sp);
3808 if (err) { 3897 if (err) {
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 420fefb99188..62398fab2e96 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -412,6 +412,10 @@ struct config_param {
412 struct tx_fifo_config tx_cfg[MAX_TX_FIFOS]; /*Per-Tx FIFO config */ 412 struct tx_fifo_config tx_cfg[MAX_TX_FIFOS]; /*Per-Tx FIFO config */
413 u32 max_txds; /*Max no. of Tx buffer descriptor per TxDL */ 413 u32 max_txds; /*Max no. of Tx buffer descriptor per TxDL */
414 u64 tx_intr_type; 414 u64 tx_intr_type;
415#define INTA 0
416#define MSI_X 2
417 u8 intr_type;
418
415 /* Specifies if Tx Intr is UTILZ or PER_LIST type. */ 419 /* Specifies if Tx Intr is UTILZ or PER_LIST type. */
416 420
417/* Rx Side */ 421/* Rx Side */
@@ -862,6 +866,8 @@ struct s2io_nic {
862 struct vlan_group *vlgrp; 866 struct vlan_group *vlgrp;
863#define MSIX_FLG 0xA5 867#define MSIX_FLG 0xA5
864 struct msix_entry *entries; 868 struct msix_entry *entries;
869 int msi_detected;
870 wait_queue_head_t msi_wait;
865 struct s2io_msix_entry *s2io_entries; 871 struct s2io_msix_entry *s2io_entries;
866 char desc[MAX_REQUESTED_MSI_X][25]; 872 char desc[MAX_REQUESTED_MSI_X][25];
867 873