Exemple #1
0
static void __devexit fnic_remove(struct pci_dev *pdev)
{
	struct fnic *fnic = pci_get_drvdata(pdev);
	unsigned long flags;

	
	spin_lock_irqsave(&fnic->fnic_lock, flags);
	fnic->stop_rx_link_events = 1;
	spin_unlock_irqrestore(&fnic->fnic_lock, flags);

	if (vnic_dev_get_intr_mode(fnic->vdev) == VNIC_DEV_INTR_MODE_MSI)
		del_timer_sync(&fnic->notify_timer);

	
	flush_workqueue(fnic_event_queue);
	skb_queue_purge(&fnic->frame_queue);

	
	fc_fabric_logoff(fnic->lport);

	spin_lock_irqsave(&fnic->fnic_lock, flags);
	fnic->in_remove = 1;
	spin_unlock_irqrestore(&fnic->fnic_lock, flags);

	fc_lport_destroy(fnic->lport);

	
	fnic_cleanup(fnic);

	BUG_ON(!skb_queue_empty(&fnic->frame_queue));

	spin_lock_irqsave(&fnic_list_lock, flags);
	list_del(&fnic->list);
	spin_unlock_irqrestore(&fnic_list_lock, flags);

	fc_remove_host(fnic->lport->host);
	scsi_remove_host(fnic->lport->host);
	fc_exch_mgr_free(fnic->lport);
	vnic_dev_notify_unset(fnic->vdev);
	fnic_free_vnic_resources(fnic);
	fnic_free_intr(fnic);
	fnic_clear_intr_mode(fnic);
	vnic_dev_close(fnic->vdev);
	vnic_dev_unregister(fnic->vdev);
	fnic_iounmap(fnic);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);
	scsi_host_put(fnic->lport->host);
}
Exemple #2
0
static void fnic_remove(struct pci_dev *pdev)
{
	struct fnic *fnic = pci_get_drvdata(pdev);
	struct fc_lport *lp = fnic->lport;
	unsigned long flags;

	/*
	 * Mark state so that the workqueue thread stops forwarding
	 * received frames and link events to the local port. ISR and
	 * other threads that can queue work items will also stop
	 * creating work items on the fnic workqueue
	 */
	spin_lock_irqsave(&fnic->fnic_lock, flags);
	fnic->stop_rx_link_events = 1;
	spin_unlock_irqrestore(&fnic->fnic_lock, flags);

	if (vnic_dev_get_intr_mode(fnic->vdev) == VNIC_DEV_INTR_MODE_MSI)
		del_timer_sync(&fnic->notify_timer);

	/*
	 * Flush the fnic event queue. After this call, there should
	 * be no event queued for this fnic device in the workqueue
	 */
	flush_workqueue(fnic_event_queue);
	skb_queue_purge(&fnic->frame_queue);
	skb_queue_purge(&fnic->tx_queue);

	if (fnic->config.flags & VFCF_FIP_CAPABLE) {
		del_timer_sync(&fnic->fip_timer);
		skb_queue_purge(&fnic->fip_frame_queue);
		fnic_fcoe_reset_vlans(fnic);
		fnic_fcoe_evlist_free(fnic);
	}

	/*
	 * Log off the fabric. This stops all remote ports, dns port,
	 * logs off the fabric. This flushes all rport, disc, lport work
	 * before returning
	 */
	fc_fabric_logoff(fnic->lport);

	spin_lock_irqsave(&fnic->fnic_lock, flags);
	fnic->in_remove = 1;
	spin_unlock_irqrestore(&fnic->fnic_lock, flags);

	fcoe_ctlr_destroy(&fnic->ctlr);
	fc_lport_destroy(lp);
	fnic_stats_debugfs_remove(fnic);

	/*
	 * This stops the fnic device, masks all interrupts. Completed
	 * CQ entries are drained. Posted WQ/RQ/Copy-WQ entries are
	 * cleaned up
	 */
	fnic_cleanup(fnic);

	BUG_ON(!skb_queue_empty(&fnic->frame_queue));
	BUG_ON(!skb_queue_empty(&fnic->tx_queue));

	spin_lock_irqsave(&fnic_list_lock, flags);
	list_del(&fnic->list);
	spin_unlock_irqrestore(&fnic_list_lock, flags);

	fc_remove_host(fnic->lport->host);
	scsi_remove_host(fnic->lport->host);
	fc_exch_mgr_free(fnic->lport);
	vnic_dev_notify_unset(fnic->vdev);
	fnic_free_intr(fnic);
	fnic_free_vnic_resources(fnic);
	fnic_clear_intr_mode(fnic);
	vnic_dev_close(fnic->vdev);
	vnic_dev_unregister(fnic->vdev);
	fnic_iounmap(fnic);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
	scsi_host_put(lp->host);
}
Exemple #3
0
/*
 * fcoe_sw_destroy - FCoE software HBA tear-down function
 * @netdev: ptr to the associated net_device
 *
 * Returns: 0 if link is OK for use by FCoE.
 */
static int fcoe_sw_destroy(struct net_device *netdev)
{
	int cpu;
	struct fc_lport *lp = NULL;
	struct fcoe_softc *fc;
	u8 flogi_maddr[ETH_ALEN];

	BUG_ON(!netdev);

	printk(KERN_DEBUG "fcoe_sw_destroy:interface on %s\n",
	       netdev->name);

	lp = fcoe_hostlist_lookup(netdev);
	if (!lp)
		return -ENODEV;

	fc = fcoe_softc(lp);

	/* Logout of the fabric */
	fc_fabric_logoff(lp);

	/* Remove the instance from fcoe's list */
	fcoe_hostlist_remove(lp);

	/* Don't listen for Ethernet packets anymore */
	dev_remove_pack(&fc->fcoe_packet_type);

	/* Cleanup the fc_lport */
	fc_lport_destroy(lp);
	fc_fcp_destroy(lp);

	/* Detach from the scsi-ml */
	fc_remove_host(lp->host);
	scsi_remove_host(lp->host);

	/* There are no more rports or I/O, free the EM */
	if (lp->emp)
		fc_exch_mgr_free(lp->emp);

	/* Delete secondary MAC addresses */
	rtnl_lock();
	memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
	dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN);
	if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
		dev_unicast_delete(fc->real_dev, fc->data_src_addr, ETH_ALEN);
	rtnl_unlock();

	/* Free the per-CPU revieve threads */
	fcoe_percpu_clean(lp);

	/* Free existing skbs */
	fcoe_clean_pending_queue(lp);

	/* Free memory used by statistical counters */
	for_each_online_cpu(cpu)
		kfree(lp->dev_stats[cpu]);

	/* Release the net_device and Scsi_Host */
	dev_put(fc->real_dev);
	scsi_host_put(lp->host);

	return 0;
}