Fix ethernet memory handling issues on CM3DS

Signed-off-by: Bence Kaposzta <bence.kaposzta@arm.com>
pull/11843/head
Bence Kaposzta 2019-11-11 14:39:08 +01:00
parent 816689d1bb
commit d5e89a25c6
4 changed files with 81 additions and 71 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Arm Limited
* Copyright (c) 2019 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -76,6 +76,7 @@ emac_mem_buf_t *SMSC9220_EMAC::low_level_input()
{
emac_mem_buf_t *p = NULL;
uint32_t message_length = 0;
uint32_t received_bytes = 0;
message_length = smsc9220_peek_next_packet_size(dev);
if (message_length == 0) {
@ -87,12 +88,19 @@ emac_mem_buf_t *SMSC9220_EMAC::low_level_input()
message_length -= CRC_LENGTH_BYTES;
}
p = _memory_manager->alloc_heap(message_length, SMSC9220_BUFF_ALIGNMENT);
p = _memory_manager->alloc_heap(SMSC9220_ETH_MAX_FRAME_SIZE,
SMSC9220_BUFF_ALIGNMENT);
if (p != NULL) {
_RXLockMutex.lock();
smsc9220_receive_by_chunks(dev, (char*)_memory_manager->get_ptr(p),
_memory_manager->get_len(p));
received_bytes = smsc9220_receive_by_chunks(dev,
(char*)_memory_manager->get_ptr(p),
_memory_manager->get_len(p));
if(received_bytes == 0){
_memory_manager->free(p);
} else {
_memory_manager->set_len(p, received_bytes);
}
_RXLockMutex.unlock();
}
@ -169,12 +177,12 @@ bool SMSC9220_EMAC::link_out(emac_mem_buf_t *buf)
(const char*)_memory_manager->get_ptr(buf),
_memory_manager->get_len(buf));
_memory_manager->free(buf);
if (error != SMSC9220_ERROR_NONE) {
_TXLockMutex.unlock();
_TXLockMutex.unlock();
if (error == SMSC9220_ERROR_NONE) {
return true;
} else {
return false;
}
_TXLockMutex.unlock();
return true;
}
}
@ -190,7 +198,7 @@ void SMSC9220_EMAC::link_status_task()
current_link_status_up = (bool)(phy_basic_status_reg_value &
(1ul << (PHY_REG_BSTATUS_LINK_STATUS_INDEX)));
/* Compare with previous state */
/* Compare with the previous state */
if (current_link_status_up != _prev_link_status_up) {
_emac_link_state_cb(current_link_status_up);
_prev_link_status_up = current_link_status_up;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018 Arm Limited
* Copyright (c) 2019 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,11 +29,12 @@
*/
#define SMSC9220_ETH_MTU_SIZE 1500U
#define SMSC9220_ETH_IF_NAME "smsc9220"
#define SMSC9220_ETH_MAX_FRAME_SIZE 1522U
/** \brief Defines for receiver thread */
#define FLAG_RX 1U
#define LINK_STATUS_THREAD_PRIORITY (osPriorityNormal)
#define LINK_STATUS_THREAD_STACKSIZE 2048U
#define LINK_STATUS_THREAD_STACKSIZE 512U
#define LINK_STATUS_TASK_PERIOD_MS 200U
#define PHY_STATE_LINK_DOWN false
#define PHY_STATE_LINK_UP true

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2018 ARM Limited
* Copyright (c) 2016-2019 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -166,7 +166,6 @@ enum phy_reg_bctrl_reg_bits_t{
* \brief TX Command A bit definitions
*
*/
#define TX_CMD_DATA_START_OFFSET_BYTES_POS 16U
#define TX_CMD_DATA_START_OFFSET_BYTES_MASK 0x1FU
@ -186,7 +185,19 @@ enum tx_command_a_bits_t{
*
*/
enum rx_fifo_status_bits_t{
RX_FIFO_STATUS_ERROR_INDEX = 15U
RX_FIFO_STATUS_CRC_ERROR_INDEX = 1U,
RX_FIFO_STATUS_DRIBBLING_BIT_INDEX = 2U,
RX_FIFO_STATUS_MII_ERROR_INDEX = 3U,
RX_FIFO_STATUS_REC_WD_TIMEOUT_INDEX = 4U,
RX_FIFO_STATUS_FRAME_TYPE_INDEX = 5U,
RX_FIFO_STATUS_COLLISION_SEEN_INDEX = 6U,
RX_FIFO_STATUS_FRAME_TOO_LONG_INDEX = 7U,
RX_FIFO_STATUS_MULTICAST_INDEX = 10U,
RX_FIFO_STATUS_RUNT_FRAME_INDEX = 11U,
RX_FIFO_STATUS_LENGTH_ERROR_INDEX = 12U,
RX_FIFO_STATUS_BROADCAST_FRAME_INDEX = 13U,
RX_FIFO_STATUS_ERROR_INDEX = 15U,
RX_FIFO_STATUS_FILTERING_FAIL_INDEX = 30U,
};
#define RX_FIFO_STATUS_PKT_LENGTH_POS 16U
#define RX_FIFO_STATUS_PKT_LENGTH_MASK 0x3FFFU
@ -299,7 +310,7 @@ static void fill_tx_fifo(const struct smsc9220_eth_dev_t* dev,
data += remainder_bytes;
while (size_bytes > 0) {
/* Keep the same endianness in data than in the temp variable */
/* Keep the same endianness in data as in the temp variable */
tx_data_port_tmp_ptr[0] = data[0];
tx_data_port_tmp_ptr[1] = data[1];
tx_data_port_tmp_ptr[2] = data[2];
@ -323,7 +334,7 @@ static void empty_rx_fifo(const struct smsc9220_eth_dev_t* dev,
size_bytes -= remainder_bytes;
while (size_bytes > 0) {
/* Keep the same endianness in data than in the temp variable */
/* Keep the same endianness in data as in the temp variable */
rx_data_port_tmp = register_map->rx_data_port;
data[0] = rx_data_port_tmp_ptr[0];
data[1] = rx_data_port_tmp_ptr[1];
@ -740,7 +751,6 @@ int smsc9220_check_id(const struct smsc9220_eth_dev_t* dev)
return ((GET_BIT_FIELD(id, CHIP_ID_MASK, CHIP_ID_POS) == CHIP_ID) ? 0 : 1);
}
void smsc9220_enable_interrupt(const struct smsc9220_eth_dev_t* dev,
enum smsc9220_interrupt_source source)
{
@ -817,7 +827,6 @@ enum smsc9220_error_t smsc9220_read_mac_address(
return SMSC9220_ERROR_PARAM;
}
/* Read current mac address. */
if (smsc9220_mac_regread(dev, SMSC9220_MAC_REG_OFFSET_ADDRH, &mac_high)) {
return SMSC9220_ERROR_INTERNAL;
}
@ -947,10 +956,7 @@ enum smsc9220_error_t smsc9220_send_by_chunks(
{
struct smsc9220_eth_reg_map_t* register_map =
(struct smsc9220_eth_reg_map_t*)dev->cfg->base;
/* signing this is the first segment of the packet to be sent */
bool is_first_segment = false;
/* signing this is the last segment of the packet to be sent */
bool is_last_segment = false;
uint32_t txcmd_a, txcmd_b = 0;
uint32_t tx_buffer_free_space = 0;
@ -1029,7 +1035,6 @@ uint32_t smsc9220_get_rxfifo_data_used_space(const struct
uint32_t smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t* dev,
char *data, uint32_t dlen)
{
uint32_t rxfifo_inf = 0;
uint32_t rxfifo_stat = 0;
uint32_t packet_length_byte = 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2018 ARM Limited
* Copyright (c) 2016-2019 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,8 +22,8 @@
#ifndef __SMSC9220_ETH_H__
#define __SMSC9220_ETH_H__
#include "stdbool.h"
#include "stdint.h"
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
@ -198,7 +198,7 @@ enum smsc9220_error_t smsc9220_init(const struct smsc9220_eth_dev_t* dev,
void(* wait_ms_function)(int));
/**
* \brief Read MAC register.
* \brief Reads the MAC register.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] regoffset Register offset
@ -212,7 +212,7 @@ enum smsc9220_error_t smsc9220_mac_regread(
uint32_t *data);
/**
* \brief Write MAC register.
* \brief Writes the MAC register.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] regoffset Register offset
@ -226,7 +226,7 @@ enum smsc9220_error_t smsc9220_mac_regwrite(
uint32_t data);
/**
* \brief Read PHY register.
* \brief Reads the PHY register.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] regoffset Register offset
@ -240,7 +240,7 @@ enum smsc9220_error_t smsc9220_phy_regread(
uint32_t *data);
/**
* \brief Write PHY register.
* \brief Writes the PHY register.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] regoffset Register offset
@ -254,7 +254,7 @@ enum smsc9220_error_t smsc9220_phy_regwrite(
uint32_t data);
/**
* \brief Read SMSC9220 ID.
* \brief Reads the Ethernet Controller's ID.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
@ -273,9 +273,9 @@ enum smsc9220_error_t smsc9220_soft_reset(
const struct smsc9220_eth_dev_t* dev);
/**
* \brief Set maximum transition unit by Tx fifo size.
* \brief Sets the Maximum Transmission Unit by Tx fifo size.
* Note: The MTU will be smaller by 512 bytes,
* because the status uses this fixed space.
* whis is used by the status.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] val Size of the fifo in kbytes
@ -286,7 +286,7 @@ void smsc9220_set_txfifo(const struct smsc9220_eth_dev_t* dev,
uint32_t val);
/**
* \brief Set FIFO level interrupt for a given source
* \brief Sets the FIFO level interrupt for a given source.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] irq_level_pos Bit position of the FIFO to set
@ -302,7 +302,7 @@ enum smsc9220_error_t smsc9220_set_fifo_level_irq(
uint32_t level);
/**
* \brief Wait for EEPROM to be ready to use.
* \brief Waits for EEPROM to be ready to use.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
@ -312,7 +312,7 @@ enum smsc9220_error_t smsc9220_wait_eeprom(
const struct smsc9220_eth_dev_t* dev);
/**
* \brief Initialise irqs by clearing and disabling all interrupt sources
* \brief Initializes irqs by clearing and disabling all interrupt sources
* and enable interrupts. Since all interrupt sources are disabled,
* interrupt won't be triggered, until interrupt sources won't be
* enabled by \ref smsc9220_enable_interrupt
@ -322,7 +322,7 @@ enum smsc9220_error_t smsc9220_wait_eeprom(
void smsc9220_init_irqs(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Check PHY ID registers.
* \brief Checks PHY ID registers.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
@ -331,7 +331,7 @@ void smsc9220_init_irqs(const struct smsc9220_eth_dev_t* dev);
enum smsc9220_error_t smsc9220_check_phy(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Reset PHY
* \brief Resets PHY.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
@ -340,56 +340,56 @@ enum smsc9220_error_t smsc9220_check_phy(const struct smsc9220_eth_dev_t* dev);
enum smsc9220_error_t smsc9220_reset_phy(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Advertise all speeds and pause capabilities
* \brief Advertises all speeds and pauses capabilities.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_advertise_cap(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Enable transmission
* \brief Enables transmission.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_enable_xmit(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Disable transmission
* \brief Disables transmission.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_disable_xmit(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Enable MAC transmitter
* \brief Enables MAC Transmitter.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_enable_mac_xmit(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Disable MAC transmitter
* \brief Disables MAC Transmitter.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_disable_mac_xmit(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Enable receive
* \brief Enables receiving.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_enable_mac_recv(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Disable receive
* \brief Disables receiving.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_disable_mac_recv(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Enable the given interrupt source.
* \brief Enables the given interrupt source.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] source Enum of the interrupt source.
@ -398,7 +398,7 @@ void smsc9220_enable_interrupt(const struct smsc9220_eth_dev_t* dev,
enum smsc9220_interrupt_source source);
/**
* \brief Disable the given interrupt source.
* \brief Disables the given interrupt source.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] source Enum of the interrupt source.
@ -407,14 +407,14 @@ void smsc9220_disable_interrupt(const struct smsc9220_eth_dev_t* dev,
enum smsc9220_interrupt_source source);
/**
* \brief Disable all of the interrupt sources.
* \brief Disables all interrupt sources.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_disable_all_interrupts(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Clear the given interrupt source.
* \brief Clears the given interrupt source.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] source Enum of the interrupt source.
@ -423,14 +423,14 @@ void smsc9220_clear_interrupt(const struct smsc9220_eth_dev_t* dev,
enum smsc9220_interrupt_source source);
/**
* \brief Clear all of the interrupt sources.
* \brief Clears all interrupt sources.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_clear_all_interrupts(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Get the status of the given interrupt source.
* \brief Gets the status of the given interrupt source.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] source Enum of the interrupt source.
@ -441,14 +441,14 @@ int smsc9220_get_interrupt(const struct smsc9220_eth_dev_t* dev,
enum smsc9220_interrupt_source source);
/**
* \brief Establish link
* \brief Establishes link
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*/
void smsc9220_establish_link(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Read MAC address from EEPROM.
* \brief Reads the Ethernet Controller's MAC address from its EEPROM.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in,out] mac array will include the read MAC address in
@ -468,7 +468,7 @@ enum smsc9220_error_t smsc9220_read_mac_address(
int smsc9220_check_id(const struct smsc9220_eth_dev_t* dev);
/**
* \brief Get the data size of the Tx buffer, aka Maximum Transition Unit
* \brief Gets the data size of the Tx buffer, aka Maximum Trasmission Unit
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
@ -478,16 +478,16 @@ uint32_t smsc9220_get_tx_data_fifo_size(const struct
smsc9220_eth_dev_t* dev);
/**
* \brief Send Ethernet packet from buffer chain.
* The full packet length should be known in the beginning
* of a new packet.
* \brief Sends data from the given buffer as an Ethernet packet.
* The full packet length must be specified at the beginning
* of a new packet transmission.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in] total_payload_length Length of the ethernet payload.
* Should be equal to the sum of passed buffers within a packet.
* \param[in] is_new_packet Should be set to true if the input buffer has to
* be sent as the start of a new packet or as a full packet.
* \param[in] data Pointer to the data should be sent.
* \param[in] data Pointer to the data buffer to be sent.
* \param[in] current_size Size of the data in bytes.
*
* \return error code /ref smsc9220_error_t
@ -499,20 +499,17 @@ enum smsc9220_error_t smsc9220_send_by_chunks(
const char *data, uint32_t current_size);
/**
* \brief Receive Ethernet packet from Rx FIFO to the passed buffer.
* \brief Reads an incoming Ethernet packet into the given buffer.
* Stops reading at packet border.
* If the passed buffer is larger than the current packet,
* the whole packet will be read into the buffer.
* If the current packet is larger than the passed buffer,
* the buffer will be filled with data and the next call
* will continue the read from that point.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
* \param[in,out] data Pointer where the data will be read to.
* The caller is responsible to allocate it.
* \param[in,out] data Pointer to a pre-allocated input buffer.
* Allocating sufficient memory space is the caller's
* responsibility, which is typically done by calling
* \ref smsc9220_peek_next_packet_size.
* \param[in] dlen Length of the allocated data in bytes.
*
* \return Remaining bytes left in the fifo of the current packet.
* \return Number of bytes read from the Rx FIFO into the given buffer.
*/
uint32_t smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t* dev,
char *data, uint32_t dlen);
@ -528,15 +525,14 @@ uint32_t smsc9220_get_rxfifo_data_used_space(const struct
smsc9220_eth_dev_t* dev);
/**
* \brief Get the size of next unread packet in Rx buffer, using the peak
* \brief Gets the size of next unread packet in Rx buffer, using the peak
* register, which is not destructive so can be read asynchronously.
* Warning: In case of heavy receiving load, it's possible this register
* is not perfectly in sync.
* Warning: In case of heavy receiving loads, this register may not
* be in perfect sync.
*
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
*
* \return Size in bytes of the next packet can be read from Rx fifo, according
* to the peek register.
* \return Size of the next packet in bytes, read from the Rx Peek register.
*/
uint32_t smsc9220_peek_next_packet_size(const struct
smsc9220_eth_dev_t* dev);