Skip to content

Commit

Permalink
Merge pull request torvalds#201 in PROCESSOR-SDK/processor-sdk-linux …
Browse files Browse the repository at this point in the history
…from ~A0400828/processor-sdk-linux:for-6.2/prueth-fixes to processor-sdk-linux-4.19.y

* commit '5c44c1766d950231a28defc725ea4b944f4f44b2':
  net: ethernet: ti: icssg-prueth: fix TX descriptor not available case
  net: ethernet: ti: icssg-prueth: optimize napi rx during netif down
  net: ethernet: ti: icssg-prueth: add missed stats counters prueth_dma_rx_push() fail
  net: ti: icssg_prueth: implement shutdown command
  dmaengine: ti: clear pkt_info2 pkt type before setting
  net: ethernet: ti: icssg-prueth: remove redundant disable FT1
  net: ethernet: ti: icssg-prueth: Simplify promiscuous mode
  net: ti: icssg-prueth: Add allmulti support
  net: ti: icssg-prueth: Fix non promiscuous mode
  • Loading branch information
Muralidharan Karicheri committed Dec 6, 2019
2 parents 3a729b7 + 5c44c17 commit 971cc5a
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 69 deletions.
53 changes: 9 additions & 44 deletions drivers/net/ethernet/ti/icssg_classifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ void icssg_class_disable(struct regmap *miig_rt, int slice)
/* configure gate */
offset = RX_CLASS_GATES_N_REG(slice, n);
regmap_read(miig_rt, offset, &data);
/* clear class_raw */
/* clear class_raw so we go through filters */
data &= ~RX_CLASS_GATES_RAW_MASK;
/* set allow and phase mask */
data |= RX_CLASS_GATES_ALLOW_MASK | RX_CLASS_GATES_PHASE_MASK;
Expand All @@ -273,35 +273,28 @@ void icssg_class_disable(struct regmap *miig_rt, int slice)
regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
}

void icssg_class_default(struct regmap *miig_rt, int slice)
void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti)
{
u32 offset, data;
u32 data;
int n;

/* defaults */
icssg_class_disable(miig_rt, slice);

/* FT1 Disabled */
for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++) {
rx_class_ft1_cfg_set_type(miig_rt, slice, n,
FT1_CFG_TYPE_DISABLED);
}

/* Setup Classifier */
for (n = 0; n < 5; n++) {
/* match on Broadcast or MAC_PRU address */
data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P;

/* multicast? */
if (allmulti)
data |= RX_CLASS_FT_MC;

rx_class_set_or(miig_rt, slice, n, data);

/* set CFG1 for OR_OR_AND for classifier */
rx_class_sel_set_type(miig_rt, slice, n,
RX_CLASS_SEL_TYPE_OR_OR_AND);

/* ungate classifier */
offset = RX_CLASS_GATES_N_REG(slice, n);
regmap_read(miig_rt, offset, &data);
data |= RX_CLASS_GATES_RAW_MASK;
regmap_write(miig_rt, offset, data);
}

/* clear CFG2 */
Expand All @@ -317,37 +310,9 @@ void icssg_class_promiscuous(struct regmap *miig_rt, int slice)
/* defaults */
icssg_class_disable(miig_rt, slice);

/* FT1 uses 6 bytes of DA address */
offset = offs[slice].ft1_start_len;
regmap_write(miig_rt, offset, FT1_LEN(6));

/* FT1 type EQ */
for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++)
rx_class_ft1_cfg_set_type(miig_rt, slice, n, FT1_CFG_TYPE_EQ);

/* FT1[0] DA compare address 00-00-00-00-00-00 */
offset = FT1_N_REG(slice, 0, FT1_DA0);
regmap_write(miig_rt, offset, 0);
offset = FT1_N_REG(slice, 0, FT1_DA1);
regmap_write(miig_rt, offset, 0);

/* FT1[0] mask FE-FF-FF-FF-FF-FF */
offset = FT1_N_REG(slice, 0, FT1_DA0_MASK);
regmap_write(miig_rt, offset, 0xfffffffe);
offset = FT1_N_REG(slice, 0, FT1_DA1_MASK);
regmap_write(miig_rt, offset, 0xffff);

/* Setup Classifier */
for (n = 0; n < 5; n++) {
/* match on multicast, broadcast or unicast (ft1-0 address) */
data = RX_CLASS_FT_MC | RX_CLASS_FT_BC | FT1_MATCH_SLOT(0);
rx_class_set_or(miig_rt, slice, n, data);

/* set CFG1 for OR_OR_AND for classifier */
rx_class_sel_set_type(miig_rt, slice, n,
RX_CLASS_SEL_TYPE_OR_OR_AND);

/* ungate classifier */
/* set RAW_MASK to bypass filters */
offset = RX_CLASS_GATES_N_REG(slice, n);
regmap_read(miig_rt, offset, &data);
data |= RX_CLASS_GATES_RAW_MASK;
Expand Down
122 changes: 99 additions & 23 deletions drivers/net/ethernet/ti/icssg_prueth.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

#define MSMC_RAM_SIZE (SZ_64K + SZ_32K + SZ_2K) /* 0x1880 x 8 x 2 */

#define PRUETH_PKT_TYPE_CMD 0x10
#define PRUETH_NAV_PS_DATA_SIZE 16 /* Protocol specific data size */
#define PRUETH_NAV_SW_DATA_SIZE 16 /* SW related data size */
#define PRUETH_MAX_TX_DESC 512
Expand Down Expand Up @@ -387,7 +388,7 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)
skb->dev = ndev;
if (!netif_running(skb->dev)) {
dev_kfree_skb_any(skb);
return -ENODEV;
return 0;
}

new_skb = netdev_alloc_skb_ip_align(ndev, PRUETH_MAX_PKT_SIZE);
Expand All @@ -408,8 +409,11 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id)

/* queue another RX DMA */
ret = prueth_dma_rx_push(emac, new_skb, &emac->rx_chns);
if (WARN_ON(ret < 0))
if (WARN_ON(ret < 0)) {
dev_kfree_skb_any(new_skb);
ndev->stats.rx_errors++;
ndev->stats.rx_dropped++;
}

return ret;
}
Expand Down Expand Up @@ -468,6 +472,65 @@ static void prueth_xmit_free(struct prueth_tx_chn *tx_chn,
k3_knav_pool_free(tx_chn->desc_pool, first_desc);
}

static int emac_shutdown(struct net_device *ndev)
{
struct prueth_emac *emac = netdev_priv(ndev);
struct device *dev = emac->prueth->dev;
dma_addr_t desc_dma, buf_dma;
struct prueth_tx_chn *tx_chn;
struct cppi5_host_desc_t *first_desc;
int ret;
u32 *epib;
u32 *data = emac->cmd_data;
u32 pkt_len = sizeof(emac->cmd_data);
void **swdata;

data[0] = cpu_to_le32(0x81010000); /* shutdown command */

/* Map the linear buffer */
buf_dma = dma_map_single(dev, data, pkt_len, DMA_TO_DEVICE);
if (dma_mapping_error(dev, buf_dma)) {
netdev_err(ndev, "shutdown: failed to map cmd buffer\n");
return -EINVAL;
}

tx_chn = &emac->tx_chns;

first_desc = k3_knav_pool_alloc(tx_chn->desc_pool);
if (!first_desc) {
netdev_err(ndev, "shutdown: failed to allocate descriptor\n");
dma_unmap_single(dev, buf_dma, pkt_len, DMA_TO_DEVICE);
return -ENOMEM;
}

cppi5_hdesc_init(first_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT,
PRUETH_NAV_PS_DATA_SIZE);
cppi5_hdesc_set_pkttype(first_desc, PRUETH_PKT_TYPE_CMD);
epib = first_desc->epib;
epib[0] = 0;
epib[1] = 0;

cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
swdata = cppi5_hdesc_get_swdata(first_desc);
*swdata = data;

cppi5_hdesc_set_pktlen(first_desc, pkt_len);
desc_dma = k3_knav_pool_virt2dma(tx_chn->desc_pool, first_desc);

ret = k3_nav_udmax_push_tx_chn(tx_chn->tx_chn, first_desc, desc_dma);
if (ret) {
netdev_err(ndev, "shutdown: push failed: %d\n", ret);
goto free_desc;
}

return 0;

free_desc:
prueth_xmit_free(tx_chn, dev, first_desc);

return ret;
}

/**
* emac_ndo_start_xmit - EMAC Transmit function
* @skb: SKB pointer
Expand Down Expand Up @@ -514,10 +577,10 @@ static int emac_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev)

first_desc = k3_knav_pool_alloc(tx_chn->desc_pool);
if (!first_desc) {
dev_err(dev, "tx: failed to allocate descriptor\n");
netdev_dbg(ndev, "tx: failed to allocate descriptor\n");
dma_unmap_single(dev, buf_dma, pkt_len, DMA_TO_DEVICE);
ret = -ENOMEM;
goto drop_stop_q;
goto drop_stop_q_busy;
}

cppi5_hdesc_init(first_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT,
Expand Down Expand Up @@ -623,6 +686,10 @@ static int emac_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev)
netdev_err(ndev, "tx: error: %d\n", ret);

return ret;

drop_stop_q_busy:
netif_stop_queue(ndev);
return NETDEV_TX_BUSY;
}

/**
Expand Down Expand Up @@ -656,6 +723,14 @@ static int emac_tx_complete_packets(struct prueth_emac *emac, int budget)

desc_tx = k3_knav_pool_dma2virt(tx_chn->desc_pool, desc_dma);
swdata = cppi5_hdesc_get_swdata(desc_tx);

/* was this shutdown cmd's TX complete? */
if (*(swdata) == emac->cmd_data) {
prueth_xmit_free(tx_chn, dev, desc_tx);
budget++; /* not a data packet */
continue;
}

skb = *(swdata);
prueth_xmit_free(tx_chn, dev, desc_tx);

Expand Down Expand Up @@ -811,6 +886,7 @@ static irqreturn_t prueth_rx_mgm_irq_thread(int irq, void *dev_id)
struct prueth_emac *emac = dev_id;
struct sk_buff *skb;
int flow = PRUETH_MAX_RX_MGM_FLOWS - 1;
u32 rsp;

while (flow--) {
skb = prueth_process_rx_mgm(emac, flow);
Expand All @@ -820,6 +896,9 @@ static irqreturn_t prueth_rx_mgm_irq_thread(int irq, void *dev_id)
switch (flow) {
case PRUETH_RX_MGM_FLOW_RESPONSE:
/* Process command response */
rsp = le32_to_cpu(*(u32 *)skb->data);
if ((rsp & 0xffff0000) == 0x81010000)
complete(&emac->shutdown_complete);
break;
case PRUETH_RX_MGM_FLOW_TIMESTAMP:
prueth_tx_ts(emac, (void *)skb->data);
Expand Down Expand Up @@ -1093,10 +1172,11 @@ static int emac_ndo_open(struct net_device *ndev)
ether_addr_copy(emac->mac_addr, ndev->dev_addr);

icssg_class_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
icssg_class_default(prueth->miig_rt, slice);
icssg_class_default(prueth->miig_rt, slice, 0);

netif_carrier_off(ndev);

init_completion(&emac->shutdown_complete);
ret = prueth_init_tx_chns(emac);
if (ret) {
dev_err(dev, "failed to init tx channel: %d\n", ret);
Expand Down Expand Up @@ -1239,6 +1319,14 @@ static int emac_ndo_stop(struct net_device *ndev)
phy_stop(emac->phydev);
icssg_class_disable(prueth->miig_rt, prueth_emac_slice(emac));

/* send shutdown command */
reinit_completion(&emac->shutdown_complete);
emac_shutdown(ndev);
ret = wait_for_completion_timeout(&emac->shutdown_complete,
msecs_to_jiffies(100));
if (!ret)
netdev_err(ndev, "shutdown completion timeout\n");

/* tear down and disable UDMA channels */
reinit_completion(&emac->tdown_complete);
k3_nav_udmax_tdown_tx_chn(emac->tx_chns.tx_chn, false);
Expand All @@ -1252,8 +1340,6 @@ static int emac_ndo_stop(struct net_device *ndev)
prueth_tx_cleanup);
k3_nav_udmax_disable_tx_chn(emac->tx_chns.tx_chn);

/* TODO: send shutdown command */

k3_nav_udmax_tdown_rx_chn(emac->rx_chns.rx_chn, true);
for (i = 0; i < PRUETH_MAX_RX_FLOWS; i++)
k3_nav_udmax_reset_rx_chn(emac->rx_chns.rx_chn, i,
Expand Down Expand Up @@ -1324,25 +1410,15 @@ static void emac_ndo_set_rx_mode(struct net_device *ndev)
struct prueth_emac *emac = netdev_priv(ndev);
struct prueth *prueth = emac->prueth;
int slice = prueth_emac_slice(emac);
bool promisc = ndev->flags & IFF_PROMISC;
bool allmulti = ndev->flags & IFF_ALLMULTI;

if (ndev->flags & IFF_PROMISC) {
/* enable promiscuous */
if (!(emac->flags & IFF_PROMISC)) {
icssg_class_promiscuous(prueth->miig_rt, slice);
emac->flags |= IFF_PROMISC;
}
if (promisc) {
icssg_class_promiscuous(prueth->miig_rt, slice);
return;
} else if (ndev->flags & IFF_ALLMULTI) {
/* TODO: enable all multicast */
} else {
if (emac->flags & IFF_PROMISC) {
/* local MAC + BC only */
icssg_class_default(prueth->miig_rt, slice);
emac->flags &= ~IFF_PROMISC;
}

/* TODO: specific multi */
}

icssg_class_default(prueth->miig_rt, slice, allmulti);
}

static int emac_set_timestamp_mode(struct prueth_emac *emac,
Expand Down
7 changes: 5 additions & 2 deletions drivers/net/ethernet/ti/icssg_prueth.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,15 @@ struct prueth_emac {
int rx_mgm_flow_id_base;

spinlock_t lock; /* serialize access */
unsigned int flags;

/* TX HW Timestamping */
u32 tx_ts_cookie;
struct sk_buff *tx_ts_skb;
unsigned long state;

/* shutdown related */
u32 cmd_data[4];
struct completion shutdown_complete;
};

/**
Expand Down Expand Up @@ -189,7 +192,7 @@ struct emac_tx_ts_response {
/* Classifier helpers */
void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac);
void icssg_class_disable(struct regmap *miig_rt, int slice);
void icssg_class_default(struct regmap *miig_rt, int slice);
void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti);
void icssg_class_promiscuous(struct regmap *miig_rt, int slice);

/* get PRUSS SLICE number from prueth_emac */
Expand Down
1 change: 1 addition & 0 deletions include/linux/dma/ti-cppi5.h
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ static inline void cppi5_hdesc_set_pkttype(struct cppi5_host_desc_t *desc,
u32 pkt_type)
{
WARN_ON(!desc);
desc->hdr.pkt_info2 &= ~CPPI5_INFO2_HDESC_PKTTYPE_MASK;
desc->hdr.pkt_info2 |=
(pkt_type << CPPI5_INFO2_HDESC_PKTTYPE_SHIFT) &
CPPI5_INFO2_HDESC_PKTTYPE_MASK;
Expand Down

0 comments on commit 971cc5a

Please sign in to comment.