Skip to content

Commit 731e7cc

Browse files
committed
Merge branch 'net-dsa-microchip-add-MIB-counters-support'
Tristram Ha says: ==================== net: dsa: microchip: add MIB counters support This series of patches is to modify the KSZ9477 DSA driver to read MIB counters periodically to avoid overflow. The MIB counters should be read only when there is link. Otherwise it is a waste of time as hardware never increases the counters. Functions are added to check the port link status so that MIB counters read call is used efficiently. v4 - Use readx_poll_timeout - Fix using mutex in a timer callback function problem - use dp->slave directly instead of checking whether it is valid - Add port_cleanup function in a separate patch - Add a mutex so that changing device variables is safe v3 - Use netif_carrier_ok instead of checking the phy device pointer v2 - Create macro similar to readx_poll_timeout to use with switch - Create ksz_port_cleanup function so that variables like on_ports and live_ports can be updated inside it v1 - Use readx_poll_timeout - Do not clear MIB counters when port is enabled - Do not advertise 1000 half-duplex mode when port is enabled - Do not use freeze function as MIB counters may miss counts ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 84f2926 + 7049f9b commit 731e7cc

File tree

4 files changed

+270
-55
lines changed

4 files changed

+270
-55
lines changed

drivers/net/dsa/microchip/ksz9477.c

Lines changed: 100 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,21 @@
22
/*
33
* Microchip KSZ9477 switch driver main logic
44
*
5-
* Copyright (C) 2017-2018 Microchip Technology Inc.
5+
* Copyright (C) 2017-2019 Microchip Technology Inc.
66
*/
77

8-
#include <linux/delay.h>
9-
#include <linux/export.h>
10-
#include <linux/gpio.h>
118
#include <linux/kernel.h>
129
#include <linux/module.h>
10+
#include <linux/iopoll.h>
1311
#include <linux/platform_data/microchip-ksz.h>
1412
#include <linux/phy.h>
15-
#include <linux/etherdevice.h>
1613
#include <linux/if_bridge.h>
1714
#include <net/dsa.h>
1815
#include <net/switchdev.h>
1916

2017
#include "ksz_priv.h"
21-
#include "ksz_common.h"
2218
#include "ksz9477_reg.h"
19+
#include "ksz_common.h"
2320

2421
static const struct {
2522
int index;
@@ -259,6 +256,75 @@ static int ksz9477_reset_switch(struct ksz_device *dev)
259256
return 0;
260257
}
261258

259+
static void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr,
260+
u64 *cnt)
261+
{
262+
struct ksz_poll_ctx ctx = {
263+
.dev = dev,
264+
.port = port,
265+
.offset = REG_PORT_MIB_CTRL_STAT__4,
266+
};
267+
struct ksz_port *p = &dev->ports[port];
268+
u32 data;
269+
int ret;
270+
271+
/* retain the flush/freeze bit */
272+
data = p->freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
273+
data |= MIB_COUNTER_READ;
274+
data |= (addr << MIB_COUNTER_INDEX_S);
275+
ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
276+
277+
ret = readx_poll_timeout(ksz_pread32_poll, &ctx, data,
278+
!(data & MIB_COUNTER_READ), 10, 1000);
279+
280+
/* failed to read MIB. get out of loop */
281+
if (ret < 0) {
282+
dev_dbg(dev->dev, "Failed to get MIB\n");
283+
return;
284+
}
285+
286+
/* count resets upon read */
287+
ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data);
288+
*cnt += data;
289+
}
290+
291+
static void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
292+
u64 *dropped, u64 *cnt)
293+
{
294+
addr = ksz9477_mib_names[addr].index;
295+
ksz9477_r_mib_cnt(dev, port, addr, cnt);
296+
}
297+
298+
static void ksz9477_freeze_mib(struct ksz_device *dev, int port, bool freeze)
299+
{
300+
u32 val = freeze ? MIB_COUNTER_FLUSH_FREEZE : 0;
301+
struct ksz_port *p = &dev->ports[port];
302+
303+
/* enable/disable the port for flush/freeze function */
304+
mutex_lock(&p->mib.cnt_mutex);
305+
ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, val);
306+
307+
/* used by MIB counter reading code to know freeze is enabled */
308+
p->freeze = freeze;
309+
mutex_unlock(&p->mib.cnt_mutex);
310+
}
311+
312+
static void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
313+
{
314+
struct ksz_port_mib *mib = &dev->ports[port].mib;
315+
316+
/* flush all enabled port MIB counters */
317+
mutex_lock(&mib->cnt_mutex);
318+
ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4,
319+
MIB_COUNTER_FLUSH_FREEZE);
320+
ksz_write8(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FLUSH);
321+
ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, 0);
322+
mutex_unlock(&mib->cnt_mutex);
323+
324+
mib->cnt_ptr = 0;
325+
memset(mib->counters, 0, dev->mib_cnt * sizeof(u64));
326+
}
327+
262328
static enum dsa_tag_protocol ksz9477_get_tag_protocol(struct dsa_switch *ds,
263329
int port)
264330
{
@@ -342,47 +408,6 @@ static void ksz9477_get_strings(struct dsa_switch *ds, int port,
342408
}
343409
}
344410

345-
static void ksz_get_ethtool_stats(struct dsa_switch *ds, int port,
346-
uint64_t *buf)
347-
{
348-
struct ksz_device *dev = ds->priv;
349-
int i;
350-
u32 data;
351-
int timeout;
352-
353-
mutex_lock(&dev->stats_mutex);
354-
355-
for (i = 0; i < TOTAL_SWITCH_COUNTER_NUM; i++) {
356-
data = MIB_COUNTER_READ;
357-
data |= ((ksz9477_mib_names[i].index & 0xFF) <<
358-
MIB_COUNTER_INDEX_S);
359-
ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data);
360-
361-
timeout = 1000;
362-
do {
363-
ksz_pread32(dev, port, REG_PORT_MIB_CTRL_STAT__4,
364-
&data);
365-
usleep_range(1, 10);
366-
if (!(data & MIB_COUNTER_READ))
367-
break;
368-
} while (timeout-- > 0);
369-
370-
/* failed to read MIB. get out of loop */
371-
if (!timeout) {
372-
dev_dbg(dev->dev, "Failed to get MIB\n");
373-
break;
374-
}
375-
376-
/* count resets upon read */
377-
ksz_pread32(dev, port, REG_PORT_MIB_DATA, &data);
378-
379-
dev->mib_value[i] += (uint64_t)data;
380-
buf[i] = dev->mib_value[i];
381-
}
382-
383-
mutex_unlock(&dev->stats_mutex);
384-
}
385-
386411
static void ksz9477_cfg_port_member(struct ksz_device *dev, int port,
387412
u8 member)
388413
{
@@ -425,12 +450,14 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port,
425450
break;
426451

427452
member = dev->host_mask | p->vid_member;
453+
mutex_lock(&dev->dev_mutex);
428454

429455
/* Port is a member of a bridge. */
430456
if (dev->br_member & (1 << port)) {
431457
dev->member |= (1 << port);
432458
member = dev->member;
433459
}
460+
mutex_unlock(&dev->dev_mutex);
434461
break;
435462
case BR_STATE_BLOCKING:
436463
data |= PORT_LEARN_DISABLE;
@@ -445,6 +472,7 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port,
445472

446473
ksz_pwrite8(dev, port, P_STP_CTRL, data);
447474
p->stp_state = state;
475+
mutex_lock(&dev->dev_mutex);
448476
if (data & PORT_RX_ENABLE)
449477
dev->rx_ports |= (1 << port);
450478
else
@@ -469,6 +497,7 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port,
469497
*/
470498
if (forward != dev->member)
471499
ksz_update_port_member(dev, port);
500+
mutex_unlock(&dev->dev_mutex);
472501
}
473502

474503
static void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port)
@@ -966,6 +995,16 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port,
966995
PORT_MIRROR_SNIFFER, false);
967996
}
968997

998+
static void ksz9477_phy_setup(struct ksz_device *dev, int port,
999+
struct phy_device *phy)
1000+
{
1001+
if (port < dev->phy_port_cnt) {
1002+
/* The MAC actually cannot run in 1000 half-duplex mode. */
1003+
phy_remove_link_mode(phy,
1004+
ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
1005+
}
1006+
}
1007+
9691008
static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
9701009
{
9711010
u8 data8;
@@ -1045,6 +1084,7 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
10451084
ksz_pwrite8(dev, port, REG_PORT_XMII_CTRL_1, data8);
10461085
p->phydev.duplex = 1;
10471086
}
1087+
mutex_lock(&dev->dev_mutex);
10481088
if (cpu_port) {
10491089
member = dev->port_mask;
10501090
dev->on_ports = dev->host_mask;
@@ -1057,6 +1097,7 @@ static void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
10571097
if (p->phydev.link)
10581098
dev->live_ports |= (1 << port);
10591099
}
1100+
mutex_unlock(&dev->dev_mutex);
10601101
ksz9477_cfg_port_member(dev, port, member);
10611102

10621103
/* clear pending interrupts */
@@ -1141,9 +1182,14 @@ static int ksz9477_setup(struct dsa_switch *ds)
11411182
/* queue based egress rate limit */
11421183
ksz_cfg(dev, REG_SW_MAC_CTRL_5, SW_OUT_RATE_LIMIT_QUEUE_BASED, true);
11431184

1185+
/* enable global MIB counter freeze function */
1186+
ksz_cfg(dev, REG_SW_MAC_CTRL_6, SW_MIB_COUNTER_FREEZE, true);
1187+
11441188
/* start switch */
11451189
ksz_cfg(dev, REG_SW_OPERATION, SW_START, true);
11461190

1191+
ksz_init_mib_timer(dev);
1192+
11471193
return 0;
11481194
}
11491195

@@ -1152,6 +1198,7 @@ static const struct dsa_switch_ops ksz9477_switch_ops = {
11521198
.setup = ksz9477_setup,
11531199
.phy_read = ksz9477_phy_read16,
11541200
.phy_write = ksz9477_phy_write16,
1201+
.adjust_link = ksz_adjust_link,
11551202
.port_enable = ksz_enable_port,
11561203
.port_disable = ksz_disable_port,
11571204
.get_strings = ksz9477_get_strings,
@@ -1277,6 +1324,7 @@ static int ksz9477_switch_init(struct ksz_device *dev)
12771324
if (!dev->ports)
12781325
return -ENOMEM;
12791326
for (i = 0; i < dev->mib_port_cnt; i++) {
1327+
mutex_init(&dev->ports[i].mib.cnt_mutex);
12801328
dev->ports[i].mib.counters =
12811329
devm_kzalloc(dev->dev,
12821330
sizeof(u64) *
@@ -1299,7 +1347,12 @@ static const struct ksz_dev_ops ksz9477_dev_ops = {
12991347
.get_port_addr = ksz9477_get_port_addr,
13001348
.cfg_port_member = ksz9477_cfg_port_member,
13011349
.flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
1350+
.phy_setup = ksz9477_phy_setup,
13021351
.port_setup = ksz9477_port_setup,
1352+
.r_mib_cnt = ksz9477_r_mib_cnt,
1353+
.r_mib_pkt = ksz9477_r_mib_pkt,
1354+
.freeze_mib = ksz9477_freeze_mib,
1355+
.port_init_cnt = ksz9477_port_init_cnt,
13031356
.shutdown = ksz9477_reset_switch,
13041357
.detect = ksz9477_switch_detect,
13051358
.init = ksz9477_switch_init,

0 commit comments

Comments
 (0)