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