Commit 54a5b21d authored by Yi Zou's avatar Yi Zou Committed by James Bottomley

[SCSI] fcoe: fix offload feature flag change from netdev

Currently, when FCoE netdev feature flags are toggled by the LLD, lport's
corresponding flags are not updated. This causes the fc_fcp to still try to
offload the I/O. This patch adds support of NETDEV_FEAT_CHANGE event in fcoe
netdev device notification callback so we can update the lport offload flags
appropriately.
Signed-off-by: default avatarYi Zou <yi.zou@intel.com>
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 92261156
...@@ -588,6 +588,50 @@ static int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type) ...@@ -588,6 +588,50 @@ static int fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
return -EINVAL; return -EINVAL;
} }
/**
* fcoe_netdev_features_change - Updates the lport's offload flags based
* on the LLD netdev's FCoE feature flags
*/
static void fcoe_netdev_features_change(struct fc_lport *lport,
struct net_device *netdev)
{
mutex_lock(&lport->lp_mutex);
if (netdev->features & NETIF_F_SG)
lport->sg_supp = 1;
else
lport->sg_supp = 0;
if (netdev->features & NETIF_F_FCOE_CRC) {
lport->crc_offload = 1;
FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n");
} else {
lport->crc_offload = 0;
}
if (netdev->features & NETIF_F_FSO) {
lport->seq_offload = 1;
lport->lso_max = netdev->gso_max_size;
FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n",
lport->lso_max);
} else {
lport->seq_offload = 0;
lport->lso_max = 0;
}
if (netdev->fcoe_ddp_xid) {
lport->lro_enabled = 1;
lport->lro_xid = netdev->fcoe_ddp_xid;
FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n",
lport->lro_xid);
} else {
lport->lro_enabled = 0;
lport->lro_xid = 0;
}
mutex_unlock(&lport->lp_mutex);
}
/** /**
* fcoe_netdev_config() - Set up net devive for SW FCoE * fcoe_netdev_config() - Set up net devive for SW FCoE
* @lport: The local port that is associated with the net device * @lport: The local port that is associated with the net device
...@@ -624,25 +668,8 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) ...@@ -624,25 +668,8 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
return -EINVAL; return -EINVAL;
/* offload features support */ /* offload features support */
if (netdev->features & NETIF_F_SG) fcoe_netdev_features_change(lport, netdev);
lport->sg_supp = 1;
if (netdev->features & NETIF_F_FCOE_CRC) {
lport->crc_offload = 1;
FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n");
}
if (netdev->features & NETIF_F_FSO) {
lport->seq_offload = 1;
lport->lso_max = netdev->gso_max_size;
FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n",
lport->lso_max);
}
if (netdev->fcoe_ddp_xid) {
lport->lro_enabled = 1;
lport->lro_xid = netdev->fcoe_ddp_xid;
FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n",
lport->lro_xid);
}
skb_queue_head_init(&port->fcoe_pending_queue); skb_queue_head_init(&port->fcoe_pending_queue);
port->fcoe_pending_queue_active = 0; port->fcoe_pending_queue_active = 0;
setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport); setup_timer(&port->timer, fcoe_queue_timer, (unsigned long)lport);
...@@ -1861,6 +1888,9 @@ static int fcoe_device_notification(struct notifier_block *notifier, ...@@ -1861,6 +1888,9 @@ static int fcoe_device_notification(struct notifier_block *notifier,
schedule_work(&port->destroy_work); schedule_work(&port->destroy_work);
goto out; goto out;
break; break;
case NETDEV_FEAT_CHANGE:
fcoe_netdev_features_change(lport, netdev);
break;
default: default:
FCOE_NETDEV_DBG(netdev, "Unknown event %ld " FCOE_NETDEV_DBG(netdev, "Unknown event %ld "
"from netdev netlink\n", event); "from netdev netlink\n", event);
...@@ -2056,8 +2086,8 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) ...@@ -2056,8 +2086,8 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
rc = -ENODEV; rc = -ENODEV;
goto out_putdev; goto out_putdev;
} }
list_del(&fcoe->list);
fcoe_interface_cleanup(fcoe); fcoe_interface_cleanup(fcoe);
list_del(&fcoe->list);
/* RTNL mutex is dropped by fcoe_if_destroy */ /* RTNL mutex is dropped by fcoe_if_destroy */
fcoe_if_destroy(fcoe->ctlr.lp); fcoe_if_destroy(fcoe->ctlr.lp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment