Commit b85c715c authored by David S. Miller's avatar David S. Miller

Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next

Ben Hutchings says:

====================
1. Extension to PPS/PTP to allow for PHC devices where pulses are
   subject to a variable but measurable delay.
2. PPS/PTP/PHC support for Solarflare boards with a timestamping
   peripheral.
3. MTD support for updating the timestamping peripheral on those boards.
4. Fix for potential over-length requests to firmware.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents aee77e4a 45078374
...@@ -34,3 +34,10 @@ config SFC_SRIOV ...@@ -34,3 +34,10 @@ config SFC_SRIOV
This enables support for the SFC9000 I/O Virtualization This enables support for the SFC9000 I/O Virtualization
features, allowing accelerated network performance in features, allowing accelerated network performance in
virtualized environments. virtualized environments.
config SFC_PTP
bool "Solarflare SFC9000-family PTP support"
depends on SFC && PTP_1588_CLOCK && !(SFC=y && PTP_1588_CLOCK=m)
default y
---help---
This enables support for the Precision Time Protocol (PTP)
on SFC9000-family NICs
...@@ -5,5 +5,6 @@ sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \ ...@@ -5,5 +5,6 @@ sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \
mcdi.o mcdi_phy.o mcdi_mon.o mcdi.o mcdi_phy.o mcdi_mon.o
sfc-$(CONFIG_SFC_MTD) += mtd.o sfc-$(CONFIG_SFC_MTD) += mtd.o
sfc-$(CONFIG_SFC_SRIOV) += siena_sriov.o sfc-$(CONFIG_SFC_SRIOV) += siena_sriov.o
sfc-$(CONFIG_SFC_PTP) += ptp.o
obj-$(CONFIG_SFC) += sfc.o obj-$(CONFIG_SFC) += sfc.o
...@@ -734,6 +734,7 @@ static void efx_remove_channel(struct efx_channel *channel) ...@@ -734,6 +734,7 @@ static void efx_remove_channel(struct efx_channel *channel)
efx_for_each_possible_channel_tx_queue(tx_queue, channel) efx_for_each_possible_channel_tx_queue(tx_queue, channel)
efx_remove_tx_queue(tx_queue); efx_remove_tx_queue(tx_queue);
efx_remove_eventq(channel); efx_remove_eventq(channel);
channel->type->post_remove(channel);
} }
static void efx_remove_channels(struct efx_nic *efx) static void efx_remove_channels(struct efx_nic *efx)
...@@ -852,6 +853,7 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue) ...@@ -852,6 +853,7 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
static const struct efx_channel_type efx_default_channel_type = { static const struct efx_channel_type efx_default_channel_type = {
.pre_probe = efx_channel_dummy_op_int, .pre_probe = efx_channel_dummy_op_int,
.post_remove = efx_channel_dummy_op_void,
.get_name = efx_get_channel_name, .get_name = efx_get_channel_name,
.copy = efx_copy_channel, .copy = efx_copy_channel,
.keep_eventq = false, .keep_eventq = false,
...@@ -862,6 +864,10 @@ int efx_channel_dummy_op_int(struct efx_channel *channel) ...@@ -862,6 +864,10 @@ int efx_channel_dummy_op_int(struct efx_channel *channel)
return 0; return 0;
} }
void efx_channel_dummy_op_void(struct efx_channel *channel)
{
}
/************************************************************************** /**************************************************************************
* *
* Port handling * Port handling
...@@ -1451,10 +1457,16 @@ static void efx_set_channels(struct efx_nic *efx) ...@@ -1451,10 +1457,16 @@ static void efx_set_channels(struct efx_nic *efx)
efx->tx_channel_offset = efx->tx_channel_offset =
separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0; separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
/* We need to adjust the TX queue numbers if we have separate /* We need to mark which channels really have RX and TX
* queues, and adjust the TX queue numbers if we have separate
* RX-only and TX-only channels. * RX-only and TX-only channels.
*/ */
efx_for_each_channel(channel, efx) { efx_for_each_channel(channel, efx) {
if (channel->channel < efx->n_rx_channels)
channel->rx_queue.core_index = channel->channel;
else
channel->rx_queue.core_index = -1;
efx_for_each_channel_tx_queue(tx_queue, channel) efx_for_each_channel_tx_queue(tx_queue, channel)
tx_queue->queue -= (efx->tx_channel_offset * tx_queue->queue -= (efx->tx_channel_offset *
EFX_TXQ_TYPES); EFX_TXQ_TYPES);
...@@ -1767,6 +1779,9 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd) ...@@ -1767,6 +1779,9 @@ static int efx_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
struct efx_nic *efx = netdev_priv(net_dev); struct efx_nic *efx = netdev_priv(net_dev);
struct mii_ioctl_data *data = if_mii(ifr); struct mii_ioctl_data *data = if_mii(ifr);
if (cmd == SIOCSHWTSTAMP)
return efx_ptp_ioctl(efx, ifr, cmd);
/* Convert phy_id from older PRTAD/DEVAD format */ /* Convert phy_id from older PRTAD/DEVAD format */
if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) && if ((cmd == SIOCGMIIREG || cmd == SIOCSMIIREG) &&
(data->phy_id & 0xfc00) == 0x0400) (data->phy_id & 0xfc00) == 0x0400)
......
...@@ -102,6 +102,7 @@ static inline void efx_filter_rfs_expire(struct efx_channel *channel) {} ...@@ -102,6 +102,7 @@ static inline void efx_filter_rfs_expire(struct efx_channel *channel) {}
/* Channels */ /* Channels */
extern int efx_channel_dummy_op_int(struct efx_channel *channel); extern int efx_channel_dummy_op_int(struct efx_channel *channel);
extern void efx_channel_dummy_op_void(struct efx_channel *channel);
extern void efx_process_channel_now(struct efx_channel *channel); extern void efx_process_channel_now(struct efx_channel *channel);
extern int extern int
efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries); efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries);
......
...@@ -1174,6 +1174,7 @@ const struct ethtool_ops efx_ethtool_ops = { ...@@ -1174,6 +1174,7 @@ const struct ethtool_ops efx_ethtool_ops = {
.get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size,
.get_rxfh_indir = efx_ethtool_get_rxfh_indir, .get_rxfh_indir = efx_ethtool_get_rxfh_indir,
.set_rxfh_indir = efx_ethtool_set_rxfh_indir, .set_rxfh_indir = efx_ethtool_set_rxfh_indir,
.get_ts_info = efx_ptp_get_ts_info,
.get_module_info = efx_ethtool_get_module_info, .get_module_info = efx_ethtool_get_module_info,
.get_module_eeprom = efx_ethtool_get_module_eeprom, .get_module_eeprom = efx_ethtool_get_module_eeprom,
}; };
...@@ -320,14 +320,20 @@ static void efx_mcdi_ev_cpl(struct efx_nic *efx, unsigned int seqno, ...@@ -320,14 +320,20 @@ static void efx_mcdi_ev_cpl(struct efx_nic *efx, unsigned int seqno,
efx_mcdi_complete(mcdi); efx_mcdi_complete(mcdi);
} }
/* Issue the given command by writing the data into the shared memory PDU,
* ring the doorbell and wait for completion. Copyout the result. */
int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
const u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen, const u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen,
size_t *outlen_actual) size_t *outlen_actual)
{
efx_mcdi_rpc_start(efx, cmd, inbuf, inlen);
return efx_mcdi_rpc_finish(efx, cmd, inlen,
outbuf, outlen, outlen_actual);
}
void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, const u8 *inbuf,
size_t inlen)
{ {
struct efx_mcdi_iface *mcdi = efx_mcdi(efx); struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
int rc;
BUG_ON(efx_nic_rev(efx) < EFX_REV_SIENA_A0); BUG_ON(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
efx_mcdi_acquire(mcdi); efx_mcdi_acquire(mcdi);
...@@ -338,6 +344,15 @@ int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, ...@@ -338,6 +344,15 @@ int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
spin_unlock_bh(&mcdi->iface_lock); spin_unlock_bh(&mcdi->iface_lock);
efx_mcdi_copyin(efx, cmd, inbuf, inlen); efx_mcdi_copyin(efx, cmd, inbuf, inlen);
}
int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
u8 *outbuf, size_t outlen, size_t *outlen_actual)
{
struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
int rc;
BUG_ON(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
if (mcdi->mode == MCDI_MODE_POLL) if (mcdi->mode == MCDI_MODE_POLL)
rc = efx_mcdi_poll(efx); rc = efx_mcdi_poll(efx);
...@@ -563,6 +578,11 @@ void efx_mcdi_process_event(struct efx_channel *channel, ...@@ -563,6 +578,11 @@ void efx_mcdi_process_event(struct efx_channel *channel,
case MCDI_EVENT_CODE_FLR: case MCDI_EVENT_CODE_FLR:
efx_sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF)); efx_sriov_flr(efx, MCDI_EVENT_FIELD(*event, FLR_VF));
break; break;
case MCDI_EVENT_CODE_PTP_RX:
case MCDI_EVENT_CODE_PTP_FAULT:
case MCDI_EVENT_CODE_PTP_PPS:
efx_ptp_event(efx, event);
break;
default: default:
netif_err(efx, hw, efx->net_dev, "Unknown MCDI event 0x%x\n", netif_err(efx, hw, efx->net_dev, "Unknown MCDI event 0x%x\n",
...@@ -641,9 +661,8 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, ...@@ -641,9 +661,8 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
u16 *fw_subtype_list, u32 *capabilities) u16 *fw_subtype_list, u32 *capabilities)
{ {
uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LENMIN]; uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LENMIN];
size_t outlen; size_t outlen, offset, i;
int port_num = efx_port_num(efx); int port_num = efx_port_num(efx);
int offset;
int rc; int rc;
BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_IN_LEN != 0); BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_IN_LEN != 0);
...@@ -663,11 +682,18 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, ...@@ -663,11 +682,18 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
: MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST; : MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST;
if (mac_address) if (mac_address)
memcpy(mac_address, outbuf + offset, ETH_ALEN); memcpy(mac_address, outbuf + offset, ETH_ALEN);
if (fw_subtype_list) if (fw_subtype_list) {
memcpy(fw_subtype_list, /* Byte-swap and truncate or zero-pad as necessary */
outbuf + MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST, offset = MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST;
MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM * for (i = 0;
sizeof(fw_subtype_list[0])); i < MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM;
i++) {
fw_subtype_list[i] =
(offset + 2 <= outlen) ?
le16_to_cpup((__le16 *)(outbuf + offset)) : 0;
offset += 2;
}
}
if (capabilities) { if (capabilities) {
if (port_num) if (port_num)
*capabilities = MCDI_DWORD(outbuf, *capabilities = MCDI_DWORD(outbuf,
...@@ -1169,6 +1195,9 @@ int efx_mcdi_flush_rxqs(struct efx_nic *efx) ...@@ -1169,6 +1195,9 @@ int efx_mcdi_flush_rxqs(struct efx_nic *efx)
__le32 *qid; __le32 *qid;
int rc, count; int rc, count;
BUILD_BUG_ON(EFX_MAX_CHANNELS >
MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM);
qid = kmalloc(EFX_MAX_CHANNELS * sizeof(*qid), GFP_KERNEL); qid = kmalloc(EFX_MAX_CHANNELS * sizeof(*qid), GFP_KERNEL);
if (qid == NULL) if (qid == NULL)
return -ENOMEM; return -ENOMEM;
......
...@@ -71,6 +71,12 @@ extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, const u8 *inbuf, ...@@ -71,6 +71,12 @@ extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, const u8 *inbuf,
size_t inlen, u8 *outbuf, size_t outlen, size_t inlen, u8 *outbuf, size_t outlen,
size_t *outlen_actual); size_t *outlen_actual);
extern void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
const u8 *inbuf, size_t inlen);
extern int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
u8 *outbuf, size_t outlen,
size_t *outlen_actual);
extern int efx_mcdi_poll_reboot(struct efx_nic *efx); extern int efx_mcdi_poll_reboot(struct efx_nic *efx);
extern void efx_mcdi_mode_poll(struct efx_nic *efx); extern void efx_mcdi_mode_poll(struct efx_nic *efx);
extern void efx_mcdi_mode_event(struct efx_nic *efx); extern void efx_mcdi_mode_event(struct efx_nic *efx);
......
...@@ -289,6 +289,7 @@ ...@@ -289,6 +289,7 @@
#define MCDI_EVENT_CODE_TX_FLUSH 0xc /* enum */ #define MCDI_EVENT_CODE_TX_FLUSH 0xc /* enum */
#define MCDI_EVENT_CODE_PTP_RX 0xd /* enum */ #define MCDI_EVENT_CODE_PTP_RX 0xd /* enum */
#define MCDI_EVENT_CODE_PTP_FAULT 0xe /* enum */ #define MCDI_EVENT_CODE_PTP_FAULT 0xe /* enum */
#define MCDI_EVENT_CODE_PTP_PPS 0xf /* enum */
#define MCDI_EVENT_CMDDONE_DATA_OFST 0 #define MCDI_EVENT_CMDDONE_DATA_OFST 0
#define MCDI_EVENT_CMDDONE_DATA_LBN 0 #define MCDI_EVENT_CMDDONE_DATA_LBN 0
#define MCDI_EVENT_CMDDONE_DATA_WIDTH 32 #define MCDI_EVENT_CMDDONE_DATA_WIDTH 32
...@@ -491,12 +492,12 @@ ...@@ -491,12 +492,12 @@
/* MC_CMD_GET_FPGAREG_OUT msgresponse */ /* MC_CMD_GET_FPGAREG_OUT msgresponse */
#define MC_CMD_GET_FPGAREG_OUT_LENMIN 1 #define MC_CMD_GET_FPGAREG_OUT_LENMIN 1
#define MC_CMD_GET_FPGAREG_OUT_LENMAX 255 #define MC_CMD_GET_FPGAREG_OUT_LENMAX 252
#define MC_CMD_GET_FPGAREG_OUT_LEN(num) (0+1*(num)) #define MC_CMD_GET_FPGAREG_OUT_LEN(num) (0+1*(num))
#define MC_CMD_GET_FPGAREG_OUT_BUFFER_OFST 0 #define MC_CMD_GET_FPGAREG_OUT_BUFFER_OFST 0
#define MC_CMD_GET_FPGAREG_OUT_BUFFER_LEN 1 #define MC_CMD_GET_FPGAREG_OUT_BUFFER_LEN 1
#define MC_CMD_GET_FPGAREG_OUT_BUFFER_MINNUM 1 #define MC_CMD_GET_FPGAREG_OUT_BUFFER_MINNUM 1
#define MC_CMD_GET_FPGAREG_OUT_BUFFER_MAXNUM 255 #define MC_CMD_GET_FPGAREG_OUT_BUFFER_MAXNUM 252
/***********************************/ /***********************************/
...@@ -507,13 +508,13 @@ ...@@ -507,13 +508,13 @@
/* MC_CMD_PUT_FPGAREG_IN msgrequest */ /* MC_CMD_PUT_FPGAREG_IN msgrequest */
#define MC_CMD_PUT_FPGAREG_IN_LENMIN 5 #define MC_CMD_PUT_FPGAREG_IN_LENMIN 5
#define MC_CMD_PUT_FPGAREG_IN_LENMAX 255 #define MC_CMD_PUT_FPGAREG_IN_LENMAX 252
#define MC_CMD_PUT_FPGAREG_IN_LEN(num) (4+1*(num)) #define MC_CMD_PUT_FPGAREG_IN_LEN(num) (4+1*(num))
#define MC_CMD_PUT_FPGAREG_IN_ADDR_OFST 0 #define MC_CMD_PUT_FPGAREG_IN_ADDR_OFST 0
#define MC_CMD_PUT_FPGAREG_IN_BUFFER_OFST 4 #define MC_CMD_PUT_FPGAREG_IN_BUFFER_OFST 4
#define MC_CMD_PUT_FPGAREG_IN_BUFFER_LEN 1 #define MC_CMD_PUT_FPGAREG_IN_BUFFER_LEN 1
#define MC_CMD_PUT_FPGAREG_IN_BUFFER_MINNUM 1 #define MC_CMD_PUT_FPGAREG_IN_BUFFER_MINNUM 1
#define MC_CMD_PUT_FPGAREG_IN_BUFFER_MAXNUM 251 #define MC_CMD_PUT_FPGAREG_IN_BUFFER_MAXNUM 248
/* MC_CMD_PUT_FPGAREG_OUT msgresponse */ /* MC_CMD_PUT_FPGAREG_OUT msgresponse */
#define MC_CMD_PUT_FPGAREG_OUT_LEN 0 #define MC_CMD_PUT_FPGAREG_OUT_LEN 0
...@@ -560,7 +561,7 @@ ...@@ -560,7 +561,7 @@
/* MC_CMD_PTP_IN_TRANSMIT msgrequest */ /* MC_CMD_PTP_IN_TRANSMIT msgrequest */
#define MC_CMD_PTP_IN_TRANSMIT_LENMIN 13 #define MC_CMD_PTP_IN_TRANSMIT_LENMIN 13
#define MC_CMD_PTP_IN_TRANSMIT_LENMAX 255 #define MC_CMD_PTP_IN_TRANSMIT_LENMAX 252
#define MC_CMD_PTP_IN_TRANSMIT_LEN(num) (12+1*(num)) #define MC_CMD_PTP_IN_TRANSMIT_LEN(num) (12+1*(num))
/* MC_CMD_PTP_IN_CMD_OFST 0 */ /* MC_CMD_PTP_IN_CMD_OFST 0 */
/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ /* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */
...@@ -568,7 +569,7 @@ ...@@ -568,7 +569,7 @@
#define MC_CMD_PTP_IN_TRANSMIT_PACKET_OFST 12 #define MC_CMD_PTP_IN_TRANSMIT_PACKET_OFST 12
#define MC_CMD_PTP_IN_TRANSMIT_PACKET_LEN 1 #define MC_CMD_PTP_IN_TRANSMIT_PACKET_LEN 1
#define MC_CMD_PTP_IN_TRANSMIT_PACKET_MINNUM 1 #define MC_CMD_PTP_IN_TRANSMIT_PACKET_MINNUM 1
#define MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM 243 #define MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM 240
/* MC_CMD_PTP_IN_READ_NIC_TIME msgrequest */ /* MC_CMD_PTP_IN_READ_NIC_TIME msgrequest */
#define MC_CMD_PTP_IN_READ_NIC_TIME_LEN 8 #define MC_CMD_PTP_IN_READ_NIC_TIME_LEN 8
...@@ -1145,7 +1146,7 @@ ...@@ -1145,7 +1146,7 @@
/* MC_CMD_PUTS_IN msgrequest */ /* MC_CMD_PUTS_IN msgrequest */
#define MC_CMD_PUTS_IN_LENMIN 13 #define MC_CMD_PUTS_IN_LENMIN 13
#define MC_CMD_PUTS_IN_LENMAX 255 #define MC_CMD_PUTS_IN_LENMAX 252
#define MC_CMD_PUTS_IN_LEN(num) (12+1*(num)) #define MC_CMD_PUTS_IN_LEN(num) (12+1*(num))
#define MC_CMD_PUTS_IN_DEST_OFST 0 #define MC_CMD_PUTS_IN_DEST_OFST 0
#define MC_CMD_PUTS_IN_UART_LBN 0 #define MC_CMD_PUTS_IN_UART_LBN 0
...@@ -1157,7 +1158,7 @@ ...@@ -1157,7 +1158,7 @@
#define MC_CMD_PUTS_IN_STRING_OFST 12 #define MC_CMD_PUTS_IN_STRING_OFST 12
#define MC_CMD_PUTS_IN_STRING_LEN 1 #define MC_CMD_PUTS_IN_STRING_LEN 1
#define MC_CMD_PUTS_IN_STRING_MINNUM 1 #define MC_CMD_PUTS_IN_STRING_MINNUM 1
#define MC_CMD_PUTS_IN_STRING_MAXNUM 243 #define MC_CMD_PUTS_IN_STRING_MAXNUM 240
/* MC_CMD_PUTS_OUT msgresponse */ /* MC_CMD_PUTS_OUT msgresponse */
#define MC_CMD_PUTS_OUT_LEN 0 #define MC_CMD_PUTS_OUT_LEN 0
...@@ -1947,12 +1948,12 @@ ...@@ -1947,12 +1948,12 @@
/* MC_CMD_NVRAM_READ_OUT msgresponse */ /* MC_CMD_NVRAM_READ_OUT msgresponse */
#define MC_CMD_NVRAM_READ_OUT_LENMIN 1 #define MC_CMD_NVRAM_READ_OUT_LENMIN 1
#define MC_CMD_NVRAM_READ_OUT_LENMAX 255 #define MC_CMD_NVRAM_READ_OUT_LENMAX 252
#define MC_CMD_NVRAM_READ_OUT_LEN(num) (0+1*(num)) #define MC_CMD_NVRAM_READ_OUT_LEN(num) (0+1*(num))
#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_OFST 0 #define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_OFST 0
#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_LEN 1 #define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_LEN 1
#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MINNUM 1 #define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MINNUM 1
#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MAXNUM 255 #define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MAXNUM 252
/***********************************/ /***********************************/
...@@ -1963,7 +1964,7 @@ ...@@ -1963,7 +1964,7 @@
/* MC_CMD_NVRAM_WRITE_IN msgrequest */ /* MC_CMD_NVRAM_WRITE_IN msgrequest */
#define MC_CMD_NVRAM_WRITE_IN_LENMIN 13 #define MC_CMD_NVRAM_WRITE_IN_LENMIN 13
#define MC_CMD_NVRAM_WRITE_IN_LENMAX 255 #define MC_CMD_NVRAM_WRITE_IN_LENMAX 252
#define MC_CMD_NVRAM_WRITE_IN_LEN(num) (12+1*(num)) #define MC_CMD_NVRAM_WRITE_IN_LEN(num) (12+1*(num))
#define MC_CMD_NVRAM_WRITE_IN_TYPE_OFST 0 #define MC_CMD_NVRAM_WRITE_IN_TYPE_OFST 0
/* Enum values, see field(s): */ /* Enum values, see field(s): */
...@@ -1973,7 +1974,7 @@ ...@@ -1973,7 +1974,7 @@
#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_OFST 12 #define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_OFST 12
#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN 1 #define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN 1
#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MINNUM 1 #define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MINNUM 1
#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM 243 #define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM 240
/* MC_CMD_NVRAM_WRITE_OUT msgresponse */ /* MC_CMD_NVRAM_WRITE_OUT msgresponse */
#define MC_CMD_NVRAM_WRITE_OUT_LEN 0 #define MC_CMD_NVRAM_WRITE_OUT_LEN 0
...@@ -2305,13 +2306,13 @@ ...@@ -2305,13 +2306,13 @@
/* MC_CMD_GET_PHY_MEDIA_INFO_OUT msgresponse */ /* MC_CMD_GET_PHY_MEDIA_INFO_OUT msgresponse */
#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMIN 5 #define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMIN 5
#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX 255 #define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX 252
#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(num) (4+1*(num)) #define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(num) (4+1*(num))
#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATALEN_OFST 0 #define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATALEN_OFST 0
#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST 4 #define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST 4
#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_LEN 1 #define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_LEN 1
#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MINNUM 1 #define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MINNUM 1
#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MAXNUM 251 #define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MAXNUM 248
/***********************************/ /***********************************/
......
...@@ -585,6 +585,7 @@ static const struct siena_nvram_type_info siena_nvram_types[] = { ...@@ -585,6 +585,7 @@ static const struct siena_nvram_type_info siena_nvram_types[] = {
[MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1] = { 1, "sfc_exp_rom_cfg" }, [MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1] = { 1, "sfc_exp_rom_cfg" },
[MC_CMD_NVRAM_TYPE_PHY_PORT0] = { 0, "sfc_phy_fw" }, [MC_CMD_NVRAM_TYPE_PHY_PORT0] = { 0, "sfc_phy_fw" },
[MC_CMD_NVRAM_TYPE_PHY_PORT1] = { 1, "sfc_phy_fw" }, [MC_CMD_NVRAM_TYPE_PHY_PORT1] = { 1, "sfc_phy_fw" },
[MC_CMD_NVRAM_TYPE_FPGA] = { 0, "sfc_fpga" },
}; };
static int siena_mtd_probe_partition(struct efx_nic *efx, static int siena_mtd_probe_partition(struct efx_nic *efx,
...@@ -598,7 +599,8 @@ static int siena_mtd_probe_partition(struct efx_nic *efx, ...@@ -598,7 +599,8 @@ static int siena_mtd_probe_partition(struct efx_nic *efx,
bool protected; bool protected;
int rc; int rc;
if (type >= ARRAY_SIZE(siena_nvram_types)) if (type >= ARRAY_SIZE(siena_nvram_types) ||
siena_nvram_types[type].name == NULL)
return -ENODEV; return -ENODEV;
info = &siena_nvram_types[type]; info = &siena_nvram_types[type];
...@@ -627,7 +629,8 @@ static int siena_mtd_get_fw_subtypes(struct efx_nic *efx, ...@@ -627,7 +629,8 @@ static int siena_mtd_get_fw_subtypes(struct efx_nic *efx,
struct efx_mtd *efx_mtd) struct efx_mtd *efx_mtd)
{ {
struct efx_mtd_partition *part; struct efx_mtd_partition *part;
uint16_t fw_subtype_list[MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM]; uint16_t fw_subtype_list[
MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM];
int rc; int rc;
rc = efx_mcdi_get_board_cfg(efx, NULL, fw_subtype_list, NULL); rc = efx_mcdi_get_board_cfg(efx, NULL, fw_subtype_list, NULL);
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* *
**************************************************************************/ **************************************************************************/
#define EFX_DRIVER_VERSION "3.1" #define EFX_DRIVER_VERSION "3.2"
#ifdef DEBUG #ifdef DEBUG
#define EFX_BUG_ON_PARANOID(x) BUG_ON(x) #define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
...@@ -56,7 +56,8 @@ ...@@ -56,7 +56,8 @@
#define EFX_MAX_CHANNELS 32U #define EFX_MAX_CHANNELS 32U
#define EFX_MAX_RX_QUEUES EFX_MAX_CHANNELS #define EFX_MAX_RX_QUEUES EFX_MAX_CHANNELS
#define EFX_EXTRA_CHANNEL_IOV 0 #define EFX_EXTRA_CHANNEL_IOV 0
#define EFX_MAX_EXTRA_CHANNELS 1U #define EFX_EXTRA_CHANNEL_PTP 1
#define EFX_MAX_EXTRA_CHANNELS 2U
/* Checksum generation is a per-queue option in hardware, so each /* Checksum generation is a per-queue option in hardware, so each
* queue visible to the networking core is backed by two hardware TX * queue visible to the networking core is backed by two hardware TX
...@@ -68,6 +69,9 @@ ...@@ -68,6 +69,9 @@
#define EFX_TXQ_TYPES 4 #define EFX_TXQ_TYPES 4
#define EFX_MAX_TX_QUEUES (EFX_TXQ_TYPES * EFX_MAX_CHANNELS) #define EFX_MAX_TX_QUEUES (EFX_TXQ_TYPES * EFX_MAX_CHANNELS)
/* Forward declare Precision Time Protocol (PTP) support structure. */
struct efx_ptp_data;
struct efx_self_tests; struct efx_self_tests;
/** /**
...@@ -242,6 +246,8 @@ struct efx_rx_page_state { ...@@ -242,6 +246,8 @@ struct efx_rx_page_state {
/** /**
* struct efx_rx_queue - An Efx RX queue * struct efx_rx_queue - An Efx RX queue
* @efx: The associated Efx NIC * @efx: The associated Efx NIC
* @core_index: Index of network core RX queue. Will be >= 0 iff this
* is associated with a real RX queue.
* @buffer: The software buffer ring * @buffer: The software buffer ring
* @rxd: The hardware descriptor ring * @rxd: The hardware descriptor ring
* @ptr_mask: The size of the ring minus 1. * @ptr_mask: The size of the ring minus 1.
...@@ -263,6 +269,7 @@ struct efx_rx_page_state { ...@@ -263,6 +269,7 @@ struct efx_rx_page_state {
*/ */
struct efx_rx_queue { struct efx_rx_queue {
struct efx_nic *efx; struct efx_nic *efx;
int core_index;
struct efx_rx_buffer *buffer; struct efx_rx_buffer *buffer;
struct efx_special_buffer rxd; struct efx_special_buffer rxd;
unsigned int ptr_mask; unsigned int ptr_mask;
...@@ -390,14 +397,17 @@ struct efx_channel { ...@@ -390,14 +397,17 @@ struct efx_channel {
* @get_name: Generate the channel's name (used for its IRQ handler) * @get_name: Generate the channel's name (used for its IRQ handler)
* @copy: Copy the channel state prior to reallocation. May be %NULL if * @copy: Copy the channel state prior to reallocation. May be %NULL if
* reallocation is not supported. * reallocation is not supported.
* @receive_skb: Handle an skb ready to be passed to netif_receive_skb()
* @keep_eventq: Flag for whether event queue should be kept initialised * @keep_eventq: Flag for whether event queue should be kept initialised
* while the device is stopped * while the device is stopped
*/ */
struct efx_channel_type { struct efx_channel_type {
void (*handle_no_channel)(struct efx_nic *); void (*handle_no_channel)(struct efx_nic *);
int (*pre_probe)(struct efx_channel *); int (*pre_probe)(struct efx_channel *);
void (*post_remove)(struct efx_channel *);
void (*get_name)(struct efx_channel *, char *buf, size_t len); void (*get_name)(struct efx_channel *, char *buf, size_t len);
struct efx_channel *(*copy)(const struct efx_channel *); struct efx_channel *(*copy)(const struct efx_channel *);
void (*receive_skb)(struct efx_channel *, struct sk_buff *);
bool keep_eventq; bool keep_eventq;
}; };
...@@ -730,6 +740,7 @@ struct vfdi_status; ...@@ -730,6 +740,7 @@ struct vfdi_status;
* %local_addr_list. Protected by %local_lock. * %local_addr_list. Protected by %local_lock.
* @local_lock: Mutex protecting %local_addr_list and %local_page_list. * @local_lock: Mutex protecting %local_addr_list and %local_page_list.
* @peer_work: Work item to broadcast peer addresses to VMs. * @peer_work: Work item to broadcast peer addresses to VMs.
* @ptp_data: PTP state data
* @monitor_work: Hardware monitor workitem * @monitor_work: Hardware monitor workitem
* @biu_lock: BIU (bus interface unit) lock * @biu_lock: BIU (bus interface unit) lock
* @last_irq_cpu: Last CPU to handle a possible test interrupt. This * @last_irq_cpu: Last CPU to handle a possible test interrupt. This
...@@ -857,6 +868,10 @@ struct efx_nic { ...@@ -857,6 +868,10 @@ struct efx_nic {
struct work_struct peer_work; struct work_struct peer_work;
#endif #endif
#ifdef CONFIG_SFC_PTP
struct efx_ptp_data *ptp_data;
#endif
/* The following fields may be written more often */ /* The following fields may be written more often */
struct delayed_work monitor_work ____cacheline_aligned_in_smp; struct delayed_work monitor_work ____cacheline_aligned_in_smp;
...@@ -1047,7 +1062,7 @@ static inline bool efx_tx_queue_used(struct efx_tx_queue *tx_queue) ...@@ -1047,7 +1062,7 @@ static inline bool efx_tx_queue_used(struct efx_tx_queue *tx_queue)
static inline bool efx_channel_has_rx_queue(struct efx_channel *channel) static inline bool efx_channel_has_rx_queue(struct efx_channel *channel)
{ {
return channel->channel < channel->efx->n_rx_channels; return channel->rx_queue.core_index >= 0;
} }
static inline struct efx_rx_queue * static inline struct efx_rx_queue *
...@@ -1119,5 +1134,13 @@ static inline void clear_bit_le(unsigned nr, unsigned char *addr) ...@@ -1119,5 +1134,13 @@ static inline void clear_bit_le(unsigned nr, unsigned char *addr)
#define EFX_MAX_FRAME_LEN(mtu) \ #define EFX_MAX_FRAME_LEN(mtu) \
((((mtu) + ETH_HLEN + VLAN_HLEN + 4/* FCS */ + 7) & ~7) + 16) ((((mtu) + ETH_HLEN + VLAN_HLEN + 4/* FCS */ + 7) & ~7) + 16)
static inline bool efx_xmit_with_hwtstamp(struct sk_buff *skb)
{
return skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP;
}
static inline void efx_xmit_hwtstamp_pending(struct sk_buff *skb)
{
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
}
#endif /* EFX_NET_DRIVER_H */ #endif /* EFX_NET_DRIVER_H */
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#ifndef EFX_NIC_H #ifndef EFX_NIC_H
#define EFX_NIC_H #define EFX_NIC_H
#include <linux/net_tstamp.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include "net_driver.h" #include "net_driver.h"
#include "efx.h" #include "efx.h"
...@@ -250,6 +251,41 @@ extern int efx_sriov_get_vf_config(struct net_device *dev, int vf, ...@@ -250,6 +251,41 @@ extern int efx_sriov_get_vf_config(struct net_device *dev, int vf,
extern int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf, extern int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf,
bool spoofchk); bool spoofchk);
struct ethtool_ts_info;
#ifdef CONFIG_SFC_PTP
extern void efx_ptp_probe(struct efx_nic *efx);
extern int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd);
extern int efx_ptp_get_ts_info(struct net_device *net_dev,
struct ethtool_ts_info *ts_info);
extern bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
extern int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
extern void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
#else
static inline void efx_ptp_probe(struct efx_nic *efx) {}
static inline int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd)
{
return -EOPNOTSUPP;
}
static inline int efx_ptp_get_ts_info(struct net_device *net_dev,
struct ethtool_ts_info *ts_info)
{
ts_info->so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
SOF_TIMESTAMPING_RX_SOFTWARE);
ts_info->phc_index = -1;
return 0;
}
static inline bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
{
return false;
}
static inline int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
{
return NETDEV_TX_OK;
}
static inline void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev) {}
#endif
extern const struct efx_nic_type falcon_a1_nic_type; extern const struct efx_nic_type falcon_a1_nic_type;
extern const struct efx_nic_type falcon_b0_nic_type; extern const struct efx_nic_type falcon_b0_nic_type;
extern const struct efx_nic_type siena_a0_nic_type; extern const struct efx_nic_type siena_a0_nic_type;
......
This diff is collapsed.
...@@ -479,7 +479,7 @@ static void efx_rx_packet_gro(struct efx_channel *channel, ...@@ -479,7 +479,7 @@ static void efx_rx_packet_gro(struct efx_channel *channel,
skb->ip_summed = ((rx_buf->flags & EFX_RX_PKT_CSUMMED) ? skb->ip_summed = ((rx_buf->flags & EFX_RX_PKT_CSUMMED) ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE); CHECKSUM_UNNECESSARY : CHECKSUM_NONE);
skb_record_rx_queue(skb, channel->channel); skb_record_rx_queue(skb, channel->rx_queue.core_index);
gro_result = napi_gro_frags(napi); gro_result = napi_gro_frags(napi);
} else { } else {
...@@ -571,7 +571,13 @@ static void efx_rx_deliver(struct efx_channel *channel, ...@@ -571,7 +571,13 @@ static void efx_rx_deliver(struct efx_channel *channel,
/* Set the SKB flags */ /* Set the SKB flags */
skb_checksum_none_assert(skb); skb_checksum_none_assert(skb);
/* Record the rx_queue */
skb_record_rx_queue(skb, channel->rx_queue.core_index);
/* Pass the packet up */ /* Pass the packet up */
if (channel->type->receive_skb)
channel->type->receive_skb(channel, skb);
else
netif_receive_skb(skb); netif_receive_skb(skb);
/* Update allocation strategy method */ /* Update allocation strategy method */
...@@ -608,13 +614,14 @@ void __efx_rx_packet(struct efx_channel *channel, struct efx_rx_buffer *rx_buf) ...@@ -608,13 +614,14 @@ void __efx_rx_packet(struct efx_channel *channel, struct efx_rx_buffer *rx_buf)
* at the ethernet header */ * at the ethernet header */
skb->protocol = eth_type_trans(skb, efx->net_dev); skb->protocol = eth_type_trans(skb, efx->net_dev);
skb_record_rx_queue(skb, channel->channel); skb_record_rx_queue(skb, channel->rx_queue.core_index);
} }
if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM))) if (unlikely(!(efx->net_dev->features & NETIF_F_RXCSUM)))
rx_buf->flags &= ~EFX_RX_PKT_CSUMMED; rx_buf->flags &= ~EFX_RX_PKT_CSUMMED;
if (likely(rx_buf->flags & (EFX_RX_BUF_PAGE | EFX_RX_PKT_CSUMMED))) if (likely(rx_buf->flags & (EFX_RX_BUF_PAGE | EFX_RX_PKT_CSUMMED)) &&
!channel->type->receive_skb)
efx_rx_packet_gro(channel, rx_buf, eh); efx_rx_packet_gro(channel, rx_buf, eh);
else else
efx_rx_deliver(channel, rx_buf); efx_rx_deliver(channel, rx_buf);
...@@ -624,6 +631,11 @@ void efx_rx_strategy(struct efx_channel *channel) ...@@ -624,6 +631,11 @@ void efx_rx_strategy(struct efx_channel *channel)
{ {
enum efx_rx_alloc_method method = rx_alloc_method; enum efx_rx_alloc_method method = rx_alloc_method;
if (channel->type->receive_skb) {
channel->rx_alloc_push_pages = false;
return;
}
/* Only makes sense to use page based allocation if GRO is enabled */ /* Only makes sense to use page based allocation if GRO is enabled */
if (!(channel->efx->net_dev->features & NETIF_F_GRO)) { if (!(channel->efx->net_dev->features & NETIF_F_GRO)) {
method = RX_ALLOC_METHOD_SKB; method = RX_ALLOC_METHOD_SKB;
......
...@@ -335,6 +335,7 @@ static int siena_probe_nic(struct efx_nic *efx) ...@@ -335,6 +335,7 @@ static int siena_probe_nic(struct efx_nic *efx)
goto fail5; goto fail5;
efx_sriov_probe(efx); efx_sriov_probe(efx);
efx_ptp_probe(efx);
return 0; return 0;
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
/* Number of longs required to track all the VIs in a VF */ /* Number of longs required to track all the VIs in a VF */
#define VI_MASK_LENGTH BITS_TO_LONGS(1 << EFX_VI_SCALE_MAX) #define VI_MASK_LENGTH BITS_TO_LONGS(1 << EFX_VI_SCALE_MAX)
/* Maximum number of RX queues supported */
#define VF_MAX_RX_QUEUES 63
/** /**
* enum efx_vf_tx_filter_mode - TX MAC filtering behaviour * enum efx_vf_tx_filter_mode - TX MAC filtering behaviour
* @VF_TX_FILTER_OFF: Disabled * @VF_TX_FILTER_OFF: Disabled
...@@ -578,6 +581,7 @@ static int efx_vfdi_init_rxq(struct efx_vf *vf) ...@@ -578,6 +581,7 @@ static int efx_vfdi_init_rxq(struct efx_vf *vf)
efx_oword_t reg; efx_oword_t reg;
if (bad_vf_index(efx, vf_evq) || bad_vf_index(efx, vf_rxq) || if (bad_vf_index(efx, vf_evq) || bad_vf_index(efx, vf_rxq) ||
vf_rxq >= VF_MAX_RX_QUEUES ||
bad_buf_count(buf_count, EFX_MAX_DMAQ_SIZE)) { bad_buf_count(buf_count, EFX_MAX_DMAQ_SIZE)) {
if (net_ratelimit()) if (net_ratelimit())
netif_err(efx, hw, efx->net_dev, netif_err(efx, hw, efx->net_dev,
...@@ -683,6 +687,9 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf) ...@@ -683,6 +687,9 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf)
__le32 *rxqs; __le32 *rxqs;
int rc; int rc;
BUILD_BUG_ON(VF_MAX_RX_QUEUES >
MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM);
rxqs = kmalloc(count * sizeof(*rxqs), GFP_KERNEL); rxqs = kmalloc(count * sizeof(*rxqs), GFP_KERNEL);
if (rxqs == NULL) if (rxqs == NULL)
return VFDI_RC_ENOMEM; return VFDI_RC_ENOMEM;
......
...@@ -339,6 +339,12 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb, ...@@ -339,6 +339,12 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
EFX_WARN_ON_PARANOID(!netif_device_present(net_dev)); EFX_WARN_ON_PARANOID(!netif_device_present(net_dev));
/* PTP "event" packet */
if (unlikely(efx_xmit_with_hwtstamp(skb)) &&
unlikely(efx_ptp_is_ptp_tx(efx, skb))) {
return efx_ptp_tx(efx, skb);
}
index = skb_get_queue_mapping(skb); index = skb_get_queue_mapping(skb);
type = skb->ip_summed == CHECKSUM_PARTIAL ? EFX_TXQ_TYPE_OFFLOAD : 0; type = skb->ip_summed == CHECKSUM_PARTIAL ? EFX_TXQ_TYPE_OFFLOAD : 0;
if (index >= efx->n_tx_channels) { if (index >= efx->n_tx_channels) {
......
...@@ -300,6 +300,11 @@ void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event) ...@@ -300,6 +300,11 @@ void ptp_clock_event(struct ptp_clock *ptp, struct ptp_clock_event *event)
pps_get_ts(&evt); pps_get_ts(&evt);
pps_event(ptp->pps_source, &evt, PTP_PPS_EVENT, NULL); pps_event(ptp->pps_source, &evt, PTP_PPS_EVENT, NULL);
break; break;
case PTP_CLOCK_PPSUSR:
pps_event(ptp->pps_source, &event->pps_times,
PTP_PPS_EVENT, NULL);
break;
} }
} }
EXPORT_SYMBOL(ptp_clock_event); EXPORT_SYMBOL(ptp_clock_event);
......
...@@ -116,5 +116,14 @@ static inline void pps_get_ts(struct pps_event_time *ts) ...@@ -116,5 +116,14 @@ static inline void pps_get_ts(struct pps_event_time *ts)
#endif /* CONFIG_NTP_PPS */ #endif /* CONFIG_NTP_PPS */
/* Subtract known time delay from PPS event time(s) */
static inline void pps_sub_ts(struct pps_event_time *ts, struct timespec delta)
{
ts->ts_real = timespec_sub(ts->ts_real, delta);
#ifdef CONFIG_NTP_PPS
ts->ts_raw = timespec_sub(ts->ts_raw, delta);
#endif
}
#endif /* LINUX_PPS_KERNEL_H */ #endif /* LINUX_PPS_KERNEL_H */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#ifndef _PTP_CLOCK_KERNEL_H_ #ifndef _PTP_CLOCK_KERNEL_H_
#define _PTP_CLOCK_KERNEL_H_ #define _PTP_CLOCK_KERNEL_H_
#include <linux/pps_kernel.h>
#include <linux/ptp_clock.h> #include <linux/ptp_clock.h>
...@@ -110,6 +111,7 @@ enum ptp_clock_events { ...@@ -110,6 +111,7 @@ enum ptp_clock_events {
PTP_CLOCK_ALARM, PTP_CLOCK_ALARM,
PTP_CLOCK_EXTTS, PTP_CLOCK_EXTTS,
PTP_CLOCK_PPS, PTP_CLOCK_PPS,
PTP_CLOCK_PPSUSR,
}; };
/** /**
...@@ -117,13 +119,17 @@ enum ptp_clock_events { ...@@ -117,13 +119,17 @@ enum ptp_clock_events {
* *
* @type: One of the ptp_clock_events enumeration values. * @type: One of the ptp_clock_events enumeration values.
* @index: Identifies the source of the event. * @index: Identifies the source of the event.
* @timestamp: When the event occured. * @timestamp: When the event occurred (%PTP_CLOCK_EXTTS only).
* @pps_times: When the event occurred (%PTP_CLOCK_PPSUSR only).
*/ */
struct ptp_clock_event { struct ptp_clock_event {
int type; int type;
int index; int index;
union {
u64 timestamp; u64 timestamp;
struct pps_event_time pps_times;
};
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment