diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-17 17:45:48 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-17 17:45:48 -0500 |
commit | 6845a44a314c0c626549de373131bf108f9cc1f1 (patch) | |
tree | 9152a5c557434515dd7306d288e8f55ecc64652e /drivers/infiniband | |
parent | eee2a817df7c5a6e569f353f8be78cc1b3604bb6 (diff) | |
parent | 4790f4dc5f4326dab5d81ed8fb8c9473e620bdbb (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
RDMA: Update workqueue usage
RDMA/nes: Fix incorrect SFP+ link status detection on driver init
RDMA/nes: Fix SFP+ link down detection issue with switch port disable
RDMA/nes: Generate IB_EVENT_PORT_ERR/PORT_ACTIVE events
RDMA/nes: Fix bonding on iw_nes
IB/srp: Test only once whether iu allocation succeeded
IB/mlx4: Handle protocol field in multicast table
RDMA: Use vzalloc() to replace vmalloc()+memset(0)
mlx4_{core, ib, en}: Fix driver when sizeof (phys_addr_t) > sizeof (long)
IB/mthca: Fix driver when sizeof (phys_addr_t) > sizeof (long)
Diffstat (limited to 'drivers/infiniband')
31 files changed, 320 insertions, 122 deletions
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 68883565b725..f9ba7d74dfc0 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c | |||
@@ -308,7 +308,7 @@ static void ib_cache_event(struct ib_event_handler *handler, | |||
308 | INIT_WORK(&work->work, ib_cache_task); | 308 | INIT_WORK(&work->work, ib_cache_task); |
309 | work->device = event->device; | 309 | work->device = event->device; |
310 | work->port_num = event->element.port_num; | 310 | work->port_num = event->element.port_num; |
311 | schedule_work(&work->work); | 311 | queue_work(ib_wq, &work->work); |
312 | } | 312 | } |
313 | } | 313 | } |
314 | } | 314 | } |
@@ -368,7 +368,7 @@ static void ib_cache_cleanup_one(struct ib_device *device) | |||
368 | int p; | 368 | int p; |
369 | 369 | ||
370 | ib_unregister_event_handler(&device->cache.event_handler); | 370 | ib_unregister_event_handler(&device->cache.event_handler); |
371 | flush_scheduled_work(); | 371 | flush_workqueue(ib_wq); |
372 | 372 | ||
373 | for (p = 0; p <= end_port(device) - start_port(device); ++p) { | 373 | for (p = 0; p <= end_port(device) - start_port(device); ++p) { |
374 | kfree(device->cache.pkey_cache[p]); | 374 | kfree(device->cache.pkey_cache[p]); |
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index a19effad0811..f793bf2f5da7 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/mutex.h> | 40 | #include <linux/mutex.h> |
41 | #include <linux/workqueue.h> | ||
42 | 41 | ||
43 | #include "core_priv.h" | 42 | #include "core_priv.h" |
44 | 43 | ||
@@ -52,6 +51,9 @@ struct ib_client_data { | |||
52 | void * data; | 51 | void * data; |
53 | }; | 52 | }; |
54 | 53 | ||
54 | struct workqueue_struct *ib_wq; | ||
55 | EXPORT_SYMBOL_GPL(ib_wq); | ||
56 | |||
55 | static LIST_HEAD(device_list); | 57 | static LIST_HEAD(device_list); |
56 | static LIST_HEAD(client_list); | 58 | static LIST_HEAD(client_list); |
57 | 59 | ||
@@ -718,6 +720,10 @@ static int __init ib_core_init(void) | |||
718 | { | 720 | { |
719 | int ret; | 721 | int ret; |
720 | 722 | ||
723 | ib_wq = alloc_workqueue("infiniband", 0, 0); | ||
724 | if (!ib_wq) | ||
725 | return -ENOMEM; | ||
726 | |||
721 | ret = ib_sysfs_setup(); | 727 | ret = ib_sysfs_setup(); |
722 | if (ret) | 728 | if (ret) |
723 | printk(KERN_WARNING "Couldn't create InfiniBand device class\n"); | 729 | printk(KERN_WARNING "Couldn't create InfiniBand device class\n"); |
@@ -726,6 +732,7 @@ static int __init ib_core_init(void) | |||
726 | if (ret) { | 732 | if (ret) { |
727 | printk(KERN_WARNING "Couldn't set up InfiniBand P_Key/GID cache\n"); | 733 | printk(KERN_WARNING "Couldn't set up InfiniBand P_Key/GID cache\n"); |
728 | ib_sysfs_cleanup(); | 734 | ib_sysfs_cleanup(); |
735 | destroy_workqueue(ib_wq); | ||
729 | } | 736 | } |
730 | 737 | ||
731 | return ret; | 738 | return ret; |
@@ -736,7 +743,7 @@ static void __exit ib_core_cleanup(void) | |||
736 | ib_cache_cleanup(); | 743 | ib_cache_cleanup(); |
737 | ib_sysfs_cleanup(); | 744 | ib_sysfs_cleanup(); |
738 | /* Make sure that any pending umem accounting work is done. */ | 745 | /* Make sure that any pending umem accounting work is done. */ |
739 | flush_scheduled_work(); | 746 | destroy_workqueue(ib_wq); |
740 | } | 747 | } |
741 | 748 | ||
742 | module_init(ib_core_init); | 749 | module_init(ib_core_init); |
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 91a660310b7c..e38be1bcc01c 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c | |||
@@ -425,7 +425,7 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event | |||
425 | port->sm_ah = NULL; | 425 | port->sm_ah = NULL; |
426 | spin_unlock_irqrestore(&port->ah_lock, flags); | 426 | spin_unlock_irqrestore(&port->ah_lock, flags); |
427 | 427 | ||
428 | schedule_work(&sa_dev->port[event->element.port_num - | 428 | queue_work(ib_wq, &sa_dev->port[event->element.port_num - |
429 | sa_dev->start_port].update_task); | 429 | sa_dev->start_port].update_task); |
430 | } | 430 | } |
431 | } | 431 | } |
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index 415e186eee32..b645e558876f 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c | |||
@@ -262,7 +262,7 @@ void ib_umem_release(struct ib_umem *umem) | |||
262 | umem->mm = mm; | 262 | umem->mm = mm; |
263 | umem->diff = diff; | 263 | umem->diff = diff; |
264 | 264 | ||
265 | schedule_work(&umem->work); | 265 | queue_work(ib_wq, &umem->work); |
266 | return; | 266 | return; |
267 | } | 267 | } |
268 | } else | 268 | } else |
diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index 85cfae4cad71..8c81992fa6db 100644 --- a/drivers/infiniband/hw/amso1100/c2_rnic.c +++ b/drivers/infiniband/hw/amso1100/c2_rnic.c | |||
@@ -459,13 +459,12 @@ int __devinit c2_rnic_init(struct c2_dev *c2dev) | |||
459 | IB_DEVICE_MEM_WINDOW); | 459 | IB_DEVICE_MEM_WINDOW); |
460 | 460 | ||
461 | /* Allocate the qptr_array */ | 461 | /* Allocate the qptr_array */ |
462 | c2dev->qptr_array = vmalloc(C2_MAX_CQS * sizeof(void *)); | 462 | c2dev->qptr_array = vzalloc(C2_MAX_CQS * sizeof(void *)); |
463 | if (!c2dev->qptr_array) { | 463 | if (!c2dev->qptr_array) { |
464 | return -ENOMEM; | 464 | return -ENOMEM; |
465 | } | 465 | } |
466 | 466 | ||
467 | /* Inialize the qptr_array */ | 467 | /* Initialize the qptr_array */ |
468 | memset(c2dev->qptr_array, 0, C2_MAX_CQS * sizeof(void *)); | ||
469 | c2dev->qptr_array[0] = (void *) &c2dev->req_vq; | 468 | c2dev->qptr_array[0] = (void *) &c2dev->req_vq; |
470 | c2dev->qptr_array[1] = (void *) &c2dev->rep_vq; | 469 | c2dev->qptr_array[1] = (void *) &c2dev->rep_vq; |
471 | c2dev->qptr_array[2] = (void *) &c2dev->aeq; | 470 | c2dev->qptr_array[2] = (void *) &c2dev->aeq; |
diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.c b/drivers/infiniband/hw/ehca/ipz_pt_fn.c index 1596e3085344..1898d6e7cce5 100644 --- a/drivers/infiniband/hw/ehca/ipz_pt_fn.c +++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.c | |||
@@ -222,15 +222,14 @@ int ipz_queue_ctor(struct ehca_pd *pd, struct ipz_queue *queue, | |||
222 | queue->small_page = NULL; | 222 | queue->small_page = NULL; |
223 | 223 | ||
224 | /* allocate queue page pointers */ | 224 | /* allocate queue page pointers */ |
225 | queue->queue_pages = kmalloc(nr_of_pages * sizeof(void *), GFP_KERNEL); | 225 | queue->queue_pages = kzalloc(nr_of_pages * sizeof(void *), GFP_KERNEL); |
226 | if (!queue->queue_pages) { | 226 | if (!queue->queue_pages) { |
227 | queue->queue_pages = vmalloc(nr_of_pages * sizeof(void *)); | 227 | queue->queue_pages = vzalloc(nr_of_pages * sizeof(void *)); |
228 | if (!queue->queue_pages) { | 228 | if (!queue->queue_pages) { |
229 | ehca_gen_err("Couldn't allocate queue page list"); | 229 | ehca_gen_err("Couldn't allocate queue page list"); |
230 | return 0; | 230 | return 0; |
231 | } | 231 | } |
232 | } | 232 | } |
233 | memset(queue->queue_pages, 0, nr_of_pages * sizeof(void *)); | ||
234 | 233 | ||
235 | /* allocate actual queue pages */ | 234 | /* allocate actual queue pages */ |
236 | if (is_small) { | 235 | if (is_small) { |
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index b33f0457a1ff..47db4bf34628 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -199,12 +199,11 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev) | |||
199 | goto bail; | 199 | goto bail; |
200 | } | 200 | } |
201 | 201 | ||
202 | dd = vmalloc(sizeof(*dd)); | 202 | dd = vzalloc(sizeof(*dd)); |
203 | if (!dd) { | 203 | if (!dd) { |
204 | dd = ERR_PTR(-ENOMEM); | 204 | dd = ERR_PTR(-ENOMEM); |
205 | goto bail; | 205 | goto bail; |
206 | } | 206 | } |
207 | memset(dd, 0, sizeof(*dd)); | ||
208 | dd->ipath_unit = -1; | 207 | dd->ipath_unit = -1; |
209 | 208 | ||
210 | spin_lock_irqsave(&ipath_devs_lock, flags); | 209 | spin_lock_irqsave(&ipath_devs_lock, flags); |
@@ -756,7 +755,7 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev) | |||
756 | */ | 755 | */ |
757 | ipath_shutdown_device(dd); | 756 | ipath_shutdown_device(dd); |
758 | 757 | ||
759 | flush_scheduled_work(); | 758 | flush_workqueue(ib_wq); |
760 | 759 | ||
761 | if (dd->verbs_dev) | 760 | if (dd->verbs_dev) |
762 | ipath_unregister_ib_device(dd->verbs_dev); | 761 | ipath_unregister_ib_device(dd->verbs_dev); |
diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index 9292a15ad7c4..6d4b29c4cd89 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c | |||
@@ -1530,7 +1530,7 @@ static int init_subports(struct ipath_devdata *dd, | |||
1530 | } | 1530 | } |
1531 | 1531 | ||
1532 | num_subports = uinfo->spu_subport_cnt; | 1532 | num_subports = uinfo->spu_subport_cnt; |
1533 | pd->subport_uregbase = vmalloc(PAGE_SIZE * num_subports); | 1533 | pd->subport_uregbase = vzalloc(PAGE_SIZE * num_subports); |
1534 | if (!pd->subport_uregbase) { | 1534 | if (!pd->subport_uregbase) { |
1535 | ret = -ENOMEM; | 1535 | ret = -ENOMEM; |
1536 | goto bail; | 1536 | goto bail; |
@@ -1538,13 +1538,13 @@ static int init_subports(struct ipath_devdata *dd, | |||
1538 | /* Note: pd->port_rcvhdrq_size isn't initialized yet. */ | 1538 | /* Note: pd->port_rcvhdrq_size isn't initialized yet. */ |
1539 | size = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize * | 1539 | size = ALIGN(dd->ipath_rcvhdrcnt * dd->ipath_rcvhdrentsize * |
1540 | sizeof(u32), PAGE_SIZE) * num_subports; | 1540 | sizeof(u32), PAGE_SIZE) * num_subports; |
1541 | pd->subport_rcvhdr_base = vmalloc(size); | 1541 | pd->subport_rcvhdr_base = vzalloc(size); |
1542 | if (!pd->subport_rcvhdr_base) { | 1542 | if (!pd->subport_rcvhdr_base) { |
1543 | ret = -ENOMEM; | 1543 | ret = -ENOMEM; |
1544 | goto bail_ureg; | 1544 | goto bail_ureg; |
1545 | } | 1545 | } |
1546 | 1546 | ||
1547 | pd->subport_rcvegrbuf = vmalloc(pd->port_rcvegrbuf_chunks * | 1547 | pd->subport_rcvegrbuf = vzalloc(pd->port_rcvegrbuf_chunks * |
1548 | pd->port_rcvegrbuf_size * | 1548 | pd->port_rcvegrbuf_size * |
1549 | num_subports); | 1549 | num_subports); |
1550 | if (!pd->subport_rcvegrbuf) { | 1550 | if (!pd->subport_rcvegrbuf) { |
@@ -1556,11 +1556,6 @@ static int init_subports(struct ipath_devdata *dd, | |||
1556 | pd->port_subport_id = uinfo->spu_subport_id; | 1556 | pd->port_subport_id = uinfo->spu_subport_id; |
1557 | pd->active_slaves = 1; | 1557 | pd->active_slaves = 1; |
1558 | set_bit(IPATH_PORT_MASTER_UNINIT, &pd->port_flag); | 1558 | set_bit(IPATH_PORT_MASTER_UNINIT, &pd->port_flag); |
1559 | memset(pd->subport_uregbase, 0, PAGE_SIZE * num_subports); | ||
1560 | memset(pd->subport_rcvhdr_base, 0, size); | ||
1561 | memset(pd->subport_rcvegrbuf, 0, pd->port_rcvegrbuf_chunks * | ||
1562 | pd->port_rcvegrbuf_size * | ||
1563 | num_subports); | ||
1564 | goto bail; | 1559 | goto bail; |
1565 | 1560 | ||
1566 | bail_rhdr: | 1561 | bail_rhdr: |
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c index 776938299e4c..fef0f4201257 100644 --- a/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c | |||
@@ -442,7 +442,7 @@ static void init_shadow_tids(struct ipath_devdata *dd) | |||
442 | struct page **pages; | 442 | struct page **pages; |
443 | dma_addr_t *addrs; | 443 | dma_addr_t *addrs; |
444 | 444 | ||
445 | pages = vmalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt * | 445 | pages = vzalloc(dd->ipath_cfgports * dd->ipath_rcvtidcnt * |
446 | sizeof(struct page *)); | 446 | sizeof(struct page *)); |
447 | if (!pages) { | 447 | if (!pages) { |
448 | ipath_dev_err(dd, "failed to allocate shadow page * " | 448 | ipath_dev_err(dd, "failed to allocate shadow page * " |
@@ -461,9 +461,6 @@ static void init_shadow_tids(struct ipath_devdata *dd) | |||
461 | return; | 461 | return; |
462 | } | 462 | } |
463 | 463 | ||
464 | memset(pages, 0, dd->ipath_cfgports * dd->ipath_rcvtidcnt * | ||
465 | sizeof(struct page *)); | ||
466 | |||
467 | dd->ipath_pageshadow = pages; | 464 | dd->ipath_pageshadow = pages; |
468 | dd->ipath_physshadow = addrs; | 465 | dd->ipath_physshadow = addrs; |
469 | } | 466 | } |
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c index 5e86d73eba2a..bab9f74c0665 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_pages.c +++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c | |||
@@ -220,7 +220,7 @@ void ipath_release_user_pages_on_close(struct page **p, size_t num_pages) | |||
220 | work->mm = mm; | 220 | work->mm = mm; |
221 | work->num_pages = num_pages; | 221 | work->num_pages = num_pages; |
222 | 222 | ||
223 | schedule_work(&work->work); | 223 | queue_work(ib_wq, &work->work); |
224 | return; | 224 | return; |
225 | 225 | ||
226 | bail_mm: | 226 | bail_mm: |
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index 4c85224aeaa7..c7a6213c6996 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c | |||
@@ -623,8 +623,9 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
623 | struct mlx4_ib_dev *mdev = to_mdev(ibqp->device); | 623 | struct mlx4_ib_dev *mdev = to_mdev(ibqp->device); |
624 | struct mlx4_ib_qp *mqp = to_mqp(ibqp); | 624 | struct mlx4_ib_qp *mqp = to_mqp(ibqp); |
625 | 625 | ||
626 | err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, !!(mqp->flags & | 626 | err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, |
627 | MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK)); | 627 | !!(mqp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK), |
628 | MLX4_PROTOCOL_IB); | ||
628 | if (err) | 629 | if (err) |
629 | return err; | 630 | return err; |
630 | 631 | ||
@@ -635,7 +636,7 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
635 | return 0; | 636 | return 0; |
636 | 637 | ||
637 | err_add: | 638 | err_add: |
638 | mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw); | 639 | mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, MLX4_PROTOCOL_IB); |
639 | return err; | 640 | return err; |
640 | } | 641 | } |
641 | 642 | ||
@@ -665,7 +666,7 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
665 | struct mlx4_ib_gid_entry *ge; | 666 | struct mlx4_ib_gid_entry *ge; |
666 | 667 | ||
667 | err = mlx4_multicast_detach(mdev->dev, | 668 | err = mlx4_multicast_detach(mdev->dev, |
668 | &mqp->mqp, gid->raw); | 669 | &mqp->mqp, gid->raw, MLX4_PROTOCOL_IB); |
669 | if (err) | 670 | if (err) |
670 | return err; | 671 | return err; |
671 | 672 | ||
@@ -1005,7 +1006,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) | |||
1005 | if (mlx4_uar_alloc(dev, &ibdev->priv_uar)) | 1006 | if (mlx4_uar_alloc(dev, &ibdev->priv_uar)) |
1006 | goto err_pd; | 1007 | goto err_pd; |
1007 | 1008 | ||
1008 | ibdev->uar_map = ioremap(ibdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE); | 1009 | ibdev->uar_map = ioremap((phys_addr_t) ibdev->priv_uar.pfn << PAGE_SHIFT, |
1010 | PAGE_SIZE); | ||
1009 | if (!ibdev->uar_map) | 1011 | if (!ibdev->uar_map) |
1010 | goto err_uar; | 1012 | goto err_uar; |
1011 | MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock); | 1013 | MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock); |
diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c index 0aa0110e4b6c..e4a08c2819e4 100644 --- a/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/drivers/infiniband/hw/mthca/mthca_catas.c | |||
@@ -146,7 +146,7 @@ static void poll_catas(unsigned long dev_ptr) | |||
146 | 146 | ||
147 | void mthca_start_catas_poll(struct mthca_dev *dev) | 147 | void mthca_start_catas_poll(struct mthca_dev *dev) |
148 | { | 148 | { |
149 | unsigned long addr; | 149 | phys_addr_t addr; |
150 | 150 | ||
151 | init_timer(&dev->catas_err.timer); | 151 | init_timer(&dev->catas_err.timer); |
152 | dev->catas_err.map = NULL; | 152 | dev->catas_err.map = NULL; |
@@ -158,7 +158,8 @@ void mthca_start_catas_poll(struct mthca_dev *dev) | |||
158 | dev->catas_err.map = ioremap(addr, dev->catas_err.size * 4); | 158 | dev->catas_err.map = ioremap(addr, dev->catas_err.size * 4); |
159 | if (!dev->catas_err.map) { | 159 | if (!dev->catas_err.map) { |
160 | mthca_warn(dev, "couldn't map catastrophic error region " | 160 | mthca_warn(dev, "couldn't map catastrophic error region " |
161 | "at 0x%lx/0x%x\n", addr, dev->catas_err.size * 4); | 161 | "at 0x%llx/0x%x\n", (unsigned long long) addr, |
162 | dev->catas_err.size * 4); | ||
162 | return; | 163 | return; |
163 | } | 164 | } |
164 | 165 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index f4ceecd9684b..7bfa2a164955 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
@@ -713,7 +713,7 @@ int mthca_RUN_FW(struct mthca_dev *dev, u8 *status) | |||
713 | 713 | ||
714 | static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base) | 714 | static void mthca_setup_cmd_doorbells(struct mthca_dev *dev, u64 base) |
715 | { | 715 | { |
716 | unsigned long addr; | 716 | phys_addr_t addr; |
717 | u16 max_off = 0; | 717 | u16 max_off = 0; |
718 | int i; | 718 | int i; |
719 | 719 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index 8e8c728aff88..76785c653c13 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c | |||
@@ -653,7 +653,7 @@ static int mthca_map_reg(struct mthca_dev *dev, | |||
653 | unsigned long offset, unsigned long size, | 653 | unsigned long offset, unsigned long size, |
654 | void __iomem **map) | 654 | void __iomem **map) |
655 | { | 655 | { |
656 | unsigned long base = pci_resource_start(dev->pdev, 0); | 656 | phys_addr_t base = pci_resource_start(dev->pdev, 0); |
657 | 657 | ||
658 | *map = ioremap(base + offset, size); | 658 | *map = ioremap(base + offset, size); |
659 | if (!*map) | 659 | if (!*map) |
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 5eee6665919a..8a40cd539ab1 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c | |||
@@ -790,7 +790,7 @@ static int mthca_setup_hca(struct mthca_dev *dev) | |||
790 | goto err_uar_table_free; | 790 | goto err_uar_table_free; |
791 | } | 791 | } |
792 | 792 | ||
793 | dev->kar = ioremap(dev->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE); | 793 | dev->kar = ioremap((phys_addr_t) dev->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE); |
794 | if (!dev->kar) { | 794 | if (!dev->kar) { |
795 | mthca_err(dev, "Couldn't map kernel access region, " | 795 | mthca_err(dev, "Couldn't map kernel access region, " |
796 | "aborting.\n"); | 796 | "aborting.\n"); |
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index 065b20899876..44045c8846db 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c | |||
@@ -853,7 +853,7 @@ void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr) | |||
853 | 853 | ||
854 | int mthca_init_mr_table(struct mthca_dev *dev) | 854 | int mthca_init_mr_table(struct mthca_dev *dev) |
855 | { | 855 | { |
856 | unsigned long addr; | 856 | phys_addr_t addr; |
857 | int mpts, mtts, err, i; | 857 | int mpts, mtts, err, i; |
858 | 858 | ||
859 | err = mthca_alloc_init(&dev->mr_table.mpt_alloc, | 859 | err = mthca_alloc_init(&dev->mr_table.mpt_alloc, |
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 0c9f0aa5d4ea..3b4ec3238ceb 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c | |||
@@ -144,6 +144,7 @@ static int nes_inetaddr_event(struct notifier_block *notifier, | |||
144 | struct nes_device *nesdev; | 144 | struct nes_device *nesdev; |
145 | struct net_device *netdev; | 145 | struct net_device *netdev; |
146 | struct nes_vnic *nesvnic; | 146 | struct nes_vnic *nesvnic; |
147 | unsigned int is_bonded; | ||
147 | 148 | ||
148 | nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %pI4, netmask %pI4.\n", | 149 | nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %pI4, netmask %pI4.\n", |
149 | &ifa->ifa_address, &ifa->ifa_mask); | 150 | &ifa->ifa_address, &ifa->ifa_mask); |
@@ -152,7 +153,8 @@ static int nes_inetaddr_event(struct notifier_block *notifier, | |||
152 | nesdev, nesdev->netdev[0]->name); | 153 | nesdev, nesdev->netdev[0]->name); |
153 | netdev = nesdev->netdev[0]; | 154 | netdev = nesdev->netdev[0]; |
154 | nesvnic = netdev_priv(netdev); | 155 | nesvnic = netdev_priv(netdev); |
155 | if (netdev == event_netdev) { | 156 | is_bonded = (netdev->master == event_netdev); |
157 | if ((netdev == event_netdev) || is_bonded) { | ||
156 | if (nesvnic->rdma_enabled == 0) { | 158 | if (nesvnic->rdma_enabled == 0) { |
157 | nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since" | 159 | nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since" |
158 | " RDMA is not enabled.\n", | 160 | " RDMA is not enabled.\n", |
@@ -169,7 +171,10 @@ static int nes_inetaddr_event(struct notifier_block *notifier, | |||
169 | nes_manage_arp_cache(netdev, netdev->dev_addr, | 171 | nes_manage_arp_cache(netdev, netdev->dev_addr, |
170 | ntohl(nesvnic->local_ipaddr), NES_ARP_DELETE); | 172 | ntohl(nesvnic->local_ipaddr), NES_ARP_DELETE); |
171 | nesvnic->local_ipaddr = 0; | 173 | nesvnic->local_ipaddr = 0; |
172 | return NOTIFY_OK; | 174 | if (is_bonded) |
175 | continue; | ||
176 | else | ||
177 | return NOTIFY_OK; | ||
173 | break; | 178 | break; |
174 | case NETDEV_UP: | 179 | case NETDEV_UP: |
175 | nes_debug(NES_DBG_NETDEV, "event:UP\n"); | 180 | nes_debug(NES_DBG_NETDEV, "event:UP\n"); |
@@ -178,15 +183,24 @@ static int nes_inetaddr_event(struct notifier_block *notifier, | |||
178 | nes_debug(NES_DBG_NETDEV, "Interface already has local_ipaddr\n"); | 183 | nes_debug(NES_DBG_NETDEV, "Interface already has local_ipaddr\n"); |
179 | return NOTIFY_OK; | 184 | return NOTIFY_OK; |
180 | } | 185 | } |
186 | /* fall through */ | ||
187 | case NETDEV_CHANGEADDR: | ||
181 | /* Add the address to the IP table */ | 188 | /* Add the address to the IP table */ |
182 | nesvnic->local_ipaddr = ifa->ifa_address; | 189 | if (netdev->master) |
190 | nesvnic->local_ipaddr = | ||
191 | ((struct in_device *)netdev->master->ip_ptr)->ifa_list->ifa_address; | ||
192 | else | ||
193 | nesvnic->local_ipaddr = ifa->ifa_address; | ||
183 | 194 | ||
184 | nes_write_indexed(nesdev, | 195 | nes_write_indexed(nesdev, |
185 | NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), | 196 | NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), |
186 | ntohl(ifa->ifa_address)); | 197 | ntohl(nesvnic->local_ipaddr)); |
187 | nes_manage_arp_cache(netdev, netdev->dev_addr, | 198 | nes_manage_arp_cache(netdev, netdev->dev_addr, |
188 | ntohl(nesvnic->local_ipaddr), NES_ARP_ADD); | 199 | ntohl(nesvnic->local_ipaddr), NES_ARP_ADD); |
189 | return NOTIFY_OK; | 200 | if (is_bonded) |
201 | continue; | ||
202 | else | ||
203 | return NOTIFY_OK; | ||
190 | break; | 204 | break; |
191 | default: | 205 | default: |
192 | break; | 206 | break; |
@@ -660,6 +674,8 @@ static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_i | |||
660 | } | 674 | } |
661 | nes_notifiers_registered++; | 675 | nes_notifiers_registered++; |
662 | 676 | ||
677 | INIT_DELAYED_WORK(&nesdev->work, nes_recheck_link_status); | ||
678 | |||
663 | /* Initialize network devices */ | 679 | /* Initialize network devices */ |
664 | if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) | 680 | if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) |
665 | goto bail7; | 681 | goto bail7; |
@@ -742,6 +758,7 @@ static void __devexit nes_remove(struct pci_dev *pcidev) | |||
742 | struct nes_device *nesdev = pci_get_drvdata(pcidev); | 758 | struct nes_device *nesdev = pci_get_drvdata(pcidev); |
743 | struct net_device *netdev; | 759 | struct net_device *netdev; |
744 | int netdev_index = 0; | 760 | int netdev_index = 0; |
761 | unsigned long flags; | ||
745 | 762 | ||
746 | if (nesdev->netdev_count) { | 763 | if (nesdev->netdev_count) { |
747 | netdev = nesdev->netdev[netdev_index]; | 764 | netdev = nesdev->netdev[netdev_index]; |
@@ -768,6 +785,14 @@ static void __devexit nes_remove(struct pci_dev *pcidev) | |||
768 | free_irq(pcidev->irq, nesdev); | 785 | free_irq(pcidev->irq, nesdev); |
769 | tasklet_kill(&nesdev->dpc_tasklet); | 786 | tasklet_kill(&nesdev->dpc_tasklet); |
770 | 787 | ||
788 | spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags); | ||
789 | if (nesdev->link_recheck) { | ||
790 | spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); | ||
791 | cancel_delayed_work_sync(&nesdev->work); | ||
792 | } else { | ||
793 | spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); | ||
794 | } | ||
795 | |||
771 | /* Deallocate the Adapter Structure */ | 796 | /* Deallocate the Adapter Structure */ |
772 | nes_destroy_adapter(nesdev->nesadapter); | 797 | nes_destroy_adapter(nesdev->nesadapter); |
773 | 798 | ||
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index b3d145e82b4c..6fe79876009e 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h | |||
@@ -268,6 +268,9 @@ struct nes_device { | |||
268 | u8 napi_isr_ran; | 268 | u8 napi_isr_ran; |
269 | u8 disable_rx_flow_control; | 269 | u8 disable_rx_flow_control; |
270 | u8 disable_tx_flow_control; | 270 | u8 disable_tx_flow_control; |
271 | |||
272 | struct delayed_work work; | ||
273 | u8 link_recheck; | ||
271 | }; | 274 | }; |
272 | 275 | ||
273 | 276 | ||
@@ -507,6 +510,7 @@ void nes_nic_ce_handler(struct nes_device *, struct nes_hw_nic_cq *); | |||
507 | void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *); | 510 | void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *); |
508 | int nes_destroy_cqp(struct nes_device *); | 511 | int nes_destroy_cqp(struct nes_device *); |
509 | int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); | 512 | int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); |
513 | void nes_recheck_link_status(struct work_struct *work); | ||
510 | 514 | ||
511 | /* nes_nic.c */ | 515 | /* nes_nic.c */ |
512 | struct net_device *nes_netdev_init(struct nes_device *, void __iomem *); | 516 | struct net_device *nes_netdev_init(struct nes_device *, void __iomem *); |
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index 25ad0f9944c0..009ec814d517 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c | |||
@@ -1107,6 +1107,7 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi | |||
1107 | struct flowi fl; | 1107 | struct flowi fl; |
1108 | struct neighbour *neigh; | 1108 | struct neighbour *neigh; |
1109 | int rc = arpindex; | 1109 | int rc = arpindex; |
1110 | struct net_device *netdev; | ||
1110 | struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter; | 1111 | struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter; |
1111 | 1112 | ||
1112 | memset(&fl, 0, sizeof fl); | 1113 | memset(&fl, 0, sizeof fl); |
@@ -1117,7 +1118,12 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi | |||
1117 | return rc; | 1118 | return rc; |
1118 | } | 1119 | } |
1119 | 1120 | ||
1120 | neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, nesvnic->netdev); | 1121 | if (nesvnic->netdev->master) |
1122 | netdev = nesvnic->netdev->master; | ||
1123 | else | ||
1124 | netdev = nesvnic->netdev; | ||
1125 | |||
1126 | neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, netdev); | ||
1121 | if (neigh) { | 1127 | if (neigh) { |
1122 | if (neigh->nud_state & NUD_VALID) { | 1128 | if (neigh->nud_state & NUD_VALID) { |
1123 | nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X" | 1129 | nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X" |
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 1980a461c499..8b606fd64022 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
@@ -2608,6 +2608,13 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2608 | netif_start_queue(nesvnic->netdev); | 2608 | netif_start_queue(nesvnic->netdev); |
2609 | nesvnic->linkup = 1; | 2609 | nesvnic->linkup = 1; |
2610 | netif_carrier_on(nesvnic->netdev); | 2610 | netif_carrier_on(nesvnic->netdev); |
2611 | |||
2612 | spin_lock(&nesvnic->port_ibevent_lock); | ||
2613 | if (nesdev->iw_status == 0) { | ||
2614 | nesdev->iw_status = 1; | ||
2615 | nes_port_ibevent(nesvnic); | ||
2616 | } | ||
2617 | spin_unlock(&nesvnic->port_ibevent_lock); | ||
2611 | } | 2618 | } |
2612 | } | 2619 | } |
2613 | } else { | 2620 | } else { |
@@ -2633,9 +2640,23 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2633 | netif_stop_queue(nesvnic->netdev); | 2640 | netif_stop_queue(nesvnic->netdev); |
2634 | nesvnic->linkup = 0; | 2641 | nesvnic->linkup = 0; |
2635 | netif_carrier_off(nesvnic->netdev); | 2642 | netif_carrier_off(nesvnic->netdev); |
2643 | |||
2644 | spin_lock(&nesvnic->port_ibevent_lock); | ||
2645 | if (nesdev->iw_status == 1) { | ||
2646 | nesdev->iw_status = 0; | ||
2647 | nes_port_ibevent(nesvnic); | ||
2648 | } | ||
2649 | spin_unlock(&nesvnic->port_ibevent_lock); | ||
2636 | } | 2650 | } |
2637 | } | 2651 | } |
2638 | } | 2652 | } |
2653 | if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_SFP_D) { | ||
2654 | if (nesdev->link_recheck) | ||
2655 | cancel_delayed_work(&nesdev->work); | ||
2656 | nesdev->link_recheck = 1; | ||
2657 | schedule_delayed_work(&nesdev->work, | ||
2658 | NES_LINK_RECHECK_DELAY); | ||
2659 | } | ||
2639 | } | 2660 | } |
2640 | 2661 | ||
2641 | spin_unlock_irqrestore(&nesadapter->phy_lock, flags); | 2662 | spin_unlock_irqrestore(&nesadapter->phy_lock, flags); |
@@ -2643,6 +2664,80 @@ static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number) | |||
2643 | nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE; | 2664 | nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE; |
2644 | } | 2665 | } |
2645 | 2666 | ||
2667 | void nes_recheck_link_status(struct work_struct *work) | ||
2668 | { | ||
2669 | unsigned long flags; | ||
2670 | struct nes_device *nesdev = container_of(work, struct nes_device, work.work); | ||
2671 | struct nes_adapter *nesadapter = nesdev->nesadapter; | ||
2672 | struct nes_vnic *nesvnic; | ||
2673 | u32 mac_index = nesdev->mac_index; | ||
2674 | u16 phy_data; | ||
2675 | u16 temp_phy_data; | ||
2676 | |||
2677 | spin_lock_irqsave(&nesadapter->phy_lock, flags); | ||
2678 | |||
2679 | /* check link status */ | ||
2680 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 1, 0x9003); | ||
2681 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
2682 | |||
2683 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021); | ||
2684 | nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
2685 | nes_read_10G_phy_reg(nesdev, nesadapter->phy_index[mac_index], 3, 0x0021); | ||
2686 | phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
2687 | |||
2688 | phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0; | ||
2689 | |||
2690 | nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n", | ||
2691 | __func__, phy_data, | ||
2692 | nesadapter->mac_link_down[mac_index] ? "DOWN" : "UP"); | ||
2693 | |||
2694 | if (phy_data & 0x0004) { | ||
2695 | nesadapter->mac_link_down[mac_index] = 0; | ||
2696 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { | ||
2697 | if (nesvnic->linkup == 0) { | ||
2698 | printk(PFX "The Link is now up for port %s, netdev %p.\n", | ||
2699 | nesvnic->netdev->name, nesvnic->netdev); | ||
2700 | if (netif_queue_stopped(nesvnic->netdev)) | ||
2701 | netif_start_queue(nesvnic->netdev); | ||
2702 | nesvnic->linkup = 1; | ||
2703 | netif_carrier_on(nesvnic->netdev); | ||
2704 | |||
2705 | spin_lock(&nesvnic->port_ibevent_lock); | ||
2706 | if (nesdev->iw_status == 0) { | ||
2707 | nesdev->iw_status = 1; | ||
2708 | nes_port_ibevent(nesvnic); | ||
2709 | } | ||
2710 | spin_unlock(&nesvnic->port_ibevent_lock); | ||
2711 | } | ||
2712 | } | ||
2713 | |||
2714 | } else { | ||
2715 | nesadapter->mac_link_down[mac_index] = 1; | ||
2716 | list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) { | ||
2717 | if (nesvnic->linkup == 1) { | ||
2718 | printk(PFX "The Link is now down for port %s, netdev %p.\n", | ||
2719 | nesvnic->netdev->name, nesvnic->netdev); | ||
2720 | if (!(netif_queue_stopped(nesvnic->netdev))) | ||
2721 | netif_stop_queue(nesvnic->netdev); | ||
2722 | nesvnic->linkup = 0; | ||
2723 | netif_carrier_off(nesvnic->netdev); | ||
2724 | |||
2725 | spin_lock(&nesvnic->port_ibevent_lock); | ||
2726 | if (nesdev->iw_status == 1) { | ||
2727 | nesdev->iw_status = 0; | ||
2728 | nes_port_ibevent(nesvnic); | ||
2729 | } | ||
2730 | spin_unlock(&nesvnic->port_ibevent_lock); | ||
2731 | } | ||
2732 | } | ||
2733 | } | ||
2734 | if (nesdev->link_recheck++ < NES_LINK_RECHECK_MAX) | ||
2735 | schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY); | ||
2736 | else | ||
2737 | nesdev->link_recheck = 0; | ||
2738 | |||
2739 | spin_unlock_irqrestore(&nesadapter->phy_lock, flags); | ||
2740 | } | ||
2646 | 2741 | ||
2647 | 2742 | ||
2648 | static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) | 2743 | static void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq) |
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 1204c3432b63..d2abe07133a5 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h | |||
@@ -1193,6 +1193,8 @@ struct nes_listener { | |||
1193 | 1193 | ||
1194 | struct nes_ib_device; | 1194 | struct nes_ib_device; |
1195 | 1195 | ||
1196 | #define NES_EVENT_DELAY msecs_to_jiffies(100) | ||
1197 | |||
1196 | struct nes_vnic { | 1198 | struct nes_vnic { |
1197 | struct nes_ib_device *nesibdev; | 1199 | struct nes_ib_device *nesibdev; |
1198 | u64 sq_full; | 1200 | u64 sq_full; |
@@ -1247,6 +1249,10 @@ struct nes_vnic { | |||
1247 | u32 lro_max_aggr; | 1249 | u32 lro_max_aggr; |
1248 | struct net_lro_mgr lro_mgr; | 1250 | struct net_lro_mgr lro_mgr; |
1249 | struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS]; | 1251 | struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS]; |
1252 | struct timer_list event_timer; | ||
1253 | enum ib_event_type delayed_event; | ||
1254 | enum ib_event_type last_dispatched_event; | ||
1255 | spinlock_t port_ibevent_lock; | ||
1250 | }; | 1256 | }; |
1251 | 1257 | ||
1252 | struct nes_ib_device { | 1258 | struct nes_ib_device { |
@@ -1348,6 +1354,10 @@ struct nes_terminate_hdr { | |||
1348 | #define BAD_FRAME_OFFSET 64 | 1354 | #define BAD_FRAME_OFFSET 64 |
1349 | #define CQE_MAJOR_DRV 0x8000 | 1355 | #define CQE_MAJOR_DRV 0x8000 |
1350 | 1356 | ||
1357 | /* Used for link status recheck after interrupt processing */ | ||
1358 | #define NES_LINK_RECHECK_DELAY msecs_to_jiffies(50) | ||
1359 | #define NES_LINK_RECHECK_MAX 60 | ||
1360 | |||
1351 | #define nes_vlan_rx vlan_hwaccel_receive_skb | 1361 | #define nes_vlan_rx vlan_hwaccel_receive_skb |
1352 | #define nes_netif_rx netif_receive_skb | 1362 | #define nes_netif_rx netif_receive_skb |
1353 | 1363 | ||
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 5a4c36484722..2c9c1933bbe3 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c | |||
@@ -144,6 +144,7 @@ static int nes_netdev_open(struct net_device *netdev) | |||
144 | u32 nic_active_bit; | 144 | u32 nic_active_bit; |
145 | u32 nic_active; | 145 | u32 nic_active; |
146 | struct list_head *list_pos, *list_temp; | 146 | struct list_head *list_pos, *list_temp; |
147 | unsigned long flags; | ||
147 | 148 | ||
148 | assert(nesdev != NULL); | 149 | assert(nesdev != NULL); |
149 | 150 | ||
@@ -233,18 +234,36 @@ static int nes_netdev_open(struct net_device *netdev) | |||
233 | first_nesvnic = nesvnic; | 234 | first_nesvnic = nesvnic; |
234 | } | 235 | } |
235 | 236 | ||
236 | if (nesvnic->of_device_registered) { | ||
237 | nesdev->iw_status = 1; | ||
238 | nesdev->nesadapter->send_term_ok = 1; | ||
239 | nes_port_ibevent(nesvnic); | ||
240 | } | ||
241 | |||
242 | if (first_nesvnic->linkup) { | 237 | if (first_nesvnic->linkup) { |
243 | /* Enable network packets */ | 238 | /* Enable network packets */ |
244 | nesvnic->linkup = 1; | 239 | nesvnic->linkup = 1; |
245 | netif_start_queue(netdev); | 240 | netif_start_queue(netdev); |
246 | netif_carrier_on(netdev); | 241 | netif_carrier_on(netdev); |
247 | } | 242 | } |
243 | |||
244 | spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags); | ||
245 | if (nesdev->nesadapter->phy_type[nesdev->mac_index] == NES_PHY_TYPE_SFP_D) { | ||
246 | if (nesdev->link_recheck) | ||
247 | cancel_delayed_work(&nesdev->work); | ||
248 | nesdev->link_recheck = 1; | ||
249 | schedule_delayed_work(&nesdev->work, NES_LINK_RECHECK_DELAY); | ||
250 | } | ||
251 | spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); | ||
252 | |||
253 | spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags); | ||
254 | if (nesvnic->of_device_registered) { | ||
255 | nesdev->nesadapter->send_term_ok = 1; | ||
256 | if (nesvnic->linkup == 1) { | ||
257 | if (nesdev->iw_status == 0) { | ||
258 | nesdev->iw_status = 1; | ||
259 | nes_port_ibevent(nesvnic); | ||
260 | } | ||
261 | } else { | ||
262 | nesdev->iw_status = 0; | ||
263 | } | ||
264 | } | ||
265 | spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags); | ||
266 | |||
248 | napi_enable(&nesvnic->napi); | 267 | napi_enable(&nesvnic->napi); |
249 | nesvnic->netdev_open = 1; | 268 | nesvnic->netdev_open = 1; |
250 | 269 | ||
@@ -263,6 +282,7 @@ static int nes_netdev_stop(struct net_device *netdev) | |||
263 | u32 nic_active; | 282 | u32 nic_active; |
264 | struct nes_vnic *first_nesvnic = NULL; | 283 | struct nes_vnic *first_nesvnic = NULL; |
265 | struct list_head *list_pos, *list_temp; | 284 | struct list_head *list_pos, *list_temp; |
285 | unsigned long flags; | ||
266 | 286 | ||
267 | nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n", | 287 | nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n", |
268 | nesvnic, nesdev, netdev, netdev->name); | 288 | nesvnic, nesdev, netdev, netdev->name); |
@@ -315,12 +335,17 @@ static int nes_netdev_stop(struct net_device *netdev) | |||
315 | nic_active &= nic_active_mask; | 335 | nic_active &= nic_active_mask; |
316 | nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active); | 336 | nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active); |
317 | 337 | ||
318 | 338 | spin_lock_irqsave(&nesvnic->port_ibevent_lock, flags); | |
319 | if (nesvnic->of_device_registered) { | 339 | if (nesvnic->of_device_registered) { |
320 | nesdev->nesadapter->send_term_ok = 0; | 340 | nesdev->nesadapter->send_term_ok = 0; |
321 | nesdev->iw_status = 0; | 341 | nesdev->iw_status = 0; |
322 | nes_port_ibevent(nesvnic); | 342 | if (nesvnic->linkup == 1) |
343 | nes_port_ibevent(nesvnic); | ||
323 | } | 344 | } |
345 | del_timer_sync(&nesvnic->event_timer); | ||
346 | nesvnic->event_timer.function = NULL; | ||
347 | spin_unlock_irqrestore(&nesvnic->port_ibevent_lock, flags); | ||
348 | |||
324 | nes_destroy_nic_qp(nesvnic); | 349 | nes_destroy_nic_qp(nesvnic); |
325 | 350 | ||
326 | nesvnic->netdev_open = 0; | 351 | nesvnic->netdev_open = 0; |
@@ -1750,7 +1775,10 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, | |||
1750 | nesvnic->rdma_enabled = 0; | 1775 | nesvnic->rdma_enabled = 0; |
1751 | } | 1776 | } |
1752 | nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id; | 1777 | nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id; |
1778 | init_timer(&nesvnic->event_timer); | ||
1779 | nesvnic->event_timer.function = NULL; | ||
1753 | spin_lock_init(&nesvnic->tx_lock); | 1780 | spin_lock_init(&nesvnic->tx_lock); |
1781 | spin_lock_init(&nesvnic->port_ibevent_lock); | ||
1754 | nesdev->netdev[nesdev->netdev_count] = netdev; | 1782 | nesdev->netdev[nesdev->netdev_count] = netdev; |
1755 | 1783 | ||
1756 | nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n", | 1784 | nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n", |
@@ -1763,8 +1791,11 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, | |||
1763 | (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) || | 1791 | (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) || |
1764 | ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) { | 1792 | ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) { |
1765 | u32 u32temp; | 1793 | u32 u32temp; |
1766 | u32 link_mask; | 1794 | u32 link_mask = 0; |
1767 | u32 link_val; | 1795 | u32 link_val = 0; |
1796 | u16 temp_phy_data; | ||
1797 | u16 phy_data = 0; | ||
1798 | unsigned long flags; | ||
1768 | 1799 | ||
1769 | u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + | 1800 | u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + |
1770 | (0x200 * (nesdev->mac_index & 1))); | 1801 | (0x200 * (nesdev->mac_index & 1))); |
@@ -1786,6 +1817,23 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, | |||
1786 | link_val = 0x02020000; | 1817 | link_val = 0x02020000; |
1787 | } | 1818 | } |
1788 | break; | 1819 | break; |
1820 | case NES_PHY_TYPE_SFP_D: | ||
1821 | spin_lock_irqsave(&nesdev->nesadapter->phy_lock, flags); | ||
1822 | nes_read_10G_phy_reg(nesdev, | ||
1823 | nesdev->nesadapter->phy_index[nesdev->mac_index], | ||
1824 | 1, 0x9003); | ||
1825 | temp_phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
1826 | nes_read_10G_phy_reg(nesdev, | ||
1827 | nesdev->nesadapter->phy_index[nesdev->mac_index], | ||
1828 | 3, 0x0021); | ||
1829 | nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
1830 | nes_read_10G_phy_reg(nesdev, | ||
1831 | nesdev->nesadapter->phy_index[nesdev->mac_index], | ||
1832 | 3, 0x0021); | ||
1833 | phy_data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL); | ||
1834 | spin_unlock_irqrestore(&nesdev->nesadapter->phy_lock, flags); | ||
1835 | phy_data = (!temp_phy_data && (phy_data == 0x8000)) ? 0x4 : 0x0; | ||
1836 | break; | ||
1789 | default: | 1837 | default: |
1790 | link_mask = 0x0f1f0000; | 1838 | link_mask = 0x0f1f0000; |
1791 | link_val = 0x0f0f0000; | 1839 | link_val = 0x0f0f0000; |
@@ -1795,8 +1843,14 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, | |||
1795 | u32temp = nes_read_indexed(nesdev, | 1843 | u32temp = nes_read_indexed(nesdev, |
1796 | NES_IDX_PHY_PCS_CONTROL_STATUS0 + | 1844 | NES_IDX_PHY_PCS_CONTROL_STATUS0 + |
1797 | (0x200 * (nesdev->mac_index & 1))); | 1845 | (0x200 * (nesdev->mac_index & 1))); |
1798 | if ((u32temp & link_mask) == link_val) | 1846 | |
1799 | nesvnic->linkup = 1; | 1847 | if (phy_type == NES_PHY_TYPE_SFP_D) { |
1848 | if (phy_data & 0x0004) | ||
1849 | nesvnic->linkup = 1; | ||
1850 | } else { | ||
1851 | if ((u32temp & link_mask) == link_val) | ||
1852 | nesvnic->linkup = 1; | ||
1853 | } | ||
1800 | 1854 | ||
1801 | /* clear the MAC interrupt status, assumes direct logical to physical mapping */ | 1855 | /* clear the MAC interrupt status, assumes direct logical to physical mapping */ |
1802 | u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index)); | 1856 | u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index)); |
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 99933e4e48ff..26d8018c0a7c 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c | |||
@@ -3936,6 +3936,30 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev) | |||
3936 | return nesibdev; | 3936 | return nesibdev; |
3937 | } | 3937 | } |
3938 | 3938 | ||
3939 | |||
3940 | /** | ||
3941 | * nes_handle_delayed_event | ||
3942 | */ | ||
3943 | static void nes_handle_delayed_event(unsigned long data) | ||
3944 | { | ||
3945 | struct nes_vnic *nesvnic = (void *) data; | ||
3946 | |||
3947 | if (nesvnic->delayed_event != nesvnic->last_dispatched_event) { | ||
3948 | struct ib_event event; | ||
3949 | |||
3950 | event.device = &nesvnic->nesibdev->ibdev; | ||
3951 | if (!event.device) | ||
3952 | goto stop_timer; | ||
3953 | event.event = nesvnic->delayed_event; | ||
3954 | event.element.port_num = nesvnic->logical_port + 1; | ||
3955 | ib_dispatch_event(&event); | ||
3956 | } | ||
3957 | |||
3958 | stop_timer: | ||
3959 | nesvnic->event_timer.function = NULL; | ||
3960 | } | ||
3961 | |||
3962 | |||
3939 | void nes_port_ibevent(struct nes_vnic *nesvnic) | 3963 | void nes_port_ibevent(struct nes_vnic *nesvnic) |
3940 | { | 3964 | { |
3941 | struct nes_ib_device *nesibdev = nesvnic->nesibdev; | 3965 | struct nes_ib_device *nesibdev = nesvnic->nesibdev; |
@@ -3944,7 +3968,18 @@ void nes_port_ibevent(struct nes_vnic *nesvnic) | |||
3944 | event.device = &nesibdev->ibdev; | 3968 | event.device = &nesibdev->ibdev; |
3945 | event.element.port_num = nesvnic->logical_port + 1; | 3969 | event.element.port_num = nesvnic->logical_port + 1; |
3946 | event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; | 3970 | event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; |
3947 | ib_dispatch_event(&event); | 3971 | |
3972 | if (!nesvnic->event_timer.function) { | ||
3973 | ib_dispatch_event(&event); | ||
3974 | nesvnic->last_dispatched_event = event.event; | ||
3975 | nesvnic->event_timer.function = nes_handle_delayed_event; | ||
3976 | nesvnic->event_timer.data = (unsigned long) nesvnic; | ||
3977 | nesvnic->event_timer.expires = jiffies + NES_EVENT_DELAY; | ||
3978 | add_timer(&nesvnic->event_timer); | ||
3979 | } else { | ||
3980 | mod_timer(&nesvnic->event_timer, jiffies + NES_EVENT_DELAY); | ||
3981 | } | ||
3982 | nesvnic->delayed_event = event.event; | ||
3948 | } | 3983 | } |
3949 | 3984 | ||
3950 | 3985 | ||
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index 127a0d5069f0..de799f17cb9e 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c | |||
@@ -1692,8 +1692,7 @@ static void qib_7220_quiet_serdes(struct qib_pportdata *ppd) | |||
1692 | ppd->lflags &= ~QIBL_IB_AUTONEG_INPROG; | 1692 | ppd->lflags &= ~QIBL_IB_AUTONEG_INPROG; |
1693 | spin_unlock_irqrestore(&ppd->lflags_lock, flags); | 1693 | spin_unlock_irqrestore(&ppd->lflags_lock, flags); |
1694 | wake_up(&ppd->cpspec->autoneg_wait); | 1694 | wake_up(&ppd->cpspec->autoneg_wait); |
1695 | cancel_delayed_work(&ppd->cpspec->autoneg_work); | 1695 | cancel_delayed_work_sync(&ppd->cpspec->autoneg_work); |
1696 | flush_scheduled_work(); | ||
1697 | 1696 | ||
1698 | shutdown_7220_relock_poll(ppd->dd); | 1697 | shutdown_7220_relock_poll(ppd->dd); |
1699 | val = qib_read_kreg64(ppd->dd, kr_xgxs_cfg); | 1698 | val = qib_read_kreg64(ppd->dd, kr_xgxs_cfg); |
@@ -3515,8 +3514,8 @@ static void try_7220_autoneg(struct qib_pportdata *ppd) | |||
3515 | 3514 | ||
3516 | toggle_7220_rclkrls(ppd->dd); | 3515 | toggle_7220_rclkrls(ppd->dd); |
3517 | /* 2 msec is minimum length of a poll cycle */ | 3516 | /* 2 msec is minimum length of a poll cycle */ |
3518 | schedule_delayed_work(&ppd->cpspec->autoneg_work, | 3517 | queue_delayed_work(ib_wq, &ppd->cpspec->autoneg_work, |
3519 | msecs_to_jiffies(2)); | 3518 | msecs_to_jiffies(2)); |
3520 | } | 3519 | } |
3521 | 3520 | ||
3522 | /* | 3521 | /* |
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index abd409d592ef..50cceb3ab885 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c | |||
@@ -2406,10 +2406,9 @@ static void qib_7322_mini_quiet_serdes(struct qib_pportdata *ppd) | |||
2406 | ppd->lflags &= ~QIBL_IB_AUTONEG_INPROG; | 2406 | ppd->lflags &= ~QIBL_IB_AUTONEG_INPROG; |
2407 | spin_unlock_irqrestore(&ppd->lflags_lock, flags); | 2407 | spin_unlock_irqrestore(&ppd->lflags_lock, flags); |
2408 | wake_up(&ppd->cpspec->autoneg_wait); | 2408 | wake_up(&ppd->cpspec->autoneg_wait); |
2409 | cancel_delayed_work(&ppd->cpspec->autoneg_work); | 2409 | cancel_delayed_work_sync(&ppd->cpspec->autoneg_work); |
2410 | if (ppd->dd->cspec->r1) | 2410 | if (ppd->dd->cspec->r1) |
2411 | cancel_delayed_work(&ppd->cpspec->ipg_work); | 2411 | cancel_delayed_work_sync(&ppd->cpspec->ipg_work); |
2412 | flush_scheduled_work(); | ||
2413 | 2412 | ||
2414 | ppd->cpspec->chase_end = 0; | 2413 | ppd->cpspec->chase_end = 0; |
2415 | if (ppd->cpspec->chase_timer.data) /* if initted */ | 2414 | if (ppd->cpspec->chase_timer.data) /* if initted */ |
@@ -2706,7 +2705,7 @@ static noinline void unknown_7322_gpio_intr(struct qib_devdata *dd) | |||
2706 | if (!(pins & mask)) { | 2705 | if (!(pins & mask)) { |
2707 | ++handled; | 2706 | ++handled; |
2708 | qd->t_insert = get_jiffies_64(); | 2707 | qd->t_insert = get_jiffies_64(); |
2709 | schedule_work(&qd->work); | 2708 | queue_work(ib_wq, &qd->work); |
2710 | } | 2709 | } |
2711 | } | 2710 | } |
2712 | } | 2711 | } |
@@ -4990,8 +4989,8 @@ static void try_7322_autoneg(struct qib_pportdata *ppd) | |||
4990 | set_7322_ibspeed_fast(ppd, QIB_IB_DDR); | 4989 | set_7322_ibspeed_fast(ppd, QIB_IB_DDR); |
4991 | qib_7322_mini_pcs_reset(ppd); | 4990 | qib_7322_mini_pcs_reset(ppd); |
4992 | /* 2 msec is minimum length of a poll cycle */ | 4991 | /* 2 msec is minimum length of a poll cycle */ |
4993 | schedule_delayed_work(&ppd->cpspec->autoneg_work, | 4992 | queue_delayed_work(ib_wq, &ppd->cpspec->autoneg_work, |
4994 | msecs_to_jiffies(2)); | 4993 | msecs_to_jiffies(2)); |
4995 | } | 4994 | } |
4996 | 4995 | ||
4997 | /* | 4996 | /* |
@@ -5121,7 +5120,8 @@ static void try_7322_ipg(struct qib_pportdata *ppd) | |||
5121 | ib_free_send_mad(send_buf); | 5120 | ib_free_send_mad(send_buf); |
5122 | retry: | 5121 | retry: |
5123 | delay = 2 << ppd->cpspec->ipg_tries; | 5122 | delay = 2 << ppd->cpspec->ipg_tries; |
5124 | schedule_delayed_work(&ppd->cpspec->ipg_work, msecs_to_jiffies(delay)); | 5123 | queue_delayed_work(ib_wq, &ppd->cpspec->ipg_work, |
5124 | msecs_to_jiffies(delay)); | ||
5125 | } | 5125 | } |
5126 | 5126 | ||
5127 | /* | 5127 | /* |
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 7896afbb9ce8..ffefb78b8949 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c | |||
@@ -80,7 +80,6 @@ unsigned qib_wc_pat = 1; /* default (1) is to use PAT, not MTRR */ | |||
80 | module_param_named(wc_pat, qib_wc_pat, uint, S_IRUGO); | 80 | module_param_named(wc_pat, qib_wc_pat, uint, S_IRUGO); |
81 | MODULE_PARM_DESC(wc_pat, "enable write-combining via PAT mechanism"); | 81 | MODULE_PARM_DESC(wc_pat, "enable write-combining via PAT mechanism"); |
82 | 82 | ||
83 | struct workqueue_struct *qib_wq; | ||
84 | struct workqueue_struct *qib_cq_wq; | 83 | struct workqueue_struct *qib_cq_wq; |
85 | 84 | ||
86 | static void verify_interrupt(unsigned long); | 85 | static void verify_interrupt(unsigned long); |
@@ -270,23 +269,20 @@ static void init_shadow_tids(struct qib_devdata *dd) | |||
270 | struct page **pages; | 269 | struct page **pages; |
271 | dma_addr_t *addrs; | 270 | dma_addr_t *addrs; |
272 | 271 | ||
273 | pages = vmalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(struct page *)); | 272 | pages = vzalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(struct page *)); |
274 | if (!pages) { | 273 | if (!pages) { |
275 | qib_dev_err(dd, "failed to allocate shadow page * " | 274 | qib_dev_err(dd, "failed to allocate shadow page * " |
276 | "array, no expected sends!\n"); | 275 | "array, no expected sends!\n"); |
277 | goto bail; | 276 | goto bail; |
278 | } | 277 | } |
279 | 278 | ||
280 | addrs = vmalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(dma_addr_t)); | 279 | addrs = vzalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(dma_addr_t)); |
281 | if (!addrs) { | 280 | if (!addrs) { |
282 | qib_dev_err(dd, "failed to allocate shadow dma handle " | 281 | qib_dev_err(dd, "failed to allocate shadow dma handle " |
283 | "array, no expected sends!\n"); | 282 | "array, no expected sends!\n"); |
284 | goto bail_free; | 283 | goto bail_free; |
285 | } | 284 | } |
286 | 285 | ||
287 | memset(pages, 0, dd->cfgctxts * dd->rcvtidcnt * sizeof(struct page *)); | ||
288 | memset(addrs, 0, dd->cfgctxts * dd->rcvtidcnt * sizeof(dma_addr_t)); | ||
289 | |||
290 | dd->pageshadow = pages; | 286 | dd->pageshadow = pages; |
291 | dd->physshadow = addrs; | 287 | dd->physshadow = addrs; |
292 | return; | 288 | return; |
@@ -1047,24 +1043,10 @@ static int __init qlogic_ib_init(void) | |||
1047 | if (ret) | 1043 | if (ret) |
1048 | goto bail; | 1044 | goto bail; |
1049 | 1045 | ||
1050 | /* | ||
1051 | * We create our own workqueue mainly because we want to be | ||
1052 | * able to flush it when devices are being removed. We can't | ||
1053 | * use schedule_work()/flush_scheduled_work() because both | ||
1054 | * unregister_netdev() and linkwatch_event take the rtnl lock, | ||
1055 | * so flush_scheduled_work() can deadlock during device | ||
1056 | * removal. | ||
1057 | */ | ||
1058 | qib_wq = create_workqueue("qib"); | ||
1059 | if (!qib_wq) { | ||
1060 | ret = -ENOMEM; | ||
1061 | goto bail_dev; | ||
1062 | } | ||
1063 | |||
1064 | qib_cq_wq = create_singlethread_workqueue("qib_cq"); | 1046 | qib_cq_wq = create_singlethread_workqueue("qib_cq"); |
1065 | if (!qib_cq_wq) { | 1047 | if (!qib_cq_wq) { |
1066 | ret = -ENOMEM; | 1048 | ret = -ENOMEM; |
1067 | goto bail_wq; | 1049 | goto bail_dev; |
1068 | } | 1050 | } |
1069 | 1051 | ||
1070 | /* | 1052 | /* |
@@ -1094,8 +1076,6 @@ bail_unit: | |||
1094 | idr_destroy(&qib_unit_table); | 1076 | idr_destroy(&qib_unit_table); |
1095 | bail_cq_wq: | 1077 | bail_cq_wq: |
1096 | destroy_workqueue(qib_cq_wq); | 1078 | destroy_workqueue(qib_cq_wq); |
1097 | bail_wq: | ||
1098 | destroy_workqueue(qib_wq); | ||
1099 | bail_dev: | 1079 | bail_dev: |
1100 | qib_dev_cleanup(); | 1080 | qib_dev_cleanup(); |
1101 | bail: | 1081 | bail: |
@@ -1119,7 +1099,6 @@ static void __exit qlogic_ib_cleanup(void) | |||
1119 | 1099 | ||
1120 | pci_unregister_driver(&qib_driver); | 1100 | pci_unregister_driver(&qib_driver); |
1121 | 1101 | ||
1122 | destroy_workqueue(qib_wq); | ||
1123 | destroy_workqueue(qib_cq_wq); | 1102 | destroy_workqueue(qib_cq_wq); |
1124 | 1103 | ||
1125 | qib_cpulist_count = 0; | 1104 | qib_cpulist_count = 0; |
@@ -1292,7 +1271,7 @@ static int __devinit qib_init_one(struct pci_dev *pdev, | |||
1292 | 1271 | ||
1293 | if (qib_mini_init || initfail || ret) { | 1272 | if (qib_mini_init || initfail || ret) { |
1294 | qib_stop_timers(dd); | 1273 | qib_stop_timers(dd); |
1295 | flush_scheduled_work(); | 1274 | flush_workqueue(ib_wq); |
1296 | for (pidx = 0; pidx < dd->num_pports; ++pidx) | 1275 | for (pidx = 0; pidx < dd->num_pports; ++pidx) |
1297 | dd->f_quiet_serdes(dd->pport + pidx); | 1276 | dd->f_quiet_serdes(dd->pport + pidx); |
1298 | if (qib_mini_init) | 1277 | if (qib_mini_init) |
@@ -1341,8 +1320,8 @@ static void __devexit qib_remove_one(struct pci_dev *pdev) | |||
1341 | 1320 | ||
1342 | qib_stop_timers(dd); | 1321 | qib_stop_timers(dd); |
1343 | 1322 | ||
1344 | /* wait until all of our (qsfp) schedule_work() calls complete */ | 1323 | /* wait until all of our (qsfp) queue_work() calls complete */ |
1345 | flush_scheduled_work(); | 1324 | flush_workqueue(ib_wq); |
1346 | 1325 | ||
1347 | ret = qibfs_remove(dd); | 1326 | ret = qibfs_remove(dd); |
1348 | if (ret) | 1327 | if (ret) |
diff --git a/drivers/infiniband/hw/qib/qib_qsfp.c b/drivers/infiniband/hw/qib/qib_qsfp.c index 35b3604b691d..3374a52232c1 100644 --- a/drivers/infiniband/hw/qib/qib_qsfp.c +++ b/drivers/infiniband/hw/qib/qib_qsfp.c | |||
@@ -485,7 +485,7 @@ void qib_qsfp_init(struct qib_qsfp_data *qd, | |||
485 | goto bail; | 485 | goto bail; |
486 | /* We see a module, but it may be unwise to look yet. Just schedule */ | 486 | /* We see a module, but it may be unwise to look yet. Just schedule */ |
487 | qd->t_insert = get_jiffies_64(); | 487 | qd->t_insert = get_jiffies_64(); |
488 | schedule_work(&qd->work); | 488 | queue_work(ib_wq, &qd->work); |
489 | bail: | 489 | bail: |
490 | return; | 490 | return; |
491 | } | 491 | } |
@@ -493,10 +493,9 @@ bail: | |||
493 | void qib_qsfp_deinit(struct qib_qsfp_data *qd) | 493 | void qib_qsfp_deinit(struct qib_qsfp_data *qd) |
494 | { | 494 | { |
495 | /* | 495 | /* |
496 | * There is nothing to do here for now. our | 496 | * There is nothing to do here for now. our work is scheduled |
497 | * work is scheduled with schedule_work(), and | 497 | * with queue_work(), and flush_workqueue() from remove_one |
498 | * flush_scheduled_work() from remove_one will | 498 | * will block until all work setup with queue_work() |
499 | * block until all work ssetup with schedule_work() | ||
500 | * completes. | 499 | * completes. |
501 | */ | 500 | */ |
502 | } | 501 | } |
diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h index 63b22a9a7feb..95e5b47223b3 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.h +++ b/drivers/infiniband/hw/qib/qib_verbs.h | |||
@@ -805,7 +805,6 @@ static inline int qib_send_ok(struct qib_qp *qp) | |||
805 | !(qp->s_flags & QIB_S_ANY_WAIT_SEND)); | 805 | !(qp->s_flags & QIB_S_ANY_WAIT_SEND)); |
806 | } | 806 | } |
807 | 807 | ||
808 | extern struct workqueue_struct *qib_wq; | ||
809 | extern struct workqueue_struct *qib_cq_wq; | 808 | extern struct workqueue_struct *qib_cq_wq; |
810 | 809 | ||
811 | /* | 810 | /* |
@@ -814,7 +813,7 @@ extern struct workqueue_struct *qib_cq_wq; | |||
814 | static inline void qib_schedule_send(struct qib_qp *qp) | 813 | static inline void qib_schedule_send(struct qib_qp *qp) |
815 | { | 814 | { |
816 | if (qib_send_ok(qp)) | 815 | if (qib_send_ok(qp)) |
817 | queue_work(qib_wq, &qp->s_work); | 816 | queue_work(ib_wq, &qp->s_work); |
818 | } | 817 | } |
819 | 818 | ||
820 | static inline int qib_pkey_ok(u16 pkey1, u16 pkey2) | 819 | static inline int qib_pkey_ok(u16 pkey1, u16 pkey2) |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index c1c49f2d35b5..93d55806b967 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
@@ -352,15 +352,13 @@ static int ipoib_cm_nonsrq_init_rx(struct net_device *dev, struct ib_cm_id *cm_i | |||
352 | int ret; | 352 | int ret; |
353 | int i; | 353 | int i; |
354 | 354 | ||
355 | rx->rx_ring = vmalloc(ipoib_recvq_size * sizeof *rx->rx_ring); | 355 | rx->rx_ring = vzalloc(ipoib_recvq_size * sizeof *rx->rx_ring); |
356 | if (!rx->rx_ring) { | 356 | if (!rx->rx_ring) { |
357 | printk(KERN_WARNING "%s: failed to allocate CM non-SRQ ring (%d entries)\n", | 357 | printk(KERN_WARNING "%s: failed to allocate CM non-SRQ ring (%d entries)\n", |
358 | priv->ca->name, ipoib_recvq_size); | 358 | priv->ca->name, ipoib_recvq_size); |
359 | return -ENOMEM; | 359 | return -ENOMEM; |
360 | } | 360 | } |
361 | 361 | ||
362 | memset(rx->rx_ring, 0, ipoib_recvq_size * sizeof *rx->rx_ring); | ||
363 | |||
364 | t = kmalloc(sizeof *t, GFP_KERNEL); | 362 | t = kmalloc(sizeof *t, GFP_KERNEL); |
365 | if (!t) { | 363 | if (!t) { |
366 | ret = -ENOMEM; | 364 | ret = -ENOMEM; |
@@ -1097,13 +1095,12 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn, | |||
1097 | struct ipoib_dev_priv *priv = netdev_priv(p->dev); | 1095 | struct ipoib_dev_priv *priv = netdev_priv(p->dev); |
1098 | int ret; | 1096 | int ret; |
1099 | 1097 | ||
1100 | p->tx_ring = vmalloc(ipoib_sendq_size * sizeof *p->tx_ring); | 1098 | p->tx_ring = vzalloc(ipoib_sendq_size * sizeof *p->tx_ring); |
1101 | if (!p->tx_ring) { | 1099 | if (!p->tx_ring) { |
1102 | ipoib_warn(priv, "failed to allocate tx ring\n"); | 1100 | ipoib_warn(priv, "failed to allocate tx ring\n"); |
1103 | ret = -ENOMEM; | 1101 | ret = -ENOMEM; |
1104 | goto err_tx; | 1102 | goto err_tx; |
1105 | } | 1103 | } |
1106 | memset(p->tx_ring, 0, ipoib_sendq_size * sizeof *p->tx_ring); | ||
1107 | 1104 | ||
1108 | p->qp = ipoib_cm_create_tx_qp(p->dev, p); | 1105 | p->qp = ipoib_cm_create_tx_qp(p->dev, p); |
1109 | if (IS_ERR(p->qp)) { | 1106 | if (IS_ERR(p->qp)) { |
@@ -1521,7 +1518,7 @@ static void ipoib_cm_create_srq(struct net_device *dev, int max_sge) | |||
1521 | return; | 1518 | return; |
1522 | } | 1519 | } |
1523 | 1520 | ||
1524 | priv->cm.srq_ring = vmalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring); | 1521 | priv->cm.srq_ring = vzalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring); |
1525 | if (!priv->cm.srq_ring) { | 1522 | if (!priv->cm.srq_ring) { |
1526 | printk(KERN_WARNING "%s: failed to allocate CM SRQ ring (%d entries)\n", | 1523 | printk(KERN_WARNING "%s: failed to allocate CM SRQ ring (%d entries)\n", |
1527 | priv->ca->name, ipoib_recvq_size); | 1524 | priv->ca->name, ipoib_recvq_size); |
@@ -1530,7 +1527,6 @@ static void ipoib_cm_create_srq(struct net_device *dev, int max_sge) | |||
1530 | return; | 1527 | return; |
1531 | } | 1528 | } |
1532 | 1529 | ||
1533 | memset(priv->cm.srq_ring, 0, ipoib_recvq_size * sizeof *priv->cm.srq_ring); | ||
1534 | } | 1530 | } |
1535 | 1531 | ||
1536 | int ipoib_cm_dev_init(struct net_device *dev) | 1532 | int ipoib_cm_dev_init(struct net_device *dev) |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 7a07a728fe0d..aca3b44f7aed 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -916,13 +916,12 @@ int ipoib_dev_init(struct net_device *dev, struct ib_device *ca, int port) | |||
916 | goto out; | 916 | goto out; |
917 | } | 917 | } |
918 | 918 | ||
919 | priv->tx_ring = vmalloc(ipoib_sendq_size * sizeof *priv->tx_ring); | 919 | priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring); |
920 | if (!priv->tx_ring) { | 920 | if (!priv->tx_ring) { |
921 | printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", | 921 | printk(KERN_WARNING "%s: failed to allocate TX ring (%d entries)\n", |
922 | ca->name, ipoib_sendq_size); | 922 | ca->name, ipoib_sendq_size); |
923 | goto out_rx_ring_cleanup; | 923 | goto out_rx_ring_cleanup; |
924 | } | 924 | } |
925 | memset(priv->tx_ring, 0, ipoib_sendq_size * sizeof *priv->tx_ring); | ||
926 | 925 | ||
927 | /* priv->tx_head, tx_tail & tx_outstanding are already 0 */ | 926 | /* priv->tx_head, tx_tail & tx_outstanding are already 0 */ |
928 | 927 | ||
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 4b62105ed1e8..83664ed2804f 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -638,7 +638,7 @@ err: | |||
638 | if (target->state == SRP_TARGET_CONNECTING) { | 638 | if (target->state == SRP_TARGET_CONNECTING) { |
639 | target->state = SRP_TARGET_DEAD; | 639 | target->state = SRP_TARGET_DEAD; |
640 | INIT_WORK(&target->work, srp_remove_work); | 640 | INIT_WORK(&target->work, srp_remove_work); |
641 | schedule_work(&target->work); | 641 | queue_work(ib_wq, &target->work); |
642 | } | 642 | } |
643 | spin_unlock_irq(&target->lock); | 643 | spin_unlock_irq(&target->lock); |
644 | 644 | ||
@@ -1132,15 +1132,12 @@ static int srp_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmnd) | |||
1132 | 1132 | ||
1133 | spin_lock_irqsave(&target->lock, flags); | 1133 | spin_lock_irqsave(&target->lock, flags); |
1134 | iu = __srp_get_tx_iu(target, SRP_IU_CMD); | 1134 | iu = __srp_get_tx_iu(target, SRP_IU_CMD); |
1135 | if (iu) { | ||
1136 | req = list_first_entry(&target->free_reqs, struct srp_request, | ||
1137 | list); | ||
1138 | list_del(&req->list); | ||
1139 | } | ||
1140 | spin_unlock_irqrestore(&target->lock, flags); | ||
1141 | |||
1142 | if (!iu) | 1135 | if (!iu) |
1143 | goto err; | 1136 | goto err_unlock; |
1137 | |||
1138 | req = list_first_entry(&target->free_reqs, struct srp_request, list); | ||
1139 | list_del(&req->list); | ||
1140 | spin_unlock_irqrestore(&target->lock, flags); | ||
1144 | 1141 | ||
1145 | dev = target->srp_host->srp_dev->dev; | 1142 | dev = target->srp_host->srp_dev->dev; |
1146 | ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len, | 1143 | ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len, |
@@ -1185,6 +1182,8 @@ err_iu: | |||
1185 | 1182 | ||
1186 | spin_lock_irqsave(&target->lock, flags); | 1183 | spin_lock_irqsave(&target->lock, flags); |
1187 | list_add(&req->list, &target->free_reqs); | 1184 | list_add(&req->list, &target->free_reqs); |
1185 | |||
1186 | err_unlock: | ||
1188 | spin_unlock_irqrestore(&target->lock, flags); | 1187 | spin_unlock_irqrestore(&target->lock, flags); |
1189 | 1188 | ||
1190 | err: | 1189 | err: |
@@ -2199,7 +2198,7 @@ static void srp_remove_one(struct ib_device *device) | |||
2199 | * started before we marked our target ports as | 2198 | * started before we marked our target ports as |
2200 | * removed, and any target port removal tasks. | 2199 | * removed, and any target port removal tasks. |
2201 | */ | 2200 | */ |
2202 | flush_scheduled_work(); | 2201 | flush_workqueue(ib_wq); |
2203 | 2202 | ||
2204 | list_for_each_entry_safe(target, tmp_target, | 2203 | list_for_each_entry_safe(target, tmp_target, |
2205 | &host->target_list, list) { | 2204 | &host->target_list, list) { |