diff options
Diffstat (limited to 'drivers/infiniband/hw/ocrdma/ocrdma_main.c')
| -rw-r--r-- | drivers/infiniband/hw/ocrdma/ocrdma_main.c | 64 | 
1 files changed, 34 insertions, 30 deletions
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c index a20d16eaae7..b050e629e9c 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c @@ -26,7 +26,6 @@   *******************************************************************/  #include <linux/module.h> -#include <linux/version.h>  #include <linux/idr.h>  #include <rdma/ib_verbs.h>  #include <rdma/ib_user_verbs.h> @@ -98,13 +97,11 @@ static void ocrdma_build_sgid_mac(union ib_gid *sgid, unsigned char *mac_addr,  	sgid->raw[15] = mac_addr[5];  } -static void ocrdma_add_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr, +static bool ocrdma_add_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr,  			    bool is_vlan, u16 vlan_id)  {  	int i; -	bool found = false;  	union ib_gid new_sgid; -	int free_idx = OCRDMA_MAX_SGID;  	unsigned long flags;  	memset(&ocrdma_zero_sgid, 0, sizeof(union ib_gid)); @@ -116,23 +113,19 @@ static void ocrdma_add_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr,  		if (!memcmp(&dev->sgid_tbl[i], &ocrdma_zero_sgid,  			    sizeof(union ib_gid))) {  			/* found free entry */ -			if (!found) { -				free_idx = i; -				found = true; -				break; -			} +			memcpy(&dev->sgid_tbl[i], &new_sgid, +			       sizeof(union ib_gid)); +			spin_unlock_irqrestore(&dev->sgid_lock, flags); +			return true;  		} else if (!memcmp(&dev->sgid_tbl[i], &new_sgid,  				   sizeof(union ib_gid))) {  			/* entry already present, no addition is required. */  			spin_unlock_irqrestore(&dev->sgid_lock, flags); -			return; +			return false;  		}  	} -	/* if entry doesn't exist and if table has some space, add entry */ -	if (found) -		memcpy(&dev->sgid_tbl[free_idx], &new_sgid, -		       sizeof(union ib_gid));  	spin_unlock_irqrestore(&dev->sgid_lock, flags); +	return false;  }  static bool ocrdma_del_sgid(struct ocrdma_dev *dev, unsigned char *mac_addr, @@ -168,7 +161,8 @@ static void ocrdma_add_default_sgid(struct ocrdma_dev *dev)  	ocrdma_get_guid(dev, &sgid->raw[8]);  } -static int ocrdma_build_sgid_tbl(struct ocrdma_dev *dev) +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) +static void ocrdma_add_vlan_sgids(struct ocrdma_dev *dev)  {  	struct net_device *netdev, *tmp;  	u16 vlan_id; @@ -176,8 +170,6 @@ static int ocrdma_build_sgid_tbl(struct ocrdma_dev *dev)  	netdev = dev->nic_info.netdev; -	ocrdma_add_default_sgid(dev); -  	rcu_read_lock();  	for_each_netdev_rcu(&init_net, tmp) {  		if (netdev == tmp || vlan_dev_real_dev(tmp) == netdev) { @@ -195,10 +187,23 @@ static int ocrdma_build_sgid_tbl(struct ocrdma_dev *dev)  		}  	}  	rcu_read_unlock(); +} +#else +static void ocrdma_add_vlan_sgids(struct ocrdma_dev *dev) +{ + +} +#endif /* VLAN */ + +static int ocrdma_build_sgid_tbl(struct ocrdma_dev *dev) +{ +	ocrdma_add_default_sgid(dev); +	ocrdma_add_vlan_sgids(dev);  	return 0;  } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) || \ +defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)  static int ocrdma_inet6addr_event(struct notifier_block *notifier,  				  unsigned long event, void *ptr) @@ -209,6 +214,7 @@ static int ocrdma_inet6addr_event(struct notifier_block *notifier,  	struct ib_event gid_event;  	struct ocrdma_dev *dev;  	bool found = false; +	bool updated = false;  	bool is_vlan = false;  	u16 vid = 0; @@ -234,23 +240,21 @@ static int ocrdma_inet6addr_event(struct notifier_block *notifier,  	mutex_lock(&dev->dev_lock);  	switch (event) {  	case NETDEV_UP: -		ocrdma_add_sgid(dev, netdev->dev_addr, is_vlan, vid); +		updated = ocrdma_add_sgid(dev, netdev->dev_addr, is_vlan, vid);  		break;  	case NETDEV_DOWN: -		found = ocrdma_del_sgid(dev, netdev->dev_addr, is_vlan, vid); -		if (found) { -			/* found the matching entry, notify -			 * the consumers about it -			 */ -			gid_event.device = &dev->ibdev; -			gid_event.element.port_num = 1; -			gid_event.event = IB_EVENT_GID_CHANGE; -			ib_dispatch_event(&gid_event); -		} +		updated = ocrdma_del_sgid(dev, netdev->dev_addr, is_vlan, vid);  		break;  	default:  		break;  	} +	if (updated) { +		/* GID table updated, notify the consumers about it */ +		gid_event.device = &dev->ibdev; +		gid_event.element.port_num = 1; +		gid_event.event = IB_EVENT_GID_CHANGE; +		ib_dispatch_event(&gid_event); +	}  	mutex_unlock(&dev->dev_lock);  	return NOTIFY_OK;  } @@ -259,7 +263,7 @@ static struct notifier_block ocrdma_inet6addr_notifier = {  	.notifier_call = ocrdma_inet6addr_event  }; -#endif /* IPV6 */ +#endif /* IPV6 and VLAN */  static enum rdma_link_layer ocrdma_link_layer(struct ib_device *device,  					      u8 port_num)  |