diff options
Diffstat (limited to 'drivers/infiniband/hw/mlx4/main.c')
-rw-r--r-- | drivers/infiniband/hw/mlx4/main.c | 448 |
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 | ||
65 | struct 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 | |||
72 | static struct workqueue_struct *wq; | ||
73 | |||
61 | static void init_query_mad(struct ib_smp *mad) | 74 | static 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 | ||
157 | static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port, | 170 | static enum rdma_link_layer |
158 | struct ib_port_attr *props) | 171 | mlx4_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 | ||
179 | static 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 | |||
206 | static u8 state_to_phys_state(enum ib_port_state state) | ||
207 | { | ||
208 | return state == IB_PORT_ACTIVE ? 5 : 3; | ||
209 | } | ||
210 | |||
211 | static 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 | |||
246 | out: | ||
247 | spin_unlock(&iboe->lock); | ||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static 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 | |||
199 | out: | 277 | out: |
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 | ||
206 | static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, | 284 | static 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 | ||
322 | static 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 | |||
332 | static 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 | |||
244 | static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, | 341 | static 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 | ||
548 | static 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 | |||
571 | int 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 | |||
450 | static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | 599 | static 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 | |||
616 | err_add: | ||
617 | mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw); | ||
618 | return err; | ||
619 | } | ||
620 | |||
621 | static 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 | ||
458 | static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | 637 | static 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 | ||
464 | static int init_node_data(struct mlx4_ib_dev *dev) | 676 | static 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 | ||
758 | static 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 | |||
767 | static 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 | |||
801 | static 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 | |||
823 | static 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 | |||
836 | static void netdev_added(struct mlx4_ib_dev *dev, int port) | ||
837 | { | ||
838 | update_ipv6_gids(dev, port, 0); | ||
839 | } | ||
840 | |||
841 | static void netdev_removed(struct mlx4_ib_dev *dev, int port) | ||
842 | { | ||
843 | update_ipv6_gids(dev, port, 1); | ||
844 | } | ||
845 | |||
846 | static 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 | |||
546 | static void *mlx4_ib_add(struct mlx4_dev *dev) | 884 | static 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 | ||
1033 | err_notif: | ||
1034 | if (unregister_netdevice_notifier(&ibdev->iboe.nb)) | ||
1035 | printk(KERN_WARNING "failure unregistering notifier\n"); | ||
1036 | flush_workqueue(wq); | ||
1037 | |||
681 | err_reg: | 1038 | err_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 | ||
749 | static struct mlx4_interface mlx4_ib_interface = { | 1111 | static 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 | ||
755 | static int __init mlx4_ib_init(void) | 1118 | static 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 | ||
760 | static void __exit mlx4_ib_cleanup(void) | 1135 | static 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 | ||
765 | module_init(mlx4_ib_init); | 1141 | module_init(mlx4_ib_init); |