aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/ocrdma/ocrdma_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/ocrdma/ocrdma_main.c')
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_main.c138
1 files changed, 40 insertions, 98 deletions
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index 91443bcb9e0e..2ca86ca818bd 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -67,46 +67,24 @@ void ocrdma_get_guid(struct ocrdma_dev *dev, u8 *guid)
67 guid[7] = mac_addr[5]; 67 guid[7] = mac_addr[5];
68} 68}
69 69
70static void ocrdma_build_sgid_mac(union ib_gid *sgid, unsigned char *mac_addr, 70static bool ocrdma_add_sgid(struct ocrdma_dev *dev, union ib_gid *new_sgid)
71 bool is_vlan, u16 vlan_id)
72{
73 sgid->global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
74 sgid->raw[8] = mac_addr[0] ^ 2;
75 sgid->raw[9] = mac_addr[1];
76 sgid->raw[10] = mac_addr[2];
77 if (is_vlan) {
78 sgid->raw[11] = vlan_id >> 8;
79 sgid->raw[12] = vlan_id & 0xff;
80 } else {
81 sgid->raw[11] = 0xff;
82 sgid->raw[12] = 0xfe;
83 }
84 sgid->raw[13] = mac_addr[3];
85 sgid->raw[14] = mac_addr[4];
86 sgid->raw[15] = mac_addr[5];
87}
88
89static bool ocrdma_add_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr,
90 bool is_vlan, u16 vlan_id)
91{ 71{
92 int i; 72 int i;
93 union ib_gid new_sgid;
94 unsigned long flags; 73 unsigned long flags;
95 74
96 memset(&ocrdma_zero_sgid, 0, sizeof(union ib_gid)); 75 memset(&ocrdma_zero_sgid, 0, sizeof(union ib_gid));
97 76
98 ocrdma_build_sgid_mac(&new_sgid, mac_addr, is_vlan, vlan_id);
99 77
100 spin_lock_irqsave(&dev->sgid_lock, flags); 78 spin_lock_irqsave(&dev->sgid_lock, flags);
101 for (i = 0; i < OCRDMA_MAX_SGID; i++) { 79 for (i = 0; i < OCRDMA_MAX_SGID; i++) {
102 if (!memcmp(&dev->sgid_tbl[i], &ocrdma_zero_sgid, 80 if (!memcmp(&dev->sgid_tbl[i], &ocrdma_zero_sgid,
103 sizeof(union ib_gid))) { 81 sizeof(union ib_gid))) {
104 /* found free entry */ 82 /* found free entry */
105 memcpy(&dev->sgid_tbl[i], &new_sgid, 83 memcpy(&dev->sgid_tbl[i], new_sgid,
106 sizeof(union ib_gid)); 84 sizeof(union ib_gid));
107 spin_unlock_irqrestore(&dev->sgid_lock, flags); 85 spin_unlock_irqrestore(&dev->sgid_lock, flags);
108 return true; 86 return true;
109 } else if (!memcmp(&dev->sgid_tbl[i], &new_sgid, 87 } else if (!memcmp(&dev->sgid_tbl[i], new_sgid,
110 sizeof(union ib_gid))) { 88 sizeof(union ib_gid))) {
111 /* entry already present, no addition is required. */ 89 /* entry already present, no addition is required. */
112 spin_unlock_irqrestore(&dev->sgid_lock, flags); 90 spin_unlock_irqrestore(&dev->sgid_lock, flags);
@@ -117,20 +95,17 @@ static bool ocrdma_add_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr,
117 return false; 95 return false;
118} 96}
119 97
120static bool ocrdma_del_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr, 98static bool ocrdma_del_sgid(struct ocrdma_dev *dev, union ib_gid *sgid)
121 bool is_vlan, u16 vlan_id)
122{ 99{
123 int found = false; 100 int found = false;
124 int i; 101 int i;
125 union ib_gid sgid;
126 unsigned long flags; 102 unsigned long flags;
127 103
128 ocrdma_build_sgid_mac(&sgid, mac_addr, is_vlan, vlan_id);
129 104
130 spin_lock_irqsave(&dev->sgid_lock, flags); 105 spin_lock_irqsave(&dev->sgid_lock, flags);
131 /* first is default sgid, which cannot be deleted. */ 106 /* first is default sgid, which cannot be deleted. */
132 for (i = 1; i < OCRDMA_MAX_SGID; i++) { 107 for (i = 1; i < OCRDMA_MAX_SGID; i++) {
133 if (!memcmp(&dev->sgid_tbl[i], &sgid, sizeof(union ib_gid))) { 108 if (!memcmp(&dev->sgid_tbl[i], sgid, sizeof(union ib_gid))) {
134 /* found matching entry */ 109 /* found matching entry */
135 memset(&dev->sgid_tbl[i], 0, sizeof(union ib_gid)); 110 memset(&dev->sgid_tbl[i], 0, sizeof(union ib_gid));
136 found = true; 111 found = true;
@@ -141,75 +116,18 @@ static bool ocrdma_del_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr,
141 return found; 116 return found;
142} 117}
143 118
144static void ocrdma_add_default_sgid(struct ocrdma_dev *dev) 119static int ocrdma_addr_event(unsigned long event, struct net_device *netdev,
145{ 120 union ib_gid *gid)
146 /* GID Index 0 - Invariant manufacturer-assigned EUI-64 */
147 union ib_gid *sgid = &dev->sgid_tbl[0];
148
149 sgid->global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
150 ocrdma_get_guid(dev, &sgid->raw[8]);
151}
152
153#if IS_ENABLED(CONFIG_VLAN_8021Q)
154static void ocrdma_add_vlan_sgids(struct ocrdma_dev *dev)
155{
156 struct net_device *netdev, *tmp;
157 u16 vlan_id;
158 bool is_vlan;
159
160 netdev = dev->nic_info.netdev;
161
162 rcu_read_lock();
163 for_each_netdev_rcu(&init_net, tmp) {
164 if (netdev == tmp || vlan_dev_real_dev(tmp) == netdev) {
165 if (!netif_running(tmp) || !netif_oper_up(tmp))
166 continue;
167 if (netdev != tmp) {
168 vlan_id = vlan_dev_vlan_id(tmp);
169 is_vlan = true;
170 } else {
171 is_vlan = false;
172 vlan_id = 0;
173 tmp = netdev;
174 }
175 ocrdma_add_sgid(dev, tmp->dev_addr, is_vlan, vlan_id);
176 }
177 }
178 rcu_read_unlock();
179}
180#else
181static void ocrdma_add_vlan_sgids(struct ocrdma_dev *dev)
182{
183
184}
185#endif /* VLAN */
186
187static int ocrdma_build_sgid_tbl(struct ocrdma_dev *dev)
188{ 121{
189 ocrdma_add_default_sgid(dev);
190 ocrdma_add_vlan_sgids(dev);
191 return 0;
192}
193
194#if IS_ENABLED(CONFIG_IPV6)
195
196static int ocrdma_inet6addr_event(struct notifier_block *notifier,
197 unsigned long event, void *ptr)
198{
199 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
200 struct net_device *netdev = ifa->idev->dev;
201 struct ib_event gid_event; 122 struct ib_event gid_event;
202 struct ocrdma_dev *dev; 123 struct ocrdma_dev *dev;
203 bool found = false; 124 bool found = false;
204 bool updated = false; 125 bool updated = false;
205 bool is_vlan = false; 126 bool is_vlan = false;
206 u16 vid = 0;
207 127
208 is_vlan = netdev->priv_flags & IFF_802_1Q_VLAN; 128 is_vlan = netdev->priv_flags & IFF_802_1Q_VLAN;
209 if (is_vlan) { 129 if (is_vlan)
210 vid = vlan_dev_vlan_id(netdev);
211 netdev = vlan_dev_real_dev(netdev); 130 netdev = vlan_dev_real_dev(netdev);
212 }
213 131
214 rcu_read_lock(); 132 rcu_read_lock();
215 list_for_each_entry_rcu(dev, &ocrdma_dev_list, entry) { 133 list_for_each_entry_rcu(dev, &ocrdma_dev_list, entry) {
@@ -222,16 +140,14 @@ static int ocrdma_inet6addr_event(struct notifier_block *notifier,
222 140
223 if (!found) 141 if (!found)
224 return NOTIFY_DONE; 142 return NOTIFY_DONE;
225 if (!rdma_link_local_addr((struct in6_addr *)&ifa->addr))
226 return NOTIFY_DONE;
227 143
228 mutex_lock(&dev->dev_lock); 144 mutex_lock(&dev->dev_lock);
229 switch (event) { 145 switch (event) {
230 case NETDEV_UP: 146 case NETDEV_UP:
231 updated = ocrdma_add_sgid(dev, netdev->dev_addr, is_vlan, vid); 147 updated = ocrdma_add_sgid(dev, gid);
232 break; 148 break;
233 case NETDEV_DOWN: 149 case NETDEV_DOWN:
234 updated = ocrdma_del_sgid(dev, netdev->dev_addr, is_vlan, vid); 150 updated = ocrdma_del_sgid(dev, gid);
235 break; 151 break;
236 default: 152 default:
237 break; 153 break;
@@ -247,6 +163,32 @@ static int ocrdma_inet6addr_event(struct notifier_block *notifier,
247 return NOTIFY_OK; 163 return NOTIFY_OK;
248} 164}
249 165
166static int ocrdma_inetaddr_event(struct notifier_block *notifier,
167 unsigned long event, void *ptr)
168{
169 struct in_ifaddr *ifa = ptr;
170 union ib_gid gid;
171 struct net_device *netdev = ifa->ifa_dev->dev;
172
173 ipv6_addr_set_v4mapped(ifa->ifa_address, (struct in6_addr *)&gid);
174 return ocrdma_addr_event(event, netdev, &gid);
175}
176
177static struct notifier_block ocrdma_inetaddr_notifier = {
178 .notifier_call = ocrdma_inetaddr_event
179};
180
181#if IS_ENABLED(CONFIG_IPV6)
182
183static int ocrdma_inet6addr_event(struct notifier_block *notifier,
184 unsigned long event, void *ptr)
185{
186 struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
187 union ib_gid *gid = (union ib_gid *)&ifa->addr;
188 struct net_device *netdev = ifa->idev->dev;
189 return ocrdma_addr_event(event, netdev, gid);
190}
191
250static struct notifier_block ocrdma_inet6addr_notifier = { 192static struct notifier_block ocrdma_inet6addr_notifier = {
251 .notifier_call = ocrdma_inet6addr_event 193 .notifier_call = ocrdma_inet6addr_event
252}; 194};
@@ -423,10 +365,6 @@ static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info)
423 if (status) 365 if (status)
424 goto alloc_err; 366 goto alloc_err;
425 367
426 status = ocrdma_build_sgid_tbl(dev);
427 if (status)
428 goto alloc_err;
429
430 status = ocrdma_register_device(dev); 368 status = ocrdma_register_device(dev);
431 if (status) 369 if (status)
432 goto alloc_err; 370 goto alloc_err;
@@ -553,6 +491,10 @@ static int __init ocrdma_init_module(void)
553{ 491{
554 int status; 492 int status;
555 493
494 status = register_inetaddr_notifier(&ocrdma_inetaddr_notifier);
495 if (status)
496 return status;
497
556#if IS_ENABLED(CONFIG_IPV6) 498#if IS_ENABLED(CONFIG_IPV6)
557 status = register_inet6addr_notifier(&ocrdma_inet6addr_notifier); 499 status = register_inet6addr_notifier(&ocrdma_inet6addr_notifier);
558 if (status) 500 if (status)