diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 871a30363560b6d9d5de8733f5325b5ec0122ece..0818eb07ef884cffabc7f14e93965d4a2a796cd3 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -473,8 +473,11 @@ bfad_im_vport_delete(struct fc_vport *fc_vport) rc = bfa_fcs_vport_delete(&vport->fcs_vport); spin_unlock_irqrestore(&bfad->bfad_lock, flags); - if (rc == BFA_STATUS_PBC) + if (rc == BFA_STATUS_PBC) { + vport->drv_port.flags &= ~BFAD_PORT_DELETE; + vport->comp_del = NULL; return -1; + } wait_for_completion(vport->comp_del); diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h index 8629f64a52871486ec88c51509dc9cf9af0e5d72..dcf28830feef4be6960ae505d42ae76e9cda90ef 100644 --- a/drivers/scsi/bfa/bfad_drv.h +++ b/drivers/scsi/bfa/bfad_drv.h @@ -185,6 +185,7 @@ struct bfad_s { bfa_boolean_t ipfc_enabled; struct fc_host_statistics link_stats; struct list_head pbc_pcfg_list; + atomic_t wq_reqcnt; }; struct bfad_pcfg_s { diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index ffbec9ba21b778166272356cd0327c52e0792290..678120b704600eff512a17f0689702fd9b838045 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -554,7 +554,7 @@ bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port, im_port->shost->transportt = bfad_im_scsi_vport_transport_template; - error = scsi_add_host(im_port->shost, dev); + error = scsi_add_host_with_dma(im_port->shost, dev, &bfad->pcidev->dev); if (error) { printk(KERN_WARNING "scsi_add_host failure %d\n", error); goto out_fc_rel; @@ -598,10 +598,12 @@ bfad_im_port_delete_handler(struct work_struct *work) { struct bfad_im_port_s *im_port = container_of(work, struct bfad_im_port_s, port_delete_work); + struct bfad_s *bfad = im_port->bfad; if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) { im_port->flags |= BFAD_PORT_DELETE; fc_vport_terminate(im_port->fc_vport); + atomic_dec(&bfad->wq_reqcnt); } } @@ -634,8 +636,11 @@ bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port) { struct bfad_im_port_s *im_port = port->im_port; - queue_work(bfad->im->drv_workq, + if (im_port->port->pvb_type != BFAD_PORT_PHYS_BASE) { + atomic_inc(&bfad->wq_reqcnt); + queue_work(bfad->im->drv_workq, &im_port->port_delete_work); + } } void @@ -696,6 +701,12 @@ void bfad_im_probe_undo(struct bfad_s *bfad) { if (bfad->im) { + while (atomic_read(&bfad->wq_reqcnt)) { + printk(KERN_INFO "bfa %s: waiting workq processing," + " wq_reqcnt:%x\n", bfad->pci_name, + atomic_read(&bfad->wq_reqcnt)); + schedule_timeout_uninterruptible(HZ); + } bfad_os_destroy_workq(bfad->im); kfree(bfad->im); bfad->im = NULL;