Skip to content

Commit ea87c8e

Browse files
committed
RDMA/core: Support link status events dispatching
JIRA: https://issues.redhat.com/browse/RHEL-78090 commit 1fb0644 Author: Yuyu Li <liyuyu6@huawei.com> Date: Fri Nov 22 18:52:58 2024 +0800 RDMA/core: Support link status events dispatching Currently the dispatching of link status events is implemented by each RDMA driver independently, and most of them have very similar patterns. Add support for this in ib_core so that we can get rid of duplicate codes in each driver. A new last_port_state is added in ib_port_cache to cache the port state of the last link status events dispatching. The original port_state in ib_port_cache is not used here because it will be updated when ib_dispatch_event() is called, which means it may be changed between two link status events, and may lead to a loss of event dispatching. Some drivers currently have some private stuff in their link status events handler in addition to event dispatching, and cannot be perfectly integrated into the ib_core handling process. For these drivers, add a new ops report_port_event() so that they can keep their current processing. Finally, events of LAG devices are not supported yet in this patch as currently there is no way to obtain ibdev from upper netdev in ib_core. This can be a TODO work after the core have more support for LAG. Signed-off-by: Yuyu Li <liyuyu6@huawei.com> Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com> Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Kamal Heib <kheib@redhat.com>
1 parent 3836c50 commit ea87c8e

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

drivers/infiniband/core/device.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2771,6 +2771,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
27712771
SET_DEVICE_OP(dev_ops, set_vf_guid);
27722772
SET_DEVICE_OP(dev_ops, set_vf_link_state);
27732773
SET_DEVICE_OP(dev_ops, ufile_hw_cleanup);
2774+
SET_DEVICE_OP(dev_ops, report_port_event);
27742775

27752776
SET_OBJ_SIZE(dev_ops, ib_ah);
27762777
SET_OBJ_SIZE(dev_ops, ib_counters);
@@ -2864,6 +2865,58 @@ static const struct rdma_nl_cbs ibnl_ls_cb_table[RDMA_NL_LS_NUM_OPS] = {
28642865
},
28652866
};
28662867

2868+
void ib_dispatch_port_state_event(struct ib_device *ibdev, struct net_device *ndev)
2869+
{
2870+
enum ib_port_state curr_state;
2871+
struct ib_event ibevent = {};
2872+
u32 port;
2873+
2874+
if (ib_query_netdev_port(ibdev, ndev, &port))
2875+
return;
2876+
2877+
curr_state = ib_get_curr_port_state(ndev);
2878+
2879+
write_lock_irq(&ibdev->cache_lock);
2880+
if (ibdev->port_data[port].cache.last_port_state == curr_state) {
2881+
write_unlock_irq(&ibdev->cache_lock);
2882+
return;
2883+
}
2884+
ibdev->port_data[port].cache.last_port_state = curr_state;
2885+
write_unlock_irq(&ibdev->cache_lock);
2886+
2887+
ibevent.event = (curr_state == IB_PORT_DOWN) ?
2888+
IB_EVENT_PORT_ERR : IB_EVENT_PORT_ACTIVE;
2889+
ibevent.device = ibdev;
2890+
ibevent.element.port_num = port;
2891+
ib_dispatch_event(&ibevent);
2892+
}
2893+
EXPORT_SYMBOL(ib_dispatch_port_state_event);
2894+
2895+
static void handle_port_event(struct net_device *ndev, unsigned long event)
2896+
{
2897+
struct ib_device *ibdev;
2898+
2899+
/* Currently, link events in bonding scenarios are still
2900+
* reported by drivers that support bonding.
2901+
*/
2902+
if (netif_is_lag_master(ndev) || netif_is_lag_port(ndev))
2903+
return;
2904+
2905+
ibdev = ib_device_get_by_netdev(ndev, RDMA_DRIVER_UNKNOWN);
2906+
if (!ibdev)
2907+
return;
2908+
2909+
if (ibdev->ops.report_port_event) {
2910+
ibdev->ops.report_port_event(ibdev, ndev, event);
2911+
goto put_ibdev;
2912+
}
2913+
2914+
ib_dispatch_port_state_event(ibdev, ndev);
2915+
2916+
put_ibdev:
2917+
ib_device_put(ibdev);
2918+
};
2919+
28672920
static int ib_netdevice_event(struct notifier_block *this,
28682921
unsigned long event, void *ptr)
28692922
{
@@ -2885,6 +2938,13 @@ static int ib_netdevice_event(struct notifier_block *this,
28852938
rdma_nl_notify_event(ibdev, port, RDMA_NETDEV_RENAME_EVENT);
28862939
ib_device_put(ibdev);
28872940
break;
2941+
2942+
case NETDEV_UP:
2943+
case NETDEV_CHANGE:
2944+
case NETDEV_DOWN:
2945+
handle_port_event(ndev, event);
2946+
break;
2947+
28882948
default:
28892949
break;
28902950
}

include/rdma/ib_verbs.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2174,6 +2174,7 @@ struct ib_port_cache {
21742174
struct ib_gid_table *gid;
21752175
u8 lmc;
21762176
enum ib_port_state port_state;
2177+
enum ib_port_state last_port_state;
21772178
};
21782179

21792180
struct ib_port_immutable {
@@ -2678,6 +2679,13 @@ struct ib_device_ops {
26782679
*/
26792680
void (*ufile_hw_cleanup)(struct ib_uverbs_file *ufile);
26802681

2682+
/**
2683+
* report_port_event - Drivers need to implement this if they have
2684+
* some private stuff to handle when link status changes.
2685+
*/
2686+
void (*report_port_event)(struct ib_device *ibdev,
2687+
struct net_device *ndev, unsigned long event);
2688+
26812689
DECLARE_RDMA_OBJ_SIZE(ib_ah);
26822690
DECLARE_RDMA_OBJ_SIZE(ib_counters);
26832691
DECLARE_RDMA_OBJ_SIZE(ib_cq);
@@ -4468,6 +4476,15 @@ struct net_device *ib_device_get_netdev(struct ib_device *ib_dev,
44684476
u32 port);
44694477
int ib_query_netdev_port(struct ib_device *ibdev, struct net_device *ndev,
44704478
u32 *port);
4479+
4480+
static inline enum ib_port_state ib_get_curr_port_state(struct net_device *net_dev)
4481+
{
4482+
return (netif_running(net_dev) && netif_carrier_ok(net_dev)) ?
4483+
IB_PORT_ACTIVE : IB_PORT_DOWN;
4484+
}
4485+
4486+
void ib_dispatch_port_state_event(struct ib_device *ibdev,
4487+
struct net_device *ndev);
44714488
struct ib_wq *ib_create_wq(struct ib_pd *pd,
44724489
struct ib_wq_init_attr *init_attr);
44734490
int ib_destroy_wq_user(struct ib_wq *wq, struct ib_udata *udata);

0 commit comments

Comments
 (0)