aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/ti
diff options
context:
space:
mode:
authorIvan Khoronzhuk <ivan.khoronzhuk@linaro.org>2016-08-22 14:18:28 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-23 03:13:11 -0400
commitce52c744574bbe31e5c30788f69d19f20d328225 (patch)
treef8bb6ff440b2fc6841cdcfd78021cc0976fb6139 /drivers/net/ethernet/ti
parent925d65e6d8a4c84c54fbad060f32385b57e210ed (diff)
net: ethernet: ti: cpsw: add ethtool channels support
These ops allow to control number of channels driver is allowed to work with at cpdma level. The maximum number of channels is 8 for rx and 8 for tx. In dual_emac mode the h/w channels are shared between two interfaces and changing number on one interface changes number of channels on another. How many channels are supported and enabled: $ ethtool -l ethX Change number of channels (up to 8) $ ethtool -L ethX rx 6 tx 6 Per-channel statistic: $ ethtool -S ethX Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org> Reviewed-by: Mugunthan V N <mugunthanvnm@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/ti')
-rw-r--r--drivers/net/ethernet/ti/cpsw.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 1fbb50f25603..4273e7f9b4aa 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -736,6 +736,11 @@ static void cpsw_rx_handler(void *token, int len, int status)
736 } 736 }
737 737
738requeue: 738requeue:
739 if (netif_dormant(ndev)) {
740 dev_kfree_skb_any(new_skb);
741 return;
742 }
743
739 ch = cpsw->rxch[skb_get_queue_mapping(new_skb)]; 744 ch = cpsw->rxch[skb_get_queue_mapping(new_skb)];
740 ret = cpdma_chan_submit(ch, new_skb, new_skb->data, 745 ret = cpdma_chan_submit(ch, new_skb, new_skb->data,
741 skb_tailroom(new_skb), 0); 746 skb_tailroom(new_skb), 0);
@@ -2060,6 +2065,179 @@ static void cpsw_ethtool_op_complete(struct net_device *ndev)
2060 cpsw_err(priv, drv, "ethtool complete failed %d\n", ret); 2065 cpsw_err(priv, drv, "ethtool complete failed %d\n", ret);
2061} 2066}
2062 2067
2068static void cpsw_get_channels(struct net_device *ndev,
2069 struct ethtool_channels *ch)
2070{
2071 struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
2072
2073 ch->max_combined = 0;
2074 ch->max_rx = CPSW_MAX_QUEUES;
2075 ch->max_tx = CPSW_MAX_QUEUES;
2076 ch->max_other = 0;
2077 ch->other_count = 0;
2078 ch->rx_count = cpsw->rx_ch_num;
2079 ch->tx_count = cpsw->tx_ch_num;
2080 ch->combined_count = 0;
2081}
2082
2083static int cpsw_check_ch_settings(struct cpsw_common *cpsw,
2084 struct ethtool_channels *ch)
2085{
2086 if (ch->combined_count)
2087 return -EINVAL;
2088
2089 /* verify we have at least one channel in each direction */
2090 if (!ch->rx_count || !ch->tx_count)
2091 return -EINVAL;
2092
2093 if (ch->rx_count > cpsw->data.channels ||
2094 ch->tx_count > cpsw->data.channels)
2095 return -EINVAL;
2096
2097 return 0;
2098}
2099
2100static int cpsw_update_channels_res(struct cpsw_priv *priv, int ch_num, int rx)
2101{
2102 int (*poll)(struct napi_struct *, int);
2103 struct cpsw_common *cpsw = priv->cpsw;
2104 void (*handler)(void *, int, int);
2105 struct cpdma_chan **chan;
2106 int ret, *ch;
2107
2108 if (rx) {
2109 ch = &cpsw->rx_ch_num;
2110 chan = cpsw->rxch;
2111 handler = cpsw_rx_handler;
2112 poll = cpsw_rx_poll;
2113 } else {
2114 ch = &cpsw->tx_ch_num;
2115 chan = cpsw->txch;
2116 handler = cpsw_tx_handler;
2117 poll = cpsw_tx_poll;
2118 }
2119
2120 while (*ch < ch_num) {
2121 chan[*ch] = cpdma_chan_create(cpsw->dma, *ch, handler, rx);
2122
2123 if (IS_ERR(chan[*ch]))
2124 return PTR_ERR(chan[*ch]);
2125
2126 if (!chan[*ch])
2127 return -EINVAL;
2128
2129 cpsw_info(priv, ifup, "created new %d %s channel\n", *ch,
2130 (rx ? "rx" : "tx"));
2131 (*ch)++;
2132 }
2133
2134 while (*ch > ch_num) {
2135 (*ch)--;
2136
2137 ret = cpdma_chan_destroy(chan[*ch]);
2138 if (ret)
2139 return ret;
2140
2141 cpsw_info(priv, ifup, "destroyed %d %s channel\n", *ch,
2142 (rx ? "rx" : "tx"));
2143 }
2144
2145 return 0;
2146}
2147
2148static int cpsw_update_channels(struct cpsw_priv *priv,
2149 struct ethtool_channels *ch)
2150{
2151 int ret;
2152
2153 ret = cpsw_update_channels_res(priv, ch->rx_count, 1);
2154 if (ret)
2155 return ret;
2156
2157 ret = cpsw_update_channels_res(priv, ch->tx_count, 0);
2158 if (ret)
2159 return ret;
2160
2161 return 0;
2162}
2163
2164static int cpsw_set_channels(struct net_device *ndev,
2165 struct ethtool_channels *chs)
2166{
2167 struct cpsw_priv *priv = netdev_priv(ndev);
2168 struct cpsw_common *cpsw = priv->cpsw;
2169 struct cpsw_slave *slave;
2170 int i, ret;
2171
2172 ret = cpsw_check_ch_settings(cpsw, chs);
2173 if (ret < 0)
2174 return ret;
2175
2176 /* Disable NAPI scheduling */
2177 cpsw_intr_disable(cpsw);
2178
2179 /* Stop all transmit queues for every network device.
2180 * Disable re-using rx descriptors with dormant_on.
2181 */
2182 for (i = cpsw->data.slaves, slave = cpsw->slaves; i; i--, slave++) {
2183 if (!(slave->ndev && netif_running(slave->ndev)))
2184 continue;
2185
2186 netif_tx_stop_all_queues(slave->ndev);
2187 netif_dormant_on(slave->ndev);
2188 }
2189
2190 /* Handle rest of tx packets and stop cpdma channels */
2191 cpdma_ctlr_stop(cpsw->dma);
2192 ret = cpsw_update_channels(priv, chs);
2193 if (ret)
2194 goto err;
2195
2196 for (i = cpsw->data.slaves, slave = cpsw->slaves; i; i--, slave++) {
2197 if (!(slave->ndev && netif_running(slave->ndev)))
2198 continue;
2199
2200 /* Inform stack about new count of queues */
2201 ret = netif_set_real_num_tx_queues(slave->ndev,
2202 cpsw->tx_ch_num);
2203 if (ret) {
2204 dev_err(priv->dev, "cannot set real number of tx queues\n");
2205 goto err;
2206 }
2207
2208 ret = netif_set_real_num_rx_queues(slave->ndev,
2209 cpsw->rx_ch_num);
2210 if (ret) {
2211 dev_err(priv->dev, "cannot set real number of rx queues\n");
2212 goto err;
2213 }
2214
2215 /* Enable rx packets handling */
2216 netif_dormant_off(slave->ndev);
2217 }
2218
2219 if (cpsw_common_res_usage_state(cpsw)) {
2220 if (cpsw_fill_rx_channels(priv))
2221 goto err;
2222
2223 /* After this receive is started */
2224 cpdma_ctlr_start(cpsw->dma);
2225 cpsw_intr_enable(cpsw);
2226 }
2227
2228 /* Resume transmit for every affected interface */
2229 for (i = cpsw->data.slaves, slave = cpsw->slaves; i; i--, slave++) {
2230 if (!(slave->ndev && netif_running(slave->ndev)))
2231 continue;
2232 netif_tx_start_all_queues(slave->ndev);
2233 }
2234 return 0;
2235err:
2236 dev_err(priv->dev, "cannot update channels number, closing device\n");
2237 dev_close(ndev);
2238 return ret;
2239}
2240
2063static const struct ethtool_ops cpsw_ethtool_ops = { 2241static const struct ethtool_ops cpsw_ethtool_ops = {
2064 .get_drvinfo = cpsw_get_drvinfo, 2242 .get_drvinfo = cpsw_get_drvinfo,
2065 .get_msglevel = cpsw_get_msglevel, 2243 .get_msglevel = cpsw_get_msglevel,
@@ -2081,6 +2259,8 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
2081 .get_regs = cpsw_get_regs, 2259 .get_regs = cpsw_get_regs,
2082 .begin = cpsw_ethtool_op_begin, 2260 .begin = cpsw_ethtool_op_begin,
2083 .complete = cpsw_ethtool_op_complete, 2261 .complete = cpsw_ethtool_op_complete,
2262 .get_channels = cpsw_get_channels,
2263 .set_channels = cpsw_set_channels,
2084}; 2264};
2085 2265
2086static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_common *cpsw, 2266static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_common *cpsw,