Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] fcoe: have fcoe log off and lport destroy before ndo_fcoe_disable

Currently fcoe interface cleanup is done after ndo_fcoe_disable
and that prevents logoff going out to the peer, so this patch
moves all netdev cleanup and its releasing inside
fcoe_interface_cleanup to have log off before ndo_fcoe_disable
disables the fcoe.

This patch also fixes asymmetric rtnl locking around fcoe_if_destroy,
as currently this function requires rtnl held by its caller
and then have this func drops the lock, instead now don't have
any processing under rtnl inside fcoe_if_destroy, this required
moving few func to get build working again.

Signed-off-by: Vasu Dev <vasu.dev@intel.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>

authored by

Vasu Dev and committed by
James Bottomley
f04ca1b6 f2817ec2

+67 -78
+67 -78
drivers/scsi/fcoe/fcoe.c
··· 381 381 } 382 382 383 383 /** 384 - * fcoe_interface_cleanup() - Clean up a FCoE interface 385 - * @fcoe: The FCoE interface to be cleaned up 386 - * 387 - * Caller must be holding the RTNL mutex 388 - */ 389 - void fcoe_interface_cleanup(struct fcoe_interface *fcoe) 390 - { 391 - struct net_device *netdev = fcoe->netdev; 392 - struct fcoe_ctlr *fip = &fcoe->ctlr; 393 - u8 flogi_maddr[ETH_ALEN]; 394 - const struct net_device_ops *ops; 395 - 396 - /* 397 - * Don't listen for Ethernet packets anymore. 398 - * synchronize_net() ensures that the packet handlers are not running 399 - * on another CPU. dev_remove_pack() would do that, this calls the 400 - * unsyncronized version __dev_remove_pack() to avoid multiple delays. 401 - */ 402 - __dev_remove_pack(&fcoe->fcoe_packet_type); 403 - __dev_remove_pack(&fcoe->fip_packet_type); 404 - synchronize_net(); 405 - 406 - /* Delete secondary MAC addresses */ 407 - memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); 408 - dev_uc_del(netdev, flogi_maddr); 409 - if (fip->spma) 410 - dev_uc_del(netdev, fip->ctl_src_addr); 411 - if (fip->mode == FIP_MODE_VN2VN) { 412 - dev_mc_del(netdev, FIP_ALL_VN2VN_MACS); 413 - dev_mc_del(netdev, FIP_ALL_P2P_MACS); 414 - } else 415 - dev_mc_del(netdev, FIP_ALL_ENODE_MACS); 416 - 417 - /* Tell the LLD we are done w/ FCoE */ 418 - ops = netdev->netdev_ops; 419 - if (ops->ndo_fcoe_disable) { 420 - if (ops->ndo_fcoe_disable(netdev)) 421 - FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE" 422 - " specific feature for LLD.\n"); 423 - } 424 - } 425 - 426 - /** 427 384 * fcoe_interface_release() - fcoe_port kref release function 428 385 * @kref: Embedded reference count in an fcoe_interface struct 429 386 */ ··· 414 457 static inline void fcoe_interface_put(struct fcoe_interface *fcoe) 415 458 { 416 459 kref_put(&fcoe->kref, fcoe_interface_release); 460 + } 461 + 462 + /** 463 + * fcoe_interface_cleanup() - Clean up a FCoE interface 464 + * @fcoe: The FCoE interface to be cleaned up 465 + * 466 + * Caller must be holding the RTNL mutex 467 + */ 468 + void fcoe_interface_cleanup(struct fcoe_interface *fcoe) 469 + { 470 + struct net_device *netdev = fcoe->netdev; 471 + struct fcoe_ctlr *fip = &fcoe->ctlr; 472 + u8 flogi_maddr[ETH_ALEN]; 473 + const struct net_device_ops *ops; 474 + struct fcoe_port *port = lport_priv(fcoe->ctlr.lp); 475 + 476 + FCOE_NETDEV_DBG(netdev, "Destroying interface\n"); 477 + 478 + /* Logout of the fabric */ 479 + fc_fabric_logoff(fcoe->ctlr.lp); 480 + 481 + /* Cleanup the fc_lport */ 482 + fc_lport_destroy(fcoe->ctlr.lp); 483 + 484 + /* Stop the transmit retry timer */ 485 + del_timer_sync(&port->timer); 486 + 487 + /* Free existing transmit skbs */ 488 + fcoe_clean_pending_queue(fcoe->ctlr.lp); 489 + 490 + /* 491 + * Don't listen for Ethernet packets anymore. 492 + * synchronize_net() ensures that the packet handlers are not running 493 + * on another CPU. dev_remove_pack() would do that, this calls the 494 + * unsyncronized version __dev_remove_pack() to avoid multiple delays. 495 + */ 496 + __dev_remove_pack(&fcoe->fcoe_packet_type); 497 + __dev_remove_pack(&fcoe->fip_packet_type); 498 + synchronize_net(); 499 + 500 + /* Delete secondary MAC addresses */ 501 + memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); 502 + dev_uc_del(netdev, flogi_maddr); 503 + if (fip->spma) 504 + dev_uc_del(netdev, fip->ctl_src_addr); 505 + if (fip->mode == FIP_MODE_VN2VN) { 506 + dev_mc_del(netdev, FIP_ALL_VN2VN_MACS); 507 + dev_mc_del(netdev, FIP_ALL_P2P_MACS); 508 + } else 509 + dev_mc_del(netdev, FIP_ALL_ENODE_MACS); 510 + 511 + if (!is_zero_ether_addr(port->data_src_addr)) 512 + dev_uc_del(netdev, port->data_src_addr); 513 + 514 + /* Tell the LLD we are done w/ FCoE */ 515 + ops = netdev->netdev_ops; 516 + if (ops->ndo_fcoe_disable) { 517 + if (ops->ndo_fcoe_disable(netdev)) 518 + FCOE_NETDEV_DBG(netdev, "Failed to disable FCoE" 519 + " specific feature for LLD.\n"); 520 + } 521 + fcoe_interface_put(fcoe); 417 522 } 418 523 419 524 /** ··· 840 821 * fcoe_if_destroy() - Tear down a SW FCoE instance 841 822 * @lport: The local port to be destroyed 842 823 * 843 - * Locking: must be called with the RTNL mutex held and RTNL mutex 844 - * needed to be dropped by this function since not dropping RTNL 845 - * would cause circular locking warning on synchronous fip worker 846 - * cancelling thru fcoe_interface_put invoked by this function. 847 - * 848 824 */ 849 825 static void fcoe_if_destroy(struct fc_lport *lport) 850 826 { 851 - struct fcoe_port *port = lport_priv(lport); 852 - struct fcoe_interface *fcoe = port->priv; 853 - struct net_device *netdev = fcoe->netdev; 854 - 855 - FCOE_NETDEV_DBG(netdev, "Destroying interface\n"); 856 - 857 - /* Logout of the fabric */ 858 - fc_fabric_logoff(lport); 859 - 860 - /* Cleanup the fc_lport */ 861 - fc_lport_destroy(lport); 862 - 863 - /* Stop the transmit retry timer */ 864 - del_timer_sync(&port->timer); 865 - 866 - /* Free existing transmit skbs */ 867 - fcoe_clean_pending_queue(lport); 868 - 869 - if (!is_zero_ether_addr(port->data_src_addr)) 870 - dev_uc_del(netdev, port->data_src_addr); 871 - rtnl_unlock(); 872 - 873 - /* receives may not be stopped until after this */ 874 - fcoe_interface_put(fcoe); 875 - 876 827 /* Free queued packets for the per-CPU receive threads */ 877 828 fcoe_percpu_clean(lport); 878 829 ··· 1825 1836 static int fcoe_destroy(struct net_device *netdev) 1826 1837 { 1827 1838 struct fcoe_interface *fcoe; 1839 + struct fc_lport *lport; 1828 1840 int rc = 0; 1829 1841 1830 1842 mutex_lock(&fcoe_config_mutex); ··· 1836 1846 rc = -ENODEV; 1837 1847 goto out_nodev; 1838 1848 } 1839 - fcoe_interface_cleanup(fcoe); 1849 + lport = fcoe->ctlr.lp; 1840 1850 list_del(&fcoe->list); 1841 - /* RTNL mutex is dropped by fcoe_if_destroy */ 1842 - fcoe_if_destroy(fcoe->ctlr.lp); 1851 + fcoe_interface_cleanup(fcoe); 1852 + rtnl_unlock(); 1853 + fcoe_if_destroy(lport); 1843 1854 out_nodev: 1844 1855 mutex_unlock(&fcoe_config_mutex); 1845 1856 return rc; ··· 1856 1865 1857 1866 port = container_of(work, struct fcoe_port, destroy_work); 1858 1867 mutex_lock(&fcoe_config_mutex); 1859 - rtnl_lock(); 1860 - /* RTNL mutex is dropped by fcoe_if_destroy */ 1861 1868 fcoe_if_destroy(port->lport); 1862 1869 mutex_unlock(&fcoe_config_mutex); 1863 1870 }