diff options
31 files changed, 316 insertions, 117 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/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 dbbb0e85afe4..ea46fbc34b17 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) { |
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index e04c4888d1fd..55cd0a0bc977 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h | |||
| @@ -47,10 +47,13 @@ | |||
| 47 | #include <linux/list.h> | 47 | #include <linux/list.h> |
| 48 | #include <linux/rwsem.h> | 48 | #include <linux/rwsem.h> |
| 49 | #include <linux/scatterlist.h> | 49 | #include <linux/scatterlist.h> |
| 50 | #include <linux/workqueue.h> | ||
| 50 | 51 | ||
| 51 | #include <asm/atomic.h> | 52 | #include <asm/atomic.h> |
| 52 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
| 53 | 54 | ||
| 55 | extern struct workqueue_struct *ib_wq; | ||
| 56 | |||
| 54 | union ib_gid { | 57 | union ib_gid { |
| 55 | u8 raw[16]; | 58 | u8 raw[16]; |
| 56 | struct { | 59 | struct { |
