summaryrefslogtreecommitdiffstats
path: root/sys/contrib/octeon-sdk
diff options
context:
space:
mode:
authorjmallett <jmallett@FreeBSD.org>2011-01-10 03:48:41 +0000
committerjmallett <jmallett@FreeBSD.org>2011-01-10 03:48:41 +0000
commitd46c3738737ebb4c643625b73a9f923c682fb95b (patch)
tree49f81cb689598f52c7df0b0597872228c9215951 /sys/contrib/octeon-sdk
parent97a7ccf9c1a69c94aae9e28ae86f30133bdc7be3 (diff)
downloadFreeBSD-src-d46c3738737ebb4c643625b73a9f923c682fb95b.zip
FreeBSD-src-d46c3738737ebb4c643625b73a9f923c682fb95b.tar.gz
o) Expand the CIU driver to be aware of newly-allocated parts of the IRQ range.
o) Add 'octm', a trivial driver for the 10/100 management ports found on some Octeon systems. o) Make the Simple Executive's management port helper routines compile on FreeBSD (namely by not doing math on void pointers.) o) Add a cvmx_mgmt_port_sendm routine to the Simple Executive to send an mbuf so there is only one copy in the transmit path, rather than having to first copy the mbuf to an intermediate buffer and then copy that to the Simple Executive's transmit ring. o) Properly work out MII addresses of management ports on the Lanner MR-730. XXX The MR-730 also needs some patches to the MII read/write routines, but this is sufficient for now. Media detection will be fixed in the future when I can spend more time reading the vendor-supplied patches.
Diffstat (limited to 'sys/contrib/octeon-sdk')
-rw-r--r--sys/contrib/octeon-sdk/cvmx-helper-board.c2
-rw-r--r--sys/contrib/octeon-sdk/cvmx-mgmt-port.c68
-rw-r--r--sys/contrib/octeon-sdk/cvmx-mgmt-port.h15
3 files changed, 78 insertions, 7 deletions
diff --git a/sys/contrib/octeon-sdk/cvmx-helper-board.c b/sys/contrib/octeon-sdk/cvmx-helper-board.c
index 4931167..fe2f236 100644
--- a/sys/contrib/octeon-sdk/cvmx-helper-board.c
+++ b/sys/contrib/octeon-sdk/cvmx-helper-board.c
@@ -272,6 +272,8 @@ int cvmx_helper_board_get_mii_address(int ipd_port)
return ipd_port - 16;
return -1;
case CVMX_BOARD_TYPE_CUST_LANNER_MR730:
+ if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2)))
+ return (ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT) + 0x81;
if ((ipd_port >= 0) && (ipd_port < 4))
return ipd_port;
return -1;
diff --git a/sys/contrib/octeon-sdk/cvmx-mgmt-port.c b/sys/contrib/octeon-sdk/cvmx-mgmt-port.c
index 108ef00..8bb064b 100644
--- a/sys/contrib/octeon-sdk/cvmx-mgmt-port.c
+++ b/sys/contrib/octeon-sdk/cvmx-mgmt-port.c
@@ -112,7 +112,7 @@ CVMX_SHARED cvmx_mgmt_port_state_t *cvmx_mgmt_port_state_ptr = NULL;
*
* @return Number of ports
*/
-int __cvmx_mgmt_port_num_ports(void)
+static int __cvmx_mgmt_port_num_ports(void)
{
if (OCTEON_IS_MODEL(OCTEON_CN56XX))
return 1;
@@ -554,6 +554,62 @@ cvmx_mgmt_port_result_t cvmx_mgmt_port_send(int port, int packet_len, void *buff
}
+#if defined(__FreeBSD__)
+/**
+ * Send a packet out the management port. The packet is copied so
+ * the input mbuf isn't used after this call.
+ *
+ * @param port Management port
+ * @param m Packet mbuf (with pkthdr)
+ *
+ * @return CVMX_MGMT_PORT_SUCCESS or an error code
+ */
+cvmx_mgmt_port_result_t cvmx_mgmt_port_sendm(int port, const struct mbuf *m)
+{
+ cvmx_mgmt_port_state_t *state;
+ cvmx_mixx_oring2_t mix_oring2;
+
+ if ((port < 0) || (port >= __cvmx_mgmt_port_num_ports()))
+ return CVMX_MGMT_PORT_INVALID_PARAM;
+
+ /* Max sure the packet size is valid */
+ if ((m->m_pkthdr.len < 1) || (m->m_pkthdr.len > CVMX_MGMT_PORT_TX_BUFFER_SIZE))
+ return CVMX_MGMT_PORT_INVALID_PARAM;
+
+ state = cvmx_mgmt_port_state_ptr + port;
+
+ cvmx_spinlock_lock(&state->lock);
+
+ mix_oring2.u64 = cvmx_read_csr(CVMX_MIXX_ORING2(port));
+ if (mix_oring2.s.odbell >= CVMX_MGMT_PORT_NUM_TX_BUFFERS - 1)
+ {
+ /* No room for another packet */
+ cvmx_spinlock_unlock(&state->lock);
+ return CVMX_MGMT_PORT_NO_MEMORY;
+ }
+ else
+ {
+ /* Copy the packet into the output buffer */
+ m_copydata(m, 0, m->m_pkthdr.len, state->tx_buffers[state->tx_write_index]);
+ /* Update the TX ring buffer entry size */
+ state->tx_ring[state->tx_write_index].s.len = m->m_pkthdr.len;
+ /* This code doesn't support TX timestamps */
+ state->tx_ring[state->tx_write_index].s.tstamp = 0;
+ /* Increment our TX index */
+ state->tx_write_index = (state->tx_write_index + 1) % CVMX_MGMT_PORT_NUM_TX_BUFFERS;
+ /* Ring the doorbell, sending the packet */
+ CVMX_SYNCWS;
+ cvmx_write_csr(CVMX_MIXX_ORING2(port), 1);
+ if (cvmx_read_csr(CVMX_MIXX_ORCNT(port)))
+ cvmx_write_csr(CVMX_MIXX_ORCNT(port), cvmx_read_csr(CVMX_MIXX_ORCNT(port)));
+
+ cvmx_spinlock_unlock(&state->lock);
+ return CVMX_MGMT_PORT_SUCCESS;
+ }
+}
+#endif
+
+
/**
* Receive a packet from the management port.
*
@@ -564,7 +620,7 @@ cvmx_mgmt_port_result_t cvmx_mgmt_port_send(int port, int packet_len, void *buff
* @return The size of the packet, or a negative erorr code on failure. Zero
* means that no packets were available.
*/
-int cvmx_mgmt_port_receive(int port, int buffer_len, void *buffer)
+int cvmx_mgmt_port_receive(int port, int buffer_len, uint8_t *buffer)
{
cvmx_mixx_ircnt_t mix_ircnt;
cvmx_mgmt_port_state_t *state;
@@ -588,13 +644,13 @@ int cvmx_mgmt_port_receive(int port, int buffer_len, void *buffer)
mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port));
if (mix_ircnt.s.ircnt)
{
- void *source = state->rx_buffers[state->rx_read_index];
- uint64_t *zero_check = source;
+ uint64_t *source = (void *)state->rx_buffers[state->rx_read_index];
+ uint64_t *zero_check = source;
/* CN56XX pass 1 has an errata where packets might start 8 bytes
into the buffer instead of at their correct lcoation. If the
first 8 bytes is zero we assume this has happened */
if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) && (*zero_check == 0))
- source += 8;
+ source++;
/* Start off with zero bytes received */
result = 0;
/* While the completion code signals more data, copy the buffers
@@ -621,7 +677,7 @@ int cvmx_mgmt_port_receive(int port, int buffer_len, void *buffer)
CVMX_SYNCWS;
/* Increment the number of RX buffers */
cvmx_write_csr(CVMX_MIXX_IRING2(port), 1);
- source = state->rx_buffers[state->rx_read_index];
+ source = (void *)state->rx_buffers[state->rx_read_index];
zero_check = source;
}
diff --git a/sys/contrib/octeon-sdk/cvmx-mgmt-port.h b/sys/contrib/octeon-sdk/cvmx-mgmt-port.h
index 90b531d..bd09ded 100644
--- a/sys/contrib/octeon-sdk/cvmx-mgmt-port.h
+++ b/sys/contrib/octeon-sdk/cvmx-mgmt-port.h
@@ -134,6 +134,19 @@ extern cvmx_mgmt_port_result_t cvmx_mgmt_port_disable(int port);
*/
extern cvmx_mgmt_port_result_t cvmx_mgmt_port_send(int port, int packet_len, void *buffer);
+#if defined(__FreeBSD__)
+/**
+ * Send a packet out the management port. The packet is copied so
+ * the input mbuf isn't used after this call.
+ *
+ * @param port Management port
+ * @param m Packet mbuf (with pkthdr)
+ *
+ * @return CVMX_MGMT_PORT_SUCCESS or an error code
+ */
+extern cvmx_mgmt_port_result_t cvmx_mgmt_port_sendm(int port, const struct mbuf *m);
+#endif
+
/**
* Receive a packet from the management port.
*
@@ -144,7 +157,7 @@ extern cvmx_mgmt_port_result_t cvmx_mgmt_port_send(int port, int packet_len, voi
* @return The size of the packet, or a negative erorr code on failure. Zero
* means that no packets were available.
*/
-extern int cvmx_mgmt_port_receive(int port, int buffer_len, void *buffer);
+extern int cvmx_mgmt_port_receive(int port, int buffer_len, uint8_t *buffer);
/**
* Set the MAC address for a management port
OpenPOWER on IntegriCloud