diff options
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 61 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/sge.c | 38 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 40 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 4 |
6 files changed, 119 insertions, 30 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 1f4b9b30b9ed..944f2cbc1795 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | |||
@@ -66,6 +66,7 @@ enum { | |||
66 | SERNUM_LEN = 24, /* Serial # length */ | 66 | SERNUM_LEN = 24, /* Serial # length */ |
67 | EC_LEN = 16, /* E/C length */ | 67 | EC_LEN = 16, /* E/C length */ |
68 | ID_LEN = 16, /* ID length */ | 68 | ID_LEN = 16, /* ID length */ |
69 | PN_LEN = 16, /* Part Number length */ | ||
69 | }; | 70 | }; |
70 | 71 | ||
71 | enum { | 72 | enum { |
@@ -254,6 +255,7 @@ struct vpd_params { | |||
254 | u8 ec[EC_LEN + 1]; | 255 | u8 ec[EC_LEN + 1]; |
255 | u8 sn[SERNUM_LEN + 1]; | 256 | u8 sn[SERNUM_LEN + 1]; |
256 | u8 id[ID_LEN + 1]; | 257 | u8 id[ID_LEN + 1]; |
258 | u8 pn[PN_LEN + 1]; | ||
257 | }; | 259 | }; |
258 | 260 | ||
259 | struct pci_params { | 261 | struct pci_params { |
@@ -306,6 +308,7 @@ struct adapter_params { | |||
306 | unsigned char bypass; | 308 | unsigned char bypass; |
307 | 309 | ||
308 | unsigned int ofldq_wr_cred; | 310 | unsigned int ofldq_wr_cred; |
311 | bool ulptx_memwrite_dsgl; /* use of T5 DSGL allowed */ | ||
309 | }; | 312 | }; |
310 | 313 | ||
311 | #include "t4fw_api.h" | 314 | #include "t4fw_api.h" |
@@ -957,7 +960,7 @@ int t4_mc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, | |||
957 | u64 *parity); | 960 | u64 *parity); |
958 | int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, | 961 | int t4_edc_read(struct adapter *adap, int idx, u32 addr, __be32 *data, |
959 | u64 *parity); | 962 | u64 *parity); |
960 | 963 | const char *t4_get_port_type_description(enum fw_port_type port_type); | |
961 | void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p); | 964 | void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p); |
962 | void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log); | 965 | void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log); |
963 | void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr, | 966 | void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr, |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index bd0321d8b612..4660f55e292b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | |||
@@ -254,6 +254,8 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = { | |||
254 | CH_DEVICE(0x5011, 4), | 254 | CH_DEVICE(0x5011, 4), |
255 | CH_DEVICE(0x5012, 4), | 255 | CH_DEVICE(0x5012, 4), |
256 | CH_DEVICE(0x5013, 4), | 256 | CH_DEVICE(0x5013, 4), |
257 | CH_DEVICE(0x5014, 4), | ||
258 | CH_DEVICE(0x5015, 4), | ||
257 | CH_DEVICE(0x5401, 4), | 259 | CH_DEVICE(0x5401, 4), |
258 | CH_DEVICE(0x5402, 4), | 260 | CH_DEVICE(0x5402, 4), |
259 | CH_DEVICE(0x5403, 4), | 261 | CH_DEVICE(0x5403, 4), |
@@ -273,6 +275,8 @@ static DEFINE_PCI_DEVICE_TABLE(cxgb4_pci_tbl) = { | |||
273 | CH_DEVICE(0x5411, 4), | 275 | CH_DEVICE(0x5411, 4), |
274 | CH_DEVICE(0x5412, 4), | 276 | CH_DEVICE(0x5412, 4), |
275 | CH_DEVICE(0x5413, 4), | 277 | CH_DEVICE(0x5413, 4), |
278 | CH_DEVICE(0x5414, 4), | ||
279 | CH_DEVICE(0x5415, 4), | ||
276 | { 0, } | 280 | { 0, } |
277 | }; | 281 | }; |
278 | 282 | ||
@@ -432,6 +436,9 @@ static void link_report(struct net_device *dev) | |||
432 | case SPEED_100: | 436 | case SPEED_100: |
433 | s = "100Mbps"; | 437 | s = "100Mbps"; |
434 | break; | 438 | break; |
439 | case 40000: /* Need a SPEED_40000 in ethtool.h */ | ||
440 | s = "40Gbps"; | ||
441 | break; | ||
435 | } | 442 | } |
436 | 443 | ||
437 | netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s, | 444 | netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s, |
@@ -2061,7 +2068,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs, | |||
2061 | 0x40200, 0x40298, | 2068 | 0x40200, 0x40298, |
2062 | 0x402ac, 0x4033c, | 2069 | 0x402ac, 0x4033c, |
2063 | 0x403f8, 0x403fc, | 2070 | 0x403f8, 0x403fc, |
2064 | 0x41300, 0x413c4, | 2071 | 0x41304, 0x413c4, |
2065 | 0x41400, 0x4141c, | 2072 | 0x41400, 0x4141c, |
2066 | 0x41480, 0x414d0, | 2073 | 0x41480, 0x414d0, |
2067 | 0x44000, 0x44078, | 2074 | 0x44000, 0x44078, |
@@ -2089,7 +2096,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs, | |||
2089 | 0x48200, 0x48298, | 2096 | 0x48200, 0x48298, |
2090 | 0x482ac, 0x4833c, | 2097 | 0x482ac, 0x4833c, |
2091 | 0x483f8, 0x483fc, | 2098 | 0x483f8, 0x483fc, |
2092 | 0x49300, 0x493c4, | 2099 | 0x49304, 0x493c4, |
2093 | 0x49400, 0x4941c, | 2100 | 0x49400, 0x4941c, |
2094 | 0x49480, 0x494d0, | 2101 | 0x49480, 0x494d0, |
2095 | 0x4c000, 0x4c078, | 2102 | 0x4c000, 0x4c078, |
@@ -2199,6 +2206,8 @@ static unsigned int from_fw_linkcaps(unsigned int type, unsigned int caps) | |||
2199 | else if (type == FW_PORT_TYPE_FIBER_XFI || | 2206 | else if (type == FW_PORT_TYPE_FIBER_XFI || |
2200 | type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP) | 2207 | type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP) |
2201 | v |= SUPPORTED_FIBRE; | 2208 | v |= SUPPORTED_FIBRE; |
2209 | else if (type == FW_PORT_TYPE_BP40_BA) | ||
2210 | v |= SUPPORTED_40000baseSR4_Full; | ||
2202 | 2211 | ||
2203 | if (caps & FW_PORT_CAP_ANEG) | 2212 | if (caps & FW_PORT_CAP_ANEG) |
2204 | v |= SUPPORTED_Autoneg; | 2213 | v |= SUPPORTED_Autoneg; |
@@ -2215,6 +2224,8 @@ static unsigned int to_fw_linkcaps(unsigned int caps) | |||
2215 | v |= FW_PORT_CAP_SPEED_1G; | 2224 | v |= FW_PORT_CAP_SPEED_1G; |
2216 | if (caps & ADVERTISED_10000baseT_Full) | 2225 | if (caps & ADVERTISED_10000baseT_Full) |
2217 | v |= FW_PORT_CAP_SPEED_10G; | 2226 | v |= FW_PORT_CAP_SPEED_10G; |
2227 | if (caps & ADVERTISED_40000baseSR4_Full) | ||
2228 | v |= FW_PORT_CAP_SPEED_40G; | ||
2218 | return v; | 2229 | return v; |
2219 | } | 2230 | } |
2220 | 2231 | ||
@@ -2269,6 +2280,8 @@ static unsigned int speed_to_caps(int speed) | |||
2269 | return FW_PORT_CAP_SPEED_1G; | 2280 | return FW_PORT_CAP_SPEED_1G; |
2270 | if (speed == SPEED_10000) | 2281 | if (speed == SPEED_10000) |
2271 | return FW_PORT_CAP_SPEED_10G; | 2282 | return FW_PORT_CAP_SPEED_10G; |
2283 | if (speed == 40000) /* Need SPEED_40000 in ethtool.h */ | ||
2284 | return FW_PORT_CAP_SPEED_40G; | ||
2272 | return 0; | 2285 | return 0; |
2273 | } | 2286 | } |
2274 | 2287 | ||
@@ -2296,8 +2309,10 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
2296 | if (cmd->autoneg == AUTONEG_DISABLE) { | 2309 | if (cmd->autoneg == AUTONEG_DISABLE) { |
2297 | cap = speed_to_caps(speed); | 2310 | cap = speed_to_caps(speed); |
2298 | 2311 | ||
2299 | if (!(lc->supported & cap) || (speed == SPEED_1000) || | 2312 | if (!(lc->supported & cap) || |
2300 | (speed == SPEED_10000)) | 2313 | (speed == SPEED_1000) || |
2314 | (speed == SPEED_10000) || | ||
2315 | (speed == 40000)) | ||
2301 | return -EINVAL; | 2316 | return -EINVAL; |
2302 | lc->requested_speed = cap; | 2317 | lc->requested_speed = cap; |
2303 | lc->advertising = 0; | 2318 | lc->advertising = 0; |
@@ -3765,6 +3780,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld) | |||
3765 | lli.dbfifo_int_thresh = dbfifo_int_thresh; | 3780 | lli.dbfifo_int_thresh = dbfifo_int_thresh; |
3766 | lli.sge_pktshift = adap->sge.pktshift; | 3781 | lli.sge_pktshift = adap->sge.pktshift; |
3767 | lli.enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN; | 3782 | lli.enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN; |
3783 | lli.ulptx_memwrite_dsgl = adap->params.ulptx_memwrite_dsgl; | ||
3768 | 3784 | ||
3769 | handle = ulds[uld].add(&lli); | 3785 | handle = ulds[uld].add(&lli); |
3770 | if (IS_ERR(handle)) { | 3786 | if (IS_ERR(handle)) { |
@@ -5370,6 +5386,21 @@ static int adap_init0(struct adapter *adap) | |||
5370 | (void) t4_set_params(adap, adap->mbox, adap->fn, 0, 1, params, val); | 5386 | (void) t4_set_params(adap, adap->mbox, adap->fn, 0, 1, params, val); |
5371 | 5387 | ||
5372 | /* | 5388 | /* |
5389 | * Find out whether we're allowed to use the T5+ ULPTX MEMWRITE DSGL | ||
5390 | * capability. Earlier versions of the firmware didn't have the | ||
5391 | * ULPTX_MEMWRITE_DSGL so we'll interpret a query failure as no | ||
5392 | * permission to use ULPTX MEMWRITE DSGL. | ||
5393 | */ | ||
5394 | if (is_t4(adap->params.chip)) { | ||
5395 | adap->params.ulptx_memwrite_dsgl = false; | ||
5396 | } else { | ||
5397 | params[0] = FW_PARAM_DEV(ULPTX_MEMWRITE_DSGL); | ||
5398 | ret = t4_query_params(adap, adap->mbox, adap->fn, 0, | ||
5399 | 1, params, val); | ||
5400 | adap->params.ulptx_memwrite_dsgl = (ret == 0 && val[0] != 0); | ||
5401 | } | ||
5402 | |||
5403 | /* | ||
5373 | * Get device capabilities so we can determine what resources we need | 5404 | * Get device capabilities so we can determine what resources we need |
5374 | * to manage. | 5405 | * to manage. |
5375 | */ | 5406 | */ |
@@ -5603,9 +5634,10 @@ static const struct pci_error_handlers cxgb4_eeh = { | |||
5603 | .resume = eeh_resume, | 5634 | .resume = eeh_resume, |
5604 | }; | 5635 | }; |
5605 | 5636 | ||
5606 | static inline bool is_10g_port(const struct link_config *lc) | 5637 | static inline bool is_x_10g_port(const struct link_config *lc) |
5607 | { | 5638 | { |
5608 | return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0; | 5639 | return (lc->supported & FW_PORT_CAP_SPEED_10G) != 0 || |
5640 | (lc->supported & FW_PORT_CAP_SPEED_40G) != 0; | ||
5609 | } | 5641 | } |
5610 | 5642 | ||
5611 | static inline void init_rspq(struct sge_rspq *q, u8 timer_idx, u8 pkt_cnt_idx, | 5643 | static inline void init_rspq(struct sge_rspq *q, u8 timer_idx, u8 pkt_cnt_idx, |
@@ -5629,7 +5661,7 @@ static void cfg_queues(struct adapter *adap) | |||
5629 | int i, q10g = 0, n10g = 0, qidx = 0; | 5661 | int i, q10g = 0, n10g = 0, qidx = 0; |
5630 | 5662 | ||
5631 | for_each_port(adap, i) | 5663 | for_each_port(adap, i) |
5632 | n10g += is_10g_port(&adap2pinfo(adap, i)->link_cfg); | 5664 | n10g += is_x_10g_port(&adap2pinfo(adap, i)->link_cfg); |
5633 | 5665 | ||
5634 | /* | 5666 | /* |
5635 | * We default to 1 queue per non-10G port and up to # of cores queues | 5667 | * We default to 1 queue per non-10G port and up to # of cores queues |
@@ -5644,7 +5676,7 @@ static void cfg_queues(struct adapter *adap) | |||
5644 | struct port_info *pi = adap2pinfo(adap, i); | 5676 | struct port_info *pi = adap2pinfo(adap, i); |
5645 | 5677 | ||
5646 | pi->first_qset = qidx; | 5678 | pi->first_qset = qidx; |
5647 | pi->nqsets = is_10g_port(&pi->link_cfg) ? q10g : 1; | 5679 | pi->nqsets = is_x_10g_port(&pi->link_cfg) ? q10g : 1; |
5648 | qidx += pi->nqsets; | 5680 | qidx += pi->nqsets; |
5649 | } | 5681 | } |
5650 | 5682 | ||
@@ -5799,11 +5831,6 @@ static int init_rss(struct adapter *adap) | |||
5799 | 5831 | ||
5800 | static void print_port_info(const struct net_device *dev) | 5832 | static void print_port_info(const struct net_device *dev) |
5801 | { | 5833 | { |
5802 | static const char *base[] = { | ||
5803 | "R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4", | ||
5804 | "KX", "KR", "R SFP+", "KR/KX", "KR/KX/KX4" | ||
5805 | }; | ||
5806 | |||
5807 | char buf[80]; | 5834 | char buf[80]; |
5808 | char *bufp = buf; | 5835 | char *bufp = buf; |
5809 | const char *spd = ""; | 5836 | const char *spd = ""; |
@@ -5821,9 +5848,11 @@ static void print_port_info(const struct net_device *dev) | |||
5821 | bufp += sprintf(bufp, "1000/"); | 5848 | bufp += sprintf(bufp, "1000/"); |
5822 | if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G) | 5849 | if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_10G) |
5823 | bufp += sprintf(bufp, "10G/"); | 5850 | bufp += sprintf(bufp, "10G/"); |
5851 | if (pi->link_cfg.supported & FW_PORT_CAP_SPEED_40G) | ||
5852 | bufp += sprintf(bufp, "40G/"); | ||
5824 | if (bufp != buf) | 5853 | if (bufp != buf) |
5825 | --bufp; | 5854 | --bufp; |
5826 | sprintf(bufp, "BASE-%s", base[pi->port_type]); | 5855 | sprintf(bufp, "BASE-%s", t4_get_port_type_description(pi->port_type)); |
5827 | 5856 | ||
5828 | netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n", | 5857 | netdev_info(dev, "Chelsio %s rev %d %s %sNIC PCIe x%d%s%s\n", |
5829 | adap->params.vpd.id, | 5858 | adap->params.vpd.id, |
@@ -5831,8 +5860,8 @@ static void print_port_info(const struct net_device *dev) | |||
5831 | is_offload(adap) ? "R" : "", adap->params.pci.width, spd, | 5860 | is_offload(adap) ? "R" : "", adap->params.pci.width, spd, |
5832 | (adap->flags & USING_MSIX) ? " MSI-X" : | 5861 | (adap->flags & USING_MSIX) ? " MSI-X" : |
5833 | (adap->flags & USING_MSI) ? " MSI" : ""); | 5862 | (adap->flags & USING_MSI) ? " MSI" : ""); |
5834 | netdev_info(dev, "S/N: %s, E/C: %s\n", | 5863 | netdev_info(dev, "S/N: %s, P/N: %s\n", |
5835 | adap->params.vpd.sn, adap->params.vpd.ec); | 5864 | adap->params.vpd.sn, adap->params.vpd.pn); |
5836 | } | 5865 | } |
5837 | 5866 | ||
5838 | static void enable_pcie_relaxed_ordering(struct pci_dev *dev) | 5867 | static void enable_pcie_relaxed_ordering(struct pci_dev *dev) |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index 4dd0a82533e4..e274a047528f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h | |||
@@ -253,6 +253,7 @@ struct cxgb4_lld_info { | |||
253 | /* packet data */ | 253 | /* packet data */ |
254 | bool enable_fw_ofld_conn; /* Enable connection through fw */ | 254 | bool enable_fw_ofld_conn; /* Enable connection through fw */ |
255 | /* WR */ | 255 | /* WR */ |
256 | bool ulptx_memwrite_dsgl; /* use of T5 DSGL allowed */ | ||
256 | }; | 257 | }; |
257 | 258 | ||
258 | struct cxgb4_uld_info { | 259 | struct cxgb4_uld_info { |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 47ffa64fcf19..af76b25bb606 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c | |||
@@ -706,11 +706,17 @@ static inline unsigned int flits_to_desc(unsigned int n) | |||
706 | * @skb: the packet | 706 | * @skb: the packet |
707 | * | 707 | * |
708 | * Returns whether an Ethernet packet is small enough to fit as | 708 | * Returns whether an Ethernet packet is small enough to fit as |
709 | * immediate data. | 709 | * immediate data. Return value corresponds to headroom required. |
710 | */ | 710 | */ |
711 | static inline int is_eth_imm(const struct sk_buff *skb) | 711 | static inline int is_eth_imm(const struct sk_buff *skb) |
712 | { | 712 | { |
713 | return skb->len <= MAX_IMM_TX_PKT_LEN - sizeof(struct cpl_tx_pkt); | 713 | int hdrlen = skb_shinfo(skb)->gso_size ? |
714 | sizeof(struct cpl_tx_pkt_lso_core) : 0; | ||
715 | |||
716 | hdrlen += sizeof(struct cpl_tx_pkt); | ||
717 | if (skb->len <= MAX_IMM_TX_PKT_LEN - hdrlen) | ||
718 | return hdrlen; | ||
719 | return 0; | ||
714 | } | 720 | } |
715 | 721 | ||
716 | /** | 722 | /** |
@@ -723,9 +729,10 @@ static inline int is_eth_imm(const struct sk_buff *skb) | |||
723 | static inline unsigned int calc_tx_flits(const struct sk_buff *skb) | 729 | static inline unsigned int calc_tx_flits(const struct sk_buff *skb) |
724 | { | 730 | { |
725 | unsigned int flits; | 731 | unsigned int flits; |
732 | int hdrlen = is_eth_imm(skb); | ||
726 | 733 | ||
727 | if (is_eth_imm(skb)) | 734 | if (hdrlen) |
728 | return DIV_ROUND_UP(skb->len + sizeof(struct cpl_tx_pkt), 8); | 735 | return DIV_ROUND_UP(skb->len + hdrlen, sizeof(__be64)); |
729 | 736 | ||
730 | flits = sgl_len(skb_shinfo(skb)->nr_frags + 1) + 4; | 737 | flits = sgl_len(skb_shinfo(skb)->nr_frags + 1) + 4; |
731 | if (skb_shinfo(skb)->gso_size) | 738 | if (skb_shinfo(skb)->gso_size) |
@@ -971,6 +978,7 @@ static inline void txq_advance(struct sge_txq *q, unsigned int n) | |||
971 | */ | 978 | */ |
972 | netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev) | 979 | netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev) |
973 | { | 980 | { |
981 | int len; | ||
974 | u32 wr_mid; | 982 | u32 wr_mid; |
975 | u64 cntrl, *end; | 983 | u64 cntrl, *end; |
976 | int qidx, credits; | 984 | int qidx, credits; |
@@ -982,6 +990,7 @@ netdev_tx_t t4_eth_xmit(struct sk_buff *skb, struct net_device *dev) | |||
982 | struct cpl_tx_pkt_core *cpl; | 990 | struct cpl_tx_pkt_core *cpl; |
983 | const struct skb_shared_info *ssi; | 991 | const struct skb_shared_info *ssi; |
984 | dma_addr_t addr[MAX_SKB_FRAGS + 1]; | 992 | dma_addr_t addr[MAX_SKB_FRAGS + 1]; |
993 | bool immediate = false; | ||
985 | 994 | ||
986 | /* | 995 | /* |
987 | * The chip min packet length is 10 octets but play safe and reject | 996 | * The chip min packet length is 10 octets but play safe and reject |
@@ -1011,7 +1020,10 @@ out_free: dev_kfree_skb(skb); | |||
1011 | return NETDEV_TX_BUSY; | 1020 | return NETDEV_TX_BUSY; |
1012 | } | 1021 | } |
1013 | 1022 | ||
1014 | if (!is_eth_imm(skb) && | 1023 | if (is_eth_imm(skb)) |
1024 | immediate = true; | ||
1025 | |||
1026 | if (!immediate && | ||
1015 | unlikely(map_skb(adap->pdev_dev, skb, addr) < 0)) { | 1027 | unlikely(map_skb(adap->pdev_dev, skb, addr) < 0)) { |
1016 | q->mapping_err++; | 1028 | q->mapping_err++; |
1017 | goto out_free; | 1029 | goto out_free; |
@@ -1028,6 +1040,8 @@ out_free: dev_kfree_skb(skb); | |||
1028 | wr->r3 = cpu_to_be64(0); | 1040 | wr->r3 = cpu_to_be64(0); |
1029 | end = (u64 *)wr + flits; | 1041 | end = (u64 *)wr + flits; |
1030 | 1042 | ||
1043 | len = immediate ? skb->len : 0; | ||
1044 | len += sizeof(*cpl); | ||
1031 | ssi = skb_shinfo(skb); | 1045 | ssi = skb_shinfo(skb); |
1032 | if (ssi->gso_size) { | 1046 | if (ssi->gso_size) { |
1033 | struct cpl_tx_pkt_lso *lso = (void *)wr; | 1047 | struct cpl_tx_pkt_lso *lso = (void *)wr; |
@@ -1035,8 +1049,9 @@ out_free: dev_kfree_skb(skb); | |||
1035 | int l3hdr_len = skb_network_header_len(skb); | 1049 | int l3hdr_len = skb_network_header_len(skb); |
1036 | int eth_xtra_len = skb_network_offset(skb) - ETH_HLEN; | 1050 | int eth_xtra_len = skb_network_offset(skb) - ETH_HLEN; |
1037 | 1051 | ||
1052 | len += sizeof(*lso); | ||
1038 | wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) | | 1053 | wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) | |
1039 | FW_WR_IMMDLEN(sizeof(*lso))); | 1054 | FW_WR_IMMDLEN(len)); |
1040 | lso->c.lso_ctrl = htonl(LSO_OPCODE(CPL_TX_PKT_LSO) | | 1055 | lso->c.lso_ctrl = htonl(LSO_OPCODE(CPL_TX_PKT_LSO) | |
1041 | LSO_FIRST_SLICE | LSO_LAST_SLICE | | 1056 | LSO_FIRST_SLICE | LSO_LAST_SLICE | |
1042 | LSO_IPV6(v6) | | 1057 | LSO_IPV6(v6) | |
@@ -1054,9 +1069,6 @@ out_free: dev_kfree_skb(skb); | |||
1054 | q->tso++; | 1069 | q->tso++; |
1055 | q->tx_cso += ssi->gso_segs; | 1070 | q->tx_cso += ssi->gso_segs; |
1056 | } else { | 1071 | } else { |
1057 | int len; | ||
1058 | |||
1059 | len = is_eth_imm(skb) ? skb->len + sizeof(*cpl) : sizeof(*cpl); | ||
1060 | wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) | | 1072 | wr->op_immdlen = htonl(FW_WR_OP(FW_ETH_TX_PKT_WR) | |
1061 | FW_WR_IMMDLEN(len)); | 1073 | FW_WR_IMMDLEN(len)); |
1062 | cpl = (void *)(wr + 1); | 1074 | cpl = (void *)(wr + 1); |
@@ -1078,7 +1090,7 @@ out_free: dev_kfree_skb(skb); | |||
1078 | cpl->len = htons(skb->len); | 1090 | cpl->len = htons(skb->len); |
1079 | cpl->ctrl1 = cpu_to_be64(cntrl); | 1091 | cpl->ctrl1 = cpu_to_be64(cntrl); |
1080 | 1092 | ||
1081 | if (is_eth_imm(skb)) { | 1093 | if (immediate) { |
1082 | inline_tx_skb(skb, &q->q, cpl + 1); | 1094 | inline_tx_skb(skb, &q->q, cpl + 1); |
1083 | dev_kfree_skb(skb); | 1095 | dev_kfree_skb(skb); |
1084 | } else { | 1096 | } else { |
@@ -1467,8 +1479,12 @@ static inline int ofld_send(struct adapter *adap, struct sk_buff *skb) | |||
1467 | { | 1479 | { |
1468 | unsigned int idx = skb_txq(skb); | 1480 | unsigned int idx = skb_txq(skb); |
1469 | 1481 | ||
1470 | if (unlikely(is_ctrl_pkt(skb))) | 1482 | if (unlikely(is_ctrl_pkt(skb))) { |
1483 | /* Single ctrl queue is a requirement for LE workaround path */ | ||
1484 | if (adap->tids.nsftids) | ||
1485 | idx = 0; | ||
1471 | return ctrl_xmit(&adap->sge.ctrlq[idx], skb); | 1486 | return ctrl_xmit(&adap->sge.ctrlq[idx], skb); |
1487 | } | ||
1472 | return ofld_xmit(&adap->sge.ofldtxq[idx], skb); | 1488 | return ofld_xmit(&adap->sge.ofldtxq[idx], skb); |
1473 | } | 1489 | } |
1474 | 1490 | ||
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 2c109343d570..7ae756defc95 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | |||
@@ -573,7 +573,7 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) | |||
573 | { | 573 | { |
574 | u32 cclk_param, cclk_val; | 574 | u32 cclk_param, cclk_val; |
575 | int i, ret, addr; | 575 | int i, ret, addr; |
576 | int ec, sn; | 576 | int ec, sn, pn; |
577 | u8 *vpd, csum; | 577 | u8 *vpd, csum; |
578 | unsigned int vpdr_len, kw_offset, id_len; | 578 | unsigned int vpdr_len, kw_offset, id_len; |
579 | 579 | ||
@@ -638,6 +638,7 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) | |||
638 | 638 | ||
639 | FIND_VPD_KW(ec, "EC"); | 639 | FIND_VPD_KW(ec, "EC"); |
640 | FIND_VPD_KW(sn, "SN"); | 640 | FIND_VPD_KW(sn, "SN"); |
641 | FIND_VPD_KW(pn, "PN"); | ||
641 | #undef FIND_VPD_KW | 642 | #undef FIND_VPD_KW |
642 | 643 | ||
643 | memcpy(p->id, vpd + PCI_VPD_LRDT_TAG_SIZE, id_len); | 644 | memcpy(p->id, vpd + PCI_VPD_LRDT_TAG_SIZE, id_len); |
@@ -647,6 +648,8 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) | |||
647 | i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE); | 648 | i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE); |
648 | memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN)); | 649 | memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN)); |
649 | strim(p->sn); | 650 | strim(p->sn); |
651 | memcpy(p->pn, vpd + pn, min(i, PN_LEN)); | ||
652 | strim(p->pn); | ||
650 | 653 | ||
651 | /* | 654 | /* |
652 | * Ask firmware for the Core Clock since it knows how to translate the | 655 | * Ask firmware for the Core Clock since it knows how to translate the |
@@ -1155,7 +1158,8 @@ out: | |||
1155 | } | 1158 | } |
1156 | 1159 | ||
1157 | #define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\ | 1160 | #define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\ |
1158 | FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_ANEG) | 1161 | FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G | \ |
1162 | FW_PORT_CAP_ANEG) | ||
1159 | 1163 | ||
1160 | /** | 1164 | /** |
1161 | * t4_link_start - apply link configuration to MAC/PHY | 1165 | * t4_link_start - apply link configuration to MAC/PHY |
@@ -2247,6 +2251,36 @@ static unsigned int get_mps_bg_map(struct adapter *adap, int idx) | |||
2247 | } | 2251 | } |
2248 | 2252 | ||
2249 | /** | 2253 | /** |
2254 | * t4_get_port_type_description - return Port Type string description | ||
2255 | * @port_type: firmware Port Type enumeration | ||
2256 | */ | ||
2257 | const char *t4_get_port_type_description(enum fw_port_type port_type) | ||
2258 | { | ||
2259 | static const char *const port_type_description[] = { | ||
2260 | "R XFI", | ||
2261 | "R XAUI", | ||
2262 | "T SGMII", | ||
2263 | "T XFI", | ||
2264 | "T XAUI", | ||
2265 | "KX4", | ||
2266 | "CX4", | ||
2267 | "KX", | ||
2268 | "KR", | ||
2269 | "R SFP+", | ||
2270 | "KR/KX", | ||
2271 | "KR/KX/KX4", | ||
2272 | "R QSFP_10G", | ||
2273 | "", | ||
2274 | "R QSFP", | ||
2275 | "R BP40_BA", | ||
2276 | }; | ||
2277 | |||
2278 | if (port_type < ARRAY_SIZE(port_type_description)) | ||
2279 | return port_type_description[port_type]; | ||
2280 | return "UNKNOWN"; | ||
2281 | } | ||
2282 | |||
2283 | /** | ||
2250 | * t4_get_port_stats - collect port statistics | 2284 | * t4_get_port_stats - collect port statistics |
2251 | * @adap: the adapter | 2285 | * @adap: the adapter |
2252 | * @idx: the port index | 2286 | * @idx: the port index |
@@ -3538,6 +3572,8 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl) | |||
3538 | speed = SPEED_1000; | 3572 | speed = SPEED_1000; |
3539 | else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G)) | 3573 | else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G)) |
3540 | speed = SPEED_10000; | 3574 | speed = SPEED_10000; |
3575 | else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G)) | ||
3576 | speed = 40000; /* Need SPEED_40000 in ethtool.h */ | ||
3541 | 3577 | ||
3542 | if (link_ok != lc->link_ok || speed != lc->speed || | 3578 | if (link_ok != lc->link_ok || speed != lc->speed || |
3543 | fc != lc->fc) { /* something changed */ | 3579 | fc != lc->fc) { /* something changed */ |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h index 74fea74ce0aa..9cc973fbcf26 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h +++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | |||
@@ -932,6 +932,7 @@ enum fw_params_param_dev { | |||
932 | FW_PARAMS_PARAM_DEV_FWREV = 0x0B, | 932 | FW_PARAMS_PARAM_DEV_FWREV = 0x0B, |
933 | FW_PARAMS_PARAM_DEV_TPREV = 0x0C, | 933 | FW_PARAMS_PARAM_DEV_TPREV = 0x0C, |
934 | FW_PARAMS_PARAM_DEV_CF = 0x0D, | 934 | FW_PARAMS_PARAM_DEV_CF = 0x0D, |
935 | FW_PARAMS_PARAM_DEV_ULPTX_MEMWRITE_DSGL = 0x17, | ||
935 | }; | 936 | }; |
936 | 937 | ||
937 | /* | 938 | /* |
@@ -1742,6 +1743,9 @@ enum fw_port_type { | |||
1742 | FW_PORT_TYPE_SFP, | 1743 | FW_PORT_TYPE_SFP, |
1743 | FW_PORT_TYPE_BP_AP, | 1744 | FW_PORT_TYPE_BP_AP, |
1744 | FW_PORT_TYPE_BP4_AP, | 1745 | FW_PORT_TYPE_BP4_AP, |
1746 | FW_PORT_TYPE_QSFP_10G, | ||
1747 | FW_PORT_TYPE_QSFP, | ||
1748 | FW_PORT_TYPE_BP40_BA, | ||
1745 | 1749 | ||
1746 | FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_MASK | 1750 | FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_MASK |
1747 | }; | 1751 | }; |