diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic')
| -rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic.h | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 220 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qla3xxx.c | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 166 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 26 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 33 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 55 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 14 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 7 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 28 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 255 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qlge/qlge_main.c | 6 | 
15 files changed, 636 insertions, 193 deletions
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h index eb3dfdbb642..322a36b7672 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h @@ -955,9 +955,10 @@ typedef struct nx_mac_list_s {  	uint8_t mac_addr[ETH_ALEN+2];  } nx_mac_list_t; -struct nx_vlan_ip_list { +struct nx_ip_list {  	struct list_head list;  	__be32 ip_addr; +	bool master;  };  /* @@ -1605,7 +1606,7 @@ struct netxen_adapter {  	struct net_device *netdev;  	struct pci_dev *pdev;  	struct list_head mac_list; -	struct list_head vlan_ip_list; +	struct list_head ip_list;  	spinlock_t tx_clean_lock; diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index 4782dcfde73..7692dfd4f26 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -27,6 +27,7 @@  #include <linux/delay.h>  #include <linux/slab.h>  #include <linux/if_vlan.h> +#include <net/checksum.h>  #include "netxen_nic.h"  #include "netxen_nic_hw.h" @@ -1641,9 +1642,8 @@ netxen_process_lro(struct netxen_adapter *adapter,  	th = (struct tcphdr *)((skb->data + vhdr_len) + (iph->ihl << 2));  	length = (iph->ihl << 2) + (th->doff << 2) + lro_length; +	csum_replace2(&iph->check, iph->tot_len, htons(length));  	iph->tot_len = htons(length); -	iph->check = 0; -	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);  	th->psh = push;  	th->seq = htonl(seq_number); diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 501f49207da..7867aebc05f 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -90,7 +90,7 @@ static irqreturn_t netxen_intr(int irq, void *data);  static irqreturn_t netxen_msi_intr(int irq, void *data);  static irqreturn_t netxen_msix_intr(int irq, void *data); -static void netxen_free_vlan_ip_list(struct netxen_adapter *); +static void netxen_free_ip_list(struct netxen_adapter *, bool);  static void netxen_restore_indev_addr(struct net_device *dev, unsigned long);  static struct rtnl_link_stats64 *netxen_nic_get_stats(struct net_device *dev,  						      struct rtnl_link_stats64 *stats); @@ -1450,7 +1450,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	spin_lock_init(&adapter->tx_clean_lock);  	INIT_LIST_HEAD(&adapter->mac_list); -	INIT_LIST_HEAD(&adapter->vlan_ip_list); +	INIT_LIST_HEAD(&adapter->ip_list);  	err = netxen_setup_pci_map(adapter);  	if (err) @@ -1585,7 +1585,7 @@ static void netxen_nic_remove(struct pci_dev *pdev)  	cancel_work_sync(&adapter->tx_timeout_task); -	netxen_free_vlan_ip_list(adapter); +	netxen_free_ip_list(adapter, false);  	netxen_nic_detach(adapter);  	nx_decr_dev_ref_cnt(adapter); @@ -3137,62 +3137,77 @@ netxen_destip_supported(struct netxen_adapter *adapter)  }  static void -netxen_free_vlan_ip_list(struct netxen_adapter *adapter) +netxen_free_ip_list(struct netxen_adapter *adapter, bool master)  { -	struct nx_vlan_ip_list  *cur; -	struct list_head *head = &adapter->vlan_ip_list; +	struct nx_ip_list  *cur, *tmp_cur; -	while (!list_empty(head)) { -		cur = list_entry(head->next, struct nx_vlan_ip_list, list); -		netxen_config_ipaddr(adapter, cur->ip_addr, NX_IP_DOWN); -		list_del(&cur->list); -		kfree(cur); +	list_for_each_entry_safe(cur, tmp_cur, &adapter->ip_list, list) { +		if (master) { +			if (cur->master) { +				netxen_config_ipaddr(adapter, cur->ip_addr, +						     NX_IP_DOWN); +				list_del(&cur->list); +				kfree(cur); +			} +		} else { +			netxen_config_ipaddr(adapter, cur->ip_addr, NX_IP_DOWN); +			list_del(&cur->list); +			kfree(cur); +		}  	} -  } -static void -netxen_list_config_vlan_ip(struct netxen_adapter *adapter, + +static bool +netxen_list_config_ip(struct netxen_adapter *adapter,  		struct in_ifaddr *ifa, unsigned long event)  {  	struct net_device *dev; -	struct nx_vlan_ip_list *cur, *tmp_cur; +	struct nx_ip_list *cur, *tmp_cur;  	struct list_head *head; +	bool ret = false;  	dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;  	if (dev == NULL) -		return; - -	if (!is_vlan_dev(dev)) -		return; +		goto out;  	switch (event) {  	case NX_IP_UP: -		list_for_each(head, &adapter->vlan_ip_list) { -			cur = list_entry(head, struct nx_vlan_ip_list, list); +		list_for_each(head, &adapter->ip_list) { +			cur = list_entry(head, struct nx_ip_list, list);  			if (cur->ip_addr == ifa->ifa_address) -				return; +				goto out;  		} -		cur = kzalloc(sizeof(struct nx_vlan_ip_list), GFP_ATOMIC); +		cur = kzalloc(sizeof(struct nx_ip_list), GFP_ATOMIC);  		if (cur == NULL) -			return; - +			goto out; +		if (dev->priv_flags & IFF_802_1Q_VLAN) +			dev = vlan_dev_real_dev(dev); +		cur->master = !!netif_is_bond_master(dev);  		cur->ip_addr = ifa->ifa_address; -		list_add_tail(&cur->list, &adapter->vlan_ip_list); +		list_add_tail(&cur->list, &adapter->ip_list); +		netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP); +		ret = true;  		break;  	case NX_IP_DOWN:  		list_for_each_entry_safe(cur, tmp_cur, -					&adapter->vlan_ip_list, list) { +					&adapter->ip_list, list) {  			if (cur->ip_addr == ifa->ifa_address) {  				list_del(&cur->list);  				kfree(cur); +				netxen_config_ipaddr(adapter, ifa->ifa_address, +						     NX_IP_DOWN); +				ret = true;  				break;  			}  		}  	} +out: +	return ret;  } +  static void  netxen_config_indev_addr(struct netxen_adapter *adapter,  		struct net_device *dev, unsigned long event) @@ -3209,14 +3224,10 @@ netxen_config_indev_addr(struct netxen_adapter *adapter,  	for_ifa(indev) {  		switch (event) {  		case NETDEV_UP: -			netxen_config_ipaddr(adapter, -					ifa->ifa_address, NX_IP_UP); -			netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP); +			netxen_list_config_ip(adapter, ifa, NX_IP_UP);  			break;  		case NETDEV_DOWN: -			netxen_config_ipaddr(adapter, -					ifa->ifa_address, NX_IP_DOWN); -			netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN); +			netxen_list_config_ip(adapter, ifa, NX_IP_DOWN);  			break;  		default:  			break; @@ -3231,23 +3242,78 @@ netxen_restore_indev_addr(struct net_device *netdev, unsigned long event)  {  	struct netxen_adapter *adapter = netdev_priv(netdev); -	struct nx_vlan_ip_list *pos, *tmp_pos; +	struct nx_ip_list *pos, *tmp_pos;  	unsigned long ip_event;  	ip_event = (event == NETDEV_UP) ? NX_IP_UP : NX_IP_DOWN;  	netxen_config_indev_addr(adapter, netdev, event); -	list_for_each_entry_safe(pos, tmp_pos, &adapter->vlan_ip_list, list) { +	list_for_each_entry_safe(pos, tmp_pos, &adapter->ip_list, list) {  		netxen_config_ipaddr(adapter, pos->ip_addr, ip_event);  	}  } +static inline bool +netxen_config_checkdev(struct net_device *dev) +{ +	struct netxen_adapter *adapter; + +	if (!is_netxen_netdev(dev)) +		return false; +	adapter = netdev_priv(dev); +	if (!adapter) +		return false; +	if (!netxen_destip_supported(adapter)) +		return false; +	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) +		return false; + +	return true; +} + +/** + * netxen_config_master - configure addresses based on master + * @dev: netxen device + * @event: netdev event + */ +static void netxen_config_master(struct net_device *dev, unsigned long event) +{ +	struct net_device *master, *slave; +	struct netxen_adapter *adapter = netdev_priv(dev); + +	rcu_read_lock(); +	master = netdev_master_upper_dev_get_rcu(dev); +	/* +	 * This is the case where the netxen nic is being +	 * enslaved and is dev_open()ed in bond_enslave() +	 * Now we should program the bond's (and its vlans') +	 * addresses in the netxen NIC. +	 */ +	if (master && netif_is_bond_master(master) && +	    !netif_is_bond_slave(dev)) { +		netxen_config_indev_addr(adapter, master, event); +		for_each_netdev_rcu(&init_net, slave) +			if (slave->priv_flags & IFF_802_1Q_VLAN && +			    vlan_dev_real_dev(slave) == master) +				netxen_config_indev_addr(adapter, slave, event); +	} +	rcu_read_unlock(); +	/* +	 * This is the case where the netxen nic is being +	 * released and is dev_close()ed in bond_release() +	 * just before IFF_BONDING is stripped. +	 */ +	if (!master && dev->priv_flags & IFF_BONDING) +		netxen_free_ip_list(adapter, true); +} +  static int netxen_netdev_event(struct notifier_block *this,  				 unsigned long event, void *ptr)  {  	struct netxen_adapter *adapter;  	struct net_device *dev = (struct net_device *)ptr;  	struct net_device *orig_dev = dev; +	struct net_device *slave;  recheck:  	if (dev == NULL) @@ -3257,19 +3323,28 @@ recheck:  		dev = vlan_dev_real_dev(dev);  		goto recheck;  	} - -	if (!is_netxen_netdev(dev)) -		goto done; - -	adapter = netdev_priv(dev); - -	if (!adapter) -		goto done; - -	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) -		goto done; - -	netxen_config_indev_addr(adapter, orig_dev, event); +	if (event == NETDEV_UP || event == NETDEV_DOWN) { +		/* If this is a bonding device, look for netxen-based slaves*/ +		if (netif_is_bond_master(dev)) { +			rcu_read_lock(); +			for_each_netdev_in_bond_rcu(dev, slave) { +				if (!netxen_config_checkdev(slave)) +					continue; +				adapter = netdev_priv(slave); +				netxen_config_indev_addr(adapter, +							 orig_dev, event); +			} +			rcu_read_unlock(); +		} else { +			if (!netxen_config_checkdev(dev)) +				goto done; +			adapter = netdev_priv(dev); +			/* Act only if the actual netxen is the target */ +			if (orig_dev == dev) +				netxen_config_master(dev, event); +			netxen_config_indev_addr(adapter, orig_dev, event); +		} +	}  done:  	return NOTIFY_DONE;  } @@ -3279,12 +3354,12 @@ netxen_inetaddr_event(struct notifier_block *this,  		unsigned long event, void *ptr)  {  	struct netxen_adapter *adapter; -	struct net_device *dev; - +	struct net_device *dev, *slave;  	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; +	unsigned long ip_event;  	dev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL; - +	ip_event = (event == NETDEV_UP) ? NX_IP_UP : NX_IP_DOWN;  recheck:  	if (dev == NULL)  		goto done; @@ -3293,31 +3368,24 @@ recheck:  		dev = vlan_dev_real_dev(dev);  		goto recheck;  	} - -	if (!is_netxen_netdev(dev)) -		goto done; - -	adapter = netdev_priv(dev); - -	if (!adapter || !netxen_destip_supported(adapter)) -		goto done; - -	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) -		goto done; - -	switch (event) { -	case NETDEV_UP: -		netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_UP); -		netxen_list_config_vlan_ip(adapter, ifa, NX_IP_UP); -		break; -	case NETDEV_DOWN: -		netxen_config_ipaddr(adapter, ifa->ifa_address, NX_IP_DOWN); -		netxen_list_config_vlan_ip(adapter, ifa, NX_IP_DOWN); -		break; -	default: -		break; +	if (event == NETDEV_UP || event == NETDEV_DOWN) { +		/* If this is a bonding device, look for netxen-based slaves*/ +		if (netif_is_bond_master(dev)) { +			rcu_read_lock(); +			for_each_netdev_in_bond_rcu(dev, slave) { +				if (!netxen_config_checkdev(slave)) +					continue; +				adapter = netdev_priv(slave); +				netxen_list_config_ip(adapter, ifa, ip_event); +			} +			rcu_read_unlock(); +		} else { +			if (!netxen_config_checkdev(dev)) +				goto done; +			adapter = netdev_priv(dev); +			netxen_list_config_ip(adapter, ifa, ip_event); +		}  	} -  done:  	return NOTIFY_DONE;  } @@ -3334,7 +3402,7 @@ static void  netxen_restore_indev_addr(struct net_device *dev, unsigned long event)  { }  static void -netxen_free_vlan_ip_list(struct netxen_adapter *adapter) +netxen_free_ip_list(struct netxen_adapter *adapter, bool master)  { }  #endif diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index 8fd38cb6d26..91a8fcd6c24 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -312,7 +312,6 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,  		lrg_buf_cb->skb = netdev_alloc_skb(qdev->ndev,  						   qdev->lrg_buffer_len);  		if (unlikely(!lrg_buf_cb->skb)) { -			netdev_err(qdev->ndev, "failed netdev_alloc_skb()\n");  			qdev->lrg_buf_skb_check++;  		} else {  			/* diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index ba3c72fce1f..72bbba03a04 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -38,8 +38,8 @@  #define _QLCNIC_LINUX_MAJOR 5  #define _QLCNIC_LINUX_MINOR 1 -#define _QLCNIC_LINUX_SUBVERSION 35 -#define QLCNIC_LINUX_VERSIONID  "5.1.35" +#define _QLCNIC_LINUX_SUBVERSION 38 +#define QLCNIC_LINUX_VERSIONID  "5.1.38"  #define QLCNIC_DRV_IDC_VER  0x01  #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\  		 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index cd5ae8813cb..8de8ca56cba 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c @@ -15,36 +15,57 @@  #define RSS_HASHTYPE_IP_TCP		0x3  /* status descriptor mailbox data - * @phy_addr: physical address of buffer + * @phy_addr_{low|high}: physical address of buffer   * @sds_ring_size: buffer size   * @intrpt_id: interrupt id   * @intrpt_val: source of interrupt   */  struct qlcnic_sds_mbx { -	u64	phy_addr; -	u8	rsvd1[16]; +	u32	phy_addr_low; +	u32	phy_addr_high; +	u32	rsvd1[4]; +#if defined(__LITTLE_ENDIAN)  	u16	sds_ring_size; -	u16	rsvd2[3]; +	u16	rsvd2; +	u16	rsvd3[2];  	u16	intrpt_id;  	u8	intrpt_val; -	u8	rsvd3[5]; +	u8	rsvd4; +#elif defined(__BIG_ENDIAN) +	u16	rsvd2; +	u16	sds_ring_size; +	u16	rsvd3[2]; +	u8	rsvd4; +	u8	intrpt_val; +	u16	intrpt_id; +#endif +	u32	rsvd5;  } __packed;  /* receive descriptor buffer data - * phy_addr_reg: physical address of regular buffer - * phy_addr_jmb: physical address of jumbo buffer + * phy_addr_reg_{low|high}: physical address of regular buffer + * phy_addr_jmb_{low|high}: physical address of jumbo buffer   * reg_ring_sz: size of regular buffer   * reg_ring_len: no. of entries in regular buffer   * jmb_ring_len: no. of entries in jumbo buffer   * jmb_ring_sz: size of jumbo buffer   */  struct qlcnic_rds_mbx { -	u64	phy_addr_reg; -	u64	phy_addr_jmb; +	u32	phy_addr_reg_low; +	u32	phy_addr_reg_high; +	u32	phy_addr_jmb_low; +	u32	phy_addr_jmb_high; +#if defined(__LITTLE_ENDIAN)  	u16	reg_ring_sz;  	u16	reg_ring_len;  	u16	jmb_ring_sz;  	u16	jmb_ring_len; +#elif defined(__BIG_ENDIAN) +	u16	reg_ring_len; +	u16	reg_ring_sz; +	u16	jmb_ring_len; +	u16	jmb_ring_sz; +#endif  } __packed;  /* host producers for regular and jumbo rings */ @@ -61,6 +82,7 @@ struct __host_producer_mbx {   * @phy_port: physical port id   */  struct qlcnic_rcv_mbx_out { +#if defined(__LITTLE_ENDIAN)  	u8	rcv_num;  	u8	sts_num;  	u16	ctx_id; @@ -68,32 +90,56 @@ struct qlcnic_rcv_mbx_out {  	u8	num_pci_func;  	u8	phy_port;  	u8	vport_id; +#elif defined(__BIG_ENDIAN) +	u16	ctx_id; +	u8	sts_num; +	u8	rcv_num; +	u8	vport_id; +	u8	phy_port; +	u8	num_pci_func; +	u8	state; +#endif  	u32	host_csmr[QLCNIC_MAX_RING_SETS];  	struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];  } __packed;  struct qlcnic_add_rings_mbx_out { +#if defined(__LITTLE_ENDIAN)  	u8      rcv_num;  	u8      sts_num; -	u16  ctx_id; +	u16	ctx_id; +#elif defined(__BIG_ENDIAN) +	u16	ctx_id; +	u8	sts_num; +	u8	rcv_num; +#endif  	u32  host_csmr[QLCNIC_MAX_RING_SETS];  	struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS];  } __packed;  /* Transmit context mailbox inbox registers - * @phys_addr: DMA address of the transmit buffer - * @cnsmr_index: host consumer index + * @phys_addr_{low|high}: DMA address of the transmit buffer + * @cnsmr_index_{low|high}: host consumer index   * @size: legth of transmit buffer ring   * @intr_id: interrput id   * @src: src of interrupt   */  struct qlcnic_tx_mbx { -	u64	phys_addr; -	u64	cnsmr_index; +	u32	phys_addr_low; +	u32	phys_addr_high; +	u32	cnsmr_index_low; +	u32	cnsmr_index_high; +#if defined(__LITTLE_ENDIAN)  	u16	size;  	u16	intr_id;  	u8	src;  	u8	rsvd[3]; +#elif defined(__BIG_ENDIAN) +	u16	intr_id; +	u16	size; +	u8	rsvd[3]; +	u8	src; +#endif  } __packed;  /* Transmit context mailbox outbox registers @@ -101,11 +147,18 @@ struct qlcnic_tx_mbx {   * @ctx_id: transmit context id   * @state: state of the transmit context   */ +  struct qlcnic_tx_mbx_out {  	u32	host_prod; +#if defined(__LITTLE_ENDIAN)  	u16	ctx_id;  	u8	state;  	u8	rsvd; +#elif defined(__BIG_ENDIAN) +	u8	rsvd; +	u8	state; +	u16	ctx_id; +#endif  } __packed;  static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = { @@ -1004,7 +1057,8 @@ static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter)  		sds = &recv_ctx->sds_rings[i];  		sds->consumer = 0;  		memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds)); -		sds_mbx.phy_addr = sds->phys_addr; +		sds_mbx.phy_addr_low = LSD(sds->phys_addr); +		sds_mbx.phy_addr_high = MSD(sds->phys_addr);  		sds_mbx.sds_ring_size = sds->num_desc;  		if (adapter->flags & QLCNIC_MSIX_ENABLED) @@ -1090,7 +1144,8 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)  		sds = &recv_ctx->sds_rings[i];  		sds->consumer = 0;  		memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds)); -		sds_mbx.phy_addr = sds->phys_addr; +		sds_mbx.phy_addr_low = LSD(sds->phys_addr); +		sds_mbx.phy_addr_high = MSD(sds->phys_addr);  		sds_mbx.sds_ring_size = sds->num_desc;  		if (adapter->flags & QLCNIC_MSIX_ENABLED)  			intrpt_id = ahw->intr_tbl[i].id; @@ -1110,13 +1165,15 @@ int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter)  	rds = &recv_ctx->rds_rings[0];  	rds->producer = 0;  	memset(&rds_mbx, 0, rds_mbx_size); -	rds_mbx.phy_addr_reg = rds->phys_addr; +	rds_mbx.phy_addr_reg_low = LSD(rds->phys_addr); +	rds_mbx.phy_addr_reg_high = MSD(rds->phys_addr);  	rds_mbx.reg_ring_sz = rds->dma_size;  	rds_mbx.reg_ring_len = rds->num_desc;  	/* Jumbo ring */  	rds = &recv_ctx->rds_rings[1];  	rds->producer = 0; -	rds_mbx.phy_addr_jmb = rds->phys_addr; +	rds_mbx.phy_addr_jmb_low = LSD(rds->phys_addr); +	rds_mbx.phy_addr_jmb_high = MSD(rds->phys_addr);  	rds_mbx.jmb_ring_sz = rds->dma_size;  	rds_mbx.jmb_ring_len = rds->num_desc;  	buf = &cmd.req.arg[index]; @@ -1182,8 +1239,10 @@ int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter,  	memset(&mbx, 0, sizeof(struct qlcnic_tx_mbx));  	/* setup mailbox inbox registerss */ -	mbx.phys_addr = tx->phys_addr; -	mbx.cnsmr_index = tx->hw_cons_phys_addr; +	mbx.phys_addr_low = LSD(tx->phys_addr); +	mbx.phys_addr_high = MSD(tx->phys_addr); +	mbx.cnsmr_index_low = LSD(tx->hw_cons_phys_addr); +	mbx.cnsmr_index_high = MSD(tx->hw_cons_phys_addr);  	mbx.size = tx->num_desc;  	if (adapter->flags & QLCNIC_MSIX_ENABLED)  		msix_id = ahw->intr_tbl[adapter->max_sds_rings + ring].id; @@ -1373,6 +1432,51 @@ mbx_err:  	}  } +int  qlcnic_83xx_set_led(struct net_device *netdev, +			 enum ethtool_phys_id_state state) +{ +	struct qlcnic_adapter *adapter = netdev_priv(netdev); +	int err = -EIO, active = 1; + +	if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { +		netdev_warn(netdev, +			    "LED test is not supported in non-privileged mode\n"); +		return -EOPNOTSUPP; +	} + +	switch (state) { +	case ETHTOOL_ID_ACTIVE: +		if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) +			return -EBUSY; + +		if (test_bit(__QLCNIC_RESETTING, &adapter->state)) +			break; + +		err = qlcnic_83xx_config_led(adapter, active, 0); +		if (err) +			netdev_err(netdev, "Failed to set LED blink state\n"); +		break; +	case ETHTOOL_ID_INACTIVE: +		active = 0; + +		if (test_bit(__QLCNIC_RESETTING, &adapter->state)) +			break; + +		err = qlcnic_83xx_config_led(adapter, active, 0); +		if (err) +			netdev_err(netdev, "Failed to reset LED blink state\n"); +		break; + +	default: +		return -EINVAL; +	} + +	if (!active || err) +		clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); + +	return err; +} +  void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter,  				       int enable)  { @@ -1713,7 +1817,12 @@ int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,  			(adapter->recv_ctx->context_id << 16);  	mv.vlan = le16_to_cpu(vlan_id); -	memcpy(&mv.mac, addr, ETH_ALEN); +	mv.mac_addr0 = addr[0]; +	mv.mac_addr1 = addr[1]; +	mv.mac_addr2 = addr[2]; +	mv.mac_addr3 = addr[3]; +	mv.mac_addr4 = addr[4]; +	mv.mac_addr5 = addr[5];  	buf = &cmd.req.arg[2];  	memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx));  	err = qlcnic_issue_cmd(adapter, &cmd); @@ -2002,9 +2111,8 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter,  int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type)  {  	int i, index, err; -	bool type;  	u8 max_ints; -	u32 val, temp; +	u32 val, temp, type;  	struct qlcnic_cmd_args cmd;  	max_ints = adapter->ahw->num_msix - 1; @@ -2163,7 +2271,7 @@ static int qlcnic_83xx_poll_flash_status_reg(struct qlcnic_adapter *adapter)  	return 0;  } -static int qlcnic_83xx_enable_flash_write_op(struct qlcnic_adapter *adapter) +int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *adapter)  {  	int ret;  	u32 cmd; @@ -2181,7 +2289,7 @@ static int qlcnic_83xx_enable_flash_write_op(struct qlcnic_adapter *adapter)  	return 0;  } -static int qlcnic_83xx_disable_flash_write_op(struct qlcnic_adapter *adapter) +int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *adapter)  {  	int ret; @@ -2255,7 +2363,7 @@ int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,  		return -EIO;  	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { -		ret = qlcnic_83xx_enable_flash_write_op(adapter); +		ret = qlcnic_83xx_enable_flash_write(adapter);  		if (ret) {  			qlcnic_83xx_unlock_flash(adapter);  			dev_err(&adapter->pdev->dev, @@ -2297,7 +2405,7 @@ int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter,  	}  	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { -		ret = qlcnic_83xx_disable_flash_write_op(adapter); +		ret = qlcnic_83xx_disable_flash_write(adapter);  		if (ret) {  			qlcnic_83xx_unlock_flash(adapter);  			dev_err(&adapter->pdev->dev, @@ -2337,8 +2445,8 @@ int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr,  	u32 temp;  	int ret = -EIO; -	if ((count < QLC_83XX_FLASH_BULK_WRITE_MIN) || -	    (count > QLC_83XX_FLASH_BULK_WRITE_MAX)) { +	if ((count < QLC_83XX_FLASH_WRITE_MIN) || +	    (count > QLC_83XX_FLASH_WRITE_MAX)) {  		dev_err(&adapter->pdev->dev,  			"%s: Invalid word count\n", __func__);  		return -EIO; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index 61f81f6c84a..fbb3d1d9e55 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h @@ -12,6 +12,8 @@  #include <linux/etherdevice.h>  #include "qlcnic_hw.h" +#define QLCNIC_83XX_BAR0_LENGTH 0x4000 +  /* Directly mapped registers */  #define QLC_83XX_CRB_WIN_BASE		0x3800  #define QLC_83XX_CRB_WIN_FUNC(f)	(QLC_83XX_CRB_WIN_BASE+((f)*4)) @@ -94,8 +96,23 @@ struct qlcnic_intrpt_config {  };  struct qlcnic_macvlan_mbx { -	u8	mac[ETH_ALEN]; +#if defined(__LITTLE_ENDIAN) +	u8	mac_addr0; +	u8	mac_addr1; +	u8	mac_addr2; +	u8	mac_addr3; +	u8	mac_addr4; +	u8	mac_addr5; +	u16	vlan; +#elif defined(__BIG_ENDIAN) +	u8	mac_addr3; +	u8	mac_addr2; +	u8	mac_addr1; +	u8	mac_addr0;  	u16	vlan; +	u8	mac_addr5; +	u8	mac_addr4; +#endif  };  struct qlc_83xx_fw_info { @@ -242,8 +259,8 @@ struct qlc_83xx_idc {  #define QLC_83XX_FLASH_BULK_WRITE_CMD		0xcadcadca  #define QLC_83XX_FLASH_READ_RETRY_COUNT	5000  #define QLC_83XX_FLASH_STATUS_READY		0x6 -#define QLC_83XX_FLASH_BULK_WRITE_MIN		2 -#define QLC_83XX_FLASH_BULK_WRITE_MAX		64 +#define QLC_83XX_FLASH_WRITE_MIN		2 +#define QLC_83XX_FLASH_WRITE_MAX		64  #define QLC_83XX_FLASH_STATUS_REG_POLL_DELAY	1  #define QLC_83XX_ERASE_MODE			1  #define QLC_83XX_WRITE_MODE			2 @@ -434,5 +451,8 @@ int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *);  int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *);  int qlcnic_83xx_loopback_test(struct net_device *, u8);  int qlcnic_83xx_interrupt_test(struct net_device *); +int qlcnic_83xx_set_led(struct net_device *, enum ethtool_phys_id_state);  int qlcnic_83xx_flash_test(struct qlcnic_adapter *); +int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *); +int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *);  #endif diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index 5c033f268ca..ba5ac69bf48 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -31,6 +31,7 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter);  /* Template header */  struct qlc_83xx_reset_hdr { +#if defined(__LITTLE_ENDIAN)  	u16	version;  	u16	signature;  	u16	size; @@ -39,14 +40,31 @@ struct qlc_83xx_reset_hdr {  	u16	checksum;  	u16	init_offset;  	u16	start_offset; +#elif defined(__BIG_ENDIAN) +	u16	signature; +	u16	version; +	u16	entries; +	u16	size; +	u16	checksum; +	u16	hdr_size; +	u16	start_offset; +	u16	init_offset; +#endif  } __packed;  /* Command entry header. */  struct qlc_83xx_entry_hdr { -	u16 cmd; -	u16 size; -	u16 count; -	u16 delay; +#if defined(__LITTLE_ENDIAN) +	u16	cmd; +	u16	size; +	u16	count; +	u16	delay; +#elif defined(__BIG_ENDIAN) +	u16	size; +	u16	cmd; +	u16	delay; +	u16	count; +#endif  } __packed;  /* Generic poll command */ @@ -60,10 +78,17 @@ struct qlc_83xx_rmw {  	u32	mask;  	u32	xor_value;  	u32	or_value; +#if defined(__LITTLE_ENDIAN)  	u8	shl;  	u8	shr;  	u8	index_a;  	u8	rsvd; +#elif defined(__BIG_ENDIAN) +	u8	rsvd; +	u8	index_a; +	u8	shr; +	u8	shl; +#endif  } __packed;  /* Generic command with 2 DWORD */ diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index a69097c6b84..c645c94b072 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -422,22 +422,20 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,  	rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);  	rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size, -			&rq_phys_addr, GFP_KERNEL); +				     &rq_phys_addr, GFP_KERNEL | __GFP_ZERO);  	if (!rq_addr)  		return -ENOMEM;  	rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx);  	rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size, -			&rsp_phys_addr, GFP_KERNEL); +				      &rsp_phys_addr, GFP_KERNEL | __GFP_ZERO);  	if (!rsp_addr) {  		err = -ENOMEM;  		goto out_free_rq;  	} -	memset(rq_addr, 0, rq_size);  	prq = rq_addr; -	memset(rsp_addr, 0, rsp_size);  	prsp = rsp_addr;  	prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr); @@ -532,20 +530,15 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)  		ptr = (__le32 *)dma_alloc_coherent(&pdev->dev, sizeof(u32),  						   &tx_ring->hw_cons_phys_addr,  						   GFP_KERNEL); - -		if (ptr == NULL) { -			dev_err(&pdev->dev, "failed to allocate tx consumer\n"); +		if (ptr == NULL)  			return -ENOMEM; -		} +  		tx_ring->hw_consumer = ptr;  		/* cmd desc ring */  		addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring),  					  &tx_ring->phys_addr,  					  GFP_KERNEL); -  		if (addr == NULL) { -			dev_err(&pdev->dev, -				"failed to allocate tx desc ring\n");  			err = -ENOMEM;  			goto err_out_free;  		} @@ -556,11 +549,9 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)  	for (ring = 0; ring < adapter->max_rds_rings; ring++) {  		rds_ring = &recv_ctx->rds_rings[ring];  		addr = dma_alloc_coherent(&adapter->pdev->dev, -				RCV_DESC_RINGSIZE(rds_ring), -				&rds_ring->phys_addr, GFP_KERNEL); +					  RCV_DESC_RINGSIZE(rds_ring), +					  &rds_ring->phys_addr, GFP_KERNEL);  		if (addr == NULL) { -			dev_err(&pdev->dev, -				"failed to allocate rds ring [%d]\n", ring);  			err = -ENOMEM;  			goto err_out_free;  		} @@ -572,11 +563,9 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)  		sds_ring = &recv_ctx->sds_rings[ring];  		addr = dma_alloc_coherent(&adapter->pdev->dev, -				STATUS_DESC_RINGSIZE(sds_ring), -				&sds_ring->phys_addr, GFP_KERNEL); +					  STATUS_DESC_RINGSIZE(sds_ring), +					  &sds_ring->phys_addr, GFP_KERNEL);  		if (addr == NULL) { -			dev_err(&pdev->dev, -				"failed to allocate sds ring [%d]\n", ring);  			err = -ENOMEM;  			goto err_out_free;  		} @@ -655,7 +644,7 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)  				qlcnic_83xx_config_intrpt(adapter, 0);  		}  		/* Allow dma queues to drain after context reset */ -		mdelay(20); +		msleep(20);  	}  } @@ -753,10 +742,9 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,  	size_t  nic_size = sizeof(struct qlcnic_info_le);  	nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, -				&nic_dma_t, GFP_KERNEL); +					   &nic_dma_t, GFP_KERNEL | __GFP_ZERO);  	if (!nic_info_addr)  		return -ENOMEM; -	memset(nic_info_addr, 0, nic_size);  	nic_info = nic_info_addr; @@ -804,11 +792,10 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,  		return err;  	nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, -			&nic_dma_t, GFP_KERNEL); +					   &nic_dma_t, GFP_KERNEL | __GFP_ZERO);  	if (!nic_info_addr)  		return -ENOMEM; -	memset(nic_info_addr, 0, nic_size);  	nic_info = nic_info_addr;  	nic_info->pci_func = cpu_to_le16(nic->pci_func); @@ -854,10 +841,10 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,  	size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;  	pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size, -			&pci_info_dma_t, GFP_KERNEL); +					   &pci_info_dma_t, +					   GFP_KERNEL | __GFP_ZERO);  	if (!pci_info_addr)  		return -ENOMEM; -	memset(pci_info_addr, 0, pci_size);  	npar = pci_info_addr;  	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO); @@ -949,12 +936,9 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,  	}  	stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size, -			&stats_dma_t, GFP_KERNEL); -	if (!stats_addr) { -		dev_err(&adapter->pdev->dev, "Unable to allocate memory\n"); +					&stats_dma_t, GFP_KERNEL | __GFP_ZERO); +	if (!stats_addr)  		return -ENOMEM; -	} -	memset(stats_addr, 0, stats_size);  	arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;  	arg1 |= rx_tx << 15 | stats_size << 16; @@ -1003,13 +987,10 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,  		return -ENOMEM;  	stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size, -			&stats_dma_t, GFP_KERNEL); -	if (!stats_addr) { -		dev_err(&adapter->pdev->dev, -			"%s: Unable to allocate memory.\n", __func__); +					&stats_dma_t, GFP_KERNEL | __GFP_ZERO); +	if (!stats_addr)  		return -ENOMEM; -	} -	memset(stats_addr, 0, stats_size); +  	qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_MAC_STATS);  	cmd.req.arg[1] = stats_size << 16;  	cmd.req.arg[2] = MSD(stats_dma_t); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 5641f8ec49a..f4f279d5cba 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -149,7 +149,8 @@ static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {  static inline int qlcnic_82xx_statistics(void)  { -	return QLCNIC_STATS_LEN + ARRAY_SIZE(qlcnic_83xx_mac_stats_strings); +	return ARRAY_SIZE(qlcnic_device_gstrings_stats) + +	       ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);  }  static inline int qlcnic_83xx_statistics(void) @@ -1070,8 +1071,7 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)  	}  } -static void -qlcnic_fill_stats(u64 *data, void *stats, int type) +static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)  {  	if (type == QLCNIC_MAC_STATS) {  		struct qlcnic_mac_statistics *mac_stats = @@ -1120,6 +1120,7 @@ qlcnic_fill_stats(u64 *data, void *stats, int type)  		*data++ = QLCNIC_FILL_STATS(esw_stats->local_frames);  		*data++ = QLCNIC_FILL_STATS(esw_stats->numbytes);  	} +	return data;  }  static void qlcnic_get_ethtool_stats(struct net_device *dev, @@ -1147,7 +1148,7 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev,  		/* Retrieve MAC statistics from firmware */  		memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));  		qlcnic_get_mac_stats(adapter, &mac_stats); -		qlcnic_fill_stats(data, &mac_stats, QLCNIC_MAC_STATS); +		data = qlcnic_fill_stats(data, &mac_stats, QLCNIC_MAC_STATS);  	}  	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) @@ -1159,7 +1160,7 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev,  	if (ret)  		return; -	qlcnic_fill_stats(data, &port_stats.rx, QLCNIC_ESW_STATS); +	data = qlcnic_fill_stats(data, &port_stats.rx, QLCNIC_ESW_STATS);  	ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,  			QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);  	if (ret) @@ -1176,7 +1177,8 @@ static int qlcnic_set_led(struct net_device *dev,  	int err = -EIO, active = 1;  	if (qlcnic_83xx_check(adapter)) -		return -EOPNOTSUPP; +		return qlcnic_83xx_set_led(dev, state); +  	if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {  		netdev_warn(dev, "LED test not supported for non "  				"privilege function\n"); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index 0e630061bff..891f12d47c9 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c @@ -9,6 +9,7 @@  #include <linux/if_vlan.h>  #include <net/ip.h>  #include <linux/ipv6.h> +#include <net/checksum.h>  #include "qlcnic.h" @@ -1132,9 +1133,8 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter,  		iph = (struct iphdr *)skb->data;  		th = (struct tcphdr *)(skb->data + (iph->ihl << 2));  		length = (iph->ihl << 2) + (th->doff << 2) + lro_length; +		csum_replace2(&iph->check, iph->tot_len, htons(length));  		iph->tot_len = htons(length); -		iph->check = 0; -		iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);  	}  	th->psh = push; @@ -1595,9 +1595,8 @@ qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter,  		iph = (struct iphdr *)skb->data;  		th = (struct tcphdr *)(skb->data + (iph->ihl << 2));  		length = (iph->ihl << 2) + (th->doff << 2) + lro_length; +		csum_replace2(&iph->check, iph->tot_len, htons(length));  		iph->tot_len = htons(length); -		iph->check = 0; -		iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);  	}  	th->psh = push; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 28a6d483836..d8b9e3b3c4a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -253,11 +253,8 @@ static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],  	struct qlcnic_adapter *adapter = netdev_priv(netdev);  	int err = -EOPNOTSUPP; -	if (!adapter->fdb_mac_learn) { -		pr_info("%s: Driver mac learn is enabled, FDB operation not allowed\n", -			__func__); -		return err; -	} +	if (!adapter->fdb_mac_learn) +		return ndo_dflt_fdb_del(ndm, tb, netdev, addr);  	if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {  		if (is_unicast_ether_addr(addr)) @@ -277,11 +274,8 @@ static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],  	struct qlcnic_adapter *adapter = netdev_priv(netdev);  	int err = 0; -	if (!adapter->fdb_mac_learn) { -		pr_info("%s: Driver mac learn is enabled, FDB operation not allowed\n", -			__func__); -		return -EOPNOTSUPP; -	} +	if (!adapter->fdb_mac_learn) +		return ndo_dflt_fdb_add(ndm, tb, netdev, addr, flags);  	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {  		pr_info("%s: FDB e-switch is not enabled\n", __func__); @@ -306,11 +300,8 @@ static int qlcnic_fdb_dump(struct sk_buff *skb, struct netlink_callback *ncb,  {  	struct qlcnic_adapter *adapter = netdev_priv(netdev); -	if (!adapter->fdb_mac_learn) { -		pr_info("%s: Driver mac learn is enabled, FDB operation not allowed\n", -			__func__); -		return -EOPNOTSUPP; -	} +	if (!adapter->fdb_mac_learn) +		return ndo_dflt_fdb_dump(skb, ncb, netdev, idx);  	if (adapter->flags & QLCNIC_ESWITCH_ENABLED)  		idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx); @@ -1421,6 +1412,7 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)  	smp_mb();  	spin_lock(&adapter->tx_clean_lock);  	netif_carrier_off(netdev); +	adapter->ahw->linkup = 0;  	netif_tx_disable(netdev);  	qlcnic_free_mac_list(adapter); @@ -1932,6 +1924,12 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  			module_name(THIS_MODULE),  			board_name, adapter->ahw->revision_id);  	} + +	if (qlcnic_83xx_check(adapter) && !qlcnic_use_msi_x && +	    !!qlcnic_use_msi) +		dev_warn(&pdev->dev, +			 "83xx adapter do not support MSI interrupts\n"); +  	err = qlcnic_setup_intr(adapter, 0);  	if (err) {  		dev_err(&pdev->dev, "Failed to setup interrupt\n"); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c index abbd22c814a..4b9bab18ebd 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c @@ -810,11 +810,8 @@ static int __qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter,  	tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, temp_size,  				      &tmp_addr_t, GFP_KERNEL); -	if (!tmp_addr) { -		dev_err(&adapter->pdev->dev, -			"Can't get memory for FW dump template\n"); +	if (!tmp_addr)  		return -ENOMEM; -	}  	if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_TEMP_HDR)) {  		err = -ENOMEM; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index 987fb6f8adc..c77675da671 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c @@ -21,8 +21,6 @@  #include <linux/aer.h>  #include <linux/log2.h> -#include <linux/sysfs.h> -  #define QLC_STATUS_UNSUPPORTED_CMD	-2  int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable) @@ -886,6 +884,244 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,  	return size;  } +static ssize_t qlcnic_83xx_sysfs_flash_read_handler(struct file *filp, +						    struct kobject *kobj, +						    struct bin_attribute *attr, +						    char *buf, loff_t offset, +						    size_t size) +{ +	unsigned char *p_read_buf; +	int  ret, count; +	struct device *dev = container_of(kobj, struct device, kobj); +	struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + +	if (!size) +		return QL_STATUS_INVALID_PARAM; +	if (!buf) +		return QL_STATUS_INVALID_PARAM; + +	count = size / sizeof(u32); + +	if (size % sizeof(u32)) +		count++; + +	p_read_buf = kcalloc(size, sizeof(unsigned char), GFP_KERNEL); +	if (!p_read_buf) +		return -ENOMEM; +	if (qlcnic_83xx_lock_flash(adapter) != 0) { +		kfree(p_read_buf); +		return -EIO; +	} + +	ret = qlcnic_83xx_lockless_flash_read32(adapter, offset, p_read_buf, +						count); + +	if (ret) { +		qlcnic_83xx_unlock_flash(adapter); +		kfree(p_read_buf); +		return ret; +	} + +	qlcnic_83xx_unlock_flash(adapter); +	memcpy(buf, p_read_buf, size); +	kfree(p_read_buf); + +	return size; +} + +static int qlcnic_83xx_sysfs_flash_bulk_write(struct qlcnic_adapter *adapter, +					      char *buf, loff_t offset, +					      size_t size) +{ +	int  i, ret, count; +	unsigned char *p_cache, *p_src; + +	p_cache = kcalloc(size, sizeof(unsigned char), GFP_KERNEL); +	if (!p_cache) +		return -ENOMEM; + +	memcpy(p_cache, buf, size); +	p_src = p_cache; +	count = size / sizeof(u32); + +	if (qlcnic_83xx_lock_flash(adapter) != 0) { +		kfree(p_cache); +		return -EIO; +	} + +	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { +		ret = qlcnic_83xx_enable_flash_write(adapter); +		if (ret) { +			kfree(p_cache); +			qlcnic_83xx_unlock_flash(adapter); +			return -EIO; +		} +	} + +	for (i = 0; i < count / QLC_83XX_FLASH_WRITE_MAX; i++) { +		ret = qlcnic_83xx_flash_bulk_write(adapter, offset, +						   (u32 *)p_src, +						   QLC_83XX_FLASH_WRITE_MAX); + +		if (ret) { +			if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { +				ret = qlcnic_83xx_disable_flash_write(adapter); +				if (ret) { +					kfree(p_cache); +					qlcnic_83xx_unlock_flash(adapter); +					return -EIO; +				} +			} + +			kfree(p_cache); +			qlcnic_83xx_unlock_flash(adapter); +			return -EIO; +		} + +		p_src = p_src + sizeof(u32)*QLC_83XX_FLASH_WRITE_MAX; +		offset = offset + sizeof(u32)*QLC_83XX_FLASH_WRITE_MAX; +	} + +	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { +		ret = qlcnic_83xx_disable_flash_write(adapter); +		if (ret) { +			kfree(p_cache); +			qlcnic_83xx_unlock_flash(adapter); +			return -EIO; +		} +	} + +	kfree(p_cache); +	qlcnic_83xx_unlock_flash(adapter); + +	return 0; +} + +static int qlcnic_83xx_sysfs_flash_write(struct qlcnic_adapter *adapter, +					 char *buf, loff_t offset, size_t size) +{ +	int  i, ret, count; +	unsigned char *p_cache, *p_src; + +	p_cache = kcalloc(size, sizeof(unsigned char), GFP_KERNEL); +	if (!p_cache) +		return -ENOMEM; + +	memcpy(p_cache, buf, size); +	p_src = p_cache; +	count = size / sizeof(u32); + +	if (qlcnic_83xx_lock_flash(adapter) != 0) { +		kfree(p_cache); +		return -EIO; +	} + +	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { +		ret = qlcnic_83xx_enable_flash_write(adapter); +		if (ret) { +			kfree(p_cache); +			qlcnic_83xx_unlock_flash(adapter); +			return -EIO; +		} +	} + +	for (i = 0; i < count; i++) { +		ret = qlcnic_83xx_flash_write32(adapter, offset, (u32 *)p_src); +		if (ret) { +			if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { +				ret = qlcnic_83xx_disable_flash_write(adapter); +				if (ret) { +					kfree(p_cache); +					qlcnic_83xx_unlock_flash(adapter); +					return -EIO; +				} +			} +			kfree(p_cache); +			qlcnic_83xx_unlock_flash(adapter); +			return -EIO; +		} + +		p_src = p_src + sizeof(u32); +		offset = offset + sizeof(u32); +	} + +	if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { +		ret = qlcnic_83xx_disable_flash_write(adapter); +		if (ret) { +			kfree(p_cache); +			qlcnic_83xx_unlock_flash(adapter); +			return -EIO; +		} +	} + +	kfree(p_cache); +	qlcnic_83xx_unlock_flash(adapter); + +	return 0; +} + +static ssize_t qlcnic_83xx_sysfs_flash_write_handler(struct file *filp, +						     struct kobject *kobj, +						     struct bin_attribute *attr, +						     char *buf, loff_t offset, +						     size_t size) +{ +	int  ret; +	static int flash_mode; +	unsigned long data; +	struct device *dev = container_of(kobj, struct device, kobj); +	struct qlcnic_adapter *adapter = dev_get_drvdata(dev); + +	if (!buf) +		return QL_STATUS_INVALID_PARAM; + +	ret = kstrtoul(buf, 16, &data); + +	switch (data) { +	case QLC_83XX_FLASH_SECTOR_ERASE_CMD: +		flash_mode = QLC_83XX_ERASE_MODE; +		ret = qlcnic_83xx_erase_flash_sector(adapter, offset); +		if (ret) { +			dev_err(&adapter->pdev->dev, +				"%s failed at %d\n", __func__, __LINE__); +			return -EIO; +		} +		break; + +	case QLC_83XX_FLASH_BULK_WRITE_CMD: +		flash_mode = QLC_83XX_BULK_WRITE_MODE; +		break; + +	case QLC_83XX_FLASH_WRITE_CMD: +		flash_mode = QLC_83XX_WRITE_MODE; +		break; +	default: +		if (flash_mode == QLC_83XX_BULK_WRITE_MODE) { +			ret = qlcnic_83xx_sysfs_flash_bulk_write(adapter, buf, +								 offset, size); +			if (ret) { +				dev_err(&adapter->pdev->dev, +					"%s failed at %d\n", +					__func__, __LINE__); +				return -EIO; +			} +		} + +		if (flash_mode == QLC_83XX_WRITE_MODE) { +			ret = qlcnic_83xx_sysfs_flash_write(adapter, buf, +							    offset, size); +			if (ret) { +				dev_err(&adapter->pdev->dev, +					"%s failed at %d\n", __func__, +					__LINE__); +				return -EIO; +			} +		} +	} + +	return size; +} +  static struct device_attribute dev_attr_bridged_mode = {         .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},         .show = qlcnic_show_bridged_mode, @@ -960,6 +1196,13 @@ static struct bin_attribute bin_attr_pm_config = {  	.write = qlcnic_sysfs_write_pm_config,  }; +static struct bin_attribute bin_attr_flash = { +	.attr = {.name = "flash", .mode = (S_IRUGO | S_IWUSR)}, +	.size = 0, +	.read = qlcnic_83xx_sysfs_flash_read_handler, +	.write = qlcnic_83xx_sysfs_flash_write_handler, +}; +  void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)  {  	struct device *dev = &adapter->pdev->dev; @@ -1048,10 +1291,18 @@ void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter)  void qlcnic_83xx_add_sysfs(struct qlcnic_adapter *adapter)  { +	struct device *dev = &adapter->pdev->dev; +  	qlcnic_create_diag_entries(adapter); + +	if (sysfs_create_bin_file(&dev->kobj, &bin_attr_flash)) +		dev_info(dev, "failed to create flash sysfs entry\n");  }  void qlcnic_83xx_remove_sysfs(struct qlcnic_adapter *adapter)  { +	struct device *dev = &adapter->pdev->dev; +  	qlcnic_remove_diag_entries(adapter); +	sysfs_remove_bin_file(&dev->kobj, &bin_attr_flash);  } diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index b13ab544a7e..1dd778a6f01 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -1211,8 +1211,6 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring)  				    netdev_alloc_skb(qdev->ndev,  						     SMALL_BUFFER_SIZE);  				if (sbq_desc->p.skb == NULL) { -					netif_err(qdev, probe, qdev->ndev, -						  "Couldn't get an skb.\n");  					rx_ring->sbq_clean_idx = clean_idx;  					return;  				} @@ -1519,8 +1517,6 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,  	skb = netdev_alloc_skb(ndev, length);  	if (!skb) { -		netif_err(qdev, drv, qdev->ndev, -			  "Couldn't get an skb, need to unwind!.\n");  		rx_ring->rx_dropped++;  		put_page(lbq_desc->p.pg_chunk.page);  		return; @@ -1605,8 +1601,6 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev,  	/* Allocate new_skb and copy */  	new_skb = netdev_alloc_skb(qdev->ndev, length + NET_IP_ALIGN);  	if (new_skb == NULL) { -		netif_err(qdev, probe, qdev->ndev, -			  "No skb available, drop the packet.\n");  		rx_ring->rx_dropped++;  		return;  	}  |