Commit 10ef9ab4 authored by Sathya Perla's avatar Sathya Perla Committed by David S. Miller

be2net: event queue re-design

v2: Fixed up the bad typecasting pointed out by David...

In the current design 8 TXQs are serviced by 1 EQ, while each RSS queue
is serviced by a separate EQ. This is being changed as follows:

- Upto 8 EQs will be used (based on the availabilty of msix vectors).
Each EQ will handle 1 RSS and 1 TX ring. The default non-RSS RX queue and
MCC queue are handled by the last EQ.

- On cards which provide support, upto 8 RSS rings will be used, instead
of the current limit of 4.

The new design allows spreading the TX multi-queue completion processing
across multiple CPUs unlike the previous design.
Signed-off-by: default avatarSathya Perla <sathya.perla@emulex.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 23677ce3
...@@ -81,7 +81,7 @@ static inline char *nic_name(struct pci_dev *pdev) ...@@ -81,7 +81,7 @@ static inline char *nic_name(struct pci_dev *pdev)
#define BE_MIN_MTU 256 #define BE_MIN_MTU 256
#define BE_NUM_VLANS_SUPPORTED 64 #define BE_NUM_VLANS_SUPPORTED 64
#define BE_MAX_EQD 96 #define BE_MAX_EQD 96u
#define BE_MAX_TX_FRAG_COUNT 30 #define BE_MAX_TX_FRAG_COUNT 30
#define EVNT_Q_LEN 1024 #define EVNT_Q_LEN 1024
...@@ -92,12 +92,16 @@ static inline char *nic_name(struct pci_dev *pdev) ...@@ -92,12 +92,16 @@ static inline char *nic_name(struct pci_dev *pdev)
#define MCC_Q_LEN 128 /* total size not to exceed 8 pages */ #define MCC_Q_LEN 128 /* total size not to exceed 8 pages */
#define MCC_CQ_LEN 256 #define MCC_CQ_LEN 256
#define MAX_RSS_QS 4 /* BE limit is 4 queues/port */ #define BE3_MAX_RSS_QS 8
#define BE2_MAX_RSS_QS 4
#define MAX_RSS_QS BE3_MAX_RSS_QS
#define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */ #define MAX_RX_QS (MAX_RSS_QS + 1) /* RSS qs + 1 def Rx */
#define MAX_TX_QS 8 #define MAX_TX_QS 8
#define BE_MAX_MSIX_VECTORS (MAX_RX_QS + 1)/* RX + TX */ #define MAX_MSIX_VECTORS MAX_RSS_QS
#define BE_TX_BUDGET 256
#define BE_NAPI_WEIGHT 64 #define BE_NAPI_WEIGHT 64
#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ #define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */
#define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) #define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST)
#define FW_VER_LEN 32 #define FW_VER_LEN 32
...@@ -165,13 +169,16 @@ struct be_eq_obj { ...@@ -165,13 +169,16 @@ struct be_eq_obj {
/* Adaptive interrupt coalescing (AIC) info */ /* Adaptive interrupt coalescing (AIC) info */
bool enable_aic; bool enable_aic;
u16 min_eqd; /* in usecs */ u32 min_eqd; /* in usecs */
u16 max_eqd; /* in usecs */ u32 max_eqd; /* in usecs */
u16 cur_eqd; /* in usecs */ u32 eqd; /* configured val when aic is off */
u8 eq_idx; u32 cur_eqd; /* in usecs */
u8 idx; /* array index */
u16 tx_budget;
struct napi_struct napi; struct napi_struct napi;
}; struct be_adapter *adapter;
} ____cacheline_aligned_in_smp;
struct be_mcc_obj { struct be_mcc_obj {
struct be_queue_info q; struct be_queue_info q;
...@@ -197,7 +204,7 @@ struct be_tx_obj { ...@@ -197,7 +204,7 @@ struct be_tx_obj {
/* Remember the skbs that were transmitted */ /* Remember the skbs that were transmitted */
struct sk_buff *sent_skb_list[TX_Q_LEN]; struct sk_buff *sent_skb_list[TX_Q_LEN];
struct be_tx_stats stats; struct be_tx_stats stats;
}; } ____cacheline_aligned_in_smp;
/* Struct to remember the pages posted for rx frags */ /* Struct to remember the pages posted for rx frags */
struct be_rx_page_info { struct be_rx_page_info {
...@@ -215,8 +222,6 @@ struct be_rx_stats { ...@@ -215,8 +222,6 @@ struct be_rx_stats {
u32 rx_drops_no_skbs; /* skb allocation errors */ u32 rx_drops_no_skbs; /* skb allocation errors */
u32 rx_drops_no_frags; /* HW has no fetched frags */ u32 rx_drops_no_frags; /* HW has no fetched frags */
u32 rx_post_fail; /* page post alloc failures */ u32 rx_post_fail; /* page post alloc failures */
u32 rx_polls; /* NAPI calls */
u32 rx_events;
u32 rx_compl; u32 rx_compl;
u32 rx_mcast_pkts; u32 rx_mcast_pkts;
u32 rx_compl_err; /* completions with err set */ u32 rx_compl_err; /* completions with err set */
...@@ -249,16 +254,13 @@ struct be_rx_obj { ...@@ -249,16 +254,13 @@ struct be_rx_obj {
struct be_queue_info cq; struct be_queue_info cq;
struct be_rx_compl_info rxcp; struct be_rx_compl_info rxcp;
struct be_rx_page_info page_info_tbl[RX_Q_LEN]; struct be_rx_page_info page_info_tbl[RX_Q_LEN];
struct be_eq_obj rx_eq;
struct be_rx_stats stats; struct be_rx_stats stats;
u8 rss_id; u8 rss_id;
bool rx_post_starved; /* Zero rx frags have been posted to BE */ bool rx_post_starved; /* Zero rx frags have been posted to BE */
u32 cache_line_barrier[16]; } ____cacheline_aligned_in_smp;
};
struct be_drv_stats { struct be_drv_stats {
u32 be_on_die_temperature; u32 be_on_die_temperature;
u32 tx_events;
u32 eth_red_drops; u32 eth_red_drops;
u32 rx_drops_no_pbuf; u32 rx_drops_no_pbuf;
u32 rx_drops_no_txpb; u32 rx_drops_no_txpb;
...@@ -320,20 +322,19 @@ struct be_adapter { ...@@ -320,20 +322,19 @@ struct be_adapter {
spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */
spinlock_t mcc_cq_lock; spinlock_t mcc_cq_lock;
struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS];
u32 num_msix_vec; u32 num_msix_vec;
u32 num_evt_qs;
struct be_eq_obj eq_obj[MAX_MSIX_VECTORS];
struct msix_entry msix_entries[MAX_MSIX_VECTORS];
bool isr_registered; bool isr_registered;
/* TX Rings */ /* TX Rings */
struct be_eq_obj tx_eq; u32 num_tx_qs;
struct be_tx_obj tx_obj[MAX_TX_QS]; struct be_tx_obj tx_obj[MAX_TX_QS];
u8 num_tx_qs;
u32 cache_line_break[8];
/* Rx rings */ /* Rx rings */
struct be_rx_obj rx_obj[MAX_RX_QS];
u32 num_rx_qs; u32 num_rx_qs;
struct be_rx_obj rx_obj[MAX_RX_QS];
u32 big_page_size; /* Compounded page size shared by rx wrbs */ u32 big_page_size; /* Compounded page size shared by rx wrbs */
u8 eq_next_idx; u8 eq_next_idx;
...@@ -404,24 +405,34 @@ struct be_adapter { ...@@ -404,24 +405,34 @@ struct be_adapter {
extern const struct ethtool_ops be_ethtool_ops; extern const struct ethtool_ops be_ethtool_ops;
#define msix_enabled(adapter) (adapter->num_msix_vec > 0) #define msix_enabled(adapter) (adapter->num_msix_vec > 0)
#define tx_stats(txo) (&txo->stats) #define num_irqs(adapter) (msix_enabled(adapter) ? \
#define rx_stats(rxo) (&rxo->stats) adapter->num_msix_vec : 1)
#define tx_stats(txo) (&(txo)->stats)
#define rx_stats(rxo) (&(rxo)->stats)
#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) /* The default RXQ is the last RXQ */
#define default_rxo(adpt) (&adpt->rx_obj[adpt->num_rx_qs - 1])
#define for_all_rx_queues(adapter, rxo, i) \ #define for_all_rx_queues(adapter, rxo, i) \
for (i = 0, rxo = &adapter->rx_obj[i]; i < adapter->num_rx_qs; \ for (i = 0, rxo = &adapter->rx_obj[i]; i < adapter->num_rx_qs; \
i++, rxo++) i++, rxo++)
/* Just skip the first default non-rss queue */ /* Skip the default non-rss queue (last one)*/
#define for_all_rss_queues(adapter, rxo, i) \ #define for_all_rss_queues(adapter, rxo, i) \
for (i = 0, rxo = &adapter->rx_obj[i+1]; i < (adapter->num_rx_qs - 1);\ for (i = 0, rxo = &adapter->rx_obj[i]; i < (adapter->num_rx_qs - 1);\
i++, rxo++) i++, rxo++)
#define for_all_tx_queues(adapter, txo, i) \ #define for_all_tx_queues(adapter, txo, i) \
for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs; \ for (i = 0, txo = &adapter->tx_obj[i]; i < adapter->num_tx_qs; \
i++, txo++) i++, txo++)
#define for_all_evt_queues(adapter, eqo, i) \
for (i = 0, eqo = &adapter->eq_obj[i]; i < adapter->num_evt_qs; \
i++, eqo++)
#define is_mcc_eqo(eqo) (eqo->idx == 0)
#define mcc_eqo(adapter) (&adapter->eq_obj[0])
#define PAGE_SHIFT_4K 12 #define PAGE_SHIFT_4K 12
#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
......
...@@ -235,10 +235,10 @@ void be_async_mcc_disable(struct be_adapter *adapter) ...@@ -235,10 +235,10 @@ void be_async_mcc_disable(struct be_adapter *adapter)
adapter->mcc_obj.rearm_cq = false; adapter->mcc_obj.rearm_cq = false;
} }
int be_process_mcc(struct be_adapter *adapter, int *status) int be_process_mcc(struct be_adapter *adapter)
{ {
struct be_mcc_compl *compl; struct be_mcc_compl *compl;
int num = 0; int num = 0, status = 0;
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
spin_lock_bh(&adapter->mcc_cq_lock); spin_lock_bh(&adapter->mcc_cq_lock);
...@@ -252,32 +252,32 @@ int be_process_mcc(struct be_adapter *adapter, int *status) ...@@ -252,32 +252,32 @@ int be_process_mcc(struct be_adapter *adapter, int *status)
be_async_grp5_evt_process(adapter, be_async_grp5_evt_process(adapter,
compl->flags, compl); compl->flags, compl);
} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
*status = be_mcc_compl_process(adapter, compl); status = be_mcc_compl_process(adapter, compl);
atomic_dec(&mcc_obj->q.used); atomic_dec(&mcc_obj->q.used);
} }
be_mcc_compl_use(compl); be_mcc_compl_use(compl);
num++; num++;
} }
if (num)
be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
spin_unlock_bh(&adapter->mcc_cq_lock); spin_unlock_bh(&adapter->mcc_cq_lock);
return num; return status;
} }
/* Wait till no more pending mcc requests are present */ /* Wait till no more pending mcc requests are present */
static int be_mcc_wait_compl(struct be_adapter *adapter) static int be_mcc_wait_compl(struct be_adapter *adapter)
{ {
#define mcc_timeout 120000 /* 12s timeout */ #define mcc_timeout 120000 /* 12s timeout */
int i, num, status = 0; int i, status = 0;
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
for (i = 0; i < mcc_timeout; i++) { for (i = 0; i < mcc_timeout; i++) {
if (be_error(adapter)) if (be_error(adapter))
return -EIO; return -EIO;
num = be_process_mcc(adapter, &status); status = be_process_mcc(adapter);
if (num)
be_cq_notify(adapter, mcc_obj->cq.id,
mcc_obj->rearm_cq, num);
if (atomic_read(&mcc_obj->q.used) == 0) if (atomic_read(&mcc_obj->q.used) == 0)
break; break;
...@@ -726,9 +726,8 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom) ...@@ -726,9 +726,8 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, int pmac_id, u32 dom)
} }
/* Uses Mbox */ /* Uses Mbox */
int be_cmd_cq_create(struct be_adapter *adapter, int be_cmd_cq_create(struct be_adapter *adapter, struct be_queue_info *cq,
struct be_queue_info *cq, struct be_queue_info *eq, struct be_queue_info *eq, bool no_delay, int coalesce_wm)
bool sol_evts, bool no_delay, int coalesce_wm)
{ {
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_cmd_req_cq_create *req; struct be_cmd_req_cq_create *req;
...@@ -759,7 +758,6 @@ int be_cmd_cq_create(struct be_adapter *adapter, ...@@ -759,7 +758,6 @@ int be_cmd_cq_create(struct be_adapter *adapter,
ctxt, 1); ctxt, 1);
AMAP_SET_BITS(struct amap_cq_context_lancer, eqid, AMAP_SET_BITS(struct amap_cq_context_lancer, eqid,
ctxt, eq->id); ctxt, eq->id);
AMAP_SET_BITS(struct amap_cq_context_lancer, armed, ctxt, 1);
} else { } else {
AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt, AMAP_SET_BITS(struct amap_cq_context_be, coalescwm, ctxt,
coalesce_wm); coalesce_wm);
...@@ -768,11 +766,8 @@ int be_cmd_cq_create(struct be_adapter *adapter, ...@@ -768,11 +766,8 @@ int be_cmd_cq_create(struct be_adapter *adapter,
AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt, AMAP_SET_BITS(struct amap_cq_context_be, count, ctxt,
__ilog2_u32(cq->len/256)); __ilog2_u32(cq->len/256));
AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1); AMAP_SET_BITS(struct amap_cq_context_be, valid, ctxt, 1);
AMAP_SET_BITS(struct amap_cq_context_be, solevent,
ctxt, sol_evts);
AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1); AMAP_SET_BITS(struct amap_cq_context_be, eventable, ctxt, 1);
AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id); AMAP_SET_BITS(struct amap_cq_context_be, eqid, ctxt, eq->id);
AMAP_SET_BITS(struct amap_cq_context_be, armed, ctxt, 1);
} }
be_dws_cpu_to_le(ctxt, sizeof(req->context)); be_dws_cpu_to_le(ctxt, sizeof(req->context));
...@@ -973,7 +968,7 @@ int be_cmd_txq_create(struct be_adapter *adapter, ...@@ -973,7 +968,7 @@ int be_cmd_txq_create(struct be_adapter *adapter,
/* Uses MCC */ /* Uses MCC */
int be_cmd_rxq_create(struct be_adapter *adapter, int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_queue_info *rxq, u16 cq_id, u16 frag_size, struct be_queue_info *rxq, u16 cq_id, u16 frag_size,
u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id) u32 if_id, u32 rss, u8 *rss_id)
{ {
struct be_mcc_wrb *wrb; struct be_mcc_wrb *wrb;
struct be_cmd_req_eth_rx_create *req; struct be_cmd_req_eth_rx_create *req;
...@@ -997,7 +992,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter, ...@@ -997,7 +992,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
req->num_pages = 2; req->num_pages = 2;
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
req->interface_id = cpu_to_le32(if_id); req->interface_id = cpu_to_le32(if_id);
req->max_frame_size = cpu_to_le16(max_frame_size); req->max_frame_size = cpu_to_le16(BE_MAX_JUMBO_FRAME_SIZE);
req->rss_queue = cpu_to_le32(rss); req->rss_queue = cpu_to_le32(rss);
status = be_mcc_notify_wait(adapter); status = be_mcc_notify_wait(adapter);
......
...@@ -1506,8 +1506,7 @@ extern int be_cmd_eq_create(struct be_adapter *adapter, ...@@ -1506,8 +1506,7 @@ extern int be_cmd_eq_create(struct be_adapter *adapter,
struct be_queue_info *eq, int eq_delay); struct be_queue_info *eq, int eq_delay);
extern int be_cmd_cq_create(struct be_adapter *adapter, extern int be_cmd_cq_create(struct be_adapter *adapter,
struct be_queue_info *cq, struct be_queue_info *eq, struct be_queue_info *cq, struct be_queue_info *eq,
bool sol_evts, bool no_delay, bool no_delay, int num_cqe_dma_coalesce);
int num_cqe_dma_coalesce);
extern int be_cmd_mccq_create(struct be_adapter *adapter, extern int be_cmd_mccq_create(struct be_adapter *adapter,
struct be_queue_info *mccq, struct be_queue_info *mccq,
struct be_queue_info *cq); struct be_queue_info *cq);
...@@ -1516,8 +1515,7 @@ extern int be_cmd_txq_create(struct be_adapter *adapter, ...@@ -1516,8 +1515,7 @@ extern int be_cmd_txq_create(struct be_adapter *adapter,
struct be_queue_info *cq); struct be_queue_info *cq);
extern int be_cmd_rxq_create(struct be_adapter *adapter, extern int be_cmd_rxq_create(struct be_adapter *adapter,
struct be_queue_info *rxq, u16 cq_id, struct be_queue_info *rxq, u16 cq_id,
u16 frag_size, u16 max_frame_size, u32 if_id, u16 frag_size, u32 if_id, u32 rss, u8 *rss_id);
u32 rss, u8 *rss_id);
extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
int type); int type);
extern int be_cmd_rxq_destroy(struct be_adapter *adapter, extern int be_cmd_rxq_destroy(struct be_adapter *adapter,
...@@ -1546,7 +1544,7 @@ extern int be_cmd_query_fw_cfg(struct be_adapter *adapter, ...@@ -1546,7 +1544,7 @@ extern int be_cmd_query_fw_cfg(struct be_adapter *adapter,
extern int be_cmd_reset_function(struct be_adapter *adapter); extern int be_cmd_reset_function(struct be_adapter *adapter);
extern int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, extern int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable,
u16 table_size); u16 table_size);
extern int be_process_mcc(struct be_adapter *adapter, int *status); extern int be_process_mcc(struct be_adapter *adapter);
extern int be_cmd_set_beacon_state(struct be_adapter *adapter, extern int be_cmd_set_beacon_state(struct be_adapter *adapter,
u8 port_num, u8 beacon, u8 status, u8 state); u8 port_num, u8 beacon, u8 status, u8 state);
extern int be_cmd_get_beacon_state(struct be_adapter *adapter, extern int be_cmd_get_beacon_state(struct be_adapter *adapter,
......
...@@ -37,7 +37,6 @@ enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT}; ...@@ -37,7 +37,6 @@ enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT};
FIELDINFO(struct be_drv_stats, field) FIELDINFO(struct be_drv_stats, field)
static const struct be_ethtool_stat et_stats[] = { static const struct be_ethtool_stat et_stats[] = {
{DRVSTAT_INFO(tx_events)},
{DRVSTAT_INFO(rx_crc_errors)}, {DRVSTAT_INFO(rx_crc_errors)},
{DRVSTAT_INFO(rx_alignment_symbol_errors)}, {DRVSTAT_INFO(rx_alignment_symbol_errors)},
{DRVSTAT_INFO(rx_pause_frames)}, {DRVSTAT_INFO(rx_pause_frames)},
...@@ -126,8 +125,6 @@ static const struct be_ethtool_stat et_stats[] = { ...@@ -126,8 +125,6 @@ static const struct be_ethtool_stat et_stats[] = {
static const struct be_ethtool_stat et_rx_stats[] = { static const struct be_ethtool_stat et_rx_stats[] = {
{DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */ {DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */
{DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */ {DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */
{DRVSTAT_RX_INFO(rx_polls)},
{DRVSTAT_RX_INFO(rx_events)},
{DRVSTAT_RX_INFO(rx_compl)}, {DRVSTAT_RX_INFO(rx_compl)},
{DRVSTAT_RX_INFO(rx_mcast_pkts)}, {DRVSTAT_RX_INFO(rx_mcast_pkts)},
/* Number of page allocation failures while posting receive buffers /* Number of page allocation failures while posting receive buffers
...@@ -154,7 +151,6 @@ static const struct be_ethtool_stat et_tx_stats[] = { ...@@ -154,7 +151,6 @@ static const struct be_ethtool_stat et_tx_stats[] = {
{DRVSTAT_TX_INFO(tx_reqs)}, {DRVSTAT_TX_INFO(tx_reqs)},
/* Number of TX work request blocks DMAed to HW */ /* Number of TX work request blocks DMAed to HW */
{DRVSTAT_TX_INFO(tx_wrbs)}, {DRVSTAT_TX_INFO(tx_wrbs)},
{DRVSTAT_TX_INFO(tx_compl)},
/* Number of times the TX queue was stopped due to lack /* Number of times the TX queue was stopped due to lack
* of spaces in the TXQ. * of spaces in the TXQ.
*/ */
...@@ -290,86 +286,42 @@ be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf) ...@@ -290,86 +286,42 @@ be_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *buf)
} }
} }
static int static int be_get_coalesce(struct net_device *netdev,
be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) struct ethtool_coalesce *et)
{ {
struct be_adapter *adapter = netdev_priv(netdev); struct be_adapter *adapter = netdev_priv(netdev);
struct be_eq_obj *rx_eq = &adapter->rx_obj[0].rx_eq; struct be_eq_obj *eqo = &adapter->eq_obj[0];
struct be_eq_obj *tx_eq = &adapter->tx_eq;
coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; et->rx_coalesce_usecs = eqo->cur_eqd;
coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd; et->rx_coalesce_usecs_high = eqo->max_eqd;
coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd; et->rx_coalesce_usecs_low = eqo->min_eqd;
coalesce->tx_coalesce_usecs = tx_eq->cur_eqd; et->tx_coalesce_usecs = eqo->cur_eqd;
coalesce->tx_coalesce_usecs_high = tx_eq->max_eqd; et->tx_coalesce_usecs_high = eqo->max_eqd;
coalesce->tx_coalesce_usecs_low = tx_eq->min_eqd; et->tx_coalesce_usecs_low = eqo->min_eqd;
coalesce->use_adaptive_rx_coalesce = rx_eq->enable_aic; et->use_adaptive_rx_coalesce = eqo->enable_aic;
coalesce->use_adaptive_tx_coalesce = tx_eq->enable_aic; et->use_adaptive_tx_coalesce = eqo->enable_aic;
return 0; return 0;
} }
/* /* TX attributes are ignored. Only RX attributes are considered
* This routine is used to set interrup coalescing delay * eqd cmd is issued in the worker thread.
*/ */
static int static int be_set_coalesce(struct net_device *netdev,
be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) struct ethtool_coalesce *et)
{ {
struct be_adapter *adapter = netdev_priv(netdev); struct be_adapter *adapter = netdev_priv(netdev);
struct be_rx_obj *rxo; struct be_eq_obj *eqo;
struct be_eq_obj *rx_eq; int i;
struct be_eq_obj *tx_eq = &adapter->tx_eq;
u32 rx_max, rx_min, rx_cur; for_all_evt_queues(adapter, eqo, i) {
int status = 0, i; eqo->enable_aic = et->use_adaptive_rx_coalesce;
u32 tx_cur; eqo->max_eqd = min(et->rx_coalesce_usecs_high, BE_MAX_EQD);
eqo->min_eqd = min(et->rx_coalesce_usecs_low, eqo->max_eqd);
if (coalesce->use_adaptive_tx_coalesce == 1) eqo->eqd = et->rx_coalesce_usecs;
return -EINVAL;
for_all_rx_queues(adapter, rxo, i) {
rx_eq = &rxo->rx_eq;
if (!rx_eq->enable_aic && coalesce->use_adaptive_rx_coalesce)
rx_eq->cur_eqd = 0;
rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce;
rx_max = coalesce->rx_coalesce_usecs_high;
rx_min = coalesce->rx_coalesce_usecs_low;
rx_cur = coalesce->rx_coalesce_usecs;
if (rx_eq->enable_aic) {
if (rx_max > BE_MAX_EQD)
rx_max = BE_MAX_EQD;
if (rx_min > rx_max)
rx_min = rx_max;
rx_eq->max_eqd = rx_max;
rx_eq->min_eqd = rx_min;
if (rx_eq->cur_eqd > rx_max)
rx_eq->cur_eqd = rx_max;
if (rx_eq->cur_eqd < rx_min)
rx_eq->cur_eqd = rx_min;
} else {
if (rx_cur > BE_MAX_EQD)
rx_cur = BE_MAX_EQD;
if (rx_eq->cur_eqd != rx_cur) {
status = be_cmd_modify_eqd(adapter, rx_eq->q.id,
rx_cur);
if (!status)
rx_eq->cur_eqd = rx_cur;
}
}
}
tx_cur = coalesce->tx_coalesce_usecs;
if (tx_cur > BE_MAX_EQD)
tx_cur = BE_MAX_EQD;
if (tx_eq->cur_eqd != tx_cur) {
status = be_cmd_modify_eqd(adapter, tx_eq->q.id, tx_cur);
if (!status)
tx_eq->cur_eqd = tx_cur;
} }
return 0; return 0;
......
This diff is collapsed.
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