aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mlx4/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/mlx4/main.c')
-rw-r--r--drivers/infiniband/hw/mlx4/main.c448
1 files changed, 412 insertions, 36 deletions
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 4e94e360e43..e65db73fc27 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -35,9 +35,13 @@
35#include <linux/init.h> 35#include <linux/init.h>
36#include <linux/slab.h> 36#include <linux/slab.h>
37#include <linux/errno.h> 37#include <linux/errno.h>
38#include <linux/netdevice.h>
39#include <linux/inetdevice.h>
40#include <linux/rtnetlink.h>
38 41
39#include <rdma/ib_smi.h> 42#include <rdma/ib_smi.h>
40#include <rdma/ib_user_verbs.h> 43#include <rdma/ib_user_verbs.h>
44#include <rdma/ib_addr.h>
41 45
42#include <linux/mlx4/driver.h> 46#include <linux/mlx4/driver.h>
43#include <linux/mlx4/cmd.h> 47#include <linux/mlx4/cmd.h>
@@ -58,6 +62,15 @@ static const char mlx4_ib_version[] =
58 DRV_NAME ": Mellanox ConnectX InfiniBand driver v" 62 DRV_NAME ": Mellanox ConnectX InfiniBand driver v"
59 DRV_VERSION " (" DRV_RELDATE ")\n"; 63 DRV_VERSION " (" DRV_RELDATE ")\n";
60 64
65struct update_gid_work {
66 struct work_struct work;
67 union ib_gid gids[128];
68 struct mlx4_ib_dev *dev;
69 int port;
70};
71
72static struct workqueue_struct *wq;
73
61static void init_query_mad(struct ib_smp *mad) 74static void init_query_mad(struct ib_smp *mad)
62{ 75{
63 mad->base_version = 1; 76 mad->base_version = 1;
@@ -154,28 +167,19 @@ out:
154 return err; 167 return err;
155} 168}
156 169
157static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port, 170static enum rdma_link_layer
158 struct ib_port_attr *props) 171mlx4_ib_port_link_layer(struct ib_device *device, u8 port_num)
159{ 172{
160 struct ib_smp *in_mad = NULL; 173 struct mlx4_dev *dev = to_mdev(device)->dev;
161 struct ib_smp *out_mad = NULL;
162 int err = -ENOMEM;
163 174
164 in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); 175 return dev->caps.port_mask & (1 << (port_num - 1)) ?
165 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); 176 IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
166 if (!in_mad || !out_mad) 177}
167 goto out;
168
169 memset(props, 0, sizeof *props);
170
171 init_query_mad(in_mad);
172 in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
173 in_mad->attr_mod = cpu_to_be32(port);
174
175 err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad);
176 if (err)
177 goto out;
178 178
179static int ib_link_query_port(struct ib_device *ibdev, u8 port,
180 struct ib_port_attr *props,
181 struct ib_smp *out_mad)
182{
179 props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16)); 183 props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16));
180 props->lmc = out_mad->data[34] & 0x7; 184 props->lmc = out_mad->data[34] & 0x7;
181 props->sm_lid = be16_to_cpup((__be16 *) (out_mad->data + 18)); 185 props->sm_lid = be16_to_cpup((__be16 *) (out_mad->data + 18));
@@ -196,6 +200,80 @@ static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
196 props->max_vl_num = out_mad->data[37] >> 4; 200 props->max_vl_num = out_mad->data[37] >> 4;
197 props->init_type_reply = out_mad->data[41] >> 4; 201 props->init_type_reply = out_mad->data[41] >> 4;
198 202
203 return 0;
204}
205
206static u8 state_to_phys_state(enum ib_port_state state)
207{
208 return state == IB_PORT_ACTIVE ? 5 : 3;
209}
210
211static int eth_link_query_port(struct ib_device *ibdev, u8 port,
212 struct ib_port_attr *props,
213 struct ib_smp *out_mad)
214{
215 struct mlx4_ib_iboe *iboe = &to_mdev(ibdev)->iboe;
216 struct net_device *ndev;
217 enum ib_mtu tmp;
218
219 props->active_width = IB_WIDTH_4X;
220 props->active_speed = 4;
221 props->port_cap_flags = IB_PORT_CM_SUP;
222 props->gid_tbl_len = to_mdev(ibdev)->dev->caps.gid_table_len[port];
223 props->max_msg_sz = to_mdev(ibdev)->dev->caps.max_msg_sz;
224 props->pkey_tbl_len = 1;
225 props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46));
226 props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48));
227 props->max_mtu = IB_MTU_2048;
228 props->subnet_timeout = 0;
229 props->max_vl_num = out_mad->data[37] >> 4;
230 props->init_type_reply = 0;
231 props->state = IB_PORT_DOWN;
232 props->phys_state = state_to_phys_state(props->state);
233 props->active_mtu = IB_MTU_256;
234 spin_lock(&iboe->lock);
235 ndev = iboe->netdevs[port - 1];
236 if (!ndev)
237 goto out;
238
239 tmp = iboe_get_mtu(ndev->mtu);
240 props->active_mtu = tmp ? min(props->max_mtu, tmp) : IB_MTU_256;
241
242 props->state = netif_running(ndev) && netif_oper_up(ndev) ?
243 IB_PORT_ACTIVE : IB_PORT_DOWN;
244 props->phys_state = state_to_phys_state(props->state);
245
246out:
247 spin_unlock(&iboe->lock);
248 return 0;
249}
250
251static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
252 struct ib_port_attr *props)
253{
254 struct ib_smp *in_mad = NULL;
255 struct ib_smp *out_mad = NULL;
256 int err = -ENOMEM;
257
258 in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL);
259 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
260 if (!in_mad || !out_mad)
261 goto out;
262
263 memset(props, 0, sizeof *props);
264
265 init_query_mad(in_mad);
266 in_mad->attr_id = IB_SMP_ATTR_PORT_INFO;
267 in_mad->attr_mod = cpu_to_be32(port);
268
269 err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad);
270 if (err)
271 goto out;
272
273 err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ?
274 ib_link_query_port(ibdev, port, props, out_mad) :
275 eth_link_query_port(ibdev, port, props, out_mad);
276
199out: 277out:
200 kfree(in_mad); 278 kfree(in_mad);
201 kfree(out_mad); 279 kfree(out_mad);
@@ -203,8 +281,8 @@ out:
203 return err; 281 return err;
204} 282}
205 283
206static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, 284static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
207 union ib_gid *gid) 285 union ib_gid *gid)
208{ 286{
209 struct ib_smp *in_mad = NULL; 287 struct ib_smp *in_mad = NULL;
210 struct ib_smp *out_mad = NULL; 288 struct ib_smp *out_mad = NULL;
@@ -241,6 +319,25 @@ out:
241 return err; 319 return err;
242} 320}
243 321
322static int iboe_query_gid(struct ib_device *ibdev, u8 port, int index,
323 union ib_gid *gid)
324{
325 struct mlx4_ib_dev *dev = to_mdev(ibdev);
326
327 *gid = dev->iboe.gid_table[port - 1][index];
328
329 return 0;
330}
331
332static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
333 union ib_gid *gid)
334{
335 if (rdma_port_get_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND)
336 return __mlx4_ib_query_gid(ibdev, port, index, gid);
337 else
338 return iboe_query_gid(ibdev, port, index, gid);
339}
340
244static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, 341static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
245 u16 *pkey) 342 u16 *pkey)
246{ 343{
@@ -289,6 +386,7 @@ static int mlx4_SET_PORT(struct mlx4_ib_dev *dev, u8 port, int reset_qkey_viols,
289{ 386{
290 struct mlx4_cmd_mailbox *mailbox; 387 struct mlx4_cmd_mailbox *mailbox;
291 int err; 388 int err;
389 u8 is_eth = dev->dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH;
292 390
293 mailbox = mlx4_alloc_cmd_mailbox(dev->dev); 391 mailbox = mlx4_alloc_cmd_mailbox(dev->dev);
294 if (IS_ERR(mailbox)) 392 if (IS_ERR(mailbox))
@@ -304,7 +402,7 @@ static int mlx4_SET_PORT(struct mlx4_ib_dev *dev, u8 port, int reset_qkey_viols,
304 ((__be32 *) mailbox->buf)[1] = cpu_to_be32(cap_mask); 402 ((__be32 *) mailbox->buf)[1] = cpu_to_be32(cap_mask);
305 } 403 }
306 404
307 err = mlx4_cmd(dev->dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT, 405 err = mlx4_cmd(dev->dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT,
308 MLX4_CMD_TIME_CLASS_B); 406 MLX4_CMD_TIME_CLASS_B);
309 407
310 mlx4_free_cmd_mailbox(dev->dev, mailbox); 408 mlx4_free_cmd_mailbox(dev->dev, mailbox);
@@ -447,18 +545,132 @@ static int mlx4_ib_dealloc_pd(struct ib_pd *pd)
447 return 0; 545 return 0;
448} 546}
449 547
548static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid)
549{
550 struct mlx4_ib_qp *mqp = to_mqp(ibqp);
551 struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
552 struct mlx4_ib_gid_entry *ge;
553
554 ge = kzalloc(sizeof *ge, GFP_KERNEL);
555 if (!ge)
556 return -ENOMEM;
557
558 ge->gid = *gid;
559 if (mlx4_ib_add_mc(mdev, mqp, gid)) {
560 ge->port = mqp->port;
561 ge->added = 1;
562 }
563
564 mutex_lock(&mqp->mutex);
565 list_add_tail(&ge->list, &mqp->gid_list);
566 mutex_unlock(&mqp->mutex);
567
568 return 0;
569}
570
571int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
572 union ib_gid *gid)
573{
574 u8 mac[6];
575 struct net_device *ndev;
576 int ret = 0;
577
578 if (!mqp->port)
579 return 0;
580
581 spin_lock(&mdev->iboe.lock);
582 ndev = mdev->iboe.netdevs[mqp->port - 1];
583 if (ndev)
584 dev_hold(ndev);
585 spin_unlock(&mdev->iboe.lock);
586
587 if (ndev) {
588 rdma_get_mcast_mac((struct in6_addr *)gid, mac);
589 rtnl_lock();
590 dev_mc_add(mdev->iboe.netdevs[mqp->port - 1], mac);
591 ret = 1;
592 rtnl_unlock();
593 dev_put(ndev);
594 }
595
596 return ret;
597}
598
450static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) 599static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
451{ 600{
452 return mlx4_multicast_attach(to_mdev(ibqp->device)->dev, 601 int err;
453 &to_mqp(ibqp)->mqp, gid->raw, 602 struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
454 !!(to_mqp(ibqp)->flags & 603 struct mlx4_ib_qp *mqp = to_mqp(ibqp);
455 MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK)); 604
605 err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, !!(mqp->flags &
606 MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK));
607 if (err)
608 return err;
609
610 err = add_gid_entry(ibqp, gid);
611 if (err)
612 goto err_add;
613
614 return 0;
615
616err_add:
617 mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw);
618 return err;
619}
620
621static struct mlx4_ib_gid_entry *find_gid_entry(struct mlx4_ib_qp *qp, u8 *raw)
622{
623 struct mlx4_ib_gid_entry *ge;
624 struct mlx4_ib_gid_entry *tmp;
625 struct mlx4_ib_gid_entry *ret = NULL;
626
627 list_for_each_entry_safe(ge, tmp, &qp->gid_list, list) {
628 if (!memcmp(raw, ge->gid.raw, 16)) {
629 ret = ge;
630 break;
631 }
632 }
633
634 return ret;
456} 635}
457 636
458static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) 637static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
459{ 638{
460 return mlx4_multicast_detach(to_mdev(ibqp->device)->dev, 639 int err;
461 &to_mqp(ibqp)->mqp, gid->raw); 640 struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
641 struct mlx4_ib_qp *mqp = to_mqp(ibqp);
642 u8 mac[6];
643 struct net_device *ndev;
644 struct mlx4_ib_gid_entry *ge;
645
646 err = mlx4_multicast_detach(mdev->dev,
647 &mqp->mqp, gid->raw);
648 if (err)
649 return err;
650
651 mutex_lock(&mqp->mutex);
652 ge = find_gid_entry(mqp, gid->raw);
653 if (ge) {
654 spin_lock(&mdev->iboe.lock);
655 ndev = ge->added ? mdev->iboe.netdevs[ge->port - 1] : NULL;
656 if (ndev)
657 dev_hold(ndev);
658 spin_unlock(&mdev->iboe.lock);
659 rdma_get_mcast_mac((struct in6_addr *)gid, mac);
660 if (ndev) {
661 rtnl_lock();
662 dev_mc_del(mdev->iboe.netdevs[ge->port - 1], mac);
663 rtnl_unlock();
664 dev_put(ndev);
665 }
666 list_del(&ge->list);
667 kfree(ge);
668 } else
669 printk(KERN_WARNING "could not find mgid entry\n");
670
671 mutex_unlock(&mqp->mutex);
672
673 return 0;
462} 674}
463 675
464static int init_node_data(struct mlx4_ib_dev *dev) 676static int init_node_data(struct mlx4_ib_dev *dev)
@@ -543,15 +755,143 @@ static struct device_attribute *mlx4_class_attributes[] = {
543 &dev_attr_board_id 755 &dev_attr_board_id
544}; 756};
545 757
758static void mlx4_addrconf_ifid_eui48(u8 *eui, struct net_device *dev)
759{
760 memcpy(eui, dev->dev_addr, 3);
761 memcpy(eui + 5, dev->dev_addr + 3, 3);
762 eui[3] = 0xFF;
763 eui[4] = 0xFE;
764 eui[0] ^= 2;
765}
766
767static void update_gids_task(struct work_struct *work)
768{
769 struct update_gid_work *gw = container_of(work, struct update_gid_work, work);
770 struct mlx4_cmd_mailbox *mailbox;
771 union ib_gid *gids;
772 int err;
773 struct mlx4_dev *dev = gw->dev->dev;
774 struct ib_event event;
775
776 mailbox = mlx4_alloc_cmd_mailbox(dev);
777 if (IS_ERR(mailbox)) {
778 printk(KERN_WARNING "update gid table failed %ld\n", PTR_ERR(mailbox));
779 return;
780 }
781
782 gids = mailbox->buf;
783 memcpy(gids, gw->gids, sizeof gw->gids);
784
785 err = mlx4_cmd(dev, mailbox->dma, MLX4_SET_PORT_GID_TABLE << 8 | gw->port,
786 1, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B);
787 if (err)
788 printk(KERN_WARNING "set port command failed\n");
789 else {
790 memcpy(gw->dev->iboe.gid_table[gw->port - 1], gw->gids, sizeof gw->gids);
791 event.device = &gw->dev->ib_dev;
792 event.element.port_num = gw->port;
793 event.event = IB_EVENT_LID_CHANGE;
794 ib_dispatch_event(&event);
795 }
796
797 mlx4_free_cmd_mailbox(dev, mailbox);
798 kfree(gw);
799}
800
801static int update_ipv6_gids(struct mlx4_ib_dev *dev, int port, int clear)
802{
803 struct net_device *ndev = dev->iboe.netdevs[port - 1];
804 struct update_gid_work *work;
805
806 work = kzalloc(sizeof *work, GFP_ATOMIC);
807 if (!work)
808 return -ENOMEM;
809
810 if (!clear) {
811 mlx4_addrconf_ifid_eui48(&work->gids[0].raw[8], ndev);
812 work->gids[0].global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
813 }
814
815 INIT_WORK(&work->work, update_gids_task);
816 work->port = port;
817 work->dev = dev;
818 queue_work(wq, &work->work);
819
820 return 0;
821}
822
823static void handle_en_event(struct mlx4_ib_dev *dev, int port, unsigned long event)
824{
825 switch (event) {
826 case NETDEV_UP:
827 update_ipv6_gids(dev, port, 0);
828 break;
829
830 case NETDEV_DOWN:
831 update_ipv6_gids(dev, port, 1);
832 dev->iboe.netdevs[port - 1] = NULL;
833 }
834}
835
836static void netdev_added(struct mlx4_ib_dev *dev, int port)
837{
838 update_ipv6_gids(dev, port, 0);
839}
840
841static void netdev_removed(struct mlx4_ib_dev *dev, int port)
842{
843 update_ipv6_gids(dev, port, 1);
844}
845
846static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event,
847 void *ptr)
848{
849 struct net_device *dev = ptr;
850 struct mlx4_ib_dev *ibdev;
851 struct net_device *oldnd;
852 struct mlx4_ib_iboe *iboe;
853 int port;
854
855 if (!net_eq(dev_net(dev), &init_net))
856 return NOTIFY_DONE;
857
858 ibdev = container_of(this, struct mlx4_ib_dev, iboe.nb);
859 iboe = &ibdev->iboe;
860
861 spin_lock(&iboe->lock);
862 mlx4_foreach_ib_transport_port(port, ibdev->dev) {
863 oldnd = iboe->netdevs[port - 1];
864 iboe->netdevs[port - 1] =
865 mlx4_get_protocol_dev(ibdev->dev, MLX4_PROTOCOL_EN, port);
866 if (oldnd != iboe->netdevs[port - 1]) {
867 if (iboe->netdevs[port - 1])
868 netdev_added(ibdev, port);
869 else
870 netdev_removed(ibdev, port);
871 }
872 }
873
874 if (dev == iboe->netdevs[0])
875 handle_en_event(ibdev, 1, event);
876 else if (dev == iboe->netdevs[1])
877 handle_en_event(ibdev, 2, event);
878
879 spin_unlock(&iboe->lock);
880
881 return NOTIFY_DONE;
882}
883
546static void *mlx4_ib_add(struct mlx4_dev *dev) 884static void *mlx4_ib_add(struct mlx4_dev *dev)
547{ 885{
548 struct mlx4_ib_dev *ibdev; 886 struct mlx4_ib_dev *ibdev;
549 int num_ports = 0; 887 int num_ports = 0;
550 int i; 888 int i;
889 int err;
890 struct mlx4_ib_iboe *iboe;
551 891
552 printk_once(KERN_INFO "%s", mlx4_ib_version); 892 printk_once(KERN_INFO "%s", mlx4_ib_version);
553 893
554 mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) 894 mlx4_foreach_ib_transport_port(i, dev)
555 num_ports++; 895 num_ports++;
556 896
557 /* No point in registering a device with no ports... */ 897 /* No point in registering a device with no ports... */
@@ -564,6 +904,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
564 return NULL; 904 return NULL;
565 } 905 }
566 906
907 iboe = &ibdev->iboe;
908
567 if (mlx4_pd_alloc(dev, &ibdev->priv_pdn)) 909 if (mlx4_pd_alloc(dev, &ibdev->priv_pdn))
568 goto err_dealloc; 910 goto err_dealloc;
569 911
@@ -612,6 +954,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
612 954
613 ibdev->ib_dev.query_device = mlx4_ib_query_device; 955 ibdev->ib_dev.query_device = mlx4_ib_query_device;
614 ibdev->ib_dev.query_port = mlx4_ib_query_port; 956 ibdev->ib_dev.query_port = mlx4_ib_query_port;
957 ibdev->ib_dev.get_link_layer = mlx4_ib_port_link_layer;
615 ibdev->ib_dev.query_gid = mlx4_ib_query_gid; 958 ibdev->ib_dev.query_gid = mlx4_ib_query_gid;
616 ibdev->ib_dev.query_pkey = mlx4_ib_query_pkey; 959 ibdev->ib_dev.query_pkey = mlx4_ib_query_pkey;
617 ibdev->ib_dev.modify_device = mlx4_ib_modify_device; 960 ibdev->ib_dev.modify_device = mlx4_ib_modify_device;
@@ -656,6 +999,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
656 ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr; 999 ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr;
657 ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc; 1000 ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc;
658 1001
1002 spin_lock_init(&iboe->lock);
1003
659 if (init_node_data(ibdev)) 1004 if (init_node_data(ibdev))
660 goto err_map; 1005 goto err_map;
661 1006
@@ -668,16 +1013,28 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
668 if (mlx4_ib_mad_init(ibdev)) 1013 if (mlx4_ib_mad_init(ibdev))
669 goto err_reg; 1014 goto err_reg;
670 1015
1016 if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE && !iboe->nb.notifier_call) {
1017 iboe->nb.notifier_call = mlx4_ib_netdev_event;
1018 err = register_netdevice_notifier(&iboe->nb);
1019 if (err)
1020 goto err_reg;
1021 }
1022
671 for (i = 0; i < ARRAY_SIZE(mlx4_class_attributes); ++i) { 1023 for (i = 0; i < ARRAY_SIZE(mlx4_class_attributes); ++i) {
672 if (device_create_file(&ibdev->ib_dev.dev, 1024 if (device_create_file(&ibdev->ib_dev.dev,
673 mlx4_class_attributes[i])) 1025 mlx4_class_attributes[i]))
674 goto err_reg; 1026 goto err_notif;
675 } 1027 }
676 1028
677 ibdev->ib_active = true; 1029 ibdev->ib_active = true;
678 1030
679 return ibdev; 1031 return ibdev;
680 1032
1033err_notif:
1034 if (unregister_netdevice_notifier(&ibdev->iboe.nb))
1035 printk(KERN_WARNING "failure unregistering notifier\n");
1036 flush_workqueue(wq);
1037
681err_reg: 1038err_reg:
682 ib_unregister_device(&ibdev->ib_dev); 1039 ib_unregister_device(&ibdev->ib_dev);
683 1040
@@ -703,11 +1060,16 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
703 1060
704 mlx4_ib_mad_cleanup(ibdev); 1061 mlx4_ib_mad_cleanup(ibdev);
705 ib_unregister_device(&ibdev->ib_dev); 1062 ib_unregister_device(&ibdev->ib_dev);
1063 if (ibdev->iboe.nb.notifier_call) {
1064 if (unregister_netdevice_notifier(&ibdev->iboe.nb))
1065 printk(KERN_WARNING "failure unregistering notifier\n");
1066 ibdev->iboe.nb.notifier_call = NULL;
1067 }
1068 iounmap(ibdev->uar_map);
706 1069
707 for (p = 1; p <= ibdev->num_ports; ++p) 1070 mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
708 mlx4_CLOSE_PORT(dev, p); 1071 mlx4_CLOSE_PORT(dev, p);
709 1072
710 iounmap(ibdev->uar_map);
711 mlx4_uar_free(dev, &ibdev->priv_uar); 1073 mlx4_uar_free(dev, &ibdev->priv_uar);
712 mlx4_pd_free(dev, ibdev->priv_pdn); 1074 mlx4_pd_free(dev, ibdev->priv_pdn);
713 ib_dealloc_device(&ibdev->ib_dev); 1075 ib_dealloc_device(&ibdev->ib_dev);
@@ -747,19 +1109,33 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
747} 1109}
748 1110
749static struct mlx4_interface mlx4_ib_interface = { 1111static struct mlx4_interface mlx4_ib_interface = {
750 .add = mlx4_ib_add, 1112 .add = mlx4_ib_add,
751 .remove = mlx4_ib_remove, 1113 .remove = mlx4_ib_remove,
752 .event = mlx4_ib_event 1114 .event = mlx4_ib_event,
1115 .protocol = MLX4_PROTOCOL_IB
753}; 1116};
754 1117
755static int __init mlx4_ib_init(void) 1118static int __init mlx4_ib_init(void)
756{ 1119{
757 return mlx4_register_interface(&mlx4_ib_interface); 1120 int err;
1121
1122 wq = create_singlethread_workqueue("mlx4_ib");
1123 if (!wq)
1124 return -ENOMEM;
1125
1126 err = mlx4_register_interface(&mlx4_ib_interface);
1127 if (err) {
1128 destroy_workqueue(wq);
1129 return err;
1130 }
1131
1132 return 0;
758} 1133}
759 1134
760static void __exit mlx4_ib_cleanup(void) 1135static void __exit mlx4_ib_cleanup(void)
761{ 1136{
762 mlx4_unregister_interface(&mlx4_ib_interface); 1137 mlx4_unregister_interface(&mlx4_ib_interface);
1138 destroy_workqueue(wq);
763} 1139}
764 1140
765module_init(mlx4_ib_init); 1141module_init(mlx4_ib_init);