Skip to content

Commit

Permalink
net/ncsi: Configure multi-package, multi-channel modes with failover
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
sammj authored and davem330 committed Nov 18, 2018
1 parent 2878a2c commit 8d951a7
Show file tree
Hide file tree
Showing 6 changed files with 493 additions and 88 deletions.
15 changes: 15 additions & 0 deletions include/uapi/linux/ncsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
* @NCSI_CMD_SEND_CMD: send NC-SI command to network card.
* Requires NCSI_ATTR_IFINDEX, NCSI_ATTR_PACKAGE_ID
* and NCSI_ATTR_CHANNEL_ID.
* @NCSI_CMD_SET_PACKAGE_MASK: set a whitelist of allowed packages.
* Requires NCSI_ATTR_IFINDEX and NCSI_ATTR_PACKAGE_MASK.
* @NCSI_CMD_SET_CHANNEL_MASK: set a whitelist of allowed channels.
* Requires NCSI_ATTR_IFINDEX, NCSI_ATTR_PACKAGE_ID, and
* NCSI_ATTR_CHANNEL_MASK. If NCSI_ATTR_CHANNEL_ID is present it sets
* the primary channel.
* @NCSI_CMD_MAX: highest command number
*/
enum ncsi_nl_commands {
Expand All @@ -34,6 +40,8 @@ enum ncsi_nl_commands {
NCSI_CMD_SET_INTERFACE,
NCSI_CMD_CLEAR_INTERFACE,
NCSI_CMD_SEND_CMD,
NCSI_CMD_SET_PACKAGE_MASK,
NCSI_CMD_SET_CHANNEL_MASK,

__NCSI_CMD_AFTER_LAST,
NCSI_CMD_MAX = __NCSI_CMD_AFTER_LAST - 1
Expand All @@ -48,6 +56,10 @@ enum ncsi_nl_commands {
* @NCSI_ATTR_PACKAGE_ID: package ID
* @NCSI_ATTR_CHANNEL_ID: channel ID
* @NCSI_ATTR_DATA: command payload
* @NCSI_ATTR_MULTI_FLAG: flag to signal that multi-mode should be enabled with
* NCSI_CMD_SET_PACKAGE_MASK or NCSI_CMD_SET_CHANNEL_MASK.
* @NCSI_ATTR_PACKAGE_MASK: 32-bit mask of allowed packages.
* @NCSI_ATTR_CHANNEL_MASK: 32-bit mask of allowed channels.
* @NCSI_ATTR_MAX: highest attribute number
*/
enum ncsi_nl_attrs {
Expand All @@ -57,6 +69,9 @@ enum ncsi_nl_attrs {
NCSI_ATTR_PACKAGE_ID,
NCSI_ATTR_CHANNEL_ID,
NCSI_ATTR_DATA,
NCSI_ATTR_MULTI_FLAG,
NCSI_ATTR_PACKAGE_MASK,
NCSI_ATTR_CHANNEL_MASK,

__NCSI_ATTR_AFTER_LAST,
NCSI_ATTR_MAX = __NCSI_ATTR_AFTER_LAST - 1
Expand Down
16 changes: 14 additions & 2 deletions net/ncsi/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ struct ncsi_package {
unsigned int channel_num; /* Number of channels */
struct list_head channels; /* List of chanels */
struct list_head node; /* Form list of packages */

bool multi_channel; /* Enable multiple channels */
u32 channel_whitelist; /* Channels to configure */
struct ncsi_channel *preferred_channel; /* Primary channel */
};

struct ncsi_request {
Expand Down Expand Up @@ -297,8 +301,6 @@ struct ncsi_dev_priv {
unsigned int package_num; /* Number of packages */
struct list_head packages; /* List of packages */
struct ncsi_channel *hot_channel; /* Channel was ever active */
struct ncsi_package *force_package; /* Force a specific package */
struct ncsi_channel *force_channel; /* Force a specific channel */
struct ncsi_request requests[256]; /* Request table */
unsigned int request_id; /* Last used request ID */
#define NCSI_REQ_START_IDX 1
Expand All @@ -311,6 +313,9 @@ struct ncsi_dev_priv {
struct list_head node; /* Form NCSI device list */
#define NCSI_MAX_VLAN_VIDS 15
struct list_head vlan_vids; /* List of active VLAN IDs */

bool multi_package; /* Enable multiple packages */
u32 package_whitelist; /* Packages to configure */
};

struct ncsi_cmd_arg {
Expand Down Expand Up @@ -364,6 +369,13 @@ struct ncsi_request *ncsi_alloc_request(struct ncsi_dev_priv *ndp,
void ncsi_free_request(struct ncsi_request *nr);
struct ncsi_dev *ncsi_find_dev(struct net_device *dev);
int ncsi_process_next_channel(struct ncsi_dev_priv *ndp);
bool ncsi_channel_has_link(struct ncsi_channel *channel);
bool ncsi_channel_is_last(struct ncsi_dev_priv *ndp,
struct ncsi_channel *channel);
int ncsi_update_tx_channel(struct ncsi_dev_priv *ndp,
struct ncsi_package *np,
struct ncsi_channel *disable,
struct ncsi_channel *enable);

/* Packet handlers */
u32 ncsi_calculate_checksum(unsigned char *data, int len);
Expand Down
63 changes: 51 additions & 12 deletions net/ncsi/ncsi-aen.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
bool chained;
int state;
unsigned long old_data, data;
unsigned long flags;
struct ncsi_aen_lsc_pkt *lsc;
struct ncsi_package *np;
bool had_link, has_link;
unsigned long flags;
bool chained;
int state;

/* Find the NCSI channel */
ncsi_find_package_and_channel(ndp, h->common.channel, NULL, &nc);
Expand Down Expand Up @@ -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,
Expand Down
Loading

0 comments on commit 8d951a7

Please sign in to comment.