aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRavinandan Arakali <ravinandan.arakali@neterion.com>2005-10-04 06:41:24 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-10-04 06:41:24 -0400
commitcc6e7c44f4b8ab13acf5521cd4b312848122179f (patch)
tree9a95e57befa59f6a50e5eb8ef4c9f8ae26816b87 /drivers
parentd9e34325fd62310b7b49243d02b774f3ef2452db (diff)
[PATCH] S2io: MSI/MSI-X support (runtime configurable)
This patch adds support for MSI/MSI-X feature to the driver. It is a runtime parameter(for now, loadable parameter). Default is INTA. Patch has been tested on IA64 platform with Xframe II adapter, both of which support MSI-X feature. An improvement of about 7% in throughput(both Tx and Rx) was observed and a reduction by 7% in CPU utilization during Tx test. Signed-off-by: Ravinandan Arakali <ravinandan.arakali@neterion.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/s2io.c543
-rw-r--r--drivers/net/s2io.h50
2 files changed, 556 insertions, 37 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index dd451e099a4c..4b9f1828845e 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -67,7 +67,7 @@
67 67
68/* S2io Driver name & version. */ 68/* S2io Driver name & version. */
69static char s2io_driver_name[] = "Neterion"; 69static char s2io_driver_name[] = "Neterion";
70static char s2io_driver_version[] = "Version 2.0.8.1"; 70static char s2io_driver_version[] = "Version 2.0.9.1";
71 71
72static inline int RXD_IS_UP2DT(RxD_t *rxdp) 72static inline int RXD_IS_UP2DT(RxD_t *rxdp)
73{ 73{
@@ -307,6 +307,8 @@ static unsigned int indicate_max_pkts;
307#endif 307#endif
308/* Frequency of Rx desc syncs expressed as power of 2 */ 308/* Frequency of Rx desc syncs expressed as power of 2 */
309static unsigned int rxsync_frequency = 3; 309static unsigned int rxsync_frequency = 3;
310/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */
311static unsigned int intr_type = 0;
310 312
311/* 313/*
312 * S2IO device table. 314 * S2IO device table.
@@ -1396,8 +1398,13 @@ static int init_nic(struct s2io_nic *nic)
1396 writeq(val64, &bar0->rti_data1_mem); 1398 writeq(val64, &bar0->rti_data1_mem);
1397 1399
1398 val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) | 1400 val64 = RTI_DATA2_MEM_RX_UFC_A(0x1) |
1399 RTI_DATA2_MEM_RX_UFC_B(0x2) | 1401 RTI_DATA2_MEM_RX_UFC_B(0x2) ;
1400 RTI_DATA2_MEM_RX_UFC_C(0x40) | RTI_DATA2_MEM_RX_UFC_D(0x80); 1402 if (nic->intr_type == MSI_X)
1403 val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x20) | \
1404 RTI_DATA2_MEM_RX_UFC_D(0x40));
1405 else
1406 val64 |= (RTI_DATA2_MEM_RX_UFC_C(0x40) | \
1407 RTI_DATA2_MEM_RX_UFC_D(0x80));
1401 writeq(val64, &bar0->rti_data2_mem); 1408 writeq(val64, &bar0->rti_data2_mem);
1402 1409
1403 for (i = 0; i < config->rx_ring_num; i++) { 1410 for (i = 0; i < config->rx_ring_num; i++) {
@@ -1507,17 +1514,15 @@ static int init_nic(struct s2io_nic *nic)
1507#define LINK_UP_DOWN_INTERRUPT 1 1514#define LINK_UP_DOWN_INTERRUPT 1
1508#define MAC_RMAC_ERR_TIMER 2 1515#define MAC_RMAC_ERR_TIMER 2
1509 1516
1510#if defined(CONFIG_MSI_MODE) || defined(CONFIG_MSIX_MODE)
1511#define s2io_link_fault_indication(x) MAC_RMAC_ERR_TIMER
1512#else
1513int s2io_link_fault_indication(nic_t *nic) 1517int s2io_link_fault_indication(nic_t *nic)
1514{ 1518{
1519 if (nic->intr_type != INTA)
1520 return MAC_RMAC_ERR_TIMER;
1515 if (nic->device_type == XFRAME_II_DEVICE) 1521 if (nic->device_type == XFRAME_II_DEVICE)
1516 return LINK_UP_DOWN_INTERRUPT; 1522 return LINK_UP_DOWN_INTERRUPT;
1517 else 1523 else
1518 return MAC_RMAC_ERR_TIMER; 1524 return MAC_RMAC_ERR_TIMER;
1519} 1525}
1520#endif
1521 1526
1522/** 1527/**
1523 * en_dis_able_nic_intrs - Enable or Disable the interrupts 1528 * en_dis_able_nic_intrs - Enable or Disable the interrupts
@@ -1941,11 +1946,14 @@ static int start_nic(struct s2io_nic *nic)
1941 } 1946 }
1942 1947
1943 /* Enable select interrupts */ 1948 /* Enable select interrupts */
1944 interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR; 1949 if (nic->intr_type != INTA)
1945 interruptible |= TX_PIC_INTR | RX_PIC_INTR; 1950 en_dis_able_nic_intrs(nic, ENA_ALL_INTRS, DISABLE_INTRS);
1946 interruptible |= TX_MAC_INTR | RX_MAC_INTR; 1951 else {
1947 1952 interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
1948 en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS); 1953 interruptible |= TX_PIC_INTR | RX_PIC_INTR;
1954 interruptible |= TX_MAC_INTR | RX_MAC_INTR;
1955 en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
1956 }
1949 1957
1950 /* 1958 /*
1951 * With some switches, link might be already up at this point. 1959 * With some switches, link might be already up at this point.
@@ -2633,11 +2641,11 @@ static void tx_intr_handler(fifo_info_t *fifo_data)
2633 err = txdlp->Control_1 & TXD_T_CODE; 2641 err = txdlp->Control_1 & TXD_T_CODE;
2634 if ((err >> 48) == 0xA) { 2642 if ((err >> 48) == 0xA) {
2635 DBG_PRINT(TX_DBG, "TxD returned due \ 2643 DBG_PRINT(TX_DBG, "TxD returned due \
2636 to loss of link\n"); 2644to loss of link\n");
2637 } 2645 }
2638 else { 2646 else {
2639 DBG_PRINT(ERR_DBG, "***TxD error \ 2647 DBG_PRINT(ERR_DBG, "***TxD error \
2640 %llx\n", err); 2648%llx\n", err);
2641 } 2649 }
2642 } 2650 }
2643 2651
@@ -2854,6 +2862,9 @@ void s2io_reset(nic_t * sp)
2854 /* Set swapper to enable I/O register access */ 2862 /* Set swapper to enable I/O register access */
2855 s2io_set_swapper(sp); 2863 s2io_set_swapper(sp);
2856 2864
2865 /* Restore the MSIX table entries from local variables */
2866 restore_xmsi_data(sp);
2867
2857 /* Clear certain PCI/PCI-X fields after reset */ 2868 /* Clear certain PCI/PCI-X fields after reset */
2858 if (sp->device_type == XFRAME_II_DEVICE) { 2869 if (sp->device_type == XFRAME_II_DEVICE) {
2859 /* Clear parity err detect bit */ 2870 /* Clear parity err detect bit */
@@ -2983,8 +2994,9 @@ int s2io_set_swapper(nic_t * sp)
2983 SWAPPER_CTRL_RXD_W_FE | 2994 SWAPPER_CTRL_RXD_W_FE |
2984 SWAPPER_CTRL_RXF_W_FE | 2995 SWAPPER_CTRL_RXF_W_FE |
2985 SWAPPER_CTRL_XMSI_FE | 2996 SWAPPER_CTRL_XMSI_FE |
2986 SWAPPER_CTRL_XMSI_SE |
2987 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE); 2997 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
2998 if (nic->intr_type == INTA)
2999 val64 |= SWAPPER_CTRL_XMSI_SE;
2988 writeq(val64, &bar0->swapper_ctrl); 3000 writeq(val64, &bar0->swapper_ctrl);
2989#else 3001#else
2990 /* 3002 /*
@@ -3005,8 +3017,9 @@ int s2io_set_swapper(nic_t * sp)
3005 SWAPPER_CTRL_RXD_W_SE | 3017 SWAPPER_CTRL_RXD_W_SE |
3006 SWAPPER_CTRL_RXF_W_FE | 3018 SWAPPER_CTRL_RXF_W_FE |
3007 SWAPPER_CTRL_XMSI_FE | 3019 SWAPPER_CTRL_XMSI_FE |
3008 SWAPPER_CTRL_XMSI_SE |
3009 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE); 3020 SWAPPER_CTRL_STATS_FE | SWAPPER_CTRL_STATS_SE);
3021 if (sp->intr_type == INTA)
3022 val64 |= SWAPPER_CTRL_XMSI_SE;
3010 writeq(val64, &bar0->swapper_ctrl); 3023 writeq(val64, &bar0->swapper_ctrl);
3011#endif 3024#endif
3012 val64 = readq(&bar0->swapper_ctrl); 3025 val64 = readq(&bar0->swapper_ctrl);
@@ -3028,6 +3041,201 @@ int s2io_set_swapper(nic_t * sp)
3028 return SUCCESS; 3041 return SUCCESS;
3029} 3042}
3030 3043
3044int wait_for_msix_trans(nic_t *nic, int i)
3045{
3046 XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
3047 u64 val64;
3048 int ret = 0, cnt = 0;
3049
3050 do {
3051 val64 = readq(&bar0->xmsi_access);
3052 if (!(val64 & BIT(15)))
3053 break;
3054 mdelay(1);
3055 cnt++;
3056 } while(cnt < 5);
3057 if (cnt == 5) {
3058 DBG_PRINT(ERR_DBG, "XMSI # %d Access failed\n", i);
3059 ret = 1;
3060 }
3061
3062 return ret;
3063}
3064
3065void restore_xmsi_data(nic_t *nic)
3066{
3067 XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
3068 u64 val64;
3069 int i;
3070
3071 for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
3072 writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
3073 writeq(nic->msix_info[i].data, &bar0->xmsi_data);
3074 val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
3075 writeq(val64, &bar0->xmsi_access);
3076 if (wait_for_msix_trans(nic, i)) {
3077 DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
3078 continue;
3079 }
3080 }
3081}
3082
3083void store_xmsi_data(nic_t *nic)
3084{
3085 XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
3086 u64 val64, addr, data;
3087 int i;
3088
3089 /* Store and display */
3090 for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
3091 val64 = (BIT(15) | vBIT(i, 26, 6));
3092 writeq(val64, &bar0->xmsi_access);
3093 if (wait_for_msix_trans(nic, i)) {
3094 DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__);
3095 continue;
3096 }
3097 addr = readq(&bar0->xmsi_address);
3098 data = readq(&bar0->xmsi_data);
3099 if (addr && data) {
3100 nic->msix_info[i].addr = addr;
3101 nic->msix_info[i].data = data;
3102 }
3103 }
3104}
3105
3106int s2io_enable_msi(nic_t *nic)
3107{
3108 XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
3109 u16 msi_ctrl, msg_val;
3110 struct config_param *config = &nic->config;
3111 struct net_device *dev = nic->dev;
3112 u64 val64, tx_mat, rx_mat;
3113 int i, err;
3114
3115 val64 = readq(&bar0->pic_control);
3116 val64 &= ~BIT(1);
3117 writeq(val64, &bar0->pic_control);
3118
3119 err = pci_enable_msi(nic->pdev);
3120 if (err) {
3121 DBG_PRINT(ERR_DBG, "%s: enabling MSI failed\n",
3122 nic->dev->name);
3123 return err;
3124 }
3125
3126 /*
3127 * Enable MSI and use MSI-1 in stead of the standard MSI-0
3128 * for interrupt handling.
3129 */
3130 pci_read_config_word(nic->pdev, 0x4c, &msg_val);
3131 msg_val ^= 0x1;
3132 pci_write_config_word(nic->pdev, 0x4c, msg_val);
3133 pci_read_config_word(nic->pdev, 0x4c, &msg_val);
3134
3135 pci_read_config_word(nic->pdev, 0x42, &msi_ctrl);
3136 msi_ctrl |= 0x10;
3137 pci_write_config_word(nic->pdev, 0x42, msi_ctrl);
3138
3139 /* program MSI-1 into all usable Tx_Mat and Rx_Mat fields */
3140 tx_mat = readq(&bar0->tx_mat0_n[0]);
3141 for (i=0; i<config->tx_fifo_num; i++) {
3142 tx_mat |= TX_MAT_SET(i, 1);
3143 }
3144 writeq(tx_mat, &bar0->tx_mat0_n[0]);
3145
3146 rx_mat = readq(&bar0->rx_mat);
3147 for (i=0; i<config->rx_ring_num; i++) {
3148 rx_mat |= RX_MAT_SET(i, 1);
3149 }
3150 writeq(rx_mat, &bar0->rx_mat);
3151
3152 dev->irq = nic->pdev->irq;
3153 return 0;
3154}
3155
3156int s2io_enable_msi_x(nic_t *nic)
3157{
3158 XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0;
3159 u64 tx_mat, rx_mat;
3160 u16 msi_control; /* Temp variable */
3161 int ret, i, j, msix_indx = 1;
3162
3163 nic->entries = kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct msix_entry),
3164 GFP_KERNEL);
3165 if (nic->entries == NULL) {
3166 DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
3167 return -ENOMEM;
3168 }
3169 memset(nic->entries, 0, MAX_REQUESTED_MSI_X * sizeof(struct msix_entry));
3170
3171 nic->s2io_entries =
3172 kmalloc(MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry),
3173 GFP_KERNEL);
3174 if (nic->s2io_entries == NULL) {
3175 DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", __FUNCTION__);
3176 kfree(nic->entries);
3177 return -ENOMEM;
3178 }
3179 memset(nic->s2io_entries, 0,
3180 MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry));
3181
3182 for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
3183 nic->entries[i].entry = i;
3184 nic->s2io_entries[i].entry = i;
3185 nic->s2io_entries[i].arg = NULL;
3186 nic->s2io_entries[i].in_use = 0;
3187 }
3188
3189 tx_mat = readq(&bar0->tx_mat0_n[0]);
3190 for (i=0; i<nic->config.tx_fifo_num; i++, msix_indx++) {
3191 tx_mat |= TX_MAT_SET(i, msix_indx);
3192 nic->s2io_entries[msix_indx].arg = &nic->mac_control.fifos[i];
3193 nic->s2io_entries[msix_indx].type = MSIX_FIFO_TYPE;
3194 nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
3195 }
3196 writeq(tx_mat, &bar0->tx_mat0_n[0]);
3197
3198 if (!nic->config.bimodal) {
3199 rx_mat = readq(&bar0->rx_mat);
3200 for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
3201 rx_mat |= RX_MAT_SET(j, msix_indx);
3202 nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
3203 nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
3204 nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
3205 }
3206 writeq(rx_mat, &bar0->rx_mat);
3207 } else {
3208 tx_mat = readq(&bar0->tx_mat0_n[7]);
3209 for (j=0; j<nic->config.rx_ring_num; j++, msix_indx++) {
3210 tx_mat |= TX_MAT_SET(i, msix_indx);
3211 nic->s2io_entries[msix_indx].arg = &nic->mac_control.rings[j];
3212 nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE;
3213 nic->s2io_entries[msix_indx].in_use = MSIX_FLG;
3214 }
3215 writeq(tx_mat, &bar0->tx_mat0_n[7]);
3216 }
3217
3218 ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
3219 if (ret) {
3220 DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
3221 kfree(nic->entries);
3222 kfree(nic->s2io_entries);
3223 nic->entries = NULL;
3224 nic->s2io_entries = NULL;
3225 return -ENOMEM;
3226 }
3227
3228 /*
3229 * To enable MSI-X, MSI also needs to be enabled, due to a bug
3230 * in the herc NIC. (Temp change, needs to be removed later)
3231 */
3232 pci_read_config_word(nic->pdev, 0x42, &msi_control);
3233 msi_control |= 0x1; /* Enable MSI */
3234 pci_write_config_word(nic->pdev, 0x42, msi_control);
3235
3236 return 0;
3237}
3238
3031/* ********************************************************* * 3239/* ********************************************************* *
3032 * Functions defined below concern the OS part of the driver * 3240 * Functions defined below concern the OS part of the driver *
3033 * ********************************************************* */ 3241 * ********************************************************* */
@@ -3048,6 +3256,8 @@ int s2io_open(struct net_device *dev)
3048{ 3256{
3049 nic_t *sp = dev->priv; 3257 nic_t *sp = dev->priv;
3050 int err = 0; 3258 int err = 0;
3259 int i;
3260 u16 msi_control; /* Temp variable */
3051 3261
3052 /* 3262 /*
3053 * Make sure you have link off by default every time 3263 * Make sure you have link off by default every time
@@ -3064,13 +3274,55 @@ int s2io_open(struct net_device *dev)
3064 goto hw_init_failed; 3274 goto hw_init_failed;
3065 } 3275 }
3066 3276
3277 /* Store the values of the MSIX table in the nic_t structure */
3278 store_xmsi_data(sp);
3279
3067 /* After proper initialization of H/W, register ISR */ 3280 /* After proper initialization of H/W, register ISR */
3068 err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ, 3281 if (sp->intr_type == MSI) {
3069 sp->name, dev); 3282 err = request_irq((int) sp->pdev->irq, s2io_msi_handle,
3070 if (err) { 3283 SA_SHIRQ, sp->name, dev);
3071 DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n", 3284 if (err) {
3072 dev->name); 3285 DBG_PRINT(ERR_DBG, "%s: MSI registration \
3073 goto isr_registration_failed; 3286failed\n", dev->name);
3287 goto isr_registration_failed;
3288 }
3289 }
3290 if (sp->intr_type == MSI_X) {
3291 for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
3292 if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
3293 sprintf(sp->desc1, "%s:MSI-X-%d-TX",
3294 dev->name, i);
3295 err = request_irq(sp->entries[i].vector,
3296 s2io_msix_fifo_handle, 0, sp->desc1,
3297 sp->s2io_entries[i].arg);
3298 DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1,
3299 sp->msix_info[i].addr);
3300 } else {
3301 sprintf(sp->desc2, "%s:MSI-X-%d-RX",
3302 dev->name, i);
3303 err = request_irq(sp->entries[i].vector,
3304 s2io_msix_ring_handle, 0, sp->desc2,
3305 sp->s2io_entries[i].arg);
3306 DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2,
3307 sp->msix_info[i].addr);
3308 }
3309 if (err) {
3310 DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
3311failed\n", dev->name, i);
3312 DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
3313 goto isr_registration_failed;
3314 }
3315 sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
3316 }
3317 }
3318 if (sp->intr_type == INTA) {
3319 err = request_irq((int) sp->pdev->irq, s2io_isr, SA_SHIRQ,
3320 sp->name, dev);
3321 if (err) {
3322 DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
3323 dev->name);
3324 goto isr_registration_failed;
3325 }
3074 } 3326 }
3075 3327
3076 if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) { 3328 if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
@@ -3083,11 +3335,37 @@ int s2io_open(struct net_device *dev)
3083 return 0; 3335 return 0;
3084 3336
3085setting_mac_address_failed: 3337setting_mac_address_failed:
3086 free_irq(sp->pdev->irq, dev); 3338 if (sp->intr_type != MSI_X)
3339 free_irq(sp->pdev->irq, dev);
3087isr_registration_failed: 3340isr_registration_failed:
3088 del_timer_sync(&sp->alarm_timer); 3341 del_timer_sync(&sp->alarm_timer);
3342 if (sp->intr_type == MSI_X) {
3343 if (sp->device_type == XFRAME_II_DEVICE) {
3344 for (i=1; (sp->s2io_entries[i].in_use ==
3345 MSIX_REGISTERED_SUCCESS); i++) {
3346 int vector = sp->entries[i].vector;
3347 void *arg = sp->s2io_entries[i].arg;
3348
3349 free_irq(vector, arg);
3350 }
3351 pci_disable_msix(sp->pdev);
3352
3353 /* Temp */
3354 pci_read_config_word(sp->pdev, 0x42, &msi_control);
3355 msi_control &= 0xFFFE; /* Disable MSI */
3356 pci_write_config_word(sp->pdev, 0x42, msi_control);
3357 }
3358 }
3359 else if (sp->intr_type == MSI)
3360 pci_disable_msi(sp->pdev);
3089 s2io_reset(sp); 3361 s2io_reset(sp);
3090hw_init_failed: 3362hw_init_failed:
3363 if (sp->intr_type == MSI_X) {
3364 if (sp->entries)
3365 kfree(sp->entries);
3366 if (sp->s2io_entries)
3367 kfree(sp->s2io_entries);
3368 }
3091 return err; 3369 return err;
3092} 3370}
3093 3371
@@ -3107,12 +3385,35 @@ hw_init_failed:
3107int s2io_close(struct net_device *dev) 3385int s2io_close(struct net_device *dev)
3108{ 3386{
3109 nic_t *sp = dev->priv; 3387 nic_t *sp = dev->priv;
3388 int i;
3389 u16 msi_control;
3390
3110 flush_scheduled_work(); 3391 flush_scheduled_work();
3111 netif_stop_queue(dev); 3392 netif_stop_queue(dev);
3112 /* Reset card, kill tasklet and free Tx and Rx buffers. */ 3393 /* Reset card, kill tasklet and free Tx and Rx buffers. */
3113 s2io_card_down(sp); 3394 s2io_card_down(sp);
3114 3395
3115 free_irq(sp->pdev->irq, dev); 3396 if (sp->intr_type == MSI_X) {
3397 if (sp->device_type == XFRAME_II_DEVICE) {
3398 for (i=1; (sp->s2io_entries[i].in_use ==
3399 MSIX_REGISTERED_SUCCESS); i++) {
3400 int vector = sp->entries[i].vector;
3401 void *arg = sp->s2io_entries[i].arg;
3402
3403 free_irq(vector, arg);
3404 }
3405 pci_read_config_word(sp->pdev, 0x42, &msi_control);
3406 msi_control &= 0xFFFE; /* Disable MSI */
3407 pci_write_config_word(sp->pdev, 0x42, msi_control);
3408
3409 pci_disable_msix(sp->pdev);
3410 }
3411 }
3412 else {
3413 free_irq(sp->pdev->irq, dev);
3414 if (sp->intr_type == MSI)
3415 pci_disable_msi(sp->pdev);
3416 }
3116 sp->device_close_flag = TRUE; /* Device is shut down. */ 3417 sp->device_close_flag = TRUE; /* Device is shut down. */
3117 return 0; 3418 return 0;
3118} 3419}
@@ -3278,6 +3579,104 @@ s2io_alarm_handle(unsigned long data)
3278 mod_timer(&sp->alarm_timer, jiffies + HZ / 2); 3579 mod_timer(&sp->alarm_timer, jiffies + HZ / 2);
3279} 3580}
3280 3581
3582static irqreturn_t
3583s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs)
3584{
3585 struct net_device *dev = (struct net_device *) dev_id;
3586 nic_t *sp = dev->priv;
3587 int i;
3588 int ret;
3589 mac_info_t *mac_control;
3590 struct config_param *config;
3591
3592 atomic_inc(&sp->isr_cnt);
3593 mac_control = &sp->mac_control;
3594 config = &sp->config;
3595 DBG_PRINT(INTR_DBG, "%s: MSI handler\n", __FUNCTION__);
3596
3597 /* If Intr is because of Rx Traffic */
3598 for (i = 0; i < config->rx_ring_num; i++)
3599 rx_intr_handler(&mac_control->rings[i]);
3600
3601 /* If Intr is because of Tx Traffic */
3602 for (i = 0; i < config->tx_fifo_num; i++)
3603 tx_intr_handler(&mac_control->fifos[i]);
3604
3605 /*
3606 * If the Rx buffer count is below the panic threshold then
3607 * reallocate the buffers from the interrupt handler itself,
3608 * else schedule a tasklet to reallocate the buffers.
3609 */
3610 for (i = 0; i < config->rx_ring_num; i++) {
3611 int rxb_size = atomic_read(&sp->rx_bufs_left[i]);
3612 int level = rx_buffer_level(sp, rxb_size, i);
3613
3614 if ((level == PANIC) && (!TASKLET_IN_USE)) {
3615 DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", dev->name);
3616 DBG_PRINT(INTR_DBG, "PANIC levels\n");
3617 if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) {
3618 DBG_PRINT(ERR_DBG, "%s:Out of memory",
3619 dev->name);
3620 DBG_PRINT(ERR_DBG, " in ISR!!\n");
3621 clear_bit(0, (&sp->tasklet_status));
3622 atomic_dec(&sp->isr_cnt);
3623 return IRQ_HANDLED;
3624 }
3625 clear_bit(0, (&sp->tasklet_status));
3626 } else if (level == LOW) {
3627 tasklet_schedule(&sp->task);
3628 }
3629 }
3630
3631 atomic_dec(&sp->isr_cnt);
3632 return IRQ_HANDLED;
3633}
3634
3635static irqreturn_t
3636s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs)
3637{
3638 ring_info_t *ring = (ring_info_t *)dev_id;
3639 nic_t *sp = ring->nic;
3640 int rxb_size, level, rng_n;
3641
3642 atomic_inc(&sp->isr_cnt);
3643 rx_intr_handler(ring);
3644
3645 rng_n = ring->ring_no;
3646 rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]);
3647 level = rx_buffer_level(sp, rxb_size, rng_n);
3648
3649 if ((level == PANIC) && (!TASKLET_IN_USE)) {
3650 int ret;
3651 DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__);
3652 DBG_PRINT(INTR_DBG, "PANIC levels\n");
3653 if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) {
3654 DBG_PRINT(ERR_DBG, "Out of memory in %s",
3655 __FUNCTION__);
3656 clear_bit(0, (&sp->tasklet_status));
3657 return IRQ_HANDLED;
3658 }
3659 clear_bit(0, (&sp->tasklet_status));
3660 } else if (level == LOW) {
3661 tasklet_schedule(&sp->task);
3662 }
3663 atomic_dec(&sp->isr_cnt);
3664
3665 return IRQ_HANDLED;
3666}
3667
3668static irqreturn_t
3669s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs)
3670{
3671 fifo_info_t *fifo = (fifo_info_t *)dev_id;
3672 nic_t *sp = fifo->nic;
3673
3674 atomic_inc(&sp->isr_cnt);
3675 tx_intr_handler(fifo);
3676 atomic_dec(&sp->isr_cnt);
3677 return IRQ_HANDLED;
3678}
3679
3281static void s2io_txpic_intr_handle(nic_t *sp) 3680static void s2io_txpic_intr_handle(nic_t *sp)
3282{ 3681{
3283 XENA_dev_config_t __iomem *bar0 = sp->bar0; 3682 XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -4932,7 +5331,7 @@ static void s2io_card_down(nic_t * sp)
4932 5331
4933static int s2io_card_up(nic_t * sp) 5332static int s2io_card_up(nic_t * sp)
4934{ 5333{
4935 int i, ret; 5334 int i, ret = 0;
4936 mac_info_t *mac_control; 5335 mac_info_t *mac_control;
4937 struct config_param *config; 5336 struct config_param *config;
4938 struct net_device *dev = (struct net_device *) sp->dev; 5337 struct net_device *dev = (struct net_device *) sp->dev;
@@ -4944,6 +5343,15 @@ static int s2io_card_up(nic_t * sp)
4944 return -ENODEV; 5343 return -ENODEV;
4945 } 5344 }
4946 5345
5346 if (sp->intr_type == MSI)
5347 ret = s2io_enable_msi(sp);
5348 else if (sp->intr_type == MSI_X)
5349 ret = s2io_enable_msi_x(sp);
5350 if (ret) {
5351 DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
5352 sp->intr_type = INTA;
5353 }
5354
4947 /* 5355 /*
4948 * Initializing the Rx buffers. For now we are considering only 1 5356 * Initializing the Rx buffers. For now we are considering only 1
4949 * Rx ring and initializing buffers into 30 Rx blocks 5357 * Rx ring and initializing buffers into 30 Rx blocks
@@ -5245,6 +5653,7 @@ module_param(bimodal, bool, 0);
5245module_param(indicate_max_pkts, int, 0); 5653module_param(indicate_max_pkts, int, 0);
5246#endif 5654#endif
5247module_param(rxsync_frequency, int, 0); 5655module_param(rxsync_frequency, int, 0);
5656module_param(intr_type, int, 0);
5248 5657
5249/** 5658/**
5250 * s2io_init_nic - Initialization of the adapter . 5659 * s2io_init_nic - Initialization of the adapter .
@@ -5274,9 +5683,16 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
5274 mac_info_t *mac_control; 5683 mac_info_t *mac_control;
5275 struct config_param *config; 5684 struct config_param *config;
5276 int mode; 5685 int mode;
5686 u8 dev_intr_type = intr_type;
5277 5687
5278#ifdef CONFIG_S2IO_NAPI 5688#ifdef CONFIG_S2IO_NAPI
5279 DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n"); 5689 if (dev_intr_type != INTA) {
5690 DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \
5691is enabled. Defaulting to INTA\n");
5692 dev_intr_type = INTA;
5693 }
5694 else
5695 DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
5280#endif 5696#endif
5281 5697
5282 if ((ret = pci_enable_device(pdev))) { 5698 if ((ret = pci_enable_device(pdev))) {
@@ -5303,10 +5719,35 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
5303 return -ENOMEM; 5719 return -ENOMEM;
5304 } 5720 }
5305 5721
5306 if (pci_request_regions(pdev, s2io_driver_name)) { 5722 if ((dev_intr_type == MSI_X) &&
5307 DBG_PRINT(ERR_DBG, "Request Regions failed\n"), 5723 ((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
5308 pci_disable_device(pdev); 5724 (pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
5309 return -ENODEV; 5725 DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \
5726Defaulting to INTA\n");
5727 dev_intr_type = INTA;
5728 }
5729 if (dev_intr_type != MSI_X) {
5730 if (pci_request_regions(pdev, s2io_driver_name)) {
5731 DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
5732 pci_disable_device(pdev);
5733 return -ENODEV;
5734 }
5735 }
5736 else {
5737 if (!(request_mem_region(pci_resource_start(pdev, 0),
5738 pci_resource_len(pdev, 0), s2io_driver_name))) {
5739 DBG_PRINT(ERR_DBG, "bar0 Request Regions failed\n");
5740 pci_disable_device(pdev);
5741 return -ENODEV;
5742 }
5743 if (!(request_mem_region(pci_resource_start(pdev, 2),
5744 pci_resource_len(pdev, 2), s2io_driver_name))) {
5745 DBG_PRINT(ERR_DBG, "bar1 Request Regions failed\n");
5746 release_mem_region(pci_resource_start(pdev, 0),
5747 pci_resource_len(pdev, 0));
5748 pci_disable_device(pdev);
5749 return -ENODEV;
5750 }
5310 } 5751 }
5311 5752
5312 dev = alloc_etherdev(sizeof(nic_t)); 5753 dev = alloc_etherdev(sizeof(nic_t));
@@ -5329,6 +5770,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
5329 sp->pdev = pdev; 5770 sp->pdev = pdev;
5330 sp->high_dma_flag = dma_flag; 5771 sp->high_dma_flag = dma_flag;
5331 sp->device_enabled_once = FALSE; 5772 sp->device_enabled_once = FALSE;
5773 sp->intr_type = dev_intr_type;
5332 5774
5333 if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) || 5775 if ((pdev->device == PCI_DEVICE_ID_HERC_WIN) ||
5334 (pdev->device == PCI_DEVICE_ID_HERC_UNI)) 5776 (pdev->device == PCI_DEVICE_ID_HERC_UNI))
@@ -5336,6 +5778,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
5336 else 5778 else
5337 sp->device_type = XFRAME_I_DEVICE; 5779 sp->device_type = XFRAME_I_DEVICE;
5338 5780
5781
5339 /* Initialize some PCI/PCI-X fields of the NIC. */ 5782 /* Initialize some PCI/PCI-X fields of the NIC. */
5340 s2io_init_pci(sp); 5783 s2io_init_pci(sp);
5341 5784
@@ -5577,6 +6020,17 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
5577#ifdef CONFIG_2BUFF_MODE 6020#ifdef CONFIG_2BUFF_MODE
5578 DBG_PRINT(ERR_DBG, ", Buffer mode %d",2); 6021 DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
5579#endif 6022#endif
6023 switch(sp->intr_type) {
6024 case INTA:
6025 DBG_PRINT(ERR_DBG, ", Intr type INTA");
6026 break;
6027 case MSI:
6028 DBG_PRINT(ERR_DBG, ", Intr type MSI");
6029 break;
6030 case MSI_X:
6031 DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
6032 break;
6033 }
5580 6034
5581 DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n"); 6035 DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
5582 DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", 6036 DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
@@ -5601,6 +6055,17 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
5601#ifdef CONFIG_2BUFF_MODE 6055#ifdef CONFIG_2BUFF_MODE
5602 DBG_PRINT(ERR_DBG, ", Buffer mode %d",2); 6056 DBG_PRINT(ERR_DBG, ", Buffer mode %d",2);
5603#endif 6057#endif
6058 switch(sp->intr_type) {
6059 case INTA:
6060 DBG_PRINT(ERR_DBG, ", Intr type INTA");
6061 break;
6062 case MSI:
6063 DBG_PRINT(ERR_DBG, ", Intr type MSI");
6064 break;
6065 case MSI_X:
6066 DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
6067 break;
6068 }
5604 DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n"); 6069 DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
5605 DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", 6070 DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
5606 sp->def_mac_addr[0].mac_addr[0], 6071 sp->def_mac_addr[0].mac_addr[0],
@@ -5644,7 +6109,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
5644 mem_alloc_failed: 6109 mem_alloc_failed:
5645 free_shared_mem(sp); 6110 free_shared_mem(sp);
5646 pci_disable_device(pdev); 6111 pci_disable_device(pdev);
5647 pci_release_regions(pdev); 6112 if (dev_intr_type != MSI_X)
6113 pci_release_regions(pdev);
6114 else {
6115 release_mem_region(pci_resource_start(pdev, 0),
6116 pci_resource_len(pdev, 0));
6117 release_mem_region(pci_resource_start(pdev, 2),
6118 pci_resource_len(pdev, 2));
6119 }
5648 pci_set_drvdata(pdev, NULL); 6120 pci_set_drvdata(pdev, NULL);
5649 free_netdev(dev); 6121 free_netdev(dev);
5650 6122
@@ -5678,7 +6150,14 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
5678 iounmap(sp->bar0); 6150 iounmap(sp->bar0);
5679 iounmap(sp->bar1); 6151 iounmap(sp->bar1);
5680 pci_disable_device(pdev); 6152 pci_disable_device(pdev);
5681 pci_release_regions(pdev); 6153 if (sp->intr_type != MSI_X)
6154 pci_release_regions(pdev);
6155 else {
6156 release_mem_region(pci_resource_start(pdev, 0),
6157 pci_resource_len(pdev, 0));
6158 release_mem_region(pci_resource_start(pdev, 2),
6159 pci_resource_len(pdev, 2));
6160 }
5682 pci_set_drvdata(pdev, NULL); 6161 pci_set_drvdata(pdev, NULL);
5683 free_netdev(dev); 6162 free_netdev(dev);
5684} 6163}
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 89151cb52181..1cc24b56760e 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -652,6 +652,30 @@ typedef struct {
652#define SMALL_BLK_CNT 30 652#define SMALL_BLK_CNT 30
653#define LARGE_BLK_CNT 100 653#define LARGE_BLK_CNT 100
654 654
655/*
656 * Structure to keep track of the MSI-X vectors and the corresponding
657 * argument registered against each vector
658 */
659#define MAX_REQUESTED_MSI_X 17
660struct s2io_msix_entry
661{
662 u16 vector;
663 u16 entry;
664 void *arg;
665
666 u8 type;
667#define MSIX_FIFO_TYPE 1
668#define MSIX_RING_TYPE 2
669
670 u8 in_use;
671#define MSIX_REGISTERED_SUCCESS 0xAA
672};
673
674struct msix_info_st {
675 u64 addr;
676 u64 data;
677};
678
655/* Structure representing one instance of the NIC */ 679/* Structure representing one instance of the NIC */
656struct s2io_nic { 680struct s2io_nic {
657#ifdef CONFIG_S2IO_NAPI 681#ifdef CONFIG_S2IO_NAPI
@@ -719,13 +743,8 @@ struct s2io_nic {
719 * a schedule task that will set the correct Link state once the 743 * a schedule task that will set the correct Link state once the
720 * NIC's PHY has stabilized after a state change. 744 * NIC's PHY has stabilized after a state change.
721 */ 745 */
722#ifdef INIT_TQUEUE
723 struct tq_struct rst_timer_task;
724 struct tq_struct set_link_task;
725#else
726 struct work_struct rst_timer_task; 746 struct work_struct rst_timer_task;
727 struct work_struct set_link_task; 747 struct work_struct set_link_task;
728#endif
729 748
730 /* Flag that can be used to turn on or turn off the Rx checksum 749 /* Flag that can be used to turn on or turn off the Rx checksum
731 * offload feature. 750 * offload feature.
@@ -748,10 +767,23 @@ struct s2io_nic {
748 atomic_t card_state; 767 atomic_t card_state;
749 volatile unsigned long link_state; 768 volatile unsigned long link_state;
750 struct vlan_group *vlgrp; 769 struct vlan_group *vlgrp;
770#define MSIX_FLG 0xA5
771 struct msix_entry *entries;
772 struct s2io_msix_entry *s2io_entries;
773 char desc1[35];
774 char desc2[35];
775
776 struct msix_info_st msix_info[0x3f];
777
751#define XFRAME_I_DEVICE 1 778#define XFRAME_I_DEVICE 1
752#define XFRAME_II_DEVICE 2 779#define XFRAME_II_DEVICE 2
753 u8 device_type; 780 u8 device_type;
754 781
782#define INTA 0
783#define MSI 1
784#define MSI_X 2
785 u8 intr_type;
786
755 spinlock_t rx_lock; 787 spinlock_t rx_lock;
756 atomic_t isr_cnt; 788 atomic_t isr_cnt;
757}; 789};
@@ -886,6 +918,13 @@ static int s2io_poll(struct net_device *dev, int *budget);
886static void s2io_init_pci(nic_t * sp); 918static void s2io_init_pci(nic_t * sp);
887int s2io_set_mac_addr(struct net_device *dev, u8 * addr); 919int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
888static void s2io_alarm_handle(unsigned long data); 920static void s2io_alarm_handle(unsigned long data);
921static int s2io_enable_msi(nic_t *nic);
922static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs);
923static irqreturn_t
924s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs);
925static irqreturn_t
926s2io_msix_fifo_handle(int irq, void *dev_id, struct pt_regs *regs);
927int s2io_enable_msi_x(nic_t *nic);
889static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs); 928static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
890static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag); 929static int verify_xena_quiescence(nic_t *sp, u64 val64, int flag);
891static struct ethtool_ops netdev_ethtool_ops; 930static struct ethtool_ops netdev_ethtool_ops;
@@ -894,4 +933,5 @@ int s2io_set_swapper(nic_t * sp);
894static void s2io_card_down(nic_t *nic); 933static void s2io_card_down(nic_t *nic);
895static int s2io_card_up(nic_t *nic); 934static int s2io_card_up(nic_t *nic);
896int get_xena_rev_id(struct pci_dev *pdev); 935int get_xena_rev_id(struct pci_dev *pdev);
936void restore_xmsi_data(nic_t *nic);
897#endif /* _S2IO_H */ 937#endif /* _S2IO_H */