Skip to content

Commit

Permalink
net/ncsi: Fix the multi thread manner of NCSI driver
Browse files Browse the repository at this point in the history
[ Upstream commit e85e271 ]

Currently NCSI driver will send several NCSI commands back to back without
waiting the response of previous NCSI command or timeout in some state
when NIC have multi channel. This operation against the single thread
manner defined by NCSI SPEC(section 6.3.2.3 in DSP0222_1.1.1)

According to NCSI SPEC(section 6.2.13.1 in DSP0222_1.1.1), we should probe
one channel at a time by sending NCSI commands (Clear initial state, Get
version ID, Get capabilities...), than repeat this steps until the max
number of channels which we got from NCSI command (Get capabilities) has
been probed.

Fixes: e6f44ed ("net/ncsi: Package and channel management")
Signed-off-by: DelphineCCChiu <delphine_cc_chiu@wiwynn.com>
Link: https://lore.kernel.org/r/20240529065856.825241-1-delphine_cc_chiu@wiwynn.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
DelphineCCChiu authored and gregkh committed Jul 5, 2024
1 parent 7329bc6 commit 3cbb2ba
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 38 deletions.
2 changes: 2 additions & 0 deletions net/ncsi/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ struct ncsi_dev_priv {
spinlock_t lock; /* Protect the NCSI device */
unsigned int package_probe_id;/* Current ID during probe */
unsigned int package_num; /* Number of packages */
unsigned int channel_probe_id;/* Current cahnnel ID during probe */
struct list_head packages; /* List of packages */
struct ncsi_channel *hot_channel; /* Channel was ever active */
struct ncsi_request requests[256]; /* Request table */
Expand All @@ -340,6 +341,7 @@ struct ncsi_dev_priv {
bool multi_package; /* Enable multiple packages */
bool mlx_multi_host; /* Enable multi host Mellanox */
u32 package_whitelist; /* Packages to configure */
unsigned char channel_count; /* Num of channels to probe */
};

struct ncsi_cmd_arg {
Expand Down
73 changes: 36 additions & 37 deletions net/ncsi/ncsi-manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,17 +510,19 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)

break;
case ncsi_dev_state_suspend_gls:
ndp->pending_req_num = np->channel_num;
ndp->pending_req_num = 1;

nca.type = NCSI_PKT_CMD_GLS;
nca.package = np->id;
nca.channel = ndp->channel_probe_id;
ret = ncsi_xmit_cmd(&nca);
if (ret)
goto error;
ndp->channel_probe_id++;

nd->state = ncsi_dev_state_suspend_dcnt;
NCSI_FOR_EACH_CHANNEL(np, nc) {
nca.channel = nc->id;
ret = ncsi_xmit_cmd(&nca);
if (ret)
goto error;
if (ndp->channel_probe_id == ndp->channel_count) {
ndp->channel_probe_id = 0;
nd->state = ncsi_dev_state_suspend_dcnt;
}

break;
Expand Down Expand Up @@ -1317,7 +1319,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)
{
struct ncsi_dev *nd = &ndp->ndev;
struct ncsi_package *np;
struct ncsi_channel *nc;
struct ncsi_cmd_arg nca;
unsigned char index;
int ret;
Expand Down Expand Up @@ -1395,23 +1396,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)

nd->state = ncsi_dev_state_probe_cis;
break;
case ncsi_dev_state_probe_cis:
ndp->pending_req_num = NCSI_RESERVED_CHANNEL;

/* Clear initial state */
nca.type = NCSI_PKT_CMD_CIS;
nca.package = ndp->active_package->id;
for (index = 0; index < NCSI_RESERVED_CHANNEL; index++) {
nca.channel = index;
ret = ncsi_xmit_cmd(&nca);
if (ret)
goto error;
}

nd->state = ncsi_dev_state_probe_gvi;
if (IS_ENABLED(CONFIG_NCSI_OEM_CMD_KEEP_PHY))
nd->state = ncsi_dev_state_probe_keep_phy;
break;
case ncsi_dev_state_probe_keep_phy:
ndp->pending_req_num = 1;

Expand All @@ -1424,34 +1408,47 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)

nd->state = ncsi_dev_state_probe_gvi;
break;
case ncsi_dev_state_probe_cis:
case ncsi_dev_state_probe_gvi:
case ncsi_dev_state_probe_gc:
case ncsi_dev_state_probe_gls:
np = ndp->active_package;
ndp->pending_req_num = np->channel_num;
ndp->pending_req_num = 1;

/* Retrieve version, capability or link status */
if (nd->state == ncsi_dev_state_probe_gvi)
/* Clear initial state Retrieve version, capability or link status */
if (nd->state == ncsi_dev_state_probe_cis)
nca.type = NCSI_PKT_CMD_CIS;
else if (nd->state == ncsi_dev_state_probe_gvi)
nca.type = NCSI_PKT_CMD_GVI;
else if (nd->state == ncsi_dev_state_probe_gc)
nca.type = NCSI_PKT_CMD_GC;
else
nca.type = NCSI_PKT_CMD_GLS;

nca.package = np->id;
NCSI_FOR_EACH_CHANNEL(np, nc) {
nca.channel = nc->id;
ret = ncsi_xmit_cmd(&nca);
if (ret)
goto error;
}
nca.channel = ndp->channel_probe_id;

if (nd->state == ncsi_dev_state_probe_gvi)
ret = ncsi_xmit_cmd(&nca);
if (ret)
goto error;

if (nd->state == ncsi_dev_state_probe_cis) {
nd->state = ncsi_dev_state_probe_gvi;
if (IS_ENABLED(CONFIG_NCSI_OEM_CMD_KEEP_PHY) && ndp->channel_probe_id == 0)
nd->state = ncsi_dev_state_probe_keep_phy;
} else if (nd->state == ncsi_dev_state_probe_gvi) {
nd->state = ncsi_dev_state_probe_gc;
else if (nd->state == ncsi_dev_state_probe_gc)
} else if (nd->state == ncsi_dev_state_probe_gc) {
nd->state = ncsi_dev_state_probe_gls;
else
} else {
nd->state = ncsi_dev_state_probe_cis;
ndp->channel_probe_id++;
}

if (ndp->channel_probe_id == ndp->channel_count) {
ndp->channel_probe_id = 0;
nd->state = ncsi_dev_state_probe_dp;
}
break;
case ncsi_dev_state_probe_dp:
ndp->pending_req_num = 1;
Expand Down Expand Up @@ -1752,6 +1749,7 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
ndp->requests[i].ndp = ndp;
timer_setup(&ndp->requests[i].timer, ncsi_request_timeout, 0);
}
ndp->channel_count = NCSI_RESERVED_CHANNEL;

spin_lock_irqsave(&ncsi_dev_lock, flags);
list_add_tail_rcu(&ndp->node, &ncsi_dev_list);
Expand Down Expand Up @@ -1784,6 +1782,7 @@ int ncsi_start_dev(struct ncsi_dev *nd)

if (!(ndp->flags & NCSI_DEV_PROBED)) {
ndp->package_probe_id = 0;
ndp->channel_probe_id = 0;
nd->state = ncsi_dev_state_probe;
schedule_work(&ndp->work);
return 0;
Expand Down
4 changes: 3 additions & 1 deletion net/ncsi/ncsi-rsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -795,12 +795,13 @@ static int ncsi_rsp_handler_gc(struct ncsi_request *nr)
struct ncsi_rsp_gc_pkt *rsp;
struct ncsi_dev_priv *ndp = nr->ndp;
struct ncsi_channel *nc;
struct ncsi_package *np;
size_t size;

/* Find the channel */
rsp = (struct ncsi_rsp_gc_pkt *)skb_network_header(nr->rsp);
ncsi_find_package_and_channel(ndp, rsp->rsp.common.channel,
NULL, &nc);
&np, &nc);
if (!nc)
return -ENODEV;

Expand Down Expand Up @@ -835,6 +836,7 @@ static int ncsi_rsp_handler_gc(struct ncsi_request *nr)
*/
nc->vlan_filter.bitmap = U64_MAX;
nc->vlan_filter.n_vids = rsp->vlan_cnt;
np->ndp->channel_count = rsp->channel_cnt;

return 0;
}
Expand Down

0 comments on commit 3cbb2ba

Please sign in to comment.