Commit 5aa1959d authored by David S. Miller's avatar David S. Miller

Merge branch 'ionic-fixes'

Shannon Nelson says:

====================
ionic: bug fixes

Fix a thread race in rx_mode, remove unnecessary log message,
fix dynamic coalescing issues, and count all csum_none cases.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 0506c93f f07f9815
...@@ -29,7 +29,7 @@ static const u8 ionic_qtype_versions[IONIC_QTYPE_MAX] = { ...@@ -29,7 +29,7 @@ static const u8 ionic_qtype_versions[IONIC_QTYPE_MAX] = {
*/ */
}; };
static void ionic_lif_rx_mode(struct ionic_lif *lif, unsigned int rx_mode); static void ionic_lif_rx_mode(struct ionic_lif *lif);
static int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr); static int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr);
static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr); static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr);
static void ionic_link_status_check(struct ionic_lif *lif); static void ionic_link_status_check(struct ionic_lif *lif);
...@@ -53,7 +53,19 @@ static void ionic_dim_work(struct work_struct *work) ...@@ -53,7 +53,19 @@ static void ionic_dim_work(struct work_struct *work)
cur_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix); cur_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix);
qcq = container_of(dim, struct ionic_qcq, dim); qcq = container_of(dim, struct ionic_qcq, dim);
new_coal = ionic_coal_usec_to_hw(qcq->q.lif->ionic, cur_moder.usec); new_coal = ionic_coal_usec_to_hw(qcq->q.lif->ionic, cur_moder.usec);
qcq->intr.dim_coal_hw = new_coal ? new_coal : 1; new_coal = new_coal ? new_coal : 1;
if (qcq->intr.dim_coal_hw != new_coal) {
unsigned int qi = qcq->cq.bound_q->index;
struct ionic_lif *lif = qcq->q.lif;
qcq->intr.dim_coal_hw = new_coal;
ionic_intr_coal_init(lif->ionic->idev.intr_ctrl,
lif->rxqcqs[qi]->intr.index,
qcq->intr.dim_coal_hw);
}
dim->state = DIM_START_MEASURE; dim->state = DIM_START_MEASURE;
} }
...@@ -77,7 +89,7 @@ static void ionic_lif_deferred_work(struct work_struct *work) ...@@ -77,7 +89,7 @@ static void ionic_lif_deferred_work(struct work_struct *work)
switch (w->type) { switch (w->type) {
case IONIC_DW_TYPE_RX_MODE: case IONIC_DW_TYPE_RX_MODE:
ionic_lif_rx_mode(lif, w->rx_mode); ionic_lif_rx_mode(lif);
break; break;
case IONIC_DW_TYPE_RX_ADDR_ADD: case IONIC_DW_TYPE_RX_ADDR_ADD:
ionic_lif_addr_add(lif, w->addr); ionic_lif_addr_add(lif, w->addr);
...@@ -1301,10 +1313,8 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr) ...@@ -1301,10 +1313,8 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr)
return 0; return 0;
} }
static int ionic_lif_addr(struct ionic_lif *lif, const u8 *addr, bool add, static int ionic_lif_addr(struct ionic_lif *lif, const u8 *addr, bool add)
bool can_sleep)
{ {
struct ionic_deferred_work *work;
unsigned int nmfilters; unsigned int nmfilters;
unsigned int nufilters; unsigned int nufilters;
...@@ -1330,97 +1340,46 @@ static int ionic_lif_addr(struct ionic_lif *lif, const u8 *addr, bool add, ...@@ -1330,97 +1340,46 @@ static int ionic_lif_addr(struct ionic_lif *lif, const u8 *addr, bool add,
lif->nucast--; lif->nucast--;
} }
if (!can_sleep) {
work = kzalloc(sizeof(*work), GFP_ATOMIC);
if (!work)
return -ENOMEM;
work->type = add ? IONIC_DW_TYPE_RX_ADDR_ADD :
IONIC_DW_TYPE_RX_ADDR_DEL;
memcpy(work->addr, addr, ETH_ALEN);
netdev_dbg(lif->netdev, "deferred: rx_filter %s %pM\n",
add ? "add" : "del", addr);
ionic_lif_deferred_enqueue(&lif->deferred, work);
} else {
netdev_dbg(lif->netdev, "rx_filter %s %pM\n", netdev_dbg(lif->netdev, "rx_filter %s %pM\n",
add ? "add" : "del", addr); add ? "add" : "del", addr);
if (add) if (add)
return ionic_lif_addr_add(lif, addr); return ionic_lif_addr_add(lif, addr);
else else
return ionic_lif_addr_del(lif, addr); return ionic_lif_addr_del(lif, addr);
}
return 0; return 0;
} }
static int ionic_addr_add(struct net_device *netdev, const u8 *addr) static int ionic_addr_add(struct net_device *netdev, const u8 *addr)
{ {
return ionic_lif_addr(netdev_priv(netdev), addr, ADD_ADDR, CAN_SLEEP); return ionic_lif_addr(netdev_priv(netdev), addr, ADD_ADDR);
}
static int ionic_ndo_addr_add(struct net_device *netdev, const u8 *addr)
{
return ionic_lif_addr(netdev_priv(netdev), addr, ADD_ADDR, CAN_NOT_SLEEP);
} }
static int ionic_addr_del(struct net_device *netdev, const u8 *addr) static int ionic_addr_del(struct net_device *netdev, const u8 *addr)
{ {
return ionic_lif_addr(netdev_priv(netdev), addr, DEL_ADDR, CAN_SLEEP); return ionic_lif_addr(netdev_priv(netdev), addr, DEL_ADDR);
}
static int ionic_ndo_addr_del(struct net_device *netdev, const u8 *addr)
{
return ionic_lif_addr(netdev_priv(netdev), addr, DEL_ADDR, CAN_NOT_SLEEP);
} }
static void ionic_lif_rx_mode(struct ionic_lif *lif, unsigned int rx_mode) static void ionic_lif_rx_mode(struct ionic_lif *lif)
{ {
struct ionic_admin_ctx ctx = { struct net_device *netdev = lif->netdev;
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work), unsigned int nfilters;
.cmd.rx_mode_set = { unsigned int nd_flags;
.opcode = IONIC_CMD_RX_MODE_SET,
.lif_index = cpu_to_le16(lif->index),
.rx_mode = cpu_to_le16(rx_mode),
},
};
char buf[128]; char buf[128];
int err; u16 rx_mode;
int i; int i;
#define REMAIN(__x) (sizeof(buf) - (__x)) #define REMAIN(__x) (sizeof(buf) - (__x))
i = scnprintf(buf, sizeof(buf), "rx_mode 0x%04x -> 0x%04x:", mutex_lock(&lif->config_lock);
lif->rx_mode, rx_mode);
if (rx_mode & IONIC_RX_MODE_F_UNICAST)
i += scnprintf(&buf[i], REMAIN(i), " RX_MODE_F_UNICAST");
if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
i += scnprintf(&buf[i], REMAIN(i), " RX_MODE_F_MULTICAST");
if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
i += scnprintf(&buf[i], REMAIN(i), " RX_MODE_F_BROADCAST");
if (rx_mode & IONIC_RX_MODE_F_PROMISC)
i += scnprintf(&buf[i], REMAIN(i), " RX_MODE_F_PROMISC");
if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
i += scnprintf(&buf[i], REMAIN(i), " RX_MODE_F_ALLMULTI");
netdev_dbg(lif->netdev, "lif%d %s\n", lif->index, buf);
err = ionic_adminq_post_wait(lif, &ctx); /* grab the flags once for local use */
if (err) nd_flags = netdev->flags;
netdev_warn(lif->netdev, "set rx_mode 0x%04x failed: %d\n",
rx_mode, err);
else
lif->rx_mode = rx_mode;
}
static void ionic_set_rx_mode(struct net_device *netdev, bool can_sleep)
{
struct ionic_lif *lif = netdev_priv(netdev);
struct ionic_deferred_work *work;
unsigned int nfilters;
unsigned int rx_mode;
rx_mode = IONIC_RX_MODE_F_UNICAST; rx_mode = IONIC_RX_MODE_F_UNICAST;
rx_mode |= (netdev->flags & IFF_MULTICAST) ? IONIC_RX_MODE_F_MULTICAST : 0; rx_mode |= (nd_flags & IFF_MULTICAST) ? IONIC_RX_MODE_F_MULTICAST : 0;
rx_mode |= (netdev->flags & IFF_BROADCAST) ? IONIC_RX_MODE_F_BROADCAST : 0; rx_mode |= (nd_flags & IFF_BROADCAST) ? IONIC_RX_MODE_F_BROADCAST : 0;
rx_mode |= (netdev->flags & IFF_PROMISC) ? IONIC_RX_MODE_F_PROMISC : 0; rx_mode |= (nd_flags & IFF_PROMISC) ? IONIC_RX_MODE_F_PROMISC : 0;
rx_mode |= (netdev->flags & IFF_ALLMULTI) ? IONIC_RX_MODE_F_ALLMULTI : 0; rx_mode |= (nd_flags & IFF_ALLMULTI) ? IONIC_RX_MODE_F_ALLMULTI : 0;
/* sync unicast addresses /* sync unicast addresses
* next check to see if we're in an overflow state * next check to see if we're in an overflow state
...@@ -1429,36 +1388,72 @@ static void ionic_set_rx_mode(struct net_device *netdev, bool can_sleep) ...@@ -1429,36 +1388,72 @@ static void ionic_set_rx_mode(struct net_device *netdev, bool can_sleep)
* we remove our overflow flag and check the netdev flags * we remove our overflow flag and check the netdev flags
* to see if we can disable NIC PROMISC * to see if we can disable NIC PROMISC
*/ */
if (can_sleep)
__dev_uc_sync(netdev, ionic_addr_add, ionic_addr_del); __dev_uc_sync(netdev, ionic_addr_add, ionic_addr_del);
else
__dev_uc_sync(netdev, ionic_ndo_addr_add, ionic_ndo_addr_del);
nfilters = le32_to_cpu(lif->identity->eth.max_ucast_filters); nfilters = le32_to_cpu(lif->identity->eth.max_ucast_filters);
if (netdev_uc_count(netdev) + 1 > nfilters) { if (netdev_uc_count(netdev) + 1 > nfilters) {
rx_mode |= IONIC_RX_MODE_F_PROMISC; rx_mode |= IONIC_RX_MODE_F_PROMISC;
lif->uc_overflow = true; lif->uc_overflow = true;
} else if (lif->uc_overflow) { } else if (lif->uc_overflow) {
lif->uc_overflow = false; lif->uc_overflow = false;
if (!(netdev->flags & IFF_PROMISC)) if (!(nd_flags & IFF_PROMISC))
rx_mode &= ~IONIC_RX_MODE_F_PROMISC; rx_mode &= ~IONIC_RX_MODE_F_PROMISC;
} }
/* same for multicast */ /* same for multicast */
if (can_sleep)
__dev_mc_sync(netdev, ionic_addr_add, ionic_addr_del); __dev_mc_sync(netdev, ionic_addr_add, ionic_addr_del);
else
__dev_mc_sync(netdev, ionic_ndo_addr_add, ionic_ndo_addr_del);
nfilters = le32_to_cpu(lif->identity->eth.max_mcast_filters); nfilters = le32_to_cpu(lif->identity->eth.max_mcast_filters);
if (netdev_mc_count(netdev) > nfilters) { if (netdev_mc_count(netdev) > nfilters) {
rx_mode |= IONIC_RX_MODE_F_ALLMULTI; rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
lif->mc_overflow = true; lif->mc_overflow = true;
} else if (lif->mc_overflow) { } else if (lif->mc_overflow) {
lif->mc_overflow = false; lif->mc_overflow = false;
if (!(netdev->flags & IFF_ALLMULTI)) if (!(nd_flags & IFF_ALLMULTI))
rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI; rx_mode &= ~IONIC_RX_MODE_F_ALLMULTI;
} }
i = scnprintf(buf, sizeof(buf), "rx_mode 0x%04x -> 0x%04x:",
lif->rx_mode, rx_mode);
if (rx_mode & IONIC_RX_MODE_F_UNICAST)
i += scnprintf(&buf[i], REMAIN(i), " RX_MODE_F_UNICAST");
if (rx_mode & IONIC_RX_MODE_F_MULTICAST)
i += scnprintf(&buf[i], REMAIN(i), " RX_MODE_F_MULTICAST");
if (rx_mode & IONIC_RX_MODE_F_BROADCAST)
i += scnprintf(&buf[i], REMAIN(i), " RX_MODE_F_BROADCAST");
if (rx_mode & IONIC_RX_MODE_F_PROMISC)
i += scnprintf(&buf[i], REMAIN(i), " RX_MODE_F_PROMISC");
if (rx_mode & IONIC_RX_MODE_F_ALLMULTI)
i += scnprintf(&buf[i], REMAIN(i), " RX_MODE_F_ALLMULTI");
if (rx_mode & IONIC_RX_MODE_F_RDMA_SNIFFER)
i += scnprintf(&buf[i], REMAIN(i), " RX_MODE_F_RDMA_SNIFFER");
netdev_dbg(netdev, "lif%d %s\n", lif->index, buf);
if (lif->rx_mode != rx_mode) { if (lif->rx_mode != rx_mode) {
struct ionic_admin_ctx ctx = {
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
.cmd.rx_mode_set = {
.opcode = IONIC_CMD_RX_MODE_SET,
.lif_index = cpu_to_le16(lif->index),
},
};
int err;
ctx.cmd.rx_mode_set.rx_mode = cpu_to_le16(rx_mode);
err = ionic_adminq_post_wait(lif, &ctx);
if (err)
netdev_warn(netdev, "set rx_mode 0x%04x failed: %d\n",
rx_mode, err);
else
lif->rx_mode = rx_mode;
}
mutex_unlock(&lif->config_lock);
}
static void ionic_set_rx_mode(struct net_device *netdev, bool can_sleep)
{
struct ionic_lif *lif = netdev_priv(netdev);
struct ionic_deferred_work *work;
if (!can_sleep) { if (!can_sleep) {
work = kzalloc(sizeof(*work), GFP_ATOMIC); work = kzalloc(sizeof(*work), GFP_ATOMIC);
if (!work) { if (!work) {
...@@ -1466,12 +1461,10 @@ static void ionic_set_rx_mode(struct net_device *netdev, bool can_sleep) ...@@ -1466,12 +1461,10 @@ static void ionic_set_rx_mode(struct net_device *netdev, bool can_sleep)
return; return;
} }
work->type = IONIC_DW_TYPE_RX_MODE; work->type = IONIC_DW_TYPE_RX_MODE;
work->rx_mode = rx_mode;
netdev_dbg(lif->netdev, "deferred: rx_mode\n"); netdev_dbg(lif->netdev, "deferred: rx_mode\n");
ionic_lif_deferred_enqueue(&lif->deferred, work); ionic_lif_deferred_enqueue(&lif->deferred, work);
} else { } else {
ionic_lif_rx_mode(lif, rx_mode); ionic_lif_rx_mode(lif);
}
} }
} }
...@@ -3058,6 +3051,7 @@ void ionic_lif_deinit(struct ionic_lif *lif) ...@@ -3058,6 +3051,7 @@ void ionic_lif_deinit(struct ionic_lif *lif)
ionic_lif_qcq_deinit(lif, lif->notifyqcq); ionic_lif_qcq_deinit(lif, lif->notifyqcq);
ionic_lif_qcq_deinit(lif, lif->adminqcq); ionic_lif_qcq_deinit(lif, lif->adminqcq);
mutex_destroy(&lif->config_lock);
mutex_destroy(&lif->queue_lock); mutex_destroy(&lif->queue_lock);
ionic_lif_reset(lif); ionic_lif_reset(lif);
} }
...@@ -3185,7 +3179,7 @@ static int ionic_station_set(struct ionic_lif *lif) ...@@ -3185,7 +3179,7 @@ static int ionic_station_set(struct ionic_lif *lif)
*/ */
if (!ether_addr_equal(ctx.comp.lif_getattr.mac, if (!ether_addr_equal(ctx.comp.lif_getattr.mac,
netdev->dev_addr)) netdev->dev_addr))
ionic_lif_addr(lif, netdev->dev_addr, ADD_ADDR, CAN_SLEEP); ionic_lif_addr(lif, netdev->dev_addr, ADD_ADDR);
} else { } else {
/* Update the netdev mac with the device's mac */ /* Update the netdev mac with the device's mac */
memcpy(addr.sa_data, ctx.comp.lif_getattr.mac, netdev->addr_len); memcpy(addr.sa_data, ctx.comp.lif_getattr.mac, netdev->addr_len);
...@@ -3202,7 +3196,7 @@ static int ionic_station_set(struct ionic_lif *lif) ...@@ -3202,7 +3196,7 @@ static int ionic_station_set(struct ionic_lif *lif)
netdev_dbg(lif->netdev, "adding station MAC addr %pM\n", netdev_dbg(lif->netdev, "adding station MAC addr %pM\n",
netdev->dev_addr); netdev->dev_addr);
ionic_lif_addr(lif, netdev->dev_addr, ADD_ADDR, CAN_SLEEP); ionic_lif_addr(lif, netdev->dev_addr, ADD_ADDR);
return 0; return 0;
} }
...@@ -3225,6 +3219,7 @@ int ionic_lif_init(struct ionic_lif *lif) ...@@ -3225,6 +3219,7 @@ int ionic_lif_init(struct ionic_lif *lif)
lif->hw_index = le16_to_cpu(comp.hw_index); lif->hw_index = le16_to_cpu(comp.hw_index);
mutex_init(&lif->queue_lock); mutex_init(&lif->queue_lock);
mutex_init(&lif->config_lock);
/* now that we have the hw_index we can figure out our doorbell page */ /* now that we have the hw_index we can figure out our doorbell page */
lif->dbid_count = le32_to_cpu(lif->ionic->ident.dev.ndbpgs_per_lif); lif->dbid_count = le32_to_cpu(lif->ionic->ident.dev.ndbpgs_per_lif);
......
...@@ -108,7 +108,6 @@ struct ionic_deferred_work { ...@@ -108,7 +108,6 @@ struct ionic_deferred_work {
struct list_head list; struct list_head list;
enum ionic_deferred_work_type type; enum ionic_deferred_work_type type;
union { union {
unsigned int rx_mode;
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
u8 fw_status; u8 fw_status;
}; };
...@@ -179,6 +178,7 @@ struct ionic_lif { ...@@ -179,6 +178,7 @@ struct ionic_lif {
unsigned int index; unsigned int index;
unsigned int hw_index; unsigned int hw_index;
struct mutex queue_lock; /* lock for queue structures */ struct mutex queue_lock; /* lock for queue structures */
struct mutex config_lock; /* lock for config actions */
spinlock_t adminq_lock; /* lock for AdminQ operations */ spinlock_t adminq_lock; /* lock for AdminQ operations */
struct ionic_qcq *adminqcq; struct ionic_qcq *adminqcq;
struct ionic_qcq *notifyqcq; struct ionic_qcq *notifyqcq;
...@@ -199,7 +199,7 @@ struct ionic_lif { ...@@ -199,7 +199,7 @@ struct ionic_lif {
unsigned int nrxq_descs; unsigned int nrxq_descs;
u32 rx_copybreak; u32 rx_copybreak;
u64 rxq_features; u64 rxq_features;
unsigned int rx_mode; u16 rx_mode;
u64 hw_features; u64 hw_features;
bool registered; bool registered;
bool mc_overflow; bool mc_overflow;
...@@ -302,7 +302,7 @@ int ionic_lif_identify(struct ionic *ionic, u8 lif_type, ...@@ -302,7 +302,7 @@ int ionic_lif_identify(struct ionic *ionic, u8 lif_type,
int ionic_lif_size(struct ionic *ionic); int ionic_lif_size(struct ionic *ionic);
#if IS_ENABLED(CONFIG_PTP_1588_CLOCK) #if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
int ionic_lif_hwstamp_replay(struct ionic_lif *lif); void ionic_lif_hwstamp_replay(struct ionic_lif *lif);
int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr); int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr);
int ionic_lif_hwstamp_get(struct ionic_lif *lif, struct ifreq *ifr); int ionic_lif_hwstamp_get(struct ionic_lif *lif, struct ifreq *ifr);
ktime_t ionic_lif_phc_ktime(struct ionic_lif *lif, u64 counter); ktime_t ionic_lif_phc_ktime(struct ionic_lif *lif, u64 counter);
...@@ -311,10 +311,7 @@ void ionic_lif_unregister_phc(struct ionic_lif *lif); ...@@ -311,10 +311,7 @@ void ionic_lif_unregister_phc(struct ionic_lif *lif);
void ionic_lif_alloc_phc(struct ionic_lif *lif); void ionic_lif_alloc_phc(struct ionic_lif *lif);
void ionic_lif_free_phc(struct ionic_lif *lif); void ionic_lif_free_phc(struct ionic_lif *lif);
#else #else
static inline int ionic_lif_hwstamp_replay(struct ionic_lif *lif) static inline void ionic_lif_hwstamp_replay(struct ionic_lif *lif) {}
{
return -EOPNOTSUPP;
}
static inline int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) static inline int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
{ {
......
...@@ -188,6 +188,9 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) ...@@ -188,6 +188,9 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
struct hwtstamp_config config; struct hwtstamp_config config;
int err; int err;
if (!lif->phc || !lif->phc->ptp)
return -EOPNOTSUPP;
if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
return -EFAULT; return -EFAULT;
...@@ -203,15 +206,16 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr) ...@@ -203,15 +206,16 @@ int ionic_lif_hwstamp_set(struct ionic_lif *lif, struct ifreq *ifr)
return 0; return 0;
} }
int ionic_lif_hwstamp_replay(struct ionic_lif *lif) void ionic_lif_hwstamp_replay(struct ionic_lif *lif)
{ {
int err; int err;
if (!lif->phc || !lif->phc->ptp)
return;
err = ionic_lif_hwstamp_set_ts_config(lif, NULL); err = ionic_lif_hwstamp_set_ts_config(lif, NULL);
if (err) if (err)
netdev_info(lif->netdev, "hwstamp replay failed: %d\n", err); netdev_info(lif->netdev, "hwstamp replay failed: %d\n", err);
return err;
} }
int ionic_lif_hwstamp_get(struct ionic_lif *lif, struct ifreq *ifr) int ionic_lif_hwstamp_get(struct ionic_lif *lif, struct ifreq *ifr)
......
...@@ -274,12 +274,11 @@ static void ionic_rx_clean(struct ionic_queue *q, ...@@ -274,12 +274,11 @@ static void ionic_rx_clean(struct ionic_queue *q,
} }
} }
if (likely(netdev->features & NETIF_F_RXCSUM)) { if (likely(netdev->features & NETIF_F_RXCSUM) &&
if (comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_CALC) { (comp->csum_flags & IONIC_RXQ_COMP_CSUM_F_CALC)) {
skb->ip_summed = CHECKSUM_COMPLETE; skb->ip_summed = CHECKSUM_COMPLETE;
skb->csum = (__force __wsum)le16_to_cpu(comp->csum); skb->csum = (__force __wsum)le16_to_cpu(comp->csum);
stats->csum_complete++; stats->csum_complete++;
}
} else { } else {
stats->csum_none++; stats->csum_none++;
} }
...@@ -451,11 +450,12 @@ void ionic_rx_empty(struct ionic_queue *q) ...@@ -451,11 +450,12 @@ void ionic_rx_empty(struct ionic_queue *q)
q->tail_idx = 0; q->tail_idx = 0;
} }
static void ionic_dim_update(struct ionic_qcq *qcq) static void ionic_dim_update(struct ionic_qcq *qcq, int napi_mode)
{ {
struct dim_sample dim_sample; struct dim_sample dim_sample;
struct ionic_lif *lif; struct ionic_lif *lif;
unsigned int qi; unsigned int qi;
u64 pkts, bytes;
if (!qcq->intr.dim_coal_hw) if (!qcq->intr.dim_coal_hw)
return; return;
...@@ -463,14 +463,23 @@ static void ionic_dim_update(struct ionic_qcq *qcq) ...@@ -463,14 +463,23 @@ static void ionic_dim_update(struct ionic_qcq *qcq)
lif = qcq->q.lif; lif = qcq->q.lif;
qi = qcq->cq.bound_q->index; qi = qcq->cq.bound_q->index;
ionic_intr_coal_init(lif->ionic->idev.intr_ctrl, switch (napi_mode) {
lif->rxqcqs[qi]->intr.index, case IONIC_LIF_F_TX_DIM_INTR:
qcq->intr.dim_coal_hw); pkts = lif->txqstats[qi].pkts;
bytes = lif->txqstats[qi].bytes;
break;
case IONIC_LIF_F_RX_DIM_INTR:
pkts = lif->rxqstats[qi].pkts;
bytes = lif->rxqstats[qi].bytes;
break;
default:
pkts = lif->txqstats[qi].pkts + lif->rxqstats[qi].pkts;
bytes = lif->txqstats[qi].bytes + lif->rxqstats[qi].bytes;
break;
}
dim_update_sample(qcq->cq.bound_intr->rearm_count, dim_update_sample(qcq->cq.bound_intr->rearm_count,
lif->txqstats[qi].pkts, pkts, bytes, &dim_sample);
lif->txqstats[qi].bytes,
&dim_sample);
net_dim(&qcq->dim, dim_sample); net_dim(&qcq->dim, dim_sample);
} }
...@@ -491,7 +500,7 @@ int ionic_tx_napi(struct napi_struct *napi, int budget) ...@@ -491,7 +500,7 @@ int ionic_tx_napi(struct napi_struct *napi, int budget)
ionic_tx_service, NULL, NULL); ionic_tx_service, NULL, NULL);
if (work_done < budget && napi_complete_done(napi, work_done)) { if (work_done < budget && napi_complete_done(napi, work_done)) {
ionic_dim_update(qcq); ionic_dim_update(qcq, IONIC_LIF_F_TX_DIM_INTR);
flags |= IONIC_INTR_CRED_UNMASK; flags |= IONIC_INTR_CRED_UNMASK;
cq->bound_intr->rearm_count++; cq->bound_intr->rearm_count++;
} }
...@@ -530,7 +539,7 @@ int ionic_rx_napi(struct napi_struct *napi, int budget) ...@@ -530,7 +539,7 @@ int ionic_rx_napi(struct napi_struct *napi, int budget)
ionic_rx_fill(cq->bound_q); ionic_rx_fill(cq->bound_q);
if (work_done < budget && napi_complete_done(napi, work_done)) { if (work_done < budget && napi_complete_done(napi, work_done)) {
ionic_dim_update(qcq); ionic_dim_update(qcq, IONIC_LIF_F_RX_DIM_INTR);
flags |= IONIC_INTR_CRED_UNMASK; flags |= IONIC_INTR_CRED_UNMASK;
cq->bound_intr->rearm_count++; cq->bound_intr->rearm_count++;
} }
...@@ -576,7 +585,7 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget) ...@@ -576,7 +585,7 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget)
ionic_rx_fill(rxcq->bound_q); ionic_rx_fill(rxcq->bound_q);
if (rx_work_done < budget && napi_complete_done(napi, rx_work_done)) { if (rx_work_done < budget && napi_complete_done(napi, rx_work_done)) {
ionic_dim_update(qcq); ionic_dim_update(qcq, 0);
flags |= IONIC_INTR_CRED_UNMASK; flags |= IONIC_INTR_CRED_UNMASK;
rxcq->bound_intr->rearm_count++; rxcq->bound_intr->rearm_count++;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment