Skip to content

Commit

Permalink
netxen: async link event handling
Browse files Browse the repository at this point in the history
Add support for asynchronous events from firmware,
received over one of the rx rings.

Add support for event based phy interrupts, enhanced links
status reporting from firmware.

Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Dhananjay Phadke authored and David S. Miller committed Apr 8, 2009
1 parent 56a0078 commit 3bf26ce
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 57 deletions.
108 changes: 79 additions & 29 deletions drivers/net/netxen/netxen_nic.h
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ struct rcv_desc {
/* opcode field in status_desc */
#define NETXEN_NIC_RXPKT_DESC 0x04
#define NETXEN_OLD_RXPKT_DESC 0x3f
#define NETXEN_NIC_RESPONSE_DESC 0x05

/* for status field in status_desc */
#define STATUS_NEED_CKSUM (1)
Expand All @@ -363,8 +364,11 @@ struct rcv_desc {
#define STATUS_OWNER_HOST (0x1ULL << 56)
#define STATUS_OWNER_PHANTOM (0x2ULL << 56)

/* Note: sizeof(status_desc) should always be a mutliple of 2 */

/* Status descriptor:
0-3 port, 4-7 status, 8-11 type, 12-27 total_length
28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
53-55 desc_cnt, 56-57 owner, 58-63 opcode
*/
#define netxen_get_sts_port(sts_data) \
((sts_data) & 0x0F)
#define netxen_get_sts_status(sts_data) \
Expand All @@ -379,35 +383,13 @@ struct rcv_desc {
(((sts_data) >> 44) & 0x0F)
#define netxen_get_sts_pkt_offset(sts_data) \
(((sts_data) >> 48) & 0x1F)
#define netxen_get_sts_desc_cnt(sts_data) \
(((sts_data) >> 53) & 0x7)
#define netxen_get_sts_opcode(sts_data) \
(((sts_data) >> 58) & 0x03F)

struct status_desc {
/* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-27 total_length
28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
53-55 desc_cnt, 56-57 owner, 58-63 opcode
*/
__le64 status_desc_data;
union {
struct {
__le32 hash_value;
u8 hash_type;
u8 msg_type;
u8 unused;
union {
/* Bit pattern: 0-6 lro_count indicates frag
* sequence, 7 last_frag indicates last frag
*/
u8 lro;

/* chained buffers */
u8 nr_frags;
};
};
struct {
__le16 frag_handles[4];
};
};
__le64 status_desc_data[2];
} __attribute__ ((aligned(16)));

/* The version of the main data structure */
Expand Down Expand Up @@ -1114,6 +1096,66 @@ typedef struct {
#define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */
#define VPORT_MISS_MODE_ACCEPT_MULTI 2 /* accept unmatched multicast */

#define NX_FW_CAPABILITY_LINK_NOTIFICATION (1 << 5)
#define NX_FW_CAPABILITY_SWITCHING (1 << 6)

/* module types */
#define LINKEVENT_MODULE_NOT_PRESENT 1
#define LINKEVENT_MODULE_OPTICAL_UNKNOWN 2
#define LINKEVENT_MODULE_OPTICAL_SRLR 3
#define LINKEVENT_MODULE_OPTICAL_LRM 4
#define LINKEVENT_MODULE_OPTICAL_SFP_1G 5
#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE 6
#define LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN 7
#define LINKEVENT_MODULE_TWINAX 8

#define LINKSPEED_10GBPS 10000
#define LINKSPEED_1GBPS 1000
#define LINKSPEED_100MBPS 100
#define LINKSPEED_10MBPS 10

#define LINKSPEED_ENCODED_10MBPS 0
#define LINKSPEED_ENCODED_100MBPS 1
#define LINKSPEED_ENCODED_1GBPS 2

#define LINKEVENT_AUTONEG_DISABLED 0
#define LINKEVENT_AUTONEG_ENABLED 1

#define LINKEVENT_HALF_DUPLEX 0
#define LINKEVENT_FULL_DUPLEX 1

#define LINKEVENT_LINKSPEED_MBPS 0
#define LINKEVENT_LINKSPEED_ENCODED 1

/* firmware response header:
* 63:58 - message type
* 57:56 - owner
* 55:53 - desc count
* 52:48 - reserved
* 47:40 - completion id
* 39:32 - opcode
* 31:16 - error code
* 15:00 - reserved
*/
#define netxen_get_nic_msgtype(msg_hdr) \
((msg_hdr >> 58) & 0x3F)
#define netxen_get_nic_msg_compid(msg_hdr) \
((msg_hdr >> 40) & 0xFF)
#define netxen_get_nic_msg_opcode(msg_hdr) \
((msg_hdr >> 32) & 0xFF)
#define netxen_get_nic_msg_errcode(msg_hdr) \
((msg_hdr >> 16) & 0xFFFF)

typedef struct {
union {
struct {
u64 hdr;
u64 body[7];
};
u64 words[8];
};
} nx_fw_msg_t;

typedef struct {
__le64 qhdr;
__le64 req_hdr;
Expand Down Expand Up @@ -1177,15 +1219,21 @@ struct netxen_adapter {

u8 mc_enabled;
u8 max_mc_count;
u16 resv2;
u32 resv3;

u8 has_link_events;
u8 resv1;
u16 tx_context_id;
u16 mtu;
u16 is_up;

u16 link_speed;
u16 link_duplex;
u16 link_autoneg;
u16 resv1;
u16 module_type;

u32 resv2;
u32 capabilities;
u32 flags;
u32 irq;
u32 temp;
Expand Down Expand Up @@ -1398,6 +1446,8 @@ void netxen_p3_free_mac_list(struct netxen_adapter *adapter);
int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32);
int netxen_config_intr_coalesce(struct netxen_adapter *adapter);
int netxen_config_rss(struct netxen_adapter *adapter, int enable);
int netxen_linkevent_request(struct netxen_adapter *adapter, int enable);
void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup);

int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu);
int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
Expand Down
32 changes: 31 additions & 1 deletion drivers/net/netxen/netxen_nic_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ static int
netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
struct netxen_adapter *adapter = netdev_priv(dev);
int check_sfp_module = 0;

/* read which mode */
if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
Expand Down Expand Up @@ -143,6 +144,13 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->advertising = ADVERTISED_10000baseT_Full;
}

if (netif_running(dev) && adapter->has_link_events) {
ecmd->speed = adapter->link_speed;
ecmd->autoneg = adapter->link_autoneg;
ecmd->duplex = adapter->link_duplex;
goto skip;
}

ecmd->port = PORT_TP;

if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
Expand All @@ -160,6 +168,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
} else
return -EIO;

skip:
ecmd->phy_address = adapter->physical_port;
ecmd->transceiver = XCVR_EXTERNAL;

Expand Down Expand Up @@ -190,14 +199,16 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
case NETXEN_BRDTYPE_P3_HMEZ:
ecmd->supported |= SUPPORTED_MII;
ecmd->advertising |= ADVERTISED_MII;
ecmd->port = PORT_FIBRE;
ecmd->port = PORT_MII;
ecmd->autoneg = AUTONEG_DISABLE;
break;
case NETXEN_BRDTYPE_P3_10G_SFP_PLUS:
case NETXEN_BRDTYPE_P3_10G_SFP_CT:
case NETXEN_BRDTYPE_P3_10G_SFP_QT:
ecmd->advertising |= ADVERTISED_TP;
ecmd->supported |= SUPPORTED_TP;
check_sfp_module = netif_running(dev) &&
adapter->has_link_events;
case NETXEN_BRDTYPE_P2_SB31_10G:
case NETXEN_BRDTYPE_P3_10G_XFP:
ecmd->supported |= SUPPORTED_FIBRE;
Expand All @@ -212,6 +223,8 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
ecmd->advertising |=
(ADVERTISED_FIBRE | ADVERTISED_TP);
ecmd->port = PORT_FIBRE;
check_sfp_module = netif_running(dev) &&
adapter->has_link_events;
} else {
ecmd->autoneg = AUTONEG_ENABLE;
ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
Expand All @@ -226,6 +239,23 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
return -EIO;
}

if (check_sfp_module) {
switch (adapter->module_type) {
case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
case LINKEVENT_MODULE_OPTICAL_SRLR:
case LINKEVENT_MODULE_OPTICAL_LRM:
case LINKEVENT_MODULE_OPTICAL_SFP_1G:
ecmd->port = PORT_FIBRE;
break;
case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
case LINKEVENT_MODULE_TWINAX:
ecmd->port = PORT_TP;
default:
ecmd->port = -1;
}
}

return 0;
}

Expand Down
22 changes: 22 additions & 0 deletions drivers/net/netxen/netxen_nic_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,28 @@ int netxen_config_rss(struct netxen_adapter *adapter, int enable)
return rv;
}

int netxen_linkevent_request(struct netxen_adapter *adapter, int enable)
{
nx_nic_req_t req;
u64 word;
int rv;

memset(&req, 0, sizeof(nx_nic_req_t));
req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23);

word = NX_NIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16);
req.req_hdr = cpu_to_le64(word);
req.words[0] = cpu_to_le64(enable);

rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0) {
printk(KERN_ERR "%s: could not configure link notification\n",
adapter->netdev->name);
}

return rv;
}

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

0 comments on commit 3bf26ce

Please sign in to comment.