|
@@ -172,15 +172,15 @@ static void ncsi_channel_monitor(unsigned long data)
|
|
struct ncsi_dev_priv *ndp = np->ndp;
|
|
struct ncsi_dev_priv *ndp = np->ndp;
|
|
struct ncsi_cmd_arg nca;
|
|
struct ncsi_cmd_arg nca;
|
|
bool enabled, chained;
|
|
bool enabled, chained;
|
|
- unsigned int timeout;
|
|
|
|
|
|
+ unsigned int monitor_state;
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
int state, ret;
|
|
int state, ret;
|
|
|
|
|
|
spin_lock_irqsave(&nc->lock, flags);
|
|
spin_lock_irqsave(&nc->lock, flags);
|
|
state = nc->state;
|
|
state = nc->state;
|
|
chained = !list_empty(&nc->link);
|
|
chained = !list_empty(&nc->link);
|
|
- timeout = nc->timeout;
|
|
|
|
- enabled = nc->enabled;
|
|
|
|
|
|
+ enabled = nc->monitor.enabled;
|
|
|
|
+ monitor_state = nc->monitor.state;
|
|
spin_unlock_irqrestore(&nc->lock, flags);
|
|
spin_unlock_irqrestore(&nc->lock, flags);
|
|
|
|
|
|
if (!enabled || chained)
|
|
if (!enabled || chained)
|
|
@@ -189,7 +189,9 @@ static void ncsi_channel_monitor(unsigned long data)
|
|
state != NCSI_CHANNEL_ACTIVE)
|
|
state != NCSI_CHANNEL_ACTIVE)
|
|
return;
|
|
return;
|
|
|
|
|
|
- if (!(timeout % 2)) {
|
|
|
|
|
|
+ switch (monitor_state) {
|
|
|
|
+ case NCSI_CHANNEL_MONITOR_START:
|
|
|
|
+ case NCSI_CHANNEL_MONITOR_RETRY:
|
|
nca.ndp = ndp;
|
|
nca.ndp = ndp;
|
|
nca.package = np->id;
|
|
nca.package = np->id;
|
|
nca.channel = nc->id;
|
|
nca.channel = nc->id;
|
|
@@ -201,12 +203,16 @@ static void ncsi_channel_monitor(unsigned long data)
|
|
ret);
|
|
ret);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
|
|
- if (timeout + 1 >= 3) {
|
|
|
|
|
|
+ break;
|
|
|
|
+ case NCSI_CHANNEL_MONITOR_WAIT ... NCSI_CHANNEL_MONITOR_WAIT_MAX:
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
if (!(ndp->flags & NCSI_DEV_HWA) &&
|
|
if (!(ndp->flags & NCSI_DEV_HWA) &&
|
|
- state == NCSI_CHANNEL_ACTIVE)
|
|
|
|
|
|
+ state == NCSI_CHANNEL_ACTIVE) {
|
|
ncsi_report_link(ndp, true);
|
|
ncsi_report_link(ndp, true);
|
|
|
|
+ ndp->flags |= NCSI_DEV_RESHUFFLE;
|
|
|
|
+ }
|
|
|
|
|
|
spin_lock_irqsave(&nc->lock, flags);
|
|
spin_lock_irqsave(&nc->lock, flags);
|
|
nc->state = NCSI_CHANNEL_INVISIBLE;
|
|
nc->state = NCSI_CHANNEL_INVISIBLE;
|
|
@@ -221,10 +227,9 @@ static void ncsi_channel_monitor(unsigned long data)
|
|
}
|
|
}
|
|
|
|
|
|
spin_lock_irqsave(&nc->lock, flags);
|
|
spin_lock_irqsave(&nc->lock, flags);
|
|
- nc->timeout = timeout + 1;
|
|
|
|
- nc->enabled = true;
|
|
|
|
|
|
+ nc->monitor.state++;
|
|
spin_unlock_irqrestore(&nc->lock, flags);
|
|
spin_unlock_irqrestore(&nc->lock, flags);
|
|
- mod_timer(&nc->timer, jiffies + HZ * (1 << (nc->timeout / 2)));
|
|
|
|
|
|
+ mod_timer(&nc->monitor.timer, jiffies + HZ);
|
|
}
|
|
}
|
|
|
|
|
|
void ncsi_start_channel_monitor(struct ncsi_channel *nc)
|
|
void ncsi_start_channel_monitor(struct ncsi_channel *nc)
|
|
@@ -232,12 +237,12 @@ void ncsi_start_channel_monitor(struct ncsi_channel *nc)
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
spin_lock_irqsave(&nc->lock, flags);
|
|
spin_lock_irqsave(&nc->lock, flags);
|
|
- WARN_ON_ONCE(nc->enabled);
|
|
|
|
- nc->timeout = 0;
|
|
|
|
- nc->enabled = true;
|
|
|
|
|
|
+ WARN_ON_ONCE(nc->monitor.enabled);
|
|
|
|
+ nc->monitor.enabled = true;
|
|
|
|
+ nc->monitor.state = NCSI_CHANNEL_MONITOR_START;
|
|
spin_unlock_irqrestore(&nc->lock, flags);
|
|
spin_unlock_irqrestore(&nc->lock, flags);
|
|
|
|
|
|
- mod_timer(&nc->timer, jiffies + HZ * (1 << (nc->timeout / 2)));
|
|
|
|
|
|
+ mod_timer(&nc->monitor.timer, jiffies + HZ);
|
|
}
|
|
}
|
|
|
|
|
|
void ncsi_stop_channel_monitor(struct ncsi_channel *nc)
|
|
void ncsi_stop_channel_monitor(struct ncsi_channel *nc)
|
|
@@ -245,14 +250,14 @@ void ncsi_stop_channel_monitor(struct ncsi_channel *nc)
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
|
|
|
|
spin_lock_irqsave(&nc->lock, flags);
|
|
spin_lock_irqsave(&nc->lock, flags);
|
|
- if (!nc->enabled) {
|
|
|
|
|
|
+ if (!nc->monitor.enabled) {
|
|
spin_unlock_irqrestore(&nc->lock, flags);
|
|
spin_unlock_irqrestore(&nc->lock, flags);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- nc->enabled = false;
|
|
|
|
|
|
+ nc->monitor.enabled = false;
|
|
spin_unlock_irqrestore(&nc->lock, flags);
|
|
spin_unlock_irqrestore(&nc->lock, flags);
|
|
|
|
|
|
- del_timer_sync(&nc->timer);
|
|
|
|
|
|
+ del_timer_sync(&nc->monitor.timer);
|
|
}
|
|
}
|
|
|
|
|
|
struct ncsi_channel *ncsi_find_channel(struct ncsi_package *np,
|
|
struct ncsi_channel *ncsi_find_channel(struct ncsi_package *np,
|
|
@@ -281,8 +286,9 @@ struct ncsi_channel *ncsi_add_channel(struct ncsi_package *np, unsigned char id)
|
|
nc->id = id;
|
|
nc->id = id;
|
|
nc->package = np;
|
|
nc->package = np;
|
|
nc->state = NCSI_CHANNEL_INACTIVE;
|
|
nc->state = NCSI_CHANNEL_INACTIVE;
|
|
- nc->enabled = false;
|
|
|
|
- setup_timer(&nc->timer, ncsi_channel_monitor, (unsigned long)nc);
|
|
|
|
|
|
+ nc->monitor.enabled = false;
|
|
|
|
+ setup_timer(&nc->monitor.timer,
|
|
|
|
+ ncsi_channel_monitor, (unsigned long)nc);
|
|
spin_lock_init(&nc->lock);
|
|
spin_lock_init(&nc->lock);
|
|
INIT_LIST_HEAD(&nc->link);
|
|
INIT_LIST_HEAD(&nc->link);
|
|
for (index = 0; index < NCSI_CAP_MAX; index++)
|
|
for (index = 0; index < NCSI_CAP_MAX; index++)
|