net/ncsi: Configure multi-package, multi-channel modes with failover
This patch extends the ncsi-netlink interface with two new commands and three new attributes to configure multiple packages and/or channels at once, and configure specific failover modes. NCSI_CMD_SET_PACKAGE mask and NCSI_CMD_SET_CHANNEL_MASK set a whitelist of packages or channels allowed to be configured with the NCSI_ATTR_PACKAGE_MASK and NCSI_ATTR_CHANNEL_MASK attributes respectively. If one of these whitelists is set only packages or channels matching the whitelist are considered for the channel queue in ncsi_choose_active_channel(). These commands may also use the NCSI_ATTR_MULTI_FLAG to signal that multiple packages or channels may be configured simultaneously. NCSI hardware arbitration (HWA) must be available in order to enable multi-package mode. Multi-channel mode is always available. If the NCSI_ATTR_CHANNEL_ID attribute is present in the NCSI_CMD_SET_CHANNEL_MASK command the it sets the preferred channel as with the NCSI_CMD_SET_INTERFACE command. The combination of preferred channel and channel whitelist defines a primary channel and the allowed failover channels. If the NCSI_ATTR_MULTI_FLAG attribute is also present then the preferred channel is configured for Tx/Rx and the other channels are enabled only for Rx. Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Этот коммит содержится в:

коммит произвёл
David S. Miller

родитель
2878a2cfe5
Коммит
8d951a75d0
@@ -50,14 +50,15 @@ static int ncsi_validate_aen_pkt(struct ncsi_aen_pkt_hdr *h,
|
||||
static int ncsi_aen_handler_lsc(struct ncsi_dev_priv *ndp,
|
||||
struct ncsi_aen_pkt_hdr *h)
|
||||
{
|
||||
struct ncsi_aen_lsc_pkt *lsc;
|
||||
struct ncsi_channel *nc;
|
||||
struct ncsi_channel *nc, *tmp;
|
||||
struct ncsi_channel_mode *ncm;
|
||||
unsigned long old_data, data;
|
||||
struct ncsi_aen_lsc_pkt *lsc;
|
||||
struct ncsi_package *np;
|
||||
bool had_link, has_link;
|
||||
unsigned long flags;
|
||||
bool chained;
|
||||
int state;
|
||||
unsigned long old_data, data;
|
||||
unsigned long flags;
|
||||
bool had_link, has_link;
|
||||
|
||||
/* Find the NCSI channel */
|
||||
ncsi_find_package_and_channel(ndp, h->common.channel, NULL, &nc);
|
||||
@@ -92,14 +93,52 @@ static int ncsi_aen_handler_lsc(struct ncsi_dev_priv *ndp,
|
||||
if ((had_link == has_link) || chained)
|
||||
return 0;
|
||||
|
||||
if (had_link)
|
||||
ndp->flags |= NCSI_DEV_RESHUFFLE;
|
||||
ncsi_stop_channel_monitor(nc);
|
||||
spin_lock_irqsave(&ndp->lock, flags);
|
||||
list_add_tail_rcu(&nc->link, &ndp->channel_queue);
|
||||
spin_unlock_irqrestore(&ndp->lock, flags);
|
||||
if (!ndp->multi_package && !nc->package->multi_channel) {
|
||||
if (had_link) {
|
||||
ndp->flags |= NCSI_DEV_RESHUFFLE;
|
||||
ncsi_stop_channel_monitor(nc);
|
||||
spin_lock_irqsave(&ndp->lock, flags);
|
||||
list_add_tail_rcu(&nc->link, &ndp->channel_queue);
|
||||
spin_unlock_irqrestore(&ndp->lock, flags);
|
||||
return ncsi_process_next_channel(ndp);
|
||||
}
|
||||
/* Configured channel came up */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ncsi_process_next_channel(ndp);
|
||||
if (had_link) {
|
||||
ncm = &nc->modes[NCSI_MODE_TX_ENABLE];
|
||||
if (ncsi_channel_is_last(ndp, nc)) {
|
||||
/* No channels left, reconfigure */
|
||||
return ncsi_reset_dev(&ndp->ndev);
|
||||
} else if (ncm->enable) {
|
||||
/* Need to failover Tx channel */
|
||||
ncsi_update_tx_channel(ndp, nc->package, nc, NULL);
|
||||
}
|
||||
} else if (has_link && nc->package->preferred_channel == nc) {
|
||||
/* Return Tx to preferred channel */
|
||||
ncsi_update_tx_channel(ndp, nc->package, NULL, nc);
|
||||
} else if (has_link) {
|
||||
NCSI_FOR_EACH_PACKAGE(ndp, np) {
|
||||
NCSI_FOR_EACH_CHANNEL(np, tmp) {
|
||||
/* Enable Tx on this channel if the current Tx
|
||||
* channel is down.
|
||||
*/
|
||||
ncm = &tmp->modes[NCSI_MODE_TX_ENABLE];
|
||||
if (ncm->enable &&
|
||||
!ncsi_channel_has_link(tmp)) {
|
||||
ncsi_update_tx_channel(ndp, nc->package,
|
||||
tmp, nc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Leave configured channels active in a multi-channel scenario so
|
||||
* AEN events are still received.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ncsi_aen_handler_cr(struct ncsi_dev_priv *ndp,
|
||||
|
Ссылка в новой задаче
Block a user