@@ -382,8 +382,8 @@ static int sja1105_init_l2_forwarding_params(struct sja1105_private *priv)
382
382
static int sja1105_init_general_params (struct sja1105_private * priv )
383
383
{
384
384
struct sja1105_general_params_entry default_general_params = {
385
- /* Disallow dynamic changing of the mirror port */
386
- .mirr_ptacu = 0 ,
385
+ /* Allow dynamic changing of the mirror port */
386
+ .mirr_ptacu = true ,
387
387
.switchid = priv -> ds -> index ,
388
388
/* Priority queue for link-local management frames
389
389
* (both ingress to and egress from CPU - PTP, STP etc)
@@ -403,8 +403,8 @@ static int sja1105_init_general_params(struct sja1105_private *priv)
403
403
* by installing a temporary 'management route'
404
404
*/
405
405
.host_port = dsa_upstream_port (priv -> ds , 0 ),
406
- /* Same as host port */
407
- .mirr_port = dsa_upstream_port ( priv -> ds , 0 ) ,
406
+ /* Default to an invalid value */
407
+ .mirr_port = SJA1105_NUM_PORTS ,
408
408
/* Link-local traffic received on casc_port will be forwarded
409
409
* to host_port without embedding the source port and device ID
410
410
* info in the destination MAC address (presumably because it
@@ -2069,6 +2069,84 @@ static int sja1105_port_setup_tc(struct dsa_switch *ds, int port,
2069
2069
}
2070
2070
}
2071
2071
2072
+ /* We have a single mirror (@to) port, but can configure ingress and egress
2073
+ * mirroring on all other (@from) ports.
2074
+ * We need to allow mirroring rules only as long as the @to port is always the
2075
+ * same, and we need to unset the @to port from mirr_port only when there is no
2076
+ * mirroring rule that references it.
2077
+ */
2078
+ static int sja1105_mirror_apply (struct sja1105_private * priv , int from , int to ,
2079
+ bool ingress , bool enabled )
2080
+ {
2081
+ struct sja1105_general_params_entry * general_params ;
2082
+ struct sja1105_mac_config_entry * mac ;
2083
+ struct sja1105_table * table ;
2084
+ bool already_enabled ;
2085
+ u64 new_mirr_port ;
2086
+ int rc ;
2087
+
2088
+ table = & priv -> static_config .tables [BLK_IDX_GENERAL_PARAMS ];
2089
+ general_params = table -> entries ;
2090
+
2091
+ mac = priv -> static_config .tables [BLK_IDX_MAC_CONFIG ].entries ;
2092
+
2093
+ already_enabled = (general_params -> mirr_port != SJA1105_NUM_PORTS );
2094
+ if (already_enabled && enabled && general_params -> mirr_port != to ) {
2095
+ dev_err (priv -> ds -> dev ,
2096
+ "Delete mirroring rules towards port %llu first\n" ,
2097
+ general_params -> mirr_port );
2098
+ return - EBUSY ;
2099
+ }
2100
+
2101
+ new_mirr_port = to ;
2102
+ if (!enabled ) {
2103
+ bool keep = false;
2104
+ int port ;
2105
+
2106
+ /* Anybody still referencing mirr_port? */
2107
+ for (port = 0 ; port < SJA1105_NUM_PORTS ; port ++ ) {
2108
+ if (mac [port ].ing_mirr || mac [port ].egr_mirr ) {
2109
+ keep = true;
2110
+ break ;
2111
+ }
2112
+ }
2113
+ /* Unset already_enabled for next time */
2114
+ if (!keep )
2115
+ new_mirr_port = SJA1105_NUM_PORTS ;
2116
+ }
2117
+ if (new_mirr_port != general_params -> mirr_port ) {
2118
+ general_params -> mirr_port = new_mirr_port ;
2119
+
2120
+ rc = sja1105_dynamic_config_write (priv , BLK_IDX_GENERAL_PARAMS ,
2121
+ 0 , general_params , true);
2122
+ if (rc < 0 )
2123
+ return rc ;
2124
+ }
2125
+
2126
+ if (ingress )
2127
+ mac [from ].ing_mirr = enabled ;
2128
+ else
2129
+ mac [from ].egr_mirr = enabled ;
2130
+
2131
+ return sja1105_dynamic_config_write (priv , BLK_IDX_MAC_CONFIG , from ,
2132
+ & mac [from ], true);
2133
+ }
2134
+
2135
+ static int sja1105_mirror_add (struct dsa_switch * ds , int port ,
2136
+ struct dsa_mall_mirror_tc_entry * mirror ,
2137
+ bool ingress )
2138
+ {
2139
+ return sja1105_mirror_apply (ds -> priv , port , mirror -> to_local_port ,
2140
+ ingress , true);
2141
+ }
2142
+
2143
+ static void sja1105_mirror_del (struct dsa_switch * ds , int port ,
2144
+ struct dsa_mall_mirror_tc_entry * mirror )
2145
+ {
2146
+ sja1105_mirror_apply (ds -> priv , port , mirror -> to_local_port ,
2147
+ mirror -> ingress , false);
2148
+ }
2149
+
2072
2150
static const struct dsa_switch_ops sja1105_switch_ops = {
2073
2151
.get_tag_protocol = sja1105_get_tag_protocol ,
2074
2152
.setup = sja1105_setup ,
@@ -2102,6 +2180,8 @@ static const struct dsa_switch_ops sja1105_switch_ops = {
2102
2180
.port_rxtstamp = sja1105_port_rxtstamp ,
2103
2181
.port_txtstamp = sja1105_port_txtstamp ,
2104
2182
.port_setup_tc = sja1105_port_setup_tc ,
2183
+ .port_mirror_add = sja1105_mirror_add ,
2184
+ .port_mirror_del = sja1105_mirror_del ,
2105
2185
};
2106
2186
2107
2187
static int sja1105_check_device_id (struct sja1105_private * priv )
0 commit comments