Skip to content

Commit

Permalink
Merge branch 'cxgb4'
Browse files Browse the repository at this point in the history
Hariprasad Shenai says:

====================
Adds support for Chelsio T5 40G adapter and Misc. fixes

This patch series adds support for Chelsio T5 40G adapters and provides
miscelleneous fixes for cxgb4 driver.

It also adds device ids of two new T5 adapters.

We would like to request this patch series to get merged via David Miller's
'net-next' tree.

We have included all the maintainers of respective drivers. Kindly review the
change and let us know in case of any review comments.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 18, 2014
2 parents 9fa9e49 + f0a8e6d commit b0b9ad7
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 30 deletions.
5 changes: 4 additions & 1 deletion drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ enum {
SERNUM_LEN = 24, /* Serial # length */
EC_LEN = 16, /* E/C length */
ID_LEN = 16, /* ID length */
PN_LEN = 16, /* Part Number length */
};

enum {
Expand Down Expand Up @@ -254,6 +255,7 @@ struct vpd_params {
u8 ec[EC_LEN + 1];
u8 sn[SERNUM_LEN + 1];
u8 id[ID_LEN + 1];
u8 pn[PN_LEN + 1];
};

struct pci_params {
Expand Down Expand Up @@ -306,6 +308,7 @@ struct adapter_params {
unsigned char bypass;

unsigned int ofldq_wr_cred;
bool ulptx_memwrite_dsgl; /* use of T5 DSGL allowed */
};

#include "t4fw_api.h"
Expand Down Expand Up @@ -957,7 +960,7 @@ int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,
u64 *parity);
int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data,
u64 *parity);

const char *t4_get_port_type_description(enum fw_port_type port_type);
void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p);
void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log);
void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
Expand Down
61 changes: 45 additions & 16 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
CH_DEVICE(0x5011, 4),
CH_DEVICE(0x5012, 4),
CH_DEVICE(0x5013, 4),
CH_DEVICE(0x5014, 4),
CH_DEVICE(0x5015, 4),
CH_DEVICE(0x5401, 4),
CH_DEVICE(0x5402, 4),
CH_DEVICE(0x5403, 4),
Expand All @@ -273,6 +275,8 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = {
CH_DEVICE(0x5411, 4),
CH_DEVICE(0x5412, 4),
CH_DEVICE(0x5413, 4),
CH_DEVICE(0x5414, 4),
CH_DEVICE(0x5415, 4),
{ 0, }
};

Expand Down Expand Up @@ -432,6 +436,9 @@ static void link_report(struct net_device *dev)
case SPEED_100:
s = "100Mbps";
break;
case 40000: /* Need a SPEED_40000 in ethtool.h */
s = "40Gbps";
break;
}

netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s,
Expand Down Expand Up @@ -2061,7 +2068,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
0x40200, 0x40298,
0x402ac, 0x4033c,
0x403f8, 0x403fc,
0x41300, 0x413c4,
0x41304, 0x413c4,
0x41400, 0x4141c,
0x41480, 0x414d0,
0x44000, 0x44078,
Expand Down Expand Up @@ -2089,7 +2096,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
0x48200, 0x48298,
0x482ac, 0x4833c,
0x483f8, 0x483fc,
0x49300, 0x493c4,
0x49304, 0x493c4,
0x49400, 0x4941c,
0x49480, 0x494d0,
0x4c000, 0x4c078,
Expand Down Expand Up @@ -2199,6 +2206,8 @@ static unsigned int from_fw_linkcaps(unsigned int type, unsigned int caps)
else if (type == FW_PORT_TYPE_FIBER_XFI ||
type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP)
v |= SUPPORTED_FIBRE;
else if (type == FW_PORT_TYPE_BP40_BA)
v |= SUPPORTED_40000baseSR4_Full;

if (caps & FW_PORT_CAP_ANEG)
v |= SUPPORTED_Autoneg;
Expand All @@ -2215,6 +2224,8 @@ static unsigned int to_fw_linkcaps(unsigned int caps)
v |= FW_PORT_CAP_SPEED_1G;
if (caps & ADVERTISED_10000baseT_Full)
v |= FW_PORT_CAP_SPEED_10G;
if (caps & ADVERTISED_40000baseSR4_Full)
v |= FW_PORT_CAP_SPEED_40G;
return v;
}

Expand Down Expand Up @@ -2269,6 +2280,8 @@ static unsigned int speed_to_caps(int speed)
return FW_PORT_CAP_SPEED_1G;
if (speed == SPEED_10000)
return FW_PORT_CAP_SPEED_10G;
if (speed == 40000) /* Need SPEED_40000 in ethtool.h */
return FW_PORT_CAP_SPEED_40G;
return 0;
}

Expand Down Expand Up @@ -2296,8 +2309,10 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (cmd->autoneg == AUTONEG_DISABLE) {
cap = speed_to_caps(speed);

if (!(lc->supported & cap) || (speed == SPEED_1000) ||
(speed == SPEED_10000))
if (!(lc->supported & cap) ||
(speed == SPEED_1000) ||
(speed == SPEED_10000) ||
(speed == 40000))
return -EINVAL;
lc->requested_speed = cap;
lc->advertising = 0;
Expand Down Expand Up @@ -3765,6 +3780,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
lli.dbfifo_int_thresh = dbfifo_int_thresh;
lli.sge_pktshift = adap->sge.pktshift;
lli.enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN;
lli.ulptx_memwrite_dsgl = adap->params.ulptx_memwrite_dsgl;

handle = ulds[uld].add(&lli);
if (IS_ERR(handle)) {
Expand Down Expand Up @@ -5369,6 +5385,21 @@ static int adap_init0(struct adapter *adap)
val[0] = 1;
(void) t4_set_params(adap, adap->mbox, adap->fn, 0, 1, params, val);

/*
* Find out whether we're allowed to use the T5+ ULPTX MEMWRITE DSGL
* capability. Earlier versions of the firmware didn't have the
* ULPTX_MEMWRITE_DSGL so we'll interpret a query failure as no
* permission to use ULPTX MEMWRITE DSGL.
*/
if (is_t4(adap->params.chip)) {
adap->params.ulptx_memwrite_dsgl = false;
} else {
params[0] = FW_PARAM_DEV(ULPTX_MEMWRITE_DSGL);
ret = t4_query_params(adap, adap->mbox, adap->fn, 0,
1, params, val);
adap->params.ulptx_memwrite_dsgl = (ret == 0 && val[0] != 0);
}

/*
* Get device capabilities so we can determine what resources we need
* to manage.
Expand Down Expand Up @@ -5603,9 +5634,10 @@ static const struct pci_error_handlers cxgb4_eeh = {
.resume = eeh_resume,
};

static inline bool is_10g_port(const struct link_config *lc)
static inline bool is_x_10g_port(const struct link_config *lc)
{
return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0;
return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0 ||
(lc->supported & FW_PORT_CAP_SPEED_40G) != 0;
}

static inline void init_rspq(struct sge_rspq *q, u8 timer_idx, u8 pkt_cnt_idx,
Expand All @@ -5629,7 +5661,7 @@ static void cfg_queues(struct adapter *adap)
int i, q10g = 0, n10g = 0, qidx = 0;

for_each_port(adap, i)
n10g += is_10g_port(&adap2pinfo(adap, i)->link_cfg);
n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg);

/*
* We default to 1 queue per non-10G port and up to # of cores queues
Expand All @@ -5644,7 +5676,7 @@ static void cfg_queues(struct adapter *adap)
struct port_info *pi = adap2pinfo(adap, i);

pi->first_qset = qidx;
pi->nqsets = is_10g_port(&pi->link_cfg) ? q10g : 1;
pi->nqsets = is_x_10g_port(&pi->link_cfg) ? q10g : 1;
qidx += pi->nqsets;
}

Expand Down Expand Up @@ -5799,11 +5831,6 @@ static int init_rss(struct adapter *adap)

static void print_port_info(const struct net_device *dev)
{
static const char *base[] = {
"R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4",
"KX", "KR", "R SFP+", "KR/KX", "KR/KX/KX4"
};

char buf[80];
char *bufp = buf;
const char *spd = "";
Expand All @@ -5821,18 +5848,20 @@ static void print_port_info(const struct net_device *dev)
bufp += sprintf(bufp, "1000/");
if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G)
bufp += sprintf(bufp, "10G/");
if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_40G)
bufp += sprintf(bufp, "40G/");
if (bufp != buf)
--bufp;
sprintf(bufp, "BASE-%s", base[pi->port_type]);
sprintf(bufp, "BASE-%s", t4_get_port_type_description(pi->port_type));

netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n",
adap->params.vpd.id,
CHELSIO_CHIP_RELEASE(adap->params.chip), buf,
is_offload(adap) ? "R" : "", adap->params.pci.width, spd,
(adap->flags & USING_MSIX) ? " MSI-X" :
(adap->flags & USING_MSI) ? " MSI" : "");
netdev_info(dev, "S/N: %s, E/C: %s\n",
adap->params.vpd.sn, adap->params.vpd.ec);
netdev_info(dev, "S/N: %s, P/N: %s\n",
adap->params.vpd.sn, adap->params.vpd.pn);
}

static void enable_pcie_relaxed_ordering(struct pci_dev *dev)
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ struct cxgb4_lld_info {
/* packet data */
bool enable_fw_ofld_conn; /* Enable connection through fw */
/* WR */
bool ulptx_memwrite_dsgl; /* use of T5 DSGL allowed */
};

struct cxgb4_uld_info {
Expand Down
38 changes: 27 additions & 11 deletions drivers/net/ethernet/chelsio/cxgb4/sge.c
Original file line number Diff line number Diff line change
Expand Up @@ -706,11 +706,17 @@ static inline unsigned int flits_to_desc(unsigned int n)
* @skb: the packet
*
* Returns whether an Ethernet packet is small enough to fit as
* immediate data.
* immediate data. Return value corresponds to headroom required.
*/
static inline int is_eth_imm(const struct sk_buff *skb)
{
return skb->len <= MAX_IMM_TX_PKT_LEN - sizeof(struct cpl_tx_pkt);
int hdrlen = skb_shinfo(skb)->gso_size ?
sizeof(struct cpl_tx_pkt_lso_core) : 0;

hdrlen += sizeof(struct cpl_tx_pkt);
if (skb->len <= MAX_IMM_TX_PKT_LEN - hdrlen)
return hdrlen;
return 0;
}

/**
Expand All @@ -723,9 +729,10 @@ static inline int is_eth_imm(const struct sk_buff *skb)
static inline unsigned int calc_tx_flits(const struct sk_buff *skb)
{
unsigned int flits;
int hdrlen = is_eth_imm(skb);

if (is_eth_imm(skb))
return DIV_ROUND_UP(skb->len + sizeof(struct cpl_tx_pkt), 8);
if (hdrlen)
return DIV_ROUND_UP(skb->len + hdrlen, sizeof(__be64));

flits = sgl_len(skb_shinfo(skb)->nr_frags + 1) + 4;
if (skb_shinfo(skb)->gso_size)
Expand Down Expand Up @@ -971,6 +978,7 @@ static inline void txq_advance(struct sge_txq *q, unsigned int n)
*/
netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
{
int len;
u32 wr_mid;
u64 cntrl, *end;
int qidx, credits;
Expand All @@ -982,6 +990,7 @@ netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev)
struct cpl_tx_pkt_core *cpl;
const struct skb_shared_info *ssi;
dma_addr_t addr[MAX_SKB_FRAGS + 1];
bool immediate = false;

/*
* The chip min packet length is 10 octets but play safe and reject
Expand Down Expand Up @@ -1011,7 +1020,10 @@ out_free: dev_kfree_skb(skb);
return NETDEV_TX_BUSY;
}

if (!is_eth_imm(skb) &&
if (is_eth_imm(skb))
immediate = true;

if (!immediate &&
unlikely(map_skb(adap->pdev_dev, skb, addr) < 0)) {
q->mapping_err++;
goto out_free;
Expand All @@ -1028,15 +1040,18 @@ out_free: dev_kfree_skb(skb);
wr->r3 = cpu_to_be64(0);
end = (u64 *)wr + flits;

len = immediate ? skb->len : 0;
len += sizeof(*cpl);
ssi = skb_shinfo(skb);
if (ssi->gso_size) {
struct cpl_tx_pkt_lso *lso = (void *)wr;
bool v6 = (ssi->gso_type & SKB_GSO_TCPV6) != 0;
int l3hdr_len = skb_network_header_len(skb);
int eth_xtra_len = skb_network_offset(skb) - ETH_HLEN;

len += sizeof(*lso);
wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) |
FW_WR_IMMDLEN(sizeof(*lso)));
FW_WR_IMMDLEN(len));
lso->c.lso_ctrl = htonl(LSO_OPCODE(CPL_TX_PKT_LSO) |
LSO_FIRST_SLICE | LSO_LAST_SLICE |
LSO_IPV6(v6) |
Expand All @@ -1054,9 +1069,6 @@ out_free: dev_kfree_skb(skb);
q->tso++;
q->tx_cso += ssi->gso_segs;
} else {
int len;

len = is_eth_imm(skb) ? skb->len + sizeof(*cpl) : sizeof(*cpl);
wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) |
FW_WR_IMMDLEN(len));
cpl = (void *)(wr + 1);
Expand All @@ -1078,7 +1090,7 @@ out_free: dev_kfree_skb(skb);
cpl->len = htons(skb->len);
cpl->ctrl1 = cpu_to_be64(cntrl);

if (is_eth_imm(skb)) {
if (immediate) {
inline_tx_skb(skb, &q->q, cpl + 1);
dev_kfree_skb(skb);
} else {
Expand Down Expand Up @@ -1467,8 +1479,12 @@ static inline int ofld_send(struct adapter *adap, struct sk_buff *skb)
{
unsigned int idx = skb_txq(skb);

if (unlikely(is_ctrl_pkt(skb)))
if (unlikely(is_ctrl_pkt(skb))) {
/* Single ctrl queue is a requirement for LE workaround path */
if (adap->tids.nsftids)
idx = 0;
return ctrl_xmit(&adap->sge.ctrlq[idx], skb);
}
return ofld_xmit(&adap->sge.ofldtxq[idx], skb);
}

Expand Down
Loading

0 comments on commit b0b9ad7

Please sign in to comment.