mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-04-16 20:17:49 +07:00
netvsc: use refcount_t for keeping track of sub channels
Rather than a lock and variable, use a refcount_t to keep track of the number of sub channels. Don't need to wait for subchannels on device removal since wait was already done in device_add. Also fix the error handling; don't wait forever in case of an error on request to create sub channels. Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a0be450e19
commit
43c7bd1ffc
@ -761,8 +761,8 @@ struct netvsc_device {
|
|||||||
|
|
||||||
u32 max_chn;
|
u32 max_chn;
|
||||||
u32 num_chn;
|
u32 num_chn;
|
||||||
spinlock_t sc_lock; /* Protects num_sc_offered variable */
|
|
||||||
u32 num_sc_offered;
|
refcount_t sc_offered;
|
||||||
|
|
||||||
/* Holds rndis device info */
|
/* Holds rndis device info */
|
||||||
void *extension;
|
void *extension;
|
||||||
|
@ -997,7 +997,6 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
|
|||||||
struct netvsc_device *nvscdev = net_device_to_netvsc_device(ndev);
|
struct netvsc_device *nvscdev = net_device_to_netvsc_device(ndev);
|
||||||
u16 chn_index = new_sc->offermsg.offer.sub_channel_index;
|
u16 chn_index = new_sc->offermsg.offer.sub_channel_index;
|
||||||
struct netvsc_channel *nvchan;
|
struct netvsc_channel *nvchan;
|
||||||
unsigned long flags;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (chn_index >= nvscdev->num_chn)
|
if (chn_index >= nvscdev->num_chn)
|
||||||
@ -1019,10 +1018,7 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
|
|||||||
|
|
||||||
napi_enable(&nvchan->napi);
|
napi_enable(&nvchan->napi);
|
||||||
|
|
||||||
spin_lock_irqsave(&nvscdev->sc_lock, flags);
|
if (refcount_dec_and_test(&nvscdev->sc_offered))
|
||||||
nvscdev->num_sc_offered--;
|
|
||||||
spin_unlock_irqrestore(&nvscdev->sc_lock, flags);
|
|
||||||
if (nvscdev->num_sc_offered == 0)
|
|
||||||
complete(&nvscdev->channel_init_wait);
|
complete(&nvscdev->channel_init_wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1039,12 +1035,9 @@ int rndis_filter_device_add(struct hv_device *dev,
|
|||||||
struct ndis_recv_scale_cap rsscap;
|
struct ndis_recv_scale_cap rsscap;
|
||||||
u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
|
u32 rsscap_size = sizeof(struct ndis_recv_scale_cap);
|
||||||
unsigned int gso_max_size = GSO_MAX_SIZE;
|
unsigned int gso_max_size = GSO_MAX_SIZE;
|
||||||
u32 mtu, size;
|
u32 mtu, size, num_rss_qs;
|
||||||
u32 num_rss_qs;
|
|
||||||
u32 sc_delta;
|
|
||||||
const struct cpumask *node_cpu_mask;
|
const struct cpumask *node_cpu_mask;
|
||||||
u32 num_possible_rss_qs;
|
u32 num_possible_rss_qs;
|
||||||
unsigned long flags;
|
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
rndis_device = get_rndis_device();
|
rndis_device = get_rndis_device();
|
||||||
@ -1067,7 +1060,7 @@ int rndis_filter_device_add(struct hv_device *dev,
|
|||||||
net_device->max_chn = 1;
|
net_device->max_chn = 1;
|
||||||
net_device->num_chn = 1;
|
net_device->num_chn = 1;
|
||||||
|
|
||||||
spin_lock_init(&net_device->sc_lock);
|
refcount_set(&net_device->sc_offered, 0);
|
||||||
|
|
||||||
net_device->extension = rndis_device;
|
net_device->extension = rndis_device;
|
||||||
rndis_device->ndev = net;
|
rndis_device->ndev = net;
|
||||||
@ -1204,6 +1197,7 @@ int rndis_filter_device_add(struct hv_device *dev,
|
|||||||
if (num_rss_qs == 0)
|
if (num_rss_qs == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
refcount_set(&net_device->sc_offered, num_rss_qs);
|
||||||
vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);
|
vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);
|
||||||
|
|
||||||
init_packet = &net_device->channel_init_pkt;
|
init_packet = &net_device->channel_init_pkt;
|
||||||
@ -1219,32 +1213,23 @@ int rndis_filter_device_add(struct hv_device *dev,
|
|||||||
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
wait_for_completion(&net_device->channel_init_wait);
|
|
||||||
|
|
||||||
if (init_packet->msg.v5_msg.subchn_comp.status !=
|
if (init_packet->msg.v5_msg.subchn_comp.status != NVSP_STAT_SUCCESS) {
|
||||||
NVSP_STAT_SUCCESS) {
|
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
wait_for_completion(&net_device->channel_init_wait);
|
||||||
|
|
||||||
net_device->num_chn = 1 +
|
net_device->num_chn = 1 +
|
||||||
init_packet->msg.v5_msg.subchn_comp.num_subchannels;
|
init_packet->msg.v5_msg.subchn_comp.num_subchannels;
|
||||||
|
|
||||||
ret = rndis_filter_set_rss_param(rndis_device, netvsc_hash_key,
|
/* ignore failues from setting rss parameters, still have channels */
|
||||||
|
rndis_filter_set_rss_param(rndis_device, netvsc_hash_key,
|
||||||
net_device->num_chn);
|
net_device->num_chn);
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the number of sub-channels to be received.
|
|
||||||
*/
|
|
||||||
spin_lock_irqsave(&net_device->sc_lock, flags);
|
|
||||||
sc_delta = num_rss_qs - (net_device->num_chn - 1);
|
|
||||||
net_device->num_sc_offered -= sc_delta;
|
|
||||||
spin_unlock_irqrestore(&net_device->sc_lock, flags);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (ret) {
|
if (ret) {
|
||||||
net_device->max_chn = 1;
|
net_device->max_chn = 1;
|
||||||
net_device->num_chn = 1;
|
net_device->num_chn = 1;
|
||||||
net_device->num_sc_offered = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; /* return 0 because primary channel can be used alone */
|
return 0; /* return 0 because primary channel can be used alone */
|
||||||
@ -1259,12 +1244,6 @@ void rndis_filter_device_remove(struct hv_device *dev,
|
|||||||
{
|
{
|
||||||
struct rndis_device *rndis_dev = net_dev->extension;
|
struct rndis_device *rndis_dev = net_dev->extension;
|
||||||
|
|
||||||
/* If not all subchannel offers are complete, wait for them until
|
|
||||||
* completion to avoid race.
|
|
||||||
*/
|
|
||||||
if (net_dev->num_sc_offered > 0)
|
|
||||||
wait_for_completion(&net_dev->channel_init_wait);
|
|
||||||
|
|
||||||
/* Halt and release the rndis device */
|
/* Halt and release the rndis device */
|
||||||
rndis_filter_halt_device(rndis_dev);
|
rndis_filter_halt_device(rndis_dev);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user