aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/s2io.c
diff options
context:
space:
mode:
authorAnanda Raju <Ananda.Raju@neterion.com>2006-07-07 02:58:23 -0400
committerJeff Garzik <jeff@garzik.org>2006-07-12 17:42:40 -0400
commite6a8fee2098f29749e4e48321611f2d661b2eb71 (patch)
treedca5a4991e41f2fcff4f792c69743cf21fc27cd3 /drivers/net/s2io.c
parent61ef5c00a6477e076b8b77be805c5f58b77539cf (diff)
[PATCH] s2io driver irq fix
Modification and bug fixes with respect to irq registration. - Enable interrupts after request_irq - Restored MSI data register value at driver unload time Signed-off-by: Ananda Raju <ananda.raju@neterion.com> Cc: Jeff Garzik <jeff@garzik.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/s2io.c')
-rw-r--r--drivers/net/s2io.c285
1 files changed, 143 insertions, 142 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index c6b77acb35ef..e1fe3a0a7b0b 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -1976,7 +1976,6 @@ static int start_nic(struct s2io_nic *nic)
1976 XENA_dev_config_t __iomem *bar0 = nic->bar0; 1976 XENA_dev_config_t __iomem *bar0 = nic->bar0;
1977 struct net_device *dev = nic->dev; 1977 struct net_device *dev = nic->dev;
1978 register u64 val64 = 0; 1978 register u64 val64 = 0;
1979 u16 interruptible;
1980 u16 subid, i; 1979 u16 subid, i;
1981 mac_info_t *mac_control; 1980 mac_info_t *mac_control;
1982 struct config_param *config; 1981 struct config_param *config;
@@ -2047,16 +2046,6 @@ static int start_nic(struct s2io_nic *nic)
2047 return FAILURE; 2046 return FAILURE;
2048 } 2047 }
2049 2048
2050 /* Enable select interrupts */
2051 if (nic->intr_type != INTA)
2052 en_dis_able_nic_intrs(nic, ENA_ALL_INTRS, DISABLE_INTRS);
2053 else {
2054 interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
2055 interruptible |= TX_PIC_INTR | RX_PIC_INTR;
2056 interruptible |= TX_MAC_INTR | RX_MAC_INTR;
2057 en_dis_able_nic_intrs(nic, interruptible, ENABLE_INTRS);
2058 }
2059
2060 /* 2049 /*
2061 * With some switches, link might be already up at this point. 2050 * With some switches, link might be already up at this point.
2062 * Because of this weird behavior, when we enable laser, 2051 * Because of this weird behavior, when we enable laser,
@@ -3749,101 +3738,19 @@ static int s2io_open(struct net_device *dev)
3749 if (err) { 3738 if (err) {
3750 DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n", 3739 DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
3751 dev->name); 3740 dev->name);
3752 if (err == -ENODEV) 3741 goto hw_init_failed;
3753 goto hw_init_failed;
3754 else
3755 goto hw_enable_failed;
3756 }
3757
3758 /* Store the values of the MSIX table in the nic_t structure */
3759 store_xmsi_data(sp);
3760
3761 /* After proper initialization of H/W, register ISR */
3762 if (sp->intr_type == MSI) {
3763 err = request_irq((int) sp->pdev->irq, s2io_msi_handle,
3764 IRQF_SHARED, sp->name, dev);
3765 if (err) {
3766 DBG_PRINT(ERR_DBG, "%s: MSI registration \
3767failed\n", dev->name);
3768 goto isr_registration_failed;
3769 }
3770 }
3771 if (sp->intr_type == MSI_X) {
3772 int i;
3773
3774 for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
3775 if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
3776 sprintf(sp->desc1, "%s:MSI-X-%d-TX",
3777 dev->name, i);
3778 err = request_irq(sp->entries[i].vector,
3779 s2io_msix_fifo_handle, 0, sp->desc1,
3780 sp->s2io_entries[i].arg);
3781 DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc1,
3782 (unsigned long long)sp->msix_info[i].addr);
3783 } else {
3784 sprintf(sp->desc2, "%s:MSI-X-%d-RX",
3785 dev->name, i);
3786 err = request_irq(sp->entries[i].vector,
3787 s2io_msix_ring_handle, 0, sp->desc2,
3788 sp->s2io_entries[i].arg);
3789 DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc2,
3790 (unsigned long long)sp->msix_info[i].addr);
3791 }
3792 if (err) {
3793 DBG_PRINT(ERR_DBG, "%s: MSI-X-%d registration \
3794failed\n", dev->name, i);
3795 DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
3796 goto isr_registration_failed;
3797 }
3798 sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
3799 }
3800 }
3801 if (sp->intr_type == INTA) {
3802 err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
3803 sp->name, dev);
3804 if (err) {
3805 DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
3806 dev->name);
3807 goto isr_registration_failed;
3808 }
3809 } 3742 }
3810 3743
3811 if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) { 3744 if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) {
3812 DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n"); 3745 DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n");
3746 s2io_card_down(sp);
3813 err = -ENODEV; 3747 err = -ENODEV;
3814 goto setting_mac_address_failed; 3748 goto hw_init_failed;
3815 } 3749 }
3816 3750
3817 netif_start_queue(dev); 3751 netif_start_queue(dev);
3818 return 0; 3752 return 0;
3819 3753
3820setting_mac_address_failed:
3821 if (sp->intr_type != MSI_X)
3822 free_irq(sp->pdev->irq, dev);
3823isr_registration_failed:
3824 del_timer_sync(&sp->alarm_timer);
3825 if (sp->intr_type == MSI_X) {
3826 int i;
3827 u16 msi_control; /* Temp variable */
3828
3829 for (i=1; (sp->s2io_entries[i].in_use ==
3830 MSIX_REGISTERED_SUCCESS); i++) {
3831 int vector = sp->entries[i].vector;
3832 void *arg = sp->s2io_entries[i].arg;
3833
3834 free_irq(vector, arg);
3835 }
3836 pci_disable_msix(sp->pdev);
3837
3838 /* Temp */
3839 pci_read_config_word(sp->pdev, 0x42, &msi_control);
3840 msi_control &= 0xFFFE; /* Disable MSI */
3841 pci_write_config_word(sp->pdev, 0x42, msi_control);
3842 }
3843 else if (sp->intr_type == MSI)
3844 pci_disable_msi(sp->pdev);
3845hw_enable_failed:
3846 s2io_reset(sp);
3847hw_init_failed: 3754hw_init_failed:
3848 if (sp->intr_type == MSI_X) { 3755 if (sp->intr_type == MSI_X) {
3849 if (sp->entries) 3756 if (sp->entries)
@@ -3874,7 +3781,7 @@ static int s2io_close(struct net_device *dev)
3874 flush_scheduled_work(); 3781 flush_scheduled_work();
3875 netif_stop_queue(dev); 3782 netif_stop_queue(dev);
3876 /* Reset card, kill tasklet and free Tx and Rx buffers. */ 3783 /* Reset card, kill tasklet and free Tx and Rx buffers. */
3877 s2io_card_down(sp, 1); 3784 s2io_card_down(sp);
3878 3785
3879 sp->device_close_flag = TRUE; /* Device is shut down. */ 3786 sp->device_close_flag = TRUE; /* Device is shut down. */
3880 return 0; 3787 return 0;
@@ -5919,7 +5826,7 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu)
5919 5826
5920 dev->mtu = new_mtu; 5827 dev->mtu = new_mtu;
5921 if (netif_running(dev)) { 5828 if (netif_running(dev)) {
5922 s2io_card_down(sp, 0); 5829 s2io_card_down(sp);
5923 netif_stop_queue(dev); 5830 netif_stop_queue(dev);
5924 if (s2io_card_up(sp)) { 5831 if (s2io_card_up(sp)) {
5925 DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", 5832 DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
@@ -6216,43 +6123,106 @@ static int rxd_owner_bit_reset(nic_t *sp)
6216 6123
6217} 6124}
6218 6125
6219static void s2io_card_down(nic_t * sp, int flag) 6126static int s2io_add_isr(nic_t * sp)
6220{ 6127{
6221 int cnt = 0; 6128 int ret = 0;
6222 XENA_dev_config_t __iomem *bar0 = sp->bar0;
6223 unsigned long flags;
6224 register u64 val64 = 0;
6225 struct net_device *dev = sp->dev; 6129 struct net_device *dev = sp->dev;
6130 int err = 0;
6226 6131
6227 del_timer_sync(&sp->alarm_timer); 6132 if (sp->intr_type == MSI)
6228 /* If s2io_set_link task is executing, wait till it completes. */ 6133 ret = s2io_enable_msi(sp);
6229 while (test_and_set_bit(0, &(sp->link_state))) { 6134 else if (sp->intr_type == MSI_X)
6230 msleep(50); 6135 ret = s2io_enable_msi_x(sp);
6136 if (ret) {
6137 DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
6138 sp->intr_type = INTA;
6231 } 6139 }
6232 atomic_set(&sp->card_state, CARD_DOWN);
6233 6140
6234 /* disable Tx and Rx traffic on the NIC */ 6141 /* Store the values of the MSIX table in the nic_t structure */
6235 stop_nic(sp); 6142 store_xmsi_data(sp);
6236 if (flag) {
6237 if (sp->intr_type == MSI_X) {
6238 int i;
6239 u16 msi_control;
6240 6143
6241 for (i=1; (sp->s2io_entries[i].in_use == 6144 /* After proper initialization of H/W, register ISR */
6242 MSIX_REGISTERED_SUCCESS); i++) { 6145 if (sp->intr_type == MSI) {
6243 int vector = sp->entries[i].vector; 6146 err = request_irq((int) sp->pdev->irq, s2io_msi_handle,
6244 void *arg = sp->s2io_entries[i].arg; 6147 IRQF_SHARED, sp->name, dev);
6148 if (err) {
6149 pci_disable_msi(sp->pdev);
6150 DBG_PRINT(ERR_DBG, "%s: MSI registration failed\n",
6151 dev->name);
6152 return -1;
6153 }
6154 }
6155 if (sp->intr_type == MSI_X) {
6156 int i;
6245 6157
6246 free_irq(vector, arg); 6158 for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
6159 if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
6160 sprintf(sp->desc[i], "%s:MSI-X-%d-TX",
6161 dev->name, i);
6162 err = request_irq(sp->entries[i].vector,
6163 s2io_msix_fifo_handle, 0, sp->desc[i],
6164 sp->s2io_entries[i].arg);
6165 DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc[i],
6166 (unsigned long long)sp->msix_info[i].addr);
6167 } else {
6168 sprintf(sp->desc[i], "%s:MSI-X-%d-RX",
6169 dev->name, i);
6170 err = request_irq(sp->entries[i].vector,
6171 s2io_msix_ring_handle, 0, sp->desc[i],
6172 sp->s2io_entries[i].arg);
6173 DBG_PRINT(ERR_DBG, "%s @ 0x%llx\n", sp->desc[i],
6174 (unsigned long long)sp->msix_info[i].addr);
6247 } 6175 }
6248 pci_read_config_word(sp->pdev, 0x42, &msi_control); 6176 if (err) {
6249 msi_control &= 0xFFFE; /* Disable MSI */ 6177 DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration "
6250 pci_write_config_word(sp->pdev, 0x42, msi_control); 6178 "failed\n", dev->name, i);
6251 pci_disable_msix(sp->pdev); 6179 DBG_PRINT(ERR_DBG, "Returned: %d\n", err);
6252 } else { 6180 return -1;
6253 free_irq(sp->pdev->irq, dev); 6181 }
6254 if (sp->intr_type == MSI) 6182 sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS;
6255 pci_disable_msi(sp->pdev); 6183 }
6184 }
6185 if (sp->intr_type == INTA) {
6186 err = request_irq((int) sp->pdev->irq, s2io_isr, IRQF_SHARED,
6187 sp->name, dev);
6188 if (err) {
6189 DBG_PRINT(ERR_DBG, "%s: ISR registration failed\n",
6190 dev->name);
6191 return -1;
6192 }
6193 }
6194 return 0;
6195}
6196static void s2io_rem_isr(nic_t * sp)
6197{
6198 int cnt = 0;
6199 struct net_device *dev = sp->dev;
6200
6201 if (sp->intr_type == MSI_X) {
6202 int i;
6203 u16 msi_control;
6204
6205 for (i=1; (sp->s2io_entries[i].in_use ==
6206 MSIX_REGISTERED_SUCCESS); i++) {
6207 int vector = sp->entries[i].vector;
6208 void *arg = sp->s2io_entries[i].arg;
6209
6210 free_irq(vector, arg);
6211 }
6212 pci_read_config_word(sp->pdev, 0x42, &msi_control);
6213 msi_control &= 0xFFFE; /* Disable MSI */
6214 pci_write_config_word(sp->pdev, 0x42, msi_control);
6215
6216 pci_disable_msix(sp->pdev);
6217 } else {
6218 free_irq(sp->pdev->irq, dev);
6219 if (sp->intr_type == MSI) {
6220 u16 val;
6221
6222 pci_disable_msi(sp->pdev);
6223 pci_read_config_word(sp->pdev, 0x4c, &val);
6224 val ^= 0x1;
6225 pci_write_config_word(sp->pdev, 0x4c, val);
6256 } 6226 }
6257 } 6227 }
6258 /* Waiting till all Interrupt handlers are complete */ 6228 /* Waiting till all Interrupt handlers are complete */
@@ -6263,6 +6233,26 @@ static void s2io_card_down(nic_t * sp, int flag)
6263 break; 6233 break;
6264 cnt++; 6234 cnt++;
6265 } while(cnt < 5); 6235 } while(cnt < 5);
6236}
6237
6238static void s2io_card_down(nic_t * sp)
6239{
6240 int cnt = 0;
6241 XENA_dev_config_t __iomem *bar0 = sp->bar0;
6242 unsigned long flags;
6243 register u64 val64 = 0;
6244
6245 del_timer_sync(&sp->alarm_timer);
6246 /* If s2io_set_link task is executing, wait till it completes. */
6247 while (test_and_set_bit(0, &(sp->link_state))) {
6248 msleep(50);
6249 }
6250 atomic_set(&sp->card_state, CARD_DOWN);
6251
6252 /* disable Tx and Rx traffic on the NIC */
6253 stop_nic(sp);
6254
6255 s2io_rem_isr(sp);
6266 6256
6267 /* Kill tasklet. */ 6257 /* Kill tasklet. */
6268 tasklet_kill(&sp->task); 6258 tasklet_kill(&sp->task);
@@ -6314,23 +6304,16 @@ static int s2io_card_up(nic_t * sp)
6314 mac_info_t *mac_control; 6304 mac_info_t *mac_control;
6315 struct config_param *config; 6305 struct config_param *config;
6316 struct net_device *dev = (struct net_device *) sp->dev; 6306 struct net_device *dev = (struct net_device *) sp->dev;
6307 u16 interruptible;
6317 6308
6318 /* Initialize the H/W I/O registers */ 6309 /* Initialize the H/W I/O registers */
6319 if (init_nic(sp) != 0) { 6310 if (init_nic(sp) != 0) {
6320 DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n", 6311 DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
6321 dev->name); 6312 dev->name);
6313 s2io_reset(sp);
6322 return -ENODEV; 6314 return -ENODEV;
6323 } 6315 }
6324 6316
6325 if (sp->intr_type == MSI)
6326 ret = s2io_enable_msi(sp);
6327 else if (sp->intr_type == MSI_X)
6328 ret = s2io_enable_msi_x(sp);
6329 if (ret) {
6330 DBG_PRINT(ERR_DBG, "%s: Defaulting to INTA\n", dev->name);
6331 sp->intr_type = INTA;
6332 }
6333
6334 /* 6317 /*
6335 * Initializing the Rx buffers. For now we are considering only 1 6318 * Initializing the Rx buffers. For now we are considering only 1
6336 * Rx ring and initializing buffers into 30 Rx blocks 6319 * Rx ring and initializing buffers into 30 Rx blocks
@@ -6361,21 +6344,39 @@ static int s2io_card_up(nic_t * sp)
6361 sp->lro_max_aggr_per_sess = lro_max_pkts; 6344 sp->lro_max_aggr_per_sess = lro_max_pkts;
6362 } 6345 }
6363 6346
6364 /* Enable tasklet for the device */
6365 tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
6366
6367 /* Enable Rx Traffic and interrupts on the NIC */ 6347 /* Enable Rx Traffic and interrupts on the NIC */
6368 if (start_nic(sp)) { 6348 if (start_nic(sp)) {
6369 DBG_PRINT(ERR_DBG, "%s: Starting NIC failed\n", dev->name); 6349 DBG_PRINT(ERR_DBG, "%s: Starting NIC failed\n", dev->name);
6370 tasklet_kill(&sp->task);
6371 s2io_reset(sp); 6350 s2io_reset(sp);
6372 free_irq(dev->irq, dev); 6351 free_rx_buffers(sp);
6352 return -ENODEV;
6353 }
6354
6355 /* Add interrupt service routine */
6356 if (s2io_add_isr(sp) != 0) {
6357 if (sp->intr_type == MSI_X)
6358 s2io_rem_isr(sp);
6359 s2io_reset(sp);
6373 free_rx_buffers(sp); 6360 free_rx_buffers(sp);
6374 return -ENODEV; 6361 return -ENODEV;
6375 } 6362 }
6376 6363
6377 S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2)); 6364 S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2));
6378 6365
6366 /* Enable tasklet for the device */
6367 tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev);
6368
6369 /* Enable select interrupts */
6370 if (sp->intr_type != INTA)
6371 en_dis_able_nic_intrs(sp, ENA_ALL_INTRS, DISABLE_INTRS);
6372 else {
6373 interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR;
6374 interruptible |= TX_PIC_INTR | RX_PIC_INTR;
6375 interruptible |= TX_MAC_INTR | RX_MAC_INTR;
6376 en_dis_able_nic_intrs(sp, interruptible, ENABLE_INTRS);
6377 }
6378
6379
6379 atomic_set(&sp->card_state, CARD_UP); 6380 atomic_set(&sp->card_state, CARD_UP);
6380 return 0; 6381 return 0;
6381} 6382}
@@ -6395,7 +6396,7 @@ static void s2io_restart_nic(unsigned long data)
6395 struct net_device *dev = (struct net_device *) data; 6396 struct net_device *dev = (struct net_device *) data;
6396 nic_t *sp = dev->priv; 6397 nic_t *sp = dev->priv;
6397 6398
6398 s2io_card_down(sp, 0); 6399 s2io_card_down(sp);
6399 if (s2io_card_up(sp)) { 6400 if (s2io_card_up(sp)) {
6400 DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n", 6401 DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
6401 dev->name); 6402 dev->name);