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

Commit c9fc891f authored by Dhananjay Phadke's avatar Dhananjay Phadke Committed by Jeff Garzik
Browse files

netxen: mtu, mac, link status changes



MAC addr, multicast filters, mtu are set through firmware commands
in firmware v4.0.0+ because of virtualization of physical ports.
Link status is also read from registers allocated by firmware for
each virtual port.

Signed-off-by: default avatarDhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 48bfd1e0
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -1119,7 +1119,7 @@ typedef struct {
	u64 qhdr;
	u64 req_hdr;
	u64 words[6];
} nic_request_t;
} nx_nic_req_t;

typedef struct {
	u8 op;
@@ -1127,6 +1127,7 @@ typedef struct {
	u8 mac_addr[6];
} nx_mac_req_t;

#define MAX_PENDING_DESC_BLOCK_SIZE	64

#define NETXEN_NIC_MSI_ENABLED		0x02
#define NETXEN_NIC_MSIX_ENABLED		0x04
@@ -1152,7 +1153,6 @@ struct netxen_adapter {
	int pci_using_dac;
	struct napi_struct napi;
	struct net_device_stats net_stats;
	unsigned char mac_addr[ETH_ALEN];
	int mtu;
	int portnum;
	u8 physical_port;
@@ -1160,6 +1160,7 @@ struct netxen_adapter {

	uint8_t		mc_enabled;
	uint8_t		max_mc_count;
	nx_mac_list_t	*mac_list;

	struct netxen_legacy_intr_set legacy_intr;
	u32	crb_intr_mask;
@@ -1231,7 +1232,6 @@ struct netxen_adapter {
	int (*phy_read) (struct netxen_adapter *, long reg, u32 *);
	int (*phy_write) (struct netxen_adapter *, long reg, u32 val);
	int (*init_port) (struct netxen_adapter *, int);
	void (*init_niu) (struct netxen_adapter *);
	int (*stop_port) (struct netxen_adapter *);

	int (*hw_read_wx)(struct netxen_adapter *, ulong, void *, int);
@@ -1316,7 +1316,6 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter,
/* Functions available from netxen_nic_hw.c */
int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu);
int netxen_nic_set_mtu_gb(struct netxen_adapter *adapter, int new_mtu);
void netxen_nic_init_niu_gb(struct netxen_adapter *adapter);
void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val);
int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off);
void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value);
@@ -1404,7 +1403,8 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
			    u32 ringid);
int netxen_process_cmd_ring(struct netxen_adapter *adapter);
u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
void netxen_nic_set_multi(struct net_device *netdev);
void netxen_p2_nic_set_multi(struct net_device *netdev);
void netxen_p3_nic_set_multi(struct net_device *netdev);

u32 nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, u32 mtu);
int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
@@ -1412,6 +1412,8 @@ int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
int netxen_nic_set_mac(struct net_device *netdev, void *p);
struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev);

void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
		uint32_t crb_producer);

/*
 * NetXen Board information
+6 −0
Original line number Diff line number Diff line
@@ -718,6 +718,12 @@ enum {
#define XG_LINK_UP	0x10
#define XG_LINK_DOWN	0x20

#define XG_LINK_UP_P3	0x01
#define XG_LINK_DOWN_P3	0x02
#define XG_LINK_STATE_P3_MASK 0xf
#define XG_LINK_STATE_P3(pcifn,val) \
	(((val) >> ((pcifn) * 4)) & XG_LINK_STATE_P3_MASK)

#define NETXEN_CAM_RAM_BASE	(NETXEN_CRB_CAM + 0x02000)
#define NETXEN_CAM_RAM(reg)	(NETXEN_CAM_RAM_BASE + (reg))
#define NETXEN_FW_VERSION_MAJOR (NETXEN_CAM_RAM(0x150))
+183 −15
Original line number Diff line number Diff line
@@ -314,6 +314,8 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p)

	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);

	/* For P3, MAC addr is not set in NIU */
	if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
		if (adapter->macaddr_set)
			adapter->macaddr_set(adapter, addr->sa_data);

@@ -405,10 +407,7 @@ netxen_nic_set_mcast_addr(struct netxen_adapter *adapter,
	return 0;
}

/*
 * netxen_nic_set_multi - Multicast
 */
void netxen_nic_set_multi(struct net_device *netdev)
void netxen_p2_nic_set_multi(struct net_device *netdev)
{
	struct netxen_adapter *adapter = netdev_priv(netdev);
	struct dev_mc_list *mc_ptr;
@@ -456,18 +455,186 @@ void netxen_nic_set_multi(struct net_device *netdev)
		netxen_nic_set_mcast_addr(adapter, index, null_addr);
}

static int nx_p3_nic_add_mac(struct netxen_adapter *adapter,
		u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list)
{
	nx_mac_list_t *cur, *prev;

	/* if in del_list, move it to adapter->mac_list */
	for (cur = *del_list, prev = NULL; cur;) {
		if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) {
			if (prev == NULL)
				*del_list = cur->next;
			else
				prev->next = cur->next;
			cur->next = adapter->mac_list;
			adapter->mac_list = cur;
			return 0;
		}
		prev = cur;
		cur = cur->next;
	}

	/* make sure to add each mac address only once */
	for (cur = adapter->mac_list; cur; cur = cur->next) {
		if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0)
			return 0;
	}
	/* not in del_list, create new entry and add to add_list */
	cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL);
	if (cur == NULL) {
		printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may"
				"not work properly from now.\n", __func__);
		return -1;
	}

	memcpy(cur->mac_addr, addr, ETH_ALEN);
	cur->next = *add_list;
	*add_list = cur;
	return 0;
}

static int
netxen_send_cmd_descs(struct netxen_adapter *adapter,
		struct cmd_desc_type0 *cmd_desc_arr, int nr_elements)
{
	uint32_t i, producer;
	struct netxen_cmd_buffer *pbuf;
	struct cmd_desc_type0 *cmd_desc;

	if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) {
		printk(KERN_WARNING "%s: Too many command descriptors in a "
			      "request\n", __func__);
		return -EINVAL;
	}

	i = 0;

	producer = adapter->cmd_producer;
	do {
		cmd_desc = &cmd_desc_arr[i];

		pbuf = &adapter->cmd_buf_arr[producer];
		pbuf->mss = 0;
		pbuf->total_length = 0;
		pbuf->skb = NULL;
		pbuf->cmd = 0;
		pbuf->frag_count = 0;
		pbuf->port = 0;

		/* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */
		memcpy(&adapter->ahw.cmd_desc_head[producer],
			&cmd_desc_arr[i], sizeof(struct cmd_desc_type0));

		producer = get_next_index(producer,
				adapter->max_tx_desc_count);
		i++;

	} while (i != nr_elements);

	adapter->cmd_producer = producer;

	/* write producer index to start the xmit */

	netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);

	return 0;
}

#define NIC_REQUEST		0x14
#define NETXEN_MAC_EVENT	0x1

static int nx_p3_sre_macaddr_change(struct net_device *dev,
		u8 *addr, unsigned op)
{
	struct netxen_adapter *adapter = (struct netxen_adapter *)dev->priv;
	nx_nic_req_t req;
	nx_mac_req_t mac_req;
	int rv;

	memset(&req, 0, sizeof(nx_nic_req_t));
	req.qhdr |= (NIC_REQUEST << 23);
	req.req_hdr |= NETXEN_MAC_EVENT;
	req.req_hdr |= ((u64)adapter->portnum << 16);
	mac_req.op = op;
	memcpy(&mac_req.mac_addr, addr, 6);
	req.words[0] = cpu_to_le64(*(u64 *)&mac_req);

	rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
	if (rv != 0) {
		printk(KERN_ERR "ERROR. Could not send mac update\n");
		return rv;
	}

	return 0;
}

void netxen_p3_nic_set_multi(struct net_device *netdev)
{
	struct netxen_adapter *adapter = netdev_priv(netdev);
	nx_mac_list_t *cur, *next, *del_list, *add_list = NULL;
	struct dev_mc_list *mc_ptr;
	u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

	adapter->set_promisc(adapter, NETXEN_NIU_PROMISC_MODE);

	/*
	 * Programming mac addresses will automaticly enabling L2 filtering.
	 * HW will replace timestamp with L2 conid when L2 filtering is
	 * enabled. This causes problem for LSA. Do not enabling L2 filtering
	 * until that problem is fixed.
	 */
	if ((netdev->flags & IFF_PROMISC) ||
			(netdev->mc_count > adapter->max_mc_count))
		return;

	del_list = adapter->mac_list;
	adapter->mac_list = NULL;

	nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list);
	if (netdev->mc_count > 0) {
		nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list);
		for (mc_ptr = netdev->mc_list; mc_ptr;
		     mc_ptr = mc_ptr->next) {
			nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr,
					  &add_list, &del_list);
		}
	}
	for (cur = del_list; cur;) {
		nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL);
		next = cur->next;
		kfree(cur);
		cur = next;
	}
	for (cur = add_list; cur;) {
		nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD);
		next = cur->next;
		cur->next = adapter->mac_list;
		adapter->mac_list = cur;
		cur = next;
	}
}

/*
 * netxen_nic_change_mtu - Change the Maximum Transfer Unit
 * @returns 0 on success, negative on failure
 */

#define MTU_FUDGE_FACTOR	100

int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
{
	struct netxen_adapter *adapter = netdev_priv(netdev);
	int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE;
	int max_mtu;

	if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) {
		printk(KERN_ERR "%s: %s %d is not supported.\n",
		       netxen_nic_driver_name, netdev->name, mtu);
	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
		max_mtu = P3_MAX_MTU;
	else
		max_mtu = P2_MAX_MTU;

	if (mtu > max_mtu) {
		printk(KERN_ERR "%s: mtu > %d bytes unsupported\n",
				netdev->name, max_mtu);
		return -EINVAL;
	}

@@ -475,6 +642,12 @@ int netxen_nic_change_mtu(struct net_device *netdev, int mtu)
		adapter->set_mtu(adapter, mtu);
	netdev->mtu = mtu;

	mtu += MTU_FUDGE_FACTOR;
	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
		nx_fw_cmd_set_mtu(adapter, mtu);
	else if (adapter->set_mtu)
		adapter->set_mtu(adapter, mtu);

	return 0;
}

@@ -1882,11 +2055,6 @@ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu)
	return 0;
}

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

void
netxen_crb_writelit_adapter(struct netxen_adapter *adapter,
		unsigned long off, int data)
+1 −1
Original line number Diff line number Diff line
@@ -329,7 +329,7 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter)
		adapter->set_promisc = netxen_niu_set_promiscuous_mode;
		adapter->phy_read = netxen_niu_gbe_phy_read;
		adapter->phy_write = netxen_niu_gbe_phy_write;
		adapter->init_niu = netxen_nic_init_niu_gb;
		adapter->init_port = netxen_niu_gbe_init_port;
		adapter->stop_port = netxen_niu_disable_gbe_port;
		break;

+25 −10
Original line number Diff line number Diff line
@@ -123,7 +123,7 @@ static uint32_t crb_cmd_producer[4] = {
	CRB_CMD_PRODUCER_OFFSET_2, CRB_CMD_PRODUCER_OFFSET_3
};

static inline void
void
netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
		uint32_t crb_producer)
{
@@ -716,7 +716,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	netdev->stop		   = netxen_nic_close;
	netdev->hard_start_xmit    = netxen_nic_xmit_frame;
	netdev->get_stats	   = netxen_nic_get_stats;
	netdev->set_multicast_list = netxen_nic_set_multi;
	if (NX_IS_REVISION_P3(revision_id))
		netdev->set_multicast_list = netxen_p3_nic_set_multi;
	else
		netdev->set_multicast_list = netxen_p2_nic_set_multi;
	netdev->set_mac_address    = netxen_nic_set_mac;
	netdev->change_mtu	   = netxen_nic_change_mtu;
	netdev->tx_timeout	   = netxen_tx_timeout;
@@ -1100,7 +1103,7 @@ static int netxen_nic_open(struct net_device *netdev)

	/* Done here again so that even if phantom sw overwrote it,
	 * we set it */
	err = adapter->init_port(adapter, adapter->portnum);
	err = adapter->init_port(adapter, adapter->physical_port);
	if (err) {
		printk(KERN_ERR "%s: Failed to initialize port %d\n",
				netxen_nic_driver_name, adapter->portnum);
@@ -1110,7 +1113,10 @@ static int netxen_nic_open(struct net_device *netdev)

	netxen_nic_set_link_parameters(adapter);

	netxen_nic_set_multi(netdev);
	netdev->set_multicast_list(netdev);
	if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
		nx_fw_cmd_set_mtu(adapter, netdev->mtu);
	else
		adapter->set_mtu(adapter, netdev->mtu);

	mod_timer(&adapter->watchdog_timer, jiffies);
@@ -1379,12 +1385,21 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter)

	port = adapter->physical_port;

	if (adapter->ahw.board_type == NETXEN_NIC_GBE) {
		val = adapter->pci_read_normalize(adapter, CRB_XG_STATE);
	if (adapter->ahw.board_type == NETXEN_NIC_GBE)
		linkup = (val >> port) & 1;
	else {
	} else {
		if (adapter->fw_major < 4) {
			val = adapter->pci_read_normalize(adapter,
					CRB_XG_STATE);
			val = (val >> port*8) & 0xff;
			linkup = (val == XG_LINK_UP);
		} else {
			val = adapter->pci_read_normalize(adapter,
				CRB_XG_STATE_P3);
			val = XG_LINK_STATE_P3(adapter->ahw.pci_func, val);
			linkup = (val == XG_LINK_UP_P3);
		}
	}

	if (adapter->ahw.linkup && !linkup) {
Loading