Skip to content

Commit

Permalink
[SCSI] bfa: vport fixes
Browse files Browse the repository at this point in the history
This patch fixes 3 bugs in vport create/delete.
1) Replace scsi_add_host() with scsi_add_host_with_dma()
2) Fix rmmod hang when there are vports configured. This is due to a race
condition between the workqueue destroy in pci remove context and the vport
delete works being handled. The fix is to use a counter to track the
vport delete work, so that workqueue destroy will not be called until all
configured vports are deleted from workqueue.
3) Fix rmmmod crash when there are PBC vport configured. PBC is not allowed
to be deleted dynamically. However, if someone try to delete it, it leaves the
vport is wrong state. The fix is to restore the vport back to original state
when the attempt to delete pbc vport delete is failed.

Signed-off-by: Jing Huang <huangj@brocade.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
  • Loading branch information
Jing Huang authored and James Bottomley committed Jul 27, 2010
1 parent 8a4adf1 commit c54d557
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 3 deletions.
5 changes: 4 additions & 1 deletion drivers/scsi/bfa/bfad_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/bfa/bfad_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
15 changes: 13 additions & 2 deletions drivers/scsi/bfa/bfad_im.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit c54d557

Please sign in to comment.