Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c80b18d authored by Mithlesh Thukral's avatar Mithlesh Thukral Committed by Jeff Garzik
Browse files

NetXen: Port swap feature for multi port cards



NetXen: Port Swap feature
This patch will allow a port numbers on the card to be swapped in
host driver. This feature is applicable to cards having more than
1 port.

Signed-off by: Milan Bag <mbag@netxen.com>
Signed-off by: Mithlesh Thukral <mithlesh@netxen.com>

Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 5d512f55
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -205,6 +205,7 @@ enum {

#define MAX_CMD_DESCRIPTORS		1024
#define MAX_RCV_DESCRIPTORS		16384
#define MAX_CMD_DESCRIPTORS_HOST	(MAX_CMD_DESCRIPTORS / 4)
#define MAX_RCV_DESCRIPTORS_1G		(MAX_RCV_DESCRIPTORS / 4)
#define MAX_JUMBO_RCV_DESCRIPTORS	1024
#define MAX_LRO_RCV_DESCRIPTORS		64
@@ -303,6 +304,8 @@ struct netxen_ring_ctx {

#define netxen_set_cmd_desc_port(cmd_desc, var)	\
	((cmd_desc)->port_ctxid |= ((var) & 0x0F))
#define netxen_set_cmd_desc_ctxid(cmd_desc, var)	\
	((cmd_desc)->port_ctxid |= ((var) & 0xF0))

#define netxen_set_cmd_desc_flags(cmd_desc, val)	\
	((cmd_desc)->flags_opcode &= ~cpu_to_le16(0x7f), \
@@ -445,7 +448,7 @@ struct status_desc {
	/* Bit pattern: 0-6 lro_count indicates frag sequence,
	   7 last_frag indicates last frag */
	u8 lro;
} __attribute__ ((aligned(8)));
} __attribute__ ((aligned(16)));

enum {
	NETXEN_RCV_PEG_0 = 0,
@@ -723,6 +726,18 @@ struct netxen_skb_frag {
	u32 length;
};

#define _netxen_set_bits(config_word, start, bits, val)	{\
	unsigned long long __tmask = (((1ULL << (bits)) - 1) << (start));\
	unsigned long long __tvalue = (val);    \
	(config_word) &= ~__tmask;      \
	(config_word) |= (((__tvalue) << (start)) & __tmask); \
}
	
#define _netxen_clear_bits(config_word, start, bits) {\
	unsigned long long __tmask = (((1ULL << (bits)) - 1) << (start));  \
	(config_word) &= ~__tmask; \
}		

/*    Following defines are for the state of the buffers    */
#define	NETXEN_BUFFER_FREE	0
#define	NETXEN_BUFFER_BUSY	1
@@ -767,6 +782,8 @@ struct netxen_hardware_context {
	void __iomem *pci_base0;
	void __iomem *pci_base1;
	void __iomem *pci_base2;
	unsigned long first_page_group_end;
	unsigned long first_page_group_start;
	void __iomem *db_base;
	unsigned long db_len;

@@ -862,6 +879,7 @@ struct netxen_adapter {
	struct netxen_adapter *master;
	struct net_device *netdev;
	struct pci_dev *pdev;
	struct net_device_stats net_stats;
	unsigned char mac_addr[ETH_ALEN];
	int mtu;
	int portnum;
@@ -1152,4 +1170,5 @@ extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr,

extern struct ethtool_ops netxen_nic_ethtool_ops;

extern int physical_port[];	/* physical port # from virtual port.*/
#endif				/* __NETXEN_NIC_H_ */
+97 −46
Original line number Diff line number Diff line
@@ -40,8 +40,8 @@
#include <linux/ethtool.h>
#include <linux/version.h>

#include "netxen_nic_hw.h"
#include "netxen_nic.h"
#include "netxen_nic_hw.h"
#include "netxen_nic_phan_reg.h"

struct netxen_nic_stats {
@@ -379,7 +379,7 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
		for (i = 3; niu_registers[mode].reg[i - 3] != -1; i++) {
			/* GB: port specific registers */
			if (mode == 0 && i >= 19)
				window = adapter->portnum * 
				window = physical_port[adapter->portnum] *
					NETXEN_NIC_PORT_WINDOW;

			NETXEN_NIC_LOCKED_READ_REG(niu_registers[mode].
@@ -537,16 +537,43 @@ netxen_nic_get_pauseparam(struct net_device *dev,
{
	struct netxen_adapter *adapter = netdev_priv(dev);
	__u32 val;
	int port = physical_port[adapter->portnum];

	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
		if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
			return;
		/* get flow control settings */
		netxen_nic_read_w0(adapter,
				   NETXEN_NIU_GB_MAC_CONFIG_0(adapter->portnum),
		netxen_nic_read_w0(adapter,NETXEN_NIU_GB_MAC_CONFIG_0(port),
				&val);
		pause->rx_pause = netxen_gb_get_rx_flowctl(val);
		pause->tx_pause = netxen_gb_get_tx_flowctl(val);
		/* get autoneg settings */
		pause->autoneg = adapter->link_autoneg;
		netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val);
		switch (port) {
			case 0:
				pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
				break;
			case 1:
				pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
				break;
			case 2:
				pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
				break;
			case 3:
			default:
				pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
				break;
		}
	} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
		if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
			return;
		pause->rx_pause = 1;
		netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val);
		if (port == 0)
			pause->tx_pause = !(netxen_xg_get_xg0_mask(val));
		else
			pause->tx_pause = !(netxen_xg_get_xg1_mask(val));
	} else {
		printk(KERN_ERR"%s: Unknown board type: %x\n", 
				netxen_nic_driver_name, adapter->ahw.board_type);
	}
}

@@ -556,39 +583,74 @@ netxen_nic_set_pauseparam(struct net_device *dev,
{
	struct netxen_adapter *adapter = netdev_priv(dev);
	__u32 val;
	unsigned int autoneg;

	int port = physical_port[adapter->portnum];
	/* read mode */
	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
		if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS))
			return -EIO;
		/* set flow control */
		netxen_nic_read_w0(adapter,
				   NETXEN_NIU_GB_MAC_CONFIG_0(adapter->portnum),
				   (u32 *) & val);
		if (pause->tx_pause)
			netxen_gb_tx_flowctl(val);
		else
			netxen_gb_unset_tx_flowctl(val);
					NETXEN_NIU_GB_MAC_CONFIG_0(port), &val);
		
		if (pause->rx_pause)
			netxen_gb_rx_flowctl(val);
		else
			netxen_gb_unset_rx_flowctl(val);

		netxen_nic_write_w0(adapter,
				    NETXEN_NIU_GB_MAC_CONFIG_0(adapter->portnum),
				    *&val);
		netxen_nic_write_w0(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port),
				val);
		/* set autoneg */
		autoneg = pause->autoneg;
		if (adapter->phy_write
		    && adapter->phy_write(adapter,
					  NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
					  autoneg) != 0)
		netxen_nic_read_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, &val);
		switch (port) {
			case 0:
				if (pause->tx_pause)
					netxen_gb_unset_gb0_mask(val);
				else
					netxen_gb_set_gb0_mask(val);
				break;
			case 1:
				if (pause->tx_pause)
					netxen_gb_unset_gb1_mask(val);
				else
					netxen_gb_set_gb1_mask(val);
				break;
			case 2:
				if (pause->tx_pause)
					netxen_gb_unset_gb2_mask(val);
				else
					netxen_gb_set_gb2_mask(val);
				break;
			case 3:
			default:
				if (pause->tx_pause)
					netxen_gb_unset_gb3_mask(val);
				else
					netxen_gb_set_gb3_mask(val);
				break;
		}
		netxen_nic_write_w0(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
	} else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
		if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS))
			return -EIO;
		else {
			adapter->link_autoneg = pause->autoneg;
			return 0;
		netxen_nic_read_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, &val);
		if (port == 0) {
			if (pause->tx_pause)
				netxen_xg_unset_xg0_mask(val);
			else
				netxen_xg_set_xg0_mask(val);
		} else {
			if (pause->tx_pause)
				netxen_xg_unset_xg1_mask(val);
			else
				netxen_xg_set_xg1_mask(val);
		}
	} else
		return -EOPNOTSUPP;
		netxen_nic_write_w0(adapter, NETXEN_NIU_XG_PAUSE_CTL, val);			
	} else {
		printk(KERN_ERR "%s: Unknown board type: %x\n",
				netxen_nic_driver_name, 
				adapter->ahw.board_type);
	}
	return 0;
}

static int netxen_nic_reg_test(struct net_device *dev)
@@ -619,24 +681,13 @@ static void
netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
		     u64 * data)
{
	if (eth_test->flags == ETH_TEST_FL_OFFLINE) {	/* offline tests */
		/* link test */
		if ((data[1] = (u64) netxen_nic_test_link(dev)))
			eth_test->flags |= ETH_TEST_FL_FAILED;

		/* register tests */
		if ((data[0] = netxen_nic_reg_test(dev)))
			eth_test->flags |= ETH_TEST_FL_FAILED;
	} else {		/* online tests */
		/* register tests */
	memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
	if ((data[0] = netxen_nic_reg_test(dev)))
		eth_test->flags |= ETH_TEST_FL_FAILED;

	/* link test */
	if ((data[1] = (u64) netxen_nic_test_link(dev)))
		eth_test->flags |= ETH_TEST_FL_FAILED;
}
}

static void
netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+3 −0
Original line number Diff line number Diff line
@@ -467,6 +467,8 @@ enum {
#define NETXEN_PCI_OCM1		(0x05100000UL)
#define NETXEN_PCI_OCM1_MAX	(0x051fffffUL)
#define NETXEN_PCI_CRBSPACE	(0x06000000UL)
#define NETXEN_PCI_128MB_SIZE	(0x08000000UL)
#define NETXEN_PCI_32MB_SIZE	(0x02000000UL)

#define NETXEN_CRB_CAM	NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_CAM)

@@ -528,6 +530,7 @@ enum {
#define	NETXEN_NIU_XG_PAUSE_CTL		(NETXEN_CRB_NIU + 0x00098)
#define	NETXEN_NIU_XG_PAUSE_LEVEL	(NETXEN_CRB_NIU + 0x000dc)
#define	NETXEN_NIU_XG_SEL		(NETXEN_CRB_NIU + 0x00128)
#define NETXEN_NIU_GB_PAUSE_CTL		(NETXEN_CRB_NIU + 0x0030c)

#define NETXEN_NIU_FULL_LEVEL_XG	(NETXEN_CRB_NIU + 0x00450)

+13 −54
Original line number Diff line number Diff line
@@ -145,7 +145,7 @@ struct netxen_recv_crb recv_crb_registers[] = {
	 NETXEN_NIC_REG(0x184),
	 },
	/*
	 * Instance 3,
	 * Instance 2,
	 */
	{
	  {
@@ -194,7 +194,7 @@ struct netxen_recv_crb recv_crb_registers[] = {
	  NETXEN_NIC_REG(0x228),
	},
	/*
	 * Instance 4,
	 * Instance 3,
	 */
	{
	  {
@@ -310,7 +310,6 @@ void netxen_nic_set_multi(struct net_device *netdev)
{
	struct netxen_adapter *adapter = netdev_priv(netdev);
	struct dev_mc_list *mc_ptr;
	__u32 netxen_mac_addr_cntl_data = 0;

	mc_ptr = netdev->mc_list;
	if (netdev->flags & IFF_PROMISC) {
@@ -318,43 +317,10 @@ void netxen_nic_set_multi(struct net_device *netdev)
			adapter->set_promisc(adapter,
					     NETXEN_NIU_PROMISC_MODE);
	} else {
		if (adapter->unset_promisc &&
		    adapter->ahw.boardcfg.board_type
		    != NETXEN_BRDTYPE_P2_SB31_10G_IMEZ)
		if (adapter->unset_promisc)
			adapter->unset_promisc(adapter,
					       NETXEN_NIU_NON_PROMISC_MODE);
	}
	if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
		netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x03);
		netxen_nic_mcr_set_id_pool0(netxen_mac_addr_cntl_data, 0x00);
		netxen_nic_mcr_set_id_pool1(netxen_mac_addr_cntl_data, 0x00);
		netxen_nic_mcr_set_id_pool2(netxen_mac_addr_cntl_data, 0x00);
		netxen_nic_mcr_set_id_pool3(netxen_mac_addr_cntl_data, 0x00);
		netxen_nic_mcr_set_enable_xtnd0(netxen_mac_addr_cntl_data);
		netxen_nic_mcr_set_enable_xtnd1(netxen_mac_addr_cntl_data);
		netxen_nic_mcr_set_enable_xtnd2(netxen_mac_addr_cntl_data);
		netxen_nic_mcr_set_enable_xtnd3(netxen_mac_addr_cntl_data);
	} else {
		netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x00);
		netxen_nic_mcr_set_id_pool0(netxen_mac_addr_cntl_data, 0x00);
		netxen_nic_mcr_set_id_pool1(netxen_mac_addr_cntl_data, 0x01);
		netxen_nic_mcr_set_id_pool2(netxen_mac_addr_cntl_data, 0x02);
		netxen_nic_mcr_set_id_pool3(netxen_mac_addr_cntl_data, 0x03);
	}
	writel(netxen_mac_addr_cntl_data,
	       NETXEN_CRB_NORMALIZE(adapter, NETXEN_MAC_ADDR_CNTL_REG));
	if (adapter->ahw.board_type == NETXEN_NIC_XGBE) {
		writel(netxen_mac_addr_cntl_data,
		       NETXEN_CRB_NORMALIZE(adapter,
					    NETXEN_MULTICAST_ADDR_HI_0));
	} else {
		writel(netxen_mac_addr_cntl_data,
		       NETXEN_CRB_NORMALIZE(adapter,
					    NETXEN_MULTICAST_ADDR_HI_1));
	}
	netxen_mac_addr_cntl_data = 0;
	writel(netxen_mac_addr_cntl_data,
	       NETXEN_CRB_NORMALIZE(adapter, NETXEN_NIU_GB_DROP_WRONGADDR));
}

/*
@@ -390,7 +356,6 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
	void *addr;
	int loops = 0, err = 0;
	int ctx, ring;
	u32 card_cmdring = 0;
	struct netxen_recv_context *recv_ctx;
	struct netxen_rcv_desc_ctx *rcv_desc;
	int func_id = adapter->portnum;
@@ -402,11 +367,6 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
	DPRINTK(INFO, "cam RAM: %lx %x", NETXEN_CAM_RAM_BASE,
		pci_base_offset(adapter, NETXEN_CAM_RAM_BASE));

	/* Window 1 call */
	card_cmdring = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_CMDRING));

	DPRINTK(INFO, "Command Peg sends 0x%x for cmdring base\n",
		card_cmdring);

	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
		DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n");
@@ -449,7 +409,7 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
	}
	memset(addr, 0, sizeof(struct netxen_ring_ctx));
	adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
	adapter->ctx_desc->ctx_id = adapter->portnum;
	adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
	adapter->ctx_desc->cmd_consumer_offset =
	    cpu_to_le64(adapter->ctx_desc_phys_addr +
			sizeof(struct netxen_ring_ctx));
@@ -551,10 +511,6 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter)
				    adapter->ahw.cmd_desc_phys_addr);
		adapter->ahw.cmd_desc_head = NULL;
	}
	/* Special handling: there are 2 ports on this board */
	if (adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) {
		adapter->ahw.max_ports = 2;
	}

	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
		recv_ctx = &adapter->recv_ctx[ctx];
@@ -735,7 +691,10 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw)
		count++;
	}

	adapter->curr_window = wndw;
	if (wndw == NETXEN_WINDOW_ONE)
		adapter->curr_window = 1;
	else
		adapter->curr_window = 0;
}

void netxen_load_firmware(struct netxen_adapter *adapter)
@@ -1055,18 +1014,18 @@ int netxen_nic_get_board_info(struct netxen_adapter *adapter)
int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu)
{
	netxen_nic_write_w0(adapter,
			    NETXEN_NIU_GB_MAX_FRAME_SIZE(adapter->portnum),
			    new_mtu);
			NETXEN_NIU_GB_MAX_FRAME_SIZE(
				physical_port[adapter->portnum]), new_mtu);
	return 0;
}

int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
{
	new_mtu += NETXEN_NIU_HDRSIZE + NETXEN_NIU_TLRSIZE;
	if (adapter->portnum == 0)
	if (physical_port[adapter->portnum] == 0)
		netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, 
				new_mtu);
	else if (adapter->portnum == 1)
	else 
		netxen_nic_write_w0(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE,
				new_mtu);
	return 0;
@@ -1074,7 +1033,7 @@ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)

void netxen_nic_init_niu_gb(struct netxen_adapter *adapter)
{
	netxen_niu_gbe_init_port(adapter, adapter->portnum);
	netxen_niu_gbe_init_port(adapter, physical_port[adapter->portnum]);
}

void
+63 −0
Original line number Diff line number Diff line
@@ -220,6 +220,69 @@ typedef enum {
		_netxen_crb_get_bit(config_word, 1)
#define netxen_get_gb_mii_mgmt_notvalid(config_word)	\
		_netxen_crb_get_bit(config_word, 2)
/*
 * NIU XG Pause Ctl Register
 *
 *      Bit 0       : xg0_mask => 1:disable tx pause frames
 *      Bit 1       : xg0_request => 1:request single pause frame
 *      Bit 2       : xg0_on_off => 1:request is pause on, 0:off
 *      Bit 3       : xg1_mask => 1:disable tx pause frames
 *      Bit 4       : xg1_request => 1:request single pause frame
 *      Bit 5       : xg1_on_off => 1:request is pause on, 0:off
 */

#define netxen_xg_set_xg0_mask(config_word)    \
	((config_word) |= 1 << 0)
#define netxen_xg_set_xg1_mask(config_word)    \
	((config_word) |= 1 << 3)
		
#define netxen_xg_get_xg0_mask(config_word)    \
	_netxen_crb_get_bit((config_word), 0)
#define netxen_xg_get_xg1_mask(config_word)    \
	_netxen_crb_get_bit((config_word), 3)

#define netxen_xg_unset_xg0_mask(config_word)  \
	((config_word) &= ~(1 << 0))
#define netxen_xg_unset_xg1_mask(config_word)  \
	((config_word) &= ~(1 << 3))

/*
 * NIU XG Pause Ctl Register
 *
 *      Bit 0       : xg0_mask => 1:disable tx pause frames
 *      Bit 1       : xg0_request => 1:request single pause frame
 *      Bit 2       : xg0_on_off => 1:request is pause on, 0:off
 *      Bit 3       : xg1_mask => 1:disable tx pause frames
 *      Bit 4       : xg1_request => 1:request single pause frame
 *      Bit 5       : xg1_on_off => 1:request is pause on, 0:off
 */
#define netxen_gb_set_gb0_mask(config_word)    \
	((config_word) |= 1 << 0)
#define netxen_gb_set_gb1_mask(config_word)    \
	((config_word) |= 1 << 2)
#define netxen_gb_set_gb2_mask(config_word)    \
	((config_word) |= 1 << 4)
#define netxen_gb_set_gb3_mask(config_word)    \
	((config_word) |= 1 << 6)

#define netxen_gb_get_gb0_mask(config_word)    \
	_netxen_crb_get_bit((config_word), 0)
#define netxen_gb_get_gb1_mask(config_word)    \
	_netxen_crb_get_bit((config_word), 2)
#define netxen_gb_get_gb2_mask(config_word)    \
	_netxen_crb_get_bit((config_word), 4)
#define netxen_gb_get_gb3_mask(config_word)    \
	_netxen_crb_get_bit((config_word), 6)
	
#define netxen_gb_unset_gb0_mask(config_word)  \
	((config_word) &= ~(1 << 0))
#define netxen_gb_unset_gb1_mask(config_word)  \
	((config_word) &= ~(1 << 2))
#define netxen_gb_unset_gb2_mask(config_word)  \
	((config_word) &= ~(1 << 4))
#define netxen_gb_unset_gb3_mask(config_word)  \
	((config_word) &= ~(1 << 6))


/*
 * PHY-Specific MII control/status registers.
Loading