Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Browse files Browse the repository at this point in the history
Pull networking fixes from David Miller:
 "One last pull request before heading to Vancouver for LPC, here we have:

   1) Don't forget to free VSI contexts during ice driver unload, from
      Victor Raj.

   2) Don't forget napi delete calls during device remove in ice driver,
      from Dave Ertman.

   3) Don't request VLAN tag insertion of ibmvnic device when SKB
      doesn't have VLAN tags at all.

   4) IPV4 frag handling code has to accomodate the situation where two
      threads try to insert the same fragment into the hash table at the
      same time. From Eric Dumazet.

   5) Relatedly, don't flow separate on protocol ports for fragmented
      frames, also from Eric Dumazet.

   6) Memory leaks in qed driver, from Denis Bolotin.

   7) Correct valid MTU range in smsc95xx driver, from Stefan Wahren.

   8) Validate cls_flower nested policies properly, from Jakub Kicinski.

   9) Clearing of stats counters in mc88e6xxx driver doesn't retain
      important bits in the G1_STATS_OP register causing the chip to
      hang. Fix from Andrew Lunn"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (41 commits)
  act_mirred: clear skb->tstamp on redirect
  net: dsa: mv88e6xxx: Fix clearing of stats counters
  tipc: fix link re-establish failure
  net: sched: cls_flower: validate nested enc_opts_policy to avoid warning
  net: mvneta: correct typo
  flow_dissector: do not dissect l4 ports for fragments
  net: qualcomm: rmnet: Fix incorrect assignment of real_dev
  net: aquantia: allow rx checksum offload configuration
  net: aquantia: invalid checksumm offload implementation
  net: aquantia: fixed enable unicast on 32 macvlan
  net: aquantia: fix potential IOMMU fault after driver unbind
  net: aquantia: synchronized flow control between mac/phy
  net: smsc95xx: Fix MTU range
  net: stmmac: Fix RX packet size > 8191
  qed: Fix potential memory corruption
  qed: Fix SPQ entries not returned to pool in error flows
  qed: Fix blocking/unlimited SPQ entries leak
  qed: Fix memory/entry leak in qed_init_sp_request()
  inet: frags: better deal with smp races
  net: hns3: bugfix for not checking return value
  ...
  • Loading branch information
torvalds committed Nov 11, 2018
2 parents e12e00e + 7236ead commit 7a3765e
Show file tree
Hide file tree
Showing 54 changed files with 430 additions and 199 deletions.
2 changes: 2 additions & 0 deletions drivers/net/dsa/mv88e6xxx/global1.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,8 @@ int mv88e6xxx_g1_stats_clear(struct mv88e6xxx_chip *chip)
if (err)
return err;

/* Keep the histogram mode bits */
val &= MV88E6XXX_G1_STATS_OP_HIST_RX_TX;
val |= MV88E6XXX_G1_STATS_OP_BUSY | MV88E6XXX_G1_STATS_OP_FLUSH_ALL;

err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
Expand Down
8 changes: 4 additions & 4 deletions drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,13 +407,13 @@ static void aq_ethtool_get_pauseparam(struct net_device *ndev,
struct ethtool_pauseparam *pause)
{
struct aq_nic_s *aq_nic = netdev_priv(ndev);
u32 fc = aq_nic->aq_nic_cfg.flow_control;

pause->autoneg = 0;

if (aq_nic->aq_hw->aq_nic_cfg->flow_control & AQ_NIC_FC_RX)
pause->rx_pause = 1;
if (aq_nic->aq_hw->aq_nic_cfg->flow_control & AQ_NIC_FC_TX)
pause->tx_pause = 1;
pause->rx_pause = !!(fc & AQ_NIC_FC_RX);
pause->tx_pause = !!(fc & AQ_NIC_FC_TX);

}

static int aq_ethtool_set_pauseparam(struct net_device *ndev,
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/aquantia/atlantic/aq_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ struct aq_hw_ops {

int (*hw_get_fw_version)(struct aq_hw_s *self, u32 *fw_version);

int (*hw_set_offload)(struct aq_hw_s *self,
struct aq_nic_cfg_s *aq_nic_cfg);

int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc);
};

struct aq_fw_ops {
Expand All @@ -226,6 +230,8 @@ struct aq_fw_ops {

int (*update_stats)(struct aq_hw_s *self);

u32 (*get_flow_control)(struct aq_hw_s *self, u32 *fcmode);

int (*set_flow_control)(struct aq_hw_s *self);

int (*set_power)(struct aq_hw_s *self, unsigned int power_state,
Expand Down
10 changes: 8 additions & 2 deletions drivers/net/ethernet/aquantia/atlantic/aq_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,11 @@ static int aq_ndev_set_features(struct net_device *ndev,
struct aq_nic_s *aq_nic = netdev_priv(ndev);
struct aq_nic_cfg_s *aq_cfg = aq_nic_get_cfg(aq_nic);
bool is_lro = false;
int err = 0;

aq_cfg->features = features;

if (aq_cfg->hw_features & NETIF_F_LRO) {
if (aq_cfg->aq_hw_caps->hw_features & NETIF_F_LRO) {
is_lro = features & NETIF_F_LRO;

if (aq_cfg->is_lro != is_lro) {
Expand All @@ -112,8 +115,11 @@ static int aq_ndev_set_features(struct net_device *ndev,
}
}
}
if ((aq_nic->ndev->features ^ features) & NETIF_F_RXCSUM)
err = aq_nic->aq_hw_ops->hw_set_offload(aq_nic->aq_hw,
aq_cfg);

return 0;
return err;
}

static int aq_ndev_set_mac_address(struct net_device *ndev, void *addr)
Expand Down
18 changes: 15 additions & 3 deletions drivers/net/ethernet/aquantia/atlantic/aq_nic.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,13 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
}

cfg->link_speed_msk &= cfg->aq_hw_caps->link_speed_msk;
cfg->hw_features = cfg->aq_hw_caps->hw_features;
cfg->features = cfg->aq_hw_caps->hw_features;
}

static int aq_nic_update_link_status(struct aq_nic_s *self)
{
int err = self->aq_fw_ops->update_link_status(self->aq_hw);
u32 fc = 0;

if (err)
return err;
Expand All @@ -133,6 +134,15 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
AQ_CFG_DRV_NAME, self->link_status.mbps,
self->aq_hw->aq_link_status.mbps);
aq_nic_update_interrupt_moderation_settings(self);

/* Driver has to update flow control settings on RX block
* on any link event.
* We should query FW whether it negotiated FC.
*/
if (self->aq_fw_ops->get_flow_control)
self->aq_fw_ops->get_flow_control(self->aq_hw, &fc);
if (self->aq_hw_ops->hw_set_fc)
self->aq_hw_ops->hw_set_fc(self->aq_hw, fc, 0);
}

self->link_status = self->aq_hw->aq_link_status;
Expand Down Expand Up @@ -590,7 +600,7 @@ int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev)
}
}

if (i > 0 && i < AQ_HW_MULTICAST_ADDRESS_MAX) {
if (i > 0 && i <= AQ_HW_MULTICAST_ADDRESS_MAX) {
packet_filter |= IFF_MULTICAST;
self->mc_list.count = i;
self->aq_hw_ops->hw_multicast_list_set(self->aq_hw,
Expand Down Expand Up @@ -772,7 +782,9 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
ethtool_link_ksettings_add_link_mode(cmd, advertising,
Pause);

if (self->aq_nic_cfg.flow_control & AQ_NIC_FC_TX)
/* Asym is when either RX or TX, but not both */
if (!!(self->aq_nic_cfg.flow_control & AQ_NIC_FC_TX) ^
!!(self->aq_nic_cfg.flow_control & AQ_NIC_FC_RX))
ethtool_link_ksettings_add_link_mode(cmd, advertising,
Asym_Pause);

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/aquantia/atlantic/aq_nic.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct aq_vec_s;

struct aq_nic_cfg_s {
const struct aq_hw_caps_s *aq_hw_caps;
u64 hw_features;
u64 features;
u32 rxds; /* rx ring size, descriptors # */
u32 txds; /* tx ring size, descriptors # */
u32 vecs; /* vecs==allocated irqs */
Expand Down
35 changes: 23 additions & 12 deletions drivers/net/ethernet/aquantia/atlantic/aq_ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,27 @@ bool aq_ring_tx_clean(struct aq_ring_s *self)
return !!budget;
}

static void aq_rx_checksum(struct aq_ring_s *self,
struct aq_ring_buff_s *buff,
struct sk_buff *skb)
{
if (!(self->aq_nic->ndev->features & NETIF_F_RXCSUM))
return;

if (unlikely(buff->is_cso_err)) {
++self->stats.rx.errors;
skb->ip_summed = CHECKSUM_NONE;
return;
}
if (buff->is_ip_cso) {
__skb_incr_checksum_unnecessary(skb);
if (buff->is_udp_cso || buff->is_tcp_cso)
__skb_incr_checksum_unnecessary(skb);
} else {
skb->ip_summed = CHECKSUM_NONE;
}
}

#define AQ_SKB_ALIGN SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
int aq_ring_rx_clean(struct aq_ring_s *self,
struct napi_struct *napi,
Expand Down Expand Up @@ -267,18 +288,8 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
}

skb->protocol = eth_type_trans(skb, ndev);
if (unlikely(buff->is_cso_err)) {
++self->stats.rx.errors;
skb->ip_summed = CHECKSUM_NONE;
} else {
if (buff->is_ip_cso) {
__skb_incr_checksum_unnecessary(skb);
if (buff->is_udp_cso || buff->is_tcp_cso)
__skb_incr_checksum_unnecessary(skb);
} else {
skb->ip_summed = CHECKSUM_NONE;
}
}

aq_rx_checksum(self, buff, skb);

skb_set_hash(skb, buff->rss_hash,
buff->is_hash_l4 ? PKT_HASH_TYPE_L4 :
Expand Down
61 changes: 38 additions & 23 deletions drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,17 @@ static int hw_atl_b0_hw_reset(struct aq_hw_s *self)
return err;
}

static int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc)
{
hw_atl_rpb_rx_xoff_en_per_tc_set(self, !!(fc & AQ_NIC_FC_RX), tc);
return 0;
}

static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self)
{
u32 tc = 0U;
u32 buff_size = 0U;
unsigned int i_priority = 0U;
bool is_rx_flow_control = false;

/* TPS Descriptor rate init */
hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U);
Expand Down Expand Up @@ -138,7 +143,6 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self)

/* QoS Rx buf size per TC */
tc = 0;
is_rx_flow_control = (AQ_NIC_FC_RX & self->aq_nic_cfg->flow_control);
buff_size = HW_ATL_B0_RXBUF_MAX;

hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, buff_size, tc);
Expand All @@ -150,7 +154,8 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self)
(buff_size *
(1024U / 32U) * 50U) /
100U, tc);
hw_atl_rpb_rx_xoff_en_per_tc_set(self, is_rx_flow_control ? 1U : 0U, tc);

hw_atl_b0_set_fc(self, self->aq_nic_cfg->flow_control, tc);

/* QoS 802.1p priority -> TC mapping */
for (i_priority = 8U; i_priority--;)
Expand Down Expand Up @@ -229,8 +234,10 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
hw_atl_tpo_tcp_udp_crc_offload_en_set(self, 1);

/* RX checksums offloads*/
hw_atl_rpo_ipv4header_crc_offload_en_set(self, 1);
hw_atl_rpo_tcp_udp_crc_offload_en_set(self, 1);
hw_atl_rpo_ipv4header_crc_offload_en_set(self, !!(aq_nic_cfg->features &
NETIF_F_RXCSUM));
hw_atl_rpo_tcp_udp_crc_offload_en_set(self, !!(aq_nic_cfg->features &
NETIF_F_RXCSUM));

/* LSO offloads*/
hw_atl_tdm_large_send_offload_en_set(self, 0xFFFFFFFFU);
Expand Down Expand Up @@ -655,45 +662,45 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,
struct hw_atl_rxd_wb_s *rxd_wb = (struct hw_atl_rxd_wb_s *)
&ring->dx_ring[ring->hw_head * HW_ATL_B0_RXD_SIZE];

unsigned int is_err = 1U;
unsigned int is_rx_check_sum_enabled = 0U;
unsigned int pkt_type = 0U;
u8 rx_stat = 0U;

if (!(rxd_wb->status & 0x1U)) { /* RxD is not done */
break;
}

buff = &ring->buff_ring[ring->hw_head];

is_err = (0x0000003CU & rxd_wb->status);
rx_stat = (0x0000003CU & rxd_wb->status) >> 2;

is_rx_check_sum_enabled = (rxd_wb->type) & (0x3U << 19);
is_err &= ~0x20U; /* exclude validity bit */

pkt_type = 0xFFU & (rxd_wb->type >> 4);

if (is_rx_check_sum_enabled) {
if (0x0U == (pkt_type & 0x3U))
buff->is_ip_cso = (is_err & 0x08U) ? 0U : 1U;
if (is_rx_check_sum_enabled & BIT(0) &&
(0x0U == (pkt_type & 0x3U)))
buff->is_ip_cso = (rx_stat & BIT(1)) ? 0U : 1U;

if (is_rx_check_sum_enabled & BIT(1)) {
if (0x4U == (pkt_type & 0x1CU))
buff->is_udp_cso = buff->is_cso_err ? 0U : 1U;
buff->is_udp_cso = (rx_stat & BIT(2)) ? 0U :
!!(rx_stat & BIT(3));
else if (0x0U == (pkt_type & 0x1CU))
buff->is_tcp_cso = buff->is_cso_err ? 0U : 1U;

/* Checksum offload workaround for small packets */
if (rxd_wb->pkt_len <= 60) {
buff->is_ip_cso = 0U;
buff->is_cso_err = 0U;
}
buff->is_tcp_cso = (rx_stat & BIT(2)) ? 0U :
!!(rx_stat & BIT(3));
}
buff->is_cso_err = !!(rx_stat & 0x6);
/* Checksum offload workaround for small packets */
if (unlikely(rxd_wb->pkt_len <= 60)) {
buff->is_ip_cso = 0U;
buff->is_cso_err = 0U;
}

is_err &= ~0x18U;

dma_unmap_page(ndev, buff->pa, buff->len, DMA_FROM_DEVICE);

if (is_err || rxd_wb->type & 0x1000U) {
/* status error or DMA error */
if ((rx_stat & BIT(0)) || rxd_wb->type & 0x1000U) {
/* MAC error or DMA error */
buff->is_error = 1U;
} else {
if (self->aq_nic_cfg->is_rss) {
Expand Down Expand Up @@ -915,6 +922,12 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self)
static int hw_atl_b0_hw_stop(struct aq_hw_s *self)
{
hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK);

/* Invalidate Descriptor Cache to prevent writing to the cached
* descriptors and to the data pointer of those descriptors
*/
hw_atl_rdm_rx_dma_desc_cache_init_set(self, 1);

return aq_hw_err_from_flags(self);
}

Expand Down Expand Up @@ -963,4 +976,6 @@ const struct aq_hw_ops hw_atl_ops_b0 = {
.hw_get_regs = hw_atl_utils_hw_get_regs,
.hw_get_hw_stats = hw_atl_utils_get_hw_stats,
.hw_get_fw_version = hw_atl_utils_get_fw_version,
.hw_set_offload = hw_atl_b0_hw_offload_set,
.hw_set_fc = hw_atl_b0_set_fc,
};
8 changes: 8 additions & 0 deletions drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,14 @@ void hw_atl_rpb_rx_flow_ctl_mode_set(struct aq_hw_s *aq_hw, u32 rx_flow_ctl_mode
HW_ATL_RPB_RX_FC_MODE_SHIFT, rx_flow_ctl_mode);
}

void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init)
{
aq_hw_write_reg_bit(aq_hw, HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR,
HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK,
HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT,
init);
}

void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw,
u32 rx_pkt_buff_size_per_tc, u32 buffer)
{
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@ void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw,
u32 rx_pkt_buff_size_per_tc,
u32 buffer);

/* set rdm rx dma descriptor cache init */
void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init);

/* set rx xoff enable (per tc) */
void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_xoff_en_per_tc,
u32 buffer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,24 @@
/* default value of bitfield desc{d}_reset */
#define HW_ATL_RDM_DESCDRESET_DEFAULT 0x0

/* rdm_desc_init_i bitfield definitions
* preprocessor definitions for the bitfield rdm_desc_init_i.
* port="pif_rdm_desc_init_i"
*/

/* register address for bitfield rdm_desc_init_i */
#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR 0x00005a00
/* bitmask for bitfield rdm_desc_init_i */
#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK 0xffffffff
/* inverted bitmask for bitfield rdm_desc_init_i */
#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSKN 0x00000000
/* lower bit position of bitfield rdm_desc_init_i */
#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT 0
/* width of bitfield rdm_desc_init_i */
#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_WIDTH 32
/* default value of bitfield rdm_desc_init_i */
#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_DEFAULT 0x0

/* rx int_desc_wrb_en bitfield definitions
* preprocessor definitions for the bitfield "int_desc_wrb_en".
* port="pif_rdm_int_desc_wrb_en_i"
Expand Down
Loading

0 comments on commit 7a3765e

Please sign in to comment.