1 /* 2 * Copyright (c) 2020 DENX Software Engineering GmbH 3 * Lukasz Majewski <lukma@denx.de> 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** @file 8 * @brief DSA definitions and handlers 9 */ 10 11 #ifndef ZEPHYR_INCLUDE_NET_DSA_H_ 12 #define ZEPHYR_INCLUDE_NET_DSA_H_ 13 14 #include <zephyr/device.h> 15 #include <zephyr/net/net_if.h> 16 17 /** 18 * @brief DSA definitions and helpers 19 * @defgroup DSA Distributed Switch Architecture definitions and helpers 20 * @since 2.5 21 * @version 0.8.0 22 * @ingroup networking 23 * @{ 24 */ 25 26 /** @cond INTERNAL_HIDDEN */ 27 28 #define NET_DSA_PORT_MAX_COUNT 8 29 #define DSA_STATUS_PERIOD_MS K_MSEC(1000) 30 31 /* 32 * Size of the DSA TAG: 33 * - KSZ8794 - 1 byte 34 */ 35 #if defined(CONFIG_DSA_KSZ8794) && defined(CONFIG_DSA_KSZ_TAIL_TAGGING) 36 #define DSA_TAG_SIZE 1 37 #else 38 #define DSA_TAG_SIZE 0 39 #endif 40 41 /** @endcond */ 42 43 #ifdef __cplusplus 44 extern "C" { 45 #endif 46 47 /** 48 * @brief DSA generic transmit function 49 * 50 * This is a generic function for passing packets from slave DSA interface to 51 * master. 52 * 53 * @param dev Device 54 * @param pkt Network packet 55 * 56 * Returns: 57 * - 0 if ok (packet sent via master iface), < 0 if error 58 */ 59 int dsa_tx(const struct device *dev, struct net_pkt *pkt); 60 61 /** 62 * @brief DSA (MGMT) Receive packet callback 63 * 64 * Callback gets called upon receiving packet. It is responsible for 65 * freeing packet or indicating to the stack that it needs to free packet 66 * by returning correct net_verdict. 67 * 68 * Returns: 69 * - NET_DROP, if packet was invalid, rejected or we want the stack to free it. 70 * In this case the core stack will free the packet. 71 * - NET_OK, if the packet was accepted, in this case the ownership of the 72 * net_pkt goes to callback and core network stack will forget it. 73 */ 74 typedef enum net_verdict (*dsa_net_recv_cb_t)(struct net_if *iface, 75 struct net_pkt *pkt); 76 77 /** 78 * @brief Register DSA Rx callback functions 79 * 80 * @param iface Network interface 81 * @param cb Receive callback function 82 * 83 * @return 0 if ok, < 0 if error 84 */ 85 int dsa_register_recv_callback(struct net_if *iface, dsa_net_recv_cb_t cb); 86 87 /** 88 * @brief Set DSA interface to packet 89 * 90 * @param iface Network interface (master) 91 * @param pkt Network packet 92 * 93 * @return Return the slave network interface 94 */ 95 struct net_if *dsa_net_recv(struct net_if *iface, struct net_pkt **pkt); 96 97 /** 98 * @brief Pointer to master interface send function 99 */ 100 typedef int (*dsa_send_t)(const struct device *dev, struct net_pkt *pkt); 101 102 /** 103 * @brief DSA helper function to register transmit function for master 104 * 105 * @param iface Network interface (master) 106 * @param fn Pointer to master interface send method 107 * 108 * Returns: 109 * - 0 if ok, < 0 if error 110 */ 111 int dsa_register_master_tx(struct net_if *iface, dsa_send_t fn); 112 113 /** 114 * @brief DSA helper function to check if port is master 115 * 116 * @param iface Network interface (master) 117 * 118 * Returns: 119 * - true if ok, false otherwise 120 */ 121 bool dsa_is_port_master(struct net_if *iface); 122 123 /** 124 * @cond INTERNAL_HIDDEN 125 * 126 * These are for internal use only, so skip these in 127 * public documentation. 128 */ 129 130 /** DSA context data */ 131 struct dsa_context { 132 /** Pointers to all DSA slave network interfaces */ 133 struct net_if *iface_slave[NET_DSA_PORT_MAX_COUNT]; 134 135 /** Pointer to DSA master network interface */ 136 struct net_if *iface_master; 137 138 /** DSA specific API callbacks - filled in the switch IC driver */ 139 struct dsa_api *dapi; 140 141 /** DSA related work (e.g. monitor if network interface is up) */ 142 struct k_work_delayable dsa_work; 143 144 /** Number of slave ports in the DSA switch */ 145 uint8_t num_slave_ports; 146 147 /** Status of each port */ 148 bool link_up[NET_DSA_PORT_MAX_COUNT]; 149 150 /** Instance specific data */ 151 void *prv_data; 152 }; 153 154 /** 155 * @brief Structure to provide DSA switch api callbacks - it is an augmented 156 * struct ethernet_api. 157 */ 158 struct dsa_api { 159 /** Function to get proper LAN{123} interface */ 160 struct net_if *(*dsa_get_iface)(struct net_if *iface, 161 struct net_pkt *pkt); 162 /* 163 * Callbacks required for DSA switch initialization and configuration. 164 * 165 * Each switch instance (e.g. two KSZ8794 ICs) would have its own struct 166 * dsa_context. 167 */ 168 /** Read value from DSA register */ 169 int (*switch_read)(const struct device *dev, uint16_t reg_addr, 170 uint8_t *value); 171 /** Write value to DSA register */ 172 int (*switch_write)(const struct device *dev, uint16_t reg_addr, 173 uint8_t value); 174 175 /** Program (set) mac table entry in the DSA switch */ 176 int (*switch_set_mac_table_entry)(const struct device *dev, 177 const uint8_t *mac, 178 uint8_t fw_port, 179 uint16_t tbl_entry_idx, 180 uint16_t flags); 181 182 /** Read mac table entry from the DSA switch */ 183 int (*switch_get_mac_table_entry)(const struct device *dev, 184 uint8_t *buf, 185 uint16_t tbl_entry_idx); 186 187 /* 188 * DSA helper callbacks 189 */ 190 struct net_pkt *(*dsa_xmit_pkt)(struct net_if *iface, 191 struct net_pkt *pkt); 192 }; 193 194 /** 195 * @endcond 196 */ 197 198 /** 199 * @brief Get network interface of a slave port 200 * 201 * @param iface Master port 202 * @param[in] slave_num Slave port number 203 * 204 * @return network interface of the slave if successful 205 * @return NULL if slave port does not exist 206 */ 207 struct net_if *dsa_get_slave_port(struct net_if *iface, int slave_num); 208 209 /** 210 * @brief Read from DSA switch register 211 * 212 * @param iface The interface 213 * @param[in] reg_addr The register address 214 * @param value The value 215 * 216 * @return 0 if successful, negative if error 217 */ 218 int dsa_switch_read(struct net_if *iface, uint16_t reg_addr, uint8_t *value); 219 220 /** 221 * @brief Write to DSA switch 222 * 223 * @param iface The interface 224 * @param[in] reg_addr The register address 225 * @param[in] value The value 226 * 227 * @return { description_of_the_return_value } 228 */ 229 int dsa_switch_write(struct net_if *iface, uint16_t reg_addr, uint8_t value); 230 231 /** 232 * @brief Write static MAC table entry 233 * 234 * @param iface Master DSA interface 235 * @param[in] mac MAC address 236 * @param[in] fw_port The firmware port 237 * @param[in] tbl_entry_idx Table entry index 238 * @param[in] flags Flags 239 * 240 * @return 0 if successful, negative if error 241 */ 242 int dsa_switch_set_mac_table_entry(struct net_if *iface, 243 const uint8_t *mac, 244 uint8_t fw_port, 245 uint16_t tbl_entry_idx, 246 uint16_t flags); 247 248 /** 249 * @brief Read static MAC table entry 250 * 251 * @param iface Master DSA interface 252 * @param buf Buffer to receive MAC address 253 * @param[in] tbl_entry_idx Table entry index 254 * 255 * @return 0 if successful, negative if error 256 */ 257 int dsa_switch_get_mac_table_entry(struct net_if *iface, 258 uint8_t *buf, 259 uint16_t tbl_entry_idx); 260 261 /** 262 * @brief Structure to provide mac address for each LAN interface 263 */ 264 265 struct dsa_slave_config { 266 /** MAC address for each LAN{123.,} ports */ 267 uint8_t mac_addr[6]; 268 }; 269 270 #ifdef __cplusplus 271 } 272 #endif 273 274 /** 275 * @} 276 */ 277 #endif /* ZEPHYR_INCLUDE_NET_DSA_H_ */ 278