ipq40xx: essedma Time-balanced scheduling

add script to adjust cpu affinity
essedma Time-balanced scheduling:
TX:
CPU:  |3          | |2          | |1          | |0          |
TX-Q: |15-14-13-12| |11-10-09-08| |07-06-05-04| |03-02-01-00|
          ___________|             |             |
          |  ______________________|             |
          |  |  _________________________________|
          |  |  |
TX-P: |15-11-07-03| |14-10-06-02| |13-09-05-01| |12-08-04-00|
TX-S: |---+--+--+-| |+-----+--+-| |+--+-----+-| |+--+--+----|
       |                |                |                |
RX:    |                |                |                |
CPU:  |3          | |   2       | |      1    | |         0 |
RX-Q: |07-06      | |05-04      | |03-02      | |01-00      |

Signed-off-by: Chen Minqiang <ptpt52@gmail.com>
This commit is contained in:
Chen Minqiang 2018-03-15 05:52:52 +08:00 committed by AmadeusGhost
parent 31f8780b0e
commit b0ee96e014
3 changed files with 46 additions and 46 deletions

View File

@ -22,14 +22,6 @@ extern struct net_device *edma_netdev[EDMA_MAX_PORTID_SUPPORTED];
bool edma_stp_rstp;
u16 edma_ath_eth_type;
/* edma_skb_priority_offset()
* get edma skb priority
*/
static unsigned int edma_skb_priority_offset(struct sk_buff *skb)
{
return (skb->priority >> 2) & 1;
}
/* edma_alloc_tx_ring()
* Allocate Tx descriptors ring
*/
@ -1014,13 +1006,14 @@ static inline u16 edma_tpd_available(struct edma_common_info *edma_cinfo,
/* edma_tx_queue_get()
* Get the starting number of the queue
*/
static inline int edma_tx_queue_get(struct edma_adapter *adapter,
static inline int edma_tx_queue_get(struct edma_common_info *edma_cinfo, struct edma_adapter *adapter,
struct sk_buff *skb, int txq_id)
{
/* skb->priority is used as an index to skb priority table
* and based on packet priority, correspong queue is assigned.
* FIXME we just simple use jiffies for time base balance
*/
return adapter->tx_start_offset[txq_id] + edma_skb_priority_offset(skb);
return adapter->tx_start_offset[txq_id] + (smp_processor_id() % edma_cinfo->num_txq_per_core_netdev);
}
/* edma_tx_update_hw_idx()
@ -1389,8 +1382,9 @@ netdev_tx_t edma_xmit(struct sk_buff *skb,
}
/* this will be one of the 4 TX queues exposed to linux kernel */
txq_id = skb_get_queue_mapping(skb);
queue_id = edma_tx_queue_get(adapter, skb, txq_id);
/* XXX what if num_online_cpus() > EDMA_CPU_CORES_SUPPORTED */
txq_id = ((jiffies >> 5) % (EDMA_CPU_CORES_SUPPORTED - 1) + smp_processor_id() + 1) % EDMA_CPU_CORES_SUPPORTED;
queue_id = edma_tx_queue_get(edma_cinfo, adapter, skb, txq_id);
etdr = edma_cinfo->tpd_ring[queue_id];
nq = netdev_get_tx_queue(net_dev, txq_id);
@ -1873,8 +1867,8 @@ void edma_free_irqs(struct edma_adapter *adapter)
int i, j;
int k = ((edma_cinfo->num_rx_queues == 4) ? 1 : 2);
for (i = 0; i < CONFIG_NR_CPUS; i++) {
for (j = edma_cinfo->edma_percpu_info[i].tx_start; j < (edma_cinfo->edma_percpu_info[i].tx_start + 4); j++)
for (i = 0; i < num_online_cpus() && i < EDMA_CPU_CORES_SUPPORTED; i++) {
for (j = edma_cinfo->edma_percpu_info[i].tx_start; j < (edma_cinfo->edma_percpu_info[i].tx_start + edma_cinfo->num_txq_per_core); j++)
free_irq(edma_cinfo->tx_irq[j], &edma_cinfo->edma_percpu_info[i]);
for (j = edma_cinfo->edma_percpu_info[i].rx_start; j < (edma_cinfo->edma_percpu_info[i].rx_start + k); j++)
@ -2087,15 +2081,13 @@ int edma_poll(struct napi_struct *napi, int budget)
int i, work_done = 0;
u16 rx_pending_fill;
/* Store the Rx/Tx status by ANDing it with
* appropriate CPU RX?TX mask
/* Store the Tx status by ANDing it with
* appropriate CPU TX mask
*/
edma_read_reg(EDMA_REG_RX_ISR, &reg_data);
edma_percpu_info->rx_status |= reg_data & edma_percpu_info->rx_mask;
shadow_rx_status = edma_percpu_info->rx_status;
edma_read_reg(EDMA_REG_TX_ISR, &reg_data);
edma_percpu_info->tx_status |= reg_data & edma_percpu_info->tx_mask;
shadow_tx_status = edma_percpu_info->tx_status;
edma_write_reg(EDMA_REG_TX_ISR, shadow_tx_status);
/* Every core will have a start, which will be computed
* in probe and stored in edma_percpu_info->tx_start variable.
@ -2110,6 +2102,14 @@ int edma_poll(struct napi_struct *napi, int budget)
edma_percpu_info->tx_status &= ~(1 << queue_id);
}
/* Store the Rx status by ANDing it with
* appropriate CPU RX mask
*/
edma_read_reg(EDMA_REG_RX_ISR, &reg_data);
edma_percpu_info->rx_status |= reg_data & edma_percpu_info->rx_mask;
shadow_rx_status = edma_percpu_info->rx_status;
edma_write_reg(EDMA_REG_RX_ISR, shadow_rx_status);
/* Every core will have a start, which will be computed
* in probe and stored in edma_percpu_info->tx_start variable.
* We will shift the status bit by tx_start to obtain
@ -2134,15 +2134,6 @@ int edma_poll(struct napi_struct *napi, int budget)
}
}
/* Clear the status register, to avoid the interrupts to
* reoccur.This clearing of interrupt status register is
* done here as writing to status register only takes place
* once the producer/consumer index has been updated to
* reflect that the packet transmission/reception went fine.
*/
edma_write_reg(EDMA_REG_RX_ISR, shadow_rx_status);
edma_write_reg(EDMA_REG_TX_ISR, shadow_tx_status);
/* If budget not fully consumed, exit the polling mode */
if (likely(work_done < budget)) {
napi_complete(napi);

View File

@ -324,6 +324,7 @@ struct edma_common_info {
u32 from_cpu; /* from CPU TPD field */
u32 num_rxq_per_core; /* Rx queues per core */
u32 num_txq_per_core; /* Tx queues per core */
u32 num_txq_per_core_netdev; /* Tx queues per core per netdev */
u16 tx_ring_count; /* Tx ring count */
u16 rx_ring_count; /* Rx ring*/
u16 rx_head_buffer_len; /* rx buffer length */
@ -331,7 +332,7 @@ struct edma_common_info {
u32 page_mode; /* Jumbo frame supported flag */
u32 fraglist_mode; /* fraglist supported flag */
struct edma_hw hw; /* edma hw specific structure */
struct edma_per_cpu_queues_info edma_percpu_info[CONFIG_NR_CPUS]; /* per cpu information */
struct edma_per_cpu_queues_info edma_percpu_info[EDMA_CPU_CORES_SUPPORTED]; /* per cpu information */
spinlock_t stats_lock; /* protect edma stats area for updation */
struct timer_list edma_stats_timer;
bool is_single_phy;
@ -401,7 +402,7 @@ struct edma_adapter {
u32 link_state; /* phy link state */
u32 phy_mdio_addr; /* PHY device address on MII interface */
u32 poll_required; /* check if link polling is required */
u32 tx_start_offset[CONFIG_NR_CPUS]; /* tx queue start */
u32 tx_start_offset[EDMA_CPU_CORES_SUPPORTED]; /* tx queue start */
u32 default_vlan_tag; /* vlan tag */
u32 dp_bitmap;
uint8_t phy_id[MII_BUS_ID_SIZE + 3];

View File

@ -718,11 +718,7 @@ static int edma_axi_probe(struct platform_device *pdev)
int i, j, k, err = 0;
int portid_bmp;
int idx = 0, idx_mac = 0;
if (CONFIG_NR_CPUS != EDMA_CPU_CORES_SUPPORTED) {
dev_err(&pdev->dev, "Invalid CPU Cores\n");
return -EINVAL;
}
int netdev_group = 2;
if ((num_rxq != 4) && (num_rxq != 8)) {
dev_err(&pdev->dev, "Invalid RX queue, edma probe failed\n");
@ -746,7 +742,7 @@ static int edma_axi_probe(struct platform_device *pdev)
/* Initialize the netdev array before allocation
* to avoid double free
*/
for (i = 0 ; i < edma_cinfo->num_gmac ; i++)
for (i = 0 ; i < EDMA_MAX_PORTID_SUPPORTED; i++)
edma_netdev[i] = NULL;
for (i = 0 ; i < edma_cinfo->num_gmac ; i++) {
@ -767,8 +763,11 @@ static int edma_axi_probe(struct platform_device *pdev)
/* Fill ring details */
edma_cinfo->num_tx_queues = EDMA_MAX_TRANSMIT_QUEUE;
edma_cinfo->num_txq_per_core = (EDMA_MAX_TRANSMIT_QUEUE / 4);
edma_cinfo->num_txq_per_core = (EDMA_MAX_TRANSMIT_QUEUE / num_online_cpus());
edma_cinfo->num_txq_per_core_netdev = (EDMA_MAX_TRANSMIT_QUEUE / netdev_group / num_online_cpus());
edma_cinfo->tx_ring_count = EDMA_TX_RING_SIZE;
if (edma_cinfo->num_txq_per_core == 0)
edma_cinfo->num_txq_per_core = 1;
/* Update num rx queues based on module parameter */
edma_cinfo->num_rx_queues = num_rxq;
@ -922,6 +921,13 @@ static int edma_axi_probe(struct platform_device *pdev)
idx_mac++;
}
if (edma_cinfo->num_gmac == 1) {
netdev_group = 1;
edma_cinfo->num_txq_per_core_netdev = (EDMA_MAX_TRANSMIT_QUEUE / netdev_group / num_online_cpus());
}
if (edma_cinfo->num_txq_per_core_netdev == 0)
edma_cinfo->num_txq_per_core_netdev = 1;
/* Populate the adapter structure register the netdevice */
for (i = 0; i < edma_cinfo->num_gmac; i++) {
int k, m;
@ -929,17 +935,16 @@ static int edma_axi_probe(struct platform_device *pdev)
adapter[i] = netdev_priv(edma_netdev[i]);
adapter[i]->netdev = edma_netdev[i];
adapter[i]->pdev = pdev;
for (j = 0; j < CONFIG_NR_CPUS; j++) {
m = i % 2;
adapter[i]->tx_start_offset[j] =
((j << EDMA_TX_CPU_START_SHIFT) + (m << 1));
for (j = 0; j < num_online_cpus() && j < EDMA_CPU_CORES_SUPPORTED; j++) {
m = i % netdev_group;
adapter[i]->tx_start_offset[j] = j * edma_cinfo->num_txq_per_core + m * edma_cinfo->num_txq_per_core_netdev;
/* Share the queues with available net-devices.
* For instance , with 5 net-devices
* eth0/eth2/eth4 will share q0,q1,q4,q5,q8,q9,q12,q13
* and eth1/eth3 will get the remaining.
*/
for (k = adapter[i]->tx_start_offset[j]; k <
(adapter[i]->tx_start_offset[j] + 2); k++) {
(adapter[i]->tx_start_offset[j] + edma_cinfo->num_txq_per_core_netdev); k++) {
if (edma_fill_netdev(edma_cinfo, k, i, j)) {
pr_err("Netdev overflow Error\n");
goto err_register;
@ -1089,9 +1094,12 @@ static int edma_axi_probe(struct platform_device *pdev)
/* populate per_core_info, do a napi_Add, request 16 TX irqs,
* 8 RX irqs, do a napi enable
*/
for (i = 0; i < CONFIG_NR_CPUS; i++) {
for (i = 0; i < num_online_cpus() && i < EDMA_CPU_CORES_SUPPORTED; i++) {
u8 rx_start;
tx_mask[i] = (0xFFFF >> (16 - edma_cinfo->num_txq_per_core)) << (i * edma_cinfo->num_txq_per_core);
tx_start[i] = i * edma_cinfo->num_txq_per_core;
edma_cinfo->edma_percpu_info[i].napi.state = 0;
netif_napi_add(edma_netdev[0],
@ -1111,7 +1119,7 @@ static int edma_axi_probe(struct platform_device *pdev)
/* Request irq per core */
for (j = edma_cinfo->edma_percpu_info[i].tx_start;
j < tx_start[i] + 4; j++) {
j < tx_start[i] + edma_cinfo->num_txq_per_core; j++) {
sprintf(&edma_tx_irq[j][0], "edma_eth_tx%d", j);
err = request_irq(edma_cinfo->tx_irq[j],
edma_interrupt,
@ -1235,7 +1243,7 @@ err_configure:
#endif
err_rmap_add_fail:
edma_free_irqs(adapter[0]);
for (i = 0; i < CONFIG_NR_CPUS; i++)
for (i = 0; i < num_online_cpus() && i < EDMA_CPU_CORES_SUPPORTED; i++)
napi_disable(&edma_cinfo->edma_percpu_info[i].napi);
err_reset:
err_unregister_sysctl_tbl:
@ -1283,7 +1291,7 @@ static int edma_axi_remove(struct platform_device *pdev)
unregister_netdev(edma_netdev[i]);
edma_stop_rx_tx(hw);
for (i = 0; i < CONFIG_NR_CPUS; i++)
for (i = 0; i < num_online_cpus() && i < EDMA_CPU_CORES_SUPPORTED; i++)
napi_disable(&edma_cinfo->edma_percpu_info[i].napi);
edma_irq_disable(edma_cinfo);