aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorUpinder Malhi <umalhi@cisco.com>2014-01-09 17:48:17 -0500
committerRoland Dreier <roland@purestorage.com>2014-01-14 03:44:44 -0500
commitc7845bcafe4d2ecd5c479fa64d1b425c21dde17c (patch)
tree14661c7eb6d065bb2bb66c7e199d2c5821e1745c /drivers/infiniband
parent6214105460842759020bdd7f4dbb50afa1be9d17 (diff)
IB/usnic: Add UDP support in u*verbs.c, u*main.c and u*util.h
Add supports for: 1) Parsing the socket file descriptor pass down from userspace. 2) IP notifiers 3) Encoding the IP in the GID 4) Other aux. changes to support UDP Signed-off-by: Upinder Malhi <umalhi@cisco.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/usnic/usnic_common_util.h17
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_main.c84
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_verbs.c44
3 files changed, 136 insertions, 9 deletions
diff --git a/drivers/infiniband/hw/usnic/usnic_common_util.h b/drivers/infiniband/hw/usnic/usnic_common_util.h
index 128550a4f9e2..afd8bfa379ed 100644
--- a/drivers/infiniband/hw/usnic/usnic_common_util.h
+++ b/drivers/infiniband/hw/usnic/usnic_common_util.h
@@ -36,6 +36,23 @@ usnic_mac_to_gid(const char *const mac, char *raw_gid)
36} 36}
37 37
38static inline void 38static inline void
39usnic_mac_ip_to_gid(const char *const mac, const uint32_t inaddr, char *raw_gid)
40{
41 raw_gid[0] = 0xfe;
42 raw_gid[1] = 0x80;
43 memset(&raw_gid[2], 0, 2);
44 memcpy(&raw_gid[4], &inaddr, 4);
45 raw_gid[8] = mac[0]^2;
46 raw_gid[9] = mac[1];
47 raw_gid[10] = mac[2];
48 raw_gid[11] = 0xff;
49 raw_gid[12] = 0xfe;
50 raw_gid[13] = mac[3];
51 raw_gid[14] = mac[4];
52 raw_gid[15] = mac[5];
53}
54
55static inline void
39usnic_write_gid_if_id_from_mac(char *mac, char *raw_gid) 56usnic_write_gid_if_id_from_mac(char *mac, char *raw_gid)
40{ 57{
41 raw_gid[8] = mac[0]^2; 58 raw_gid[8] = mac[0]^2;
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c
index 6ab0b41be9c5..3b7e8bd22df6 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_main.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c
@@ -25,6 +25,7 @@
25 */ 25 */
26 26
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/inetdevice.h>
28#include <linux/init.h> 29#include <linux/init.h>
29#include <linux/slab.h> 30#include <linux/slab.h>
30#include <linux/errno.h> 31#include <linux/errno.h>
@@ -236,13 +237,79 @@ static struct notifier_block usnic_ib_netdevice_notifier = {
236}; 237};
237/* End of netdev section */ 238/* End of netdev section */
238 239
240/* Start of inet section */
241static int usnic_ib_handle_inet_event(struct usnic_ib_dev *us_ibdev,
242 unsigned long event, void *ptr)
243{
244 struct in_ifaddr *ifa = ptr;
245 struct ib_event ib_event;
246
247 mutex_lock(&us_ibdev->usdev_lock);
248
249 switch (event) {
250 case NETDEV_DOWN:
251 usnic_info("%s via ip notifiers",
252 usnic_ib_netdev_event_to_string(event));
253 usnic_fwd_del_ipaddr(us_ibdev->ufdev);
254 usnic_ib_qp_grp_modify_active_to_err(us_ibdev);
255 ib_event.event = IB_EVENT_GID_CHANGE;
256 ib_event.device = &us_ibdev->ib_dev;
257 ib_event.element.port_num = 1;
258 ib_dispatch_event(&ib_event);
259 break;
260 case NETDEV_UP:
261 usnic_fwd_add_ipaddr(us_ibdev->ufdev, ifa->ifa_address);
262 usnic_info("%s via ip notifiers: ip %pI4",
263 usnic_ib_netdev_event_to_string(event),
264 &us_ibdev->ufdev->inaddr);
265 ib_event.event = IB_EVENT_GID_CHANGE;
266 ib_event.device = &us_ibdev->ib_dev;
267 ib_event.element.port_num = 1;
268 ib_dispatch_event(&ib_event);
269 break;
270 default:
271 usnic_info("Ignorning event %s on %s",
272 usnic_ib_netdev_event_to_string(event),
273 us_ibdev->ib_dev.name);
274 }
275 mutex_unlock(&us_ibdev->usdev_lock);
276
277 return NOTIFY_DONE;
278}
279
280static int usnic_ib_inetaddr_event(struct notifier_block *notifier,
281 unsigned long event, void *ptr)
282{
283 struct usnic_ib_dev *us_ibdev;
284 struct in_ifaddr *ifa = ptr;
285 struct net_device *netdev = ifa->ifa_dev->dev;
286
287 mutex_lock(&usnic_ib_ibdev_list_lock);
288 list_for_each_entry(us_ibdev, &usnic_ib_ibdev_list, ib_dev_link) {
289 if (us_ibdev->netdev == netdev) {
290 usnic_ib_handle_inet_event(us_ibdev, event, ptr);
291 break;
292 }
293 }
294 mutex_unlock(&usnic_ib_ibdev_list_lock);
295
296 return NOTIFY_DONE;
297}
298static struct notifier_block usnic_ib_inetaddr_notifier = {
299 .notifier_call = usnic_ib_inetaddr_event
300};
301/* End of inet section*/
302
239/* Start of PF discovery section */ 303/* Start of PF discovery section */
240static void *usnic_ib_device_add(struct pci_dev *dev) 304static void *usnic_ib_device_add(struct pci_dev *dev)
241{ 305{
242 struct usnic_ib_dev *us_ibdev; 306 struct usnic_ib_dev *us_ibdev;
243 union ib_gid gid; 307 union ib_gid gid;
308 struct in_ifaddr *in;
309 struct net_device *netdev;
244 310
245 usnic_dbg("\n"); 311 usnic_dbg("\n");
312 netdev = pci_get_drvdata(dev);
246 313
247 us_ibdev = (struct usnic_ib_dev *)ib_alloc_device(sizeof(*us_ibdev)); 314 us_ibdev = (struct usnic_ib_dev *)ib_alloc_device(sizeof(*us_ibdev));
248 if (IS_ERR_OR_NULL(us_ibdev)) { 315 if (IS_ERR_OR_NULL(us_ibdev)) {
@@ -326,6 +393,12 @@ static void *usnic_ib_device_add(struct pci_dev *dev)
326 if (netif_carrier_ok(us_ibdev->netdev)) 393 if (netif_carrier_ok(us_ibdev->netdev))
327 usnic_fwd_carrier_up(us_ibdev->ufdev); 394 usnic_fwd_carrier_up(us_ibdev->ufdev);
328 395
396 in = ((struct in_device *)(netdev->ip_ptr))->ifa_list;
397 if (in != NULL)
398 usnic_fwd_add_ipaddr(us_ibdev->ufdev, in->ifa_address);
399
400 usnic_mac_ip_to_gid(us_ibdev->netdev->perm_addr,
401 us_ibdev->ufdev->inaddr, &gid.raw[0]);
329 memcpy(&us_ibdev->ib_dev.node_guid, &gid.global.interface_id, 402 memcpy(&us_ibdev->ib_dev.node_guid, &gid.global.interface_id,
330 sizeof(gid.global.interface_id)); 403 sizeof(gid.global.interface_id));
331 kref_init(&us_ibdev->vf_cnt); 404 kref_init(&us_ibdev->vf_cnt);
@@ -555,16 +628,24 @@ static int __init usnic_ib_init(void)
555 goto out_pci_unreg; 628 goto out_pci_unreg;
556 } 629 }
557 630
631 err = register_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
632 if (err) {
633 usnic_err("Failed to register inet addr notifier\n");
634 goto out_unreg_netdev_notifier;
635 }
636
558 err = usnic_transport_init(); 637 err = usnic_transport_init();
559 if (err) { 638 if (err) {
560 usnic_err("Failed to initialize transport\n"); 639 usnic_err("Failed to initialize transport\n");
561 goto out_unreg_netdev_notifier; 640 goto out_unreg_inetaddr_notifier;
562 } 641 }
563 642
564 usnic_debugfs_init(); 643 usnic_debugfs_init();
565 644
566 return 0; 645 return 0;
567 646
647out_unreg_inetaddr_notifier:
648 unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
568out_unreg_netdev_notifier: 649out_unreg_netdev_notifier:
569 unregister_netdevice_notifier(&usnic_ib_netdevice_notifier); 650 unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);
570out_pci_unreg: 651out_pci_unreg:
@@ -580,6 +661,7 @@ static void __exit usnic_ib_destroy(void)
580 usnic_dbg("\n"); 661 usnic_dbg("\n");
581 usnic_debugfs_exit(); 662 usnic_debugfs_exit();
582 usnic_transport_fini(); 663 usnic_transport_fini();
664 unregister_inetaddr_notifier(&usnic_ib_inetaddr_notifier);
583 unregister_netdevice_notifier(&usnic_ib_netdevice_notifier); 665 unregister_netdevice_notifier(&usnic_ib_netdevice_notifier);
584 pci_unregister_driver(&usnic_ib_pci_driver); 666 pci_unregister_driver(&usnic_ib_pci_driver);
585 usnic_uiom_fini(); 667 usnic_uiom_fini();
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
index 2217bc0a6bbe..937113f2eeec 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -230,6 +230,15 @@ static void eth_speed_to_ib_speed(int speed, u8 *active_speed,
230 } 230 }
231} 231}
232 232
233static int create_qp_validate_user_data(struct usnic_ib_create_qp_cmd cmd)
234{
235 if (cmd.spec.trans_type <= USNIC_TRANSPORT_UNKNOWN ||
236 cmd.spec.trans_type >= USNIC_TRANSPORT_MAX)
237 return -EINVAL;
238
239 return 0;
240}
241
233/* Start of ib callback functions */ 242/* Start of ib callback functions */
234 243
235enum rdma_link_layer usnic_ib_port_link_layer(struct ib_device *device, 244enum rdma_link_layer usnic_ib_port_link_layer(struct ib_device *device,
@@ -252,7 +261,8 @@ int usnic_ib_query_device(struct ib_device *ibdev,
252 us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info); 261 us_ibdev->netdev->ethtool_ops->get_drvinfo(us_ibdev->netdev, &info);
253 us_ibdev->netdev->ethtool_ops->get_settings(us_ibdev->netdev, &cmd); 262 us_ibdev->netdev->ethtool_ops->get_settings(us_ibdev->netdev, &cmd);
254 memset(props, 0, sizeof(*props)); 263 memset(props, 0, sizeof(*props));
255 usnic_mac_to_gid(us_ibdev->ufdev->mac, &gid.raw[0]); 264 usnic_mac_ip_to_gid(us_ibdev->ufdev->mac, us_ibdev->ufdev->inaddr,
265 &gid.raw[0]);
256 memcpy(&props->sys_image_guid, &gid.global.interface_id, 266 memcpy(&props->sys_image_guid, &gid.global.interface_id,
257 sizeof(gid.global.interface_id)); 267 sizeof(gid.global.interface_id));
258 usnic_ib_fw_string_to_u64(&info.fw_version[0], &props->fw_ver); 268 usnic_ib_fw_string_to_u64(&info.fw_version[0], &props->fw_ver);
@@ -310,12 +320,15 @@ int usnic_ib_query_port(struct ib_device *ibdev, u8 port,
310 props->sm_lid = 0; 320 props->sm_lid = 0;
311 props->sm_sl = 0; 321 props->sm_sl = 0;
312 322
313 if (us_ibdev->ufdev->link_up) { 323 if (!us_ibdev->ufdev->link_up) {
314 props->state = IB_PORT_ACTIVE;
315 props->phys_state = 5;
316 } else {
317 props->state = IB_PORT_DOWN; 324 props->state = IB_PORT_DOWN;
318 props->phys_state = 3; 325 props->phys_state = 3;
326 } else if (!us_ibdev->ufdev->inaddr) {
327 props->state = IB_PORT_INIT;
328 props->phys_state = 4;
329 } else {
330 props->state = IB_PORT_ACTIVE;
331 props->phys_state = 5;
319 } 332 }
320 333
321 props->port_cap_flags = 0; 334 props->port_cap_flags = 0;
@@ -385,7 +398,8 @@ int usnic_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
385 398
386 mutex_lock(&us_ibdev->usdev_lock); 399 mutex_lock(&us_ibdev->usdev_lock);
387 memset(&(gid->raw[0]), 0, sizeof(gid->raw)); 400 memset(&(gid->raw[0]), 0, sizeof(gid->raw));
388 usnic_mac_to_gid(us_ibdev->ufdev->mac, &gid->raw[0]); 401 usnic_mac_ip_to_gid(us_ibdev->ufdev->mac, us_ibdev->ufdev->inaddr,
402 &gid->raw[0]);
389 mutex_unlock(&us_ibdev->usdev_lock); 403 mutex_unlock(&us_ibdev->usdev_lock);
390 404
391 return 0; 405 return 0;
@@ -444,6 +458,7 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
444 struct usnic_ib_ucontext *ucontext; 458 struct usnic_ib_ucontext *ucontext;
445 int cq_cnt; 459 int cq_cnt;
446 struct usnic_vnic_res_spec res_spec; 460 struct usnic_vnic_res_spec res_spec;
461 struct usnic_ib_create_qp_cmd cmd;
447 struct usnic_transport_spec trans_spec; 462 struct usnic_transport_spec trans_spec;
448 463
449 usnic_dbg("\n"); 464 usnic_dbg("\n");
@@ -451,14 +466,27 @@ struct ib_qp *usnic_ib_create_qp(struct ib_pd *pd,
451 ucontext = to_uucontext(pd->uobject->context); 466 ucontext = to_uucontext(pd->uobject->context);
452 us_ibdev = to_usdev(pd->device); 467 us_ibdev = to_usdev(pd->device);
453 468
469 err = ib_copy_from_udata(&cmd, udata, sizeof(cmd));
470 if (err) {
471 usnic_err("%s: cannot copy udata for create_qp\n",
472 us_ibdev->ib_dev.name);
473 return ERR_PTR(-EINVAL);
474 }
475
476 err = create_qp_validate_user_data(cmd);
477 if (err) {
478 usnic_err("%s: Failed to validate user data\n",
479 us_ibdev->ib_dev.name);
480 return ERR_PTR(-EINVAL);
481 }
482
454 if (init_attr->qp_type != IB_QPT_UD) { 483 if (init_attr->qp_type != IB_QPT_UD) {
455 usnic_err("%s asked to make a non-UD QP: %d\n", 484 usnic_err("%s asked to make a non-UD QP: %d\n",
456 us_ibdev->ib_dev.name, init_attr->qp_type); 485 us_ibdev->ib_dev.name, init_attr->qp_type);
457 return ERR_PTR(-EINVAL); 486 return ERR_PTR(-EINVAL);
458 } 487 }
459 488
460 memset(&trans_spec, 0, sizeof(trans_spec)); 489 trans_spec = cmd.spec;
461 trans_spec.trans_type = USNIC_TRANSPORT_ROCE_CUSTOM;
462 mutex_lock(&us_ibdev->usdev_lock); 490 mutex_lock(&us_ibdev->usdev_lock);
463 cq_cnt = (init_attr->send_cq == init_attr->recv_cq) ? 1 : 2; 491 cq_cnt = (init_attr->send_cq == init_attr->recv_cq) ? 1 : 2;
464 res_spec = min_transport_spec[trans_spec.trans_type]; 492 res_spec = min_transport_spec[trans_spec.trans_type];