diff options
Diffstat (limited to 'drivers/scsi/fcoe/fcoe.c')
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 7022a16b14f6..4834d3c130d6 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -74,6 +74,7 @@ static int fcoe_rcv(struct sk_buff *, struct net_device *, | |||
74 | static int fcoe_percpu_receive_thread(void *); | 74 | static int fcoe_percpu_receive_thread(void *); |
75 | static void fcoe_clean_pending_queue(struct fc_lport *); | 75 | static void fcoe_clean_pending_queue(struct fc_lport *); |
76 | static void fcoe_percpu_clean(struct fc_lport *); | 76 | static void fcoe_percpu_clean(struct fc_lport *); |
77 | static int fcoe_link_speed_update(struct fc_lport *); | ||
77 | static int fcoe_link_ok(struct fc_lport *); | 78 | static int fcoe_link_ok(struct fc_lport *); |
78 | 79 | ||
79 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); | 80 | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); |
@@ -631,6 +632,8 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) | |||
631 | port->fcoe_pending_queue_active = 0; | 632 | port->fcoe_pending_queue_active = 0; |
632 | setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport); | 633 | setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport); |
633 | 634 | ||
635 | fcoe_link_speed_update(lport); | ||
636 | |||
634 | if (!lport->vport) { | 637 | if (!lport->vport) { |
635 | /* | 638 | /* |
636 | * Use NAA 1&2 (FC-FS Rev. 2.0, Sec. 15) to generate WWNN/WWPN: | 639 | * Use NAA 1&2 (FC-FS Rev. 2.0, Sec. 15) to generate WWNN/WWPN: |
@@ -1829,6 +1832,9 @@ static int fcoe_device_notification(struct notifier_block *notifier, | |||
1829 | FCOE_NETDEV_DBG(netdev, "Unknown event %ld " | 1832 | FCOE_NETDEV_DBG(netdev, "Unknown event %ld " |
1830 | "from netdev netlink\n", event); | 1833 | "from netdev netlink\n", event); |
1831 | } | 1834 | } |
1835 | |||
1836 | fcoe_link_speed_update(lport); | ||
1837 | |||
1832 | if (link_possible && !fcoe_link_ok(lport)) | 1838 | if (link_possible && !fcoe_link_ok(lport)) |
1833 | fcoe_ctlr_link_up(&fcoe->ctlr); | 1839 | fcoe_ctlr_link_up(&fcoe->ctlr); |
1834 | else if (fcoe_ctlr_link_down(&fcoe->ctlr)) { | 1840 | else if (fcoe_ctlr_link_down(&fcoe->ctlr)) { |
@@ -2128,26 +2134,19 @@ out_nomod: | |||
2128 | } | 2134 | } |
2129 | 2135 | ||
2130 | /** | 2136 | /** |
2131 | * fcoe_link_ok() - Check if the link is OK for a local port | 2137 | * fcoe_link_speed_update() - Update the supported and actual link speeds |
2132 | * @lport: The local port to check link on | 2138 | * @lport: The local port to update speeds for |
2133 | * | ||
2134 | * Any permanently-disqualifying conditions have been previously checked. | ||
2135 | * This also updates the speed setting, which may change with link for 100/1000. | ||
2136 | * | ||
2137 | * This function should probably be checking for PAUSE support at some point | ||
2138 | * in the future. Currently Per-priority-pause is not determinable using | ||
2139 | * ethtool, so we shouldn't be restrictive until that problem is resolved. | ||
2140 | * | ||
2141 | * Returns: 0 if link is OK for use by FCoE. | ||
2142 | * | 2139 | * |
2140 | * Returns: 0 if the ethtool query was successful | ||
2141 | * -1 if the ethtool query failed | ||
2143 | */ | 2142 | */ |
2144 | int fcoe_link_ok(struct fc_lport *lport) | 2143 | int fcoe_link_speed_update(struct fc_lport *lport) |
2145 | { | 2144 | { |
2146 | struct fcoe_port *port = lport_priv(lport); | 2145 | struct fcoe_port *port = lport_priv(lport); |
2147 | struct net_device *netdev = port->fcoe->netdev; | 2146 | struct net_device *netdev = port->fcoe->netdev; |
2148 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; | 2147 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; |
2149 | 2148 | ||
2150 | if (netif_oper_up(netdev) && !dev_ethtool_get_settings(netdev, &ecmd)) { | 2149 | if (!dev_ethtool_get_settings(netdev, &ecmd)) { |
2151 | lport->link_supported_speeds &= | 2150 | lport->link_supported_speeds &= |
2152 | ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); | 2151 | ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); |
2153 | if (ecmd.supported & (SUPPORTED_1000baseT_Half | | 2152 | if (ecmd.supported & (SUPPORTED_1000baseT_Half | |
@@ -2167,6 +2166,23 @@ int fcoe_link_ok(struct fc_lport *lport) | |||
2167 | } | 2166 | } |
2168 | 2167 | ||
2169 | /** | 2168 | /** |
2169 | * fcoe_link_ok() - Check if the link is OK for a local port | ||
2170 | * @lport: The local port to check link on | ||
2171 | * | ||
2172 | * Returns: 0 if link is UP and OK, -1 if not | ||
2173 | * | ||
2174 | */ | ||
2175 | int fcoe_link_ok(struct fc_lport *lport) | ||
2176 | { | ||
2177 | struct fcoe_port *port = lport_priv(lport); | ||
2178 | struct net_device *netdev = port->fcoe->netdev; | ||
2179 | |||
2180 | if (netif_oper_up(netdev)) | ||
2181 | return 0; | ||
2182 | return -1; | ||
2183 | } | ||
2184 | |||
2185 | /** | ||
2170 | * fcoe_percpu_clean() - Clear all pending skbs for an local port | 2186 | * fcoe_percpu_clean() - Clear all pending skbs for an local port |
2171 | * @lport: The local port whose skbs are to be cleared | 2187 | * @lport: The local port whose skbs are to be cleared |
2172 | * | 2188 | * |