diff options
-rw-r--r-- | drivers/staging/sxg/sxg.c | 72 | ||||
-rw-r--r-- | drivers/staging/sxg/sxg.h | 3 |
2 files changed, 59 insertions, 16 deletions
diff --git a/drivers/staging/sxg/sxg.c b/drivers/staging/sxg/sxg.c index c41dea0013bc..dbda031d4053 100644 --- a/drivers/staging/sxg/sxg.c +++ b/drivers/staging/sxg/sxg.c | |||
@@ -136,6 +136,9 @@ static int sxg_register_interrupt(struct adapter_t *adapter); | |||
136 | static void sxg_remove_isr(struct adapter_t *adapter); | 136 | static void sxg_remove_isr(struct adapter_t *adapter); |
137 | static irqreturn_t sxg_isr(int irq, void *dev_id); | 137 | static irqreturn_t sxg_isr(int irq, void *dev_id); |
138 | 138 | ||
139 | static void sxg_watchdog(unsigned long data); | ||
140 | static void sxg_update_link_status (struct work_struct *work); | ||
141 | |||
139 | #define XXXTODO 0 | 142 | #define XXXTODO 0 |
140 | 143 | ||
141 | #if XXXTODO | 144 | #if XXXTODO |
@@ -1122,6 +1125,12 @@ static int sxg_entry_probe(struct pci_dev *pcidev, | |||
1122 | 1125 | ||
1123 | netif_napi_add(netdev, &adapter->napi, | 1126 | netif_napi_add(netdev, &adapter->napi, |
1124 | sxg_poll, SXG_NETDEV_WEIGHT); | 1127 | sxg_poll, SXG_NETDEV_WEIGHT); |
1128 | netdev->watchdog_timeo = 2 * HZ; | ||
1129 | init_timer(&adapter->watchdog_timer); | ||
1130 | adapter->watchdog_timer.function = &sxg_watchdog; | ||
1131 | adapter->watchdog_timer.data = (unsigned long) adapter; | ||
1132 | INIT_WORK(&adapter->update_link_status, sxg_update_link_status); | ||
1133 | |||
1125 | DBG_ERROR | 1134 | DBG_ERROR |
1126 | ("sxg: %s addr 0x%lx, irq %d, MAC addr \ | 1135 | ("sxg: %s addr 0x%lx, irq %d, MAC addr \ |
1127 | %02X:%02X:%02X:%02X:%02X:%02X\n", | 1136 | %02X:%02X:%02X:%02X:%02X:%02X\n", |
@@ -1441,7 +1450,10 @@ static int sxg_process_isr(struct adapter_t *adapter, u32 MessageId) | |||
1441 | } | 1450 | } |
1442 | /* Link event */ | 1451 | /* Link event */ |
1443 | if (Isr & SXG_ISR_LINK) { | 1452 | if (Isr & SXG_ISR_LINK) { |
1444 | sxg_link_event(adapter); | 1453 | if (adapter->state != ADAPT_DOWN) { |
1454 | adapter->link_status_changed = 1; | ||
1455 | schedule_work(&adapter->update_link_status); | ||
1456 | } | ||
1445 | } | 1457 | } |
1446 | /* Debug - breakpoint hit */ | 1458 | /* Debug - breakpoint hit */ |
1447 | if (Isr & SXG_ISR_BREAK) { | 1459 | if (Isr & SXG_ISR_BREAK) { |
@@ -2260,6 +2272,7 @@ int sxg_second_open(struct net_device * dev) | |||
2260 | 2272 | ||
2261 | sxg_register_intr(adapter); | 2273 | sxg_register_intr(adapter); |
2262 | spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags); | 2274 | spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags); |
2275 | mod_timer(&adapter->watchdog_timer, jiffies); | ||
2263 | return (STATUS_SUCCESS); | 2276 | return (STATUS_SUCCESS); |
2264 | 2277 | ||
2265 | } | 2278 | } |
@@ -2312,27 +2325,28 @@ static int sxg_entry_halt(struct net_device *dev) | |||
2312 | 2325 | ||
2313 | RssIds = SXG_RSS_CPU_COUNT(adapter); | 2326 | RssIds = SXG_RSS_CPU_COUNT(adapter); |
2314 | IsrCount = adapter->msi_enabled ? RssIds : 1; | 2327 | IsrCount = adapter->msi_enabled ? RssIds : 1; |
2315 | 2328 | /* Disable interrupts */ | |
2316 | napi_disable(&adapter->napi); | ||
2317 | spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags); | 2329 | spin_lock_irqsave(&sxg_global.driver_lock, sxg_global.flags); |
2318 | DBG_ERROR("sxg: %s (%s) ENTER\n", __func__, dev->name); | 2330 | SXG_DISABLE_ALL_INTERRUPTS(adapter); |
2319 | |||
2320 | WRITE_REG(adapter->UcodeRegs[0].RcvCmd, 0, true); | ||
2321 | netif_stop_queue(adapter->netdev); | ||
2322 | adapter->state = ADAPT_DOWN; | 2331 | adapter->state = ADAPT_DOWN; |
2323 | adapter->linkstate = LINK_DOWN; | 2332 | adapter->linkstate = LINK_DOWN; |
2324 | adapter->devflags_prev = 0; | ||
2325 | DBG_ERROR("sxg: %s (%s) set adapter[%p] state to ADAPT_DOWN(%d)\n", | ||
2326 | __func__, dev->name, adapter, adapter->state); | ||
2327 | |||
2328 | /* Disable interrupts */ | ||
2329 | SXG_DISABLE_ALL_INTERRUPTS(adapter); | ||
2330 | 2333 | ||
2331 | spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags); | 2334 | spin_unlock_irqrestore(&sxg_global.driver_lock, sxg_global.flags); |
2332 | |||
2333 | sxg_deregister_interrupt(adapter); | 2335 | sxg_deregister_interrupt(adapter); |
2334 | WRITE_REG(HwRegs->Reset, 0xDEAD, FLUSH); | 2336 | WRITE_REG(HwRegs->Reset, 0xDEAD, FLUSH); |
2335 | mdelay(5000); | 2337 | mdelay(5000); |
2338 | |||
2339 | del_timer_sync(&adapter->watchdog_timer); | ||
2340 | netif_stop_queue(dev); | ||
2341 | netif_carrier_off(dev); | ||
2342 | |||
2343 | napi_disable(&adapter->napi); | ||
2344 | |||
2345 | WRITE_REG(adapter->UcodeRegs[0].RcvCmd, 0, true); | ||
2346 | adapter->devflags_prev = 0; | ||
2347 | DBG_ERROR("sxg: %s (%s) set adapter[%p] state to ADAPT_DOWN(%d)\n", | ||
2348 | __func__, dev->name, adapter, adapter->state); | ||
2349 | |||
2336 | spin_lock(&adapter->RcvQLock); | 2350 | spin_lock(&adapter->RcvQLock); |
2337 | /* Free all the blocks and the buffers, moved from remove() routine */ | 2351 | /* Free all the blocks and the buffers, moved from remove() routine */ |
2338 | if (!(IsListEmpty(&adapter->AllRcvBlocks))) { | 2352 | if (!(IsListEmpty(&adapter->AllRcvBlocks))) { |
@@ -3013,6 +3027,8 @@ static void sxg_link_event(struct adapter_t *adapter) | |||
3013 | int status; | 3027 | int status; |
3014 | u32 Value; | 3028 | u32 Value; |
3015 | 3029 | ||
3030 | if (adapter->state == ADAPT_DOWN) | ||
3031 | return; | ||
3016 | SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "LinkEvnt", | 3032 | SXG_TRACE(TRACE_SXG, SxgTraceBuffer, TRACE_NOISY, "LinkEvnt", |
3017 | adapter, 0, 0, 0); | 3033 | adapter, 0, 0, 0); |
3018 | DBG_ERROR("ENTER %s\n", __func__); | 3034 | DBG_ERROR("ENTER %s\n", __func__); |
@@ -3053,10 +3069,13 @@ static void sxg_link_event(struct adapter_t *adapter) | |||
3053 | sxg_link_state(adapter, LinkState); | 3069 | sxg_link_state(adapter, LinkState); |
3054 | DBG_ERROR("SXG: Link Alarm occurred. Link is %s\n", | 3070 | DBG_ERROR("SXG: Link Alarm occurred. Link is %s\n", |
3055 | ((LinkState == SXG_LINK_UP) ? "UP" : "DOWN")); | 3071 | ((LinkState == SXG_LINK_UP) ? "UP" : "DOWN")); |
3056 | if (LinkState == SXG_LINK_UP) | 3072 | if (LinkState == SXG_LINK_UP) { |
3057 | netif_carrier_on(netdev); | 3073 | netif_carrier_on(netdev); |
3058 | else | 3074 | netif_tx_start_all_queues(netdev); |
3075 | } else { | ||
3076 | netif_tx_stop_all_queues(netdev); | ||
3059 | netif_carrier_off(netdev); | 3077 | netif_carrier_off(netdev); |
3078 | } | ||
3060 | } else { | 3079 | } else { |
3061 | /* | 3080 | /* |
3062 | * XXXTODO - Assuming Link Attention is only being generated | 3081 | * XXXTODO - Assuming Link Attention is only being generated |
@@ -4435,6 +4454,27 @@ static struct net_device_stats *sxg_get_stats(struct net_device * dev) | |||
4435 | return (&adapter->stats); | 4454 | return (&adapter->stats); |
4436 | } | 4455 | } |
4437 | 4456 | ||
4457 | static void sxg_watchdog(unsigned long data) | ||
4458 | { | ||
4459 | struct adapter_t *adapter = (struct adapter_t *) data; | ||
4460 | |||
4461 | if (adapter->state != ADAPT_DOWN) { | ||
4462 | sxg_link_event(adapter); | ||
4463 | /* Reset the timer */ | ||
4464 | mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 2 * HZ)); | ||
4465 | } | ||
4466 | } | ||
4467 | |||
4468 | static void sxg_update_link_status (struct work_struct *work) | ||
4469 | { | ||
4470 | struct adapter_t *adapter = (struct adapter_t *)container_of | ||
4471 | (work, struct adapter_t, update_link_status); | ||
4472 | if (likely(adapter->link_status_changed)) { | ||
4473 | sxg_link_event(adapter); | ||
4474 | adapter->link_status_changed = 0; | ||
4475 | } | ||
4476 | } | ||
4477 | |||
4438 | static struct pci_driver sxg_driver = { | 4478 | static struct pci_driver sxg_driver = { |
4439 | .name = sxg_driver_name, | 4479 | .name = sxg_driver_name, |
4440 | .id_table = sxg_pci_tbl, | 4480 | .id_table = sxg_pci_tbl, |
diff --git a/drivers/staging/sxg/sxg.h b/drivers/staging/sxg/sxg.h index 899cf1510f91..f07aa708d862 100644 --- a/drivers/staging/sxg/sxg.h +++ b/drivers/staging/sxg/sxg.h | |||
@@ -715,6 +715,9 @@ struct adapter_t { | |||
715 | /*MSI-X related data elements*/ | 715 | /*MSI-X related data elements*/ |
716 | u32 nr_msix_entries; | 716 | u32 nr_msix_entries; |
717 | struct msix_entry *msi_entries; | 717 | struct msix_entry *msi_entries; |
718 | struct timer_list watchdog_timer; | ||
719 | struct work_struct update_link_status; | ||
720 | u32 link_status_changed; | ||
718 | }; | 721 | }; |
719 | 722 | ||
720 | #if SLIC_DUMP_ENABLED | 723 | #if SLIC_DUMP_ENABLED |