Skip to content

Commit 0d97338

Browse files
tlfalconkuba-moo
authored andcommitted
ibmvnic: Introduce xmit_more support using batched subCRQ hcalls
Include support for the xmit_more feature utilizing the H_SEND_SUB_CRQ_INDIRECT hypervisor call which allows the sending of multiple subordinate Command Response Queue descriptors in one hypervisor call via a DMA-mapped buffer. This update reduces hypervisor calls and thus hypervisor call overhead per TX descriptor. Signed-off-by: Thomas Falcon <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 4f0b681 commit 0d97338

File tree

1 file changed

+139
-65
lines changed

1 file changed

+139
-65
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 139 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,7 @@ static int __ibmvnic_open(struct net_device *netdev)
11651165
if (prev_state == VNIC_CLOSED)
11661166
enable_irq(adapter->tx_scrq[i]->irq);
11671167
enable_scrq_irq(adapter, adapter->tx_scrq[i]);
1168+
netdev_tx_reset_queue(netdev_get_tx_queue(netdev, i));
11681169
}
11691170

11701171
rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP);
@@ -1523,16 +1524,93 @@ static int ibmvnic_xmit_workarounds(struct sk_buff *skb,
15231524
return 0;
15241525
}
15251526

1527+
static void ibmvnic_tx_scrq_clean_buffer(struct ibmvnic_adapter *adapter,
1528+
struct ibmvnic_sub_crq_queue *tx_scrq)
1529+
{
1530+
struct ibmvnic_ind_xmit_queue *ind_bufp;
1531+
struct ibmvnic_tx_buff *tx_buff;
1532+
struct ibmvnic_tx_pool *tx_pool;
1533+
union sub_crq tx_scrq_entry;
1534+
int queue_num;
1535+
int entries;
1536+
int index;
1537+
int i;
1538+
1539+
ind_bufp = &tx_scrq->ind_buf;
1540+
entries = (u64)ind_bufp->index;
1541+
queue_num = tx_scrq->pool_index;
1542+
1543+
for (i = entries - 1; i >= 0; --i) {
1544+
tx_scrq_entry = ind_bufp->indir_arr[i];
1545+
if (tx_scrq_entry.v1.type != IBMVNIC_TX_DESC)
1546+
continue;
1547+
index = be32_to_cpu(tx_scrq_entry.v1.correlator);
1548+
if (index & IBMVNIC_TSO_POOL_MASK) {
1549+
tx_pool = &adapter->tso_pool[queue_num];
1550+
index &= ~IBMVNIC_TSO_POOL_MASK;
1551+
} else {
1552+
tx_pool = &adapter->tx_pool[queue_num];
1553+
}
1554+
tx_pool->free_map[tx_pool->consumer_index] = index;
1555+
tx_pool->consumer_index = tx_pool->consumer_index == 0 ?
1556+
tx_pool->num_buffers - 1 :
1557+
tx_pool->consumer_index - 1;
1558+
tx_buff = &tx_pool->tx_buff[index];
1559+
adapter->netdev->stats.tx_packets--;
1560+
adapter->netdev->stats.tx_bytes -= tx_buff->skb->len;
1561+
adapter->tx_stats_buffers[queue_num].packets--;
1562+
adapter->tx_stats_buffers[queue_num].bytes -=
1563+
tx_buff->skb->len;
1564+
dev_kfree_skb_any(tx_buff->skb);
1565+
tx_buff->skb = NULL;
1566+
adapter->netdev->stats.tx_dropped++;
1567+
}
1568+
ind_bufp->index = 0;
1569+
if (atomic_sub_return(entries, &tx_scrq->used) <=
1570+
(adapter->req_tx_entries_per_subcrq / 2) &&
1571+
__netif_subqueue_stopped(adapter->netdev, queue_num)) {
1572+
netif_wake_subqueue(adapter->netdev, queue_num);
1573+
netdev_dbg(adapter->netdev, "Started queue %d\n",
1574+
queue_num);
1575+
}
1576+
}
1577+
1578+
static int ibmvnic_tx_scrq_flush(struct ibmvnic_adapter *adapter,
1579+
struct ibmvnic_sub_crq_queue *tx_scrq)
1580+
{
1581+
struct ibmvnic_ind_xmit_queue *ind_bufp;
1582+
u64 dma_addr;
1583+
u64 entries;
1584+
u64 handle;
1585+
int rc;
1586+
1587+
ind_bufp = &tx_scrq->ind_buf;
1588+
dma_addr = (u64)ind_bufp->indir_dma;
1589+
entries = (u64)ind_bufp->index;
1590+
handle = tx_scrq->handle;
1591+
1592+
if (!entries)
1593+
return 0;
1594+
rc = send_subcrq_indirect(adapter, handle, dma_addr, entries);
1595+
if (rc)
1596+
ibmvnic_tx_scrq_clean_buffer(adapter, tx_scrq);
1597+
else
1598+
ind_bufp->index = 0;
1599+
return 0;
1600+
}
1601+
15261602
static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
15271603
{
15281604
struct ibmvnic_adapter *adapter = netdev_priv(netdev);
15291605
int queue_num = skb_get_queue_mapping(skb);
15301606
u8 *hdrs = (u8 *)&adapter->tx_rx_desc_req;
15311607
struct device *dev = &adapter->vdev->dev;
1608+
struct ibmvnic_ind_xmit_queue *ind_bufp;
15321609
struct ibmvnic_tx_buff *tx_buff = NULL;
15331610
struct ibmvnic_sub_crq_queue *tx_scrq;
15341611
struct ibmvnic_tx_pool *tx_pool;
15351612
unsigned int tx_send_failed = 0;
1613+
netdev_tx_t ret = NETDEV_TX_OK;
15361614
unsigned int tx_map_failed = 0;
15371615
unsigned int tx_dropped = 0;
15381616
unsigned int tx_packets = 0;
@@ -1546,8 +1624,10 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
15461624
unsigned char *dst;
15471625
int index = 0;
15481626
u8 proto = 0;
1549-
u64 handle;
1550-
netdev_tx_t ret = NETDEV_TX_OK;
1627+
1628+
tx_scrq = adapter->tx_scrq[queue_num];
1629+
txq = netdev_get_tx_queue(netdev, queue_num);
1630+
ind_bufp = &tx_scrq->ind_buf;
15511631

15521632
if (test_bit(0, &adapter->resetting)) {
15531633
if (!netif_subqueue_stopped(netdev, skb))
@@ -1557,31 +1637,30 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
15571637
tx_send_failed++;
15581638
tx_dropped++;
15591639
ret = NETDEV_TX_OK;
1640+
ibmvnic_tx_scrq_flush(adapter, tx_scrq);
15601641
goto out;
15611642
}
15621643

15631644
if (ibmvnic_xmit_workarounds(skb, netdev)) {
15641645
tx_dropped++;
15651646
tx_send_failed++;
15661647
ret = NETDEV_TX_OK;
1648+
ibmvnic_tx_scrq_flush(adapter, tx_scrq);
15671649
goto out;
15681650
}
15691651
if (skb_is_gso(skb))
15701652
tx_pool = &adapter->tso_pool[queue_num];
15711653
else
15721654
tx_pool = &adapter->tx_pool[queue_num];
15731655

1574-
tx_scrq = adapter->tx_scrq[queue_num];
1575-
txq = netdev_get_tx_queue(netdev, skb_get_queue_mapping(skb));
1576-
handle = tx_scrq->handle;
1577-
15781656
index = tx_pool->free_map[tx_pool->consumer_index];
15791657

15801658
if (index == IBMVNIC_INVALID_MAP) {
15811659
dev_kfree_skb_any(skb);
15821660
tx_send_failed++;
15831661
tx_dropped++;
15841662
ret = NETDEV_TX_OK;
1663+
ibmvnic_tx_scrq_flush(adapter, tx_scrq);
15851664
goto out;
15861665
}
15871666

@@ -1666,55 +1745,29 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
16661745
tx_crq.v1.mss = cpu_to_be16(skb_shinfo(skb)->gso_size);
16671746
hdrs += 2;
16681747
}
1669-
/* determine if l2/3/4 headers are sent to firmware */
1670-
if ((*hdrs >> 7) & 1) {
1748+
1749+
if ((*hdrs >> 7) & 1)
16711750
build_hdr_descs_arr(tx_buff, &num_entries, *hdrs);
1672-
tx_crq.v1.n_crq_elem = num_entries;
1673-
tx_buff->num_entries = num_entries;
1674-
tx_buff->indir_arr[0] = tx_crq;
1675-
tx_buff->indir_dma = dma_map_single(dev, tx_buff->indir_arr,
1676-
sizeof(tx_buff->indir_arr),
1677-
DMA_TO_DEVICE);
1678-
if (dma_mapping_error(dev, tx_buff->indir_dma)) {
1679-
dev_kfree_skb_any(skb);
1680-
tx_buff->skb = NULL;
1681-
if (!firmware_has_feature(FW_FEATURE_CMO))
1682-
dev_err(dev, "tx: unable to map descriptor array\n");
1683-
tx_map_failed++;
1684-
tx_dropped++;
1685-
ret = NETDEV_TX_OK;
1686-
goto tx_err_out;
1687-
}
1688-
lpar_rc = send_subcrq_indirect(adapter, handle,
1689-
(u64)tx_buff->indir_dma,
1690-
(u64)num_entries);
1691-
dma_unmap_single(dev, tx_buff->indir_dma,
1692-
sizeof(tx_buff->indir_arr), DMA_TO_DEVICE);
1693-
} else {
1694-
tx_buff->num_entries = num_entries;
1695-
lpar_rc = send_subcrq(adapter, handle,
1696-
&tx_crq);
1697-
}
1698-
if (lpar_rc != H_SUCCESS) {
1699-
if (lpar_rc != H_CLOSED && lpar_rc != H_PARAMETER)
1700-
dev_err_ratelimited(dev, "tx: send failed\n");
1701-
dev_kfree_skb_any(skb);
1702-
tx_buff->skb = NULL;
17031751

1704-
if (lpar_rc == H_CLOSED || adapter->failover_pending) {
1705-
/* Disable TX and report carrier off if queue is closed
1706-
* or pending failover.
1707-
* Firmware guarantees that a signal will be sent to the
1708-
* driver, triggering a reset or some other action.
1709-
*/
1710-
netif_tx_stop_all_queues(netdev);
1711-
netif_carrier_off(netdev);
1712-
}
1752+
tx_crq.v1.n_crq_elem = num_entries;
1753+
tx_buff->num_entries = num_entries;
1754+
/* flush buffer if current entry can not fit */
1755+
if (num_entries + ind_bufp->index > IBMVNIC_MAX_IND_DESCS) {
1756+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
1757+
if (lpar_rc != H_SUCCESS)
1758+
goto tx_flush_err;
1759+
}
17131760

1714-
tx_send_failed++;
1715-
tx_dropped++;
1716-
ret = NETDEV_TX_OK;
1717-
goto tx_err_out;
1761+
tx_buff->indir_arr[0] = tx_crq;
1762+
memcpy(&ind_bufp->indir_arr[ind_bufp->index], tx_buff->indir_arr,
1763+
num_entries * sizeof(struct ibmvnic_generic_scrq));
1764+
ind_bufp->index += num_entries;
1765+
if (__netdev_tx_sent_queue(txq, skb->len,
1766+
netdev_xmit_more() &&
1767+
ind_bufp->index < IBMVNIC_MAX_IND_DESCS)) {
1768+
lpar_rc = ibmvnic_tx_scrq_flush(adapter, tx_scrq);
1769+
if (lpar_rc != H_SUCCESS)
1770+
goto tx_err;
17181771
}
17191772

17201773
if (atomic_add_return(num_entries, &tx_scrq->used)
@@ -1729,14 +1782,26 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
17291782
ret = NETDEV_TX_OK;
17301783
goto out;
17311784

1732-
tx_err_out:
1733-
/* roll back consumer index and map array*/
1734-
if (tx_pool->consumer_index == 0)
1735-
tx_pool->consumer_index =
1736-
tx_pool->num_buffers - 1;
1737-
else
1738-
tx_pool->consumer_index--;
1739-
tx_pool->free_map[tx_pool->consumer_index] = index;
1785+
tx_flush_err:
1786+
dev_kfree_skb_any(skb);
1787+
tx_buff->skb = NULL;
1788+
tx_pool->consumer_index = tx_pool->consumer_index == 0 ?
1789+
tx_pool->num_buffers - 1 :
1790+
tx_pool->consumer_index - 1;
1791+
tx_dropped++;
1792+
tx_err:
1793+
if (lpar_rc != H_CLOSED && lpar_rc != H_PARAMETER)
1794+
dev_err_ratelimited(dev, "tx: send failed\n");
1795+
1796+
if (lpar_rc == H_CLOSED || adapter->failover_pending) {
1797+
/* Disable TX and report carrier off if queue is closed
1798+
* or pending failover.
1799+
* Firmware guarantees that a signal will be sent to the
1800+
* driver, triggering a reset or some other action.
1801+
*/
1802+
netif_tx_stop_all_queues(netdev);
1803+
netif_carrier_off(netdev);
1804+
}
17401805
out:
17411806
netdev->stats.tx_dropped += tx_dropped;
17421807
netdev->stats.tx_bytes += tx_bytes;
@@ -3117,6 +3182,7 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
31173182
struct device *dev = &adapter->vdev->dev;
31183183
struct ibmvnic_tx_pool *tx_pool;
31193184
struct ibmvnic_tx_buff *txbuff;
3185+
struct netdev_queue *txq;
31203186
union sub_crq *next;
31213187
int index;
31223188
int i, j;
@@ -3125,6 +3191,8 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
31253191
while (pending_scrq(adapter, scrq)) {
31263192
unsigned int pool = scrq->pool_index;
31273193
int num_entries = 0;
3194+
int total_bytes = 0;
3195+
int num_packets = 0;
31283196

31293197
next = ibmvnic_next_scrq(adapter, scrq);
31303198
for (i = 0; i < next->tx_comp.num_comps; i++) {
@@ -3150,13 +3218,16 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
31503218
txbuff->data_dma[j] = 0;
31513219
}
31523220

3153-
if (txbuff->last_frag) {
3154-
dev_kfree_skb_any(txbuff->skb);
3221+
num_packets++;
3222+
num_entries += txbuff->num_entries;
3223+
if (txbuff->skb) {
3224+
total_bytes += txbuff->skb->len;
3225+
dev_consume_skb_irq(txbuff->skb);
31553226
txbuff->skb = NULL;
3227+
} else {
3228+
netdev_warn(adapter->netdev,
3229+
"TX completion received with NULL socket buffer\n");
31563230
}
3157-
3158-
num_entries += txbuff->num_entries;
3159-
31603231
tx_pool->free_map[tx_pool->producer_index] = index;
31613232
tx_pool->producer_index =
31623233
(tx_pool->producer_index + 1) %
@@ -3165,6 +3236,9 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter,
31653236
/* remove tx_comp scrq*/
31663237
next->tx_comp.first = 0;
31673238

3239+
txq = netdev_get_tx_queue(adapter->netdev, scrq->pool_index);
3240+
netdev_tx_completed_queue(txq, num_packets, total_bytes);
3241+
31683242
if (atomic_sub_return(num_entries, &scrq->used) <=
31693243
(adapter->req_tx_entries_per_subcrq / 2) &&
31703244
__netif_subqueue_stopped(adapter->netdev,

0 commit comments

Comments
 (0)