aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/sfc/nic.h4
-rw-r--r--drivers/net/ethernet/sfc/ptp.c59
-rw-r--r--drivers/net/ethernet/sfc/siena.c2
3 files changed, 41 insertions, 24 deletions
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 7ac9c000696f..25178536f053 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -554,7 +554,9 @@ int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf,
554 bool spoofchk); 554 bool spoofchk);
555 555
556struct ethtool_ts_info; 556struct ethtool_ts_info;
557void efx_ptp_probe(struct efx_nic *efx); 557int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel);
558void efx_ptp_defer_probe_with_channel(struct efx_nic *efx);
559void efx_ptp_remove(struct efx_nic *efx);
558int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr); 560int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr);
559int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr); 561int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr);
560void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); 562void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info);
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index 7ae66d900256..aa4876edaac6 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -214,7 +214,8 @@ struct efx_ptp_timeset {
214 214
215/** 215/**
216 * struct efx_ptp_data - Precision Time Protocol (PTP) state 216 * struct efx_ptp_data - Precision Time Protocol (PTP) state
217 * @channel: The PTP channel 217 * @efx: The NIC context
218 * @channel: The PTP channel (Siena only)
218 * @rxq: Receive queue (awaiting timestamps) 219 * @rxq: Receive queue (awaiting timestamps)
219 * @txq: Transmit queue 220 * @txq: Transmit queue
220 * @evt_list: List of MC receive events awaiting packets 221 * @evt_list: List of MC receive events awaiting packets
@@ -265,6 +266,7 @@ struct efx_ptp_timeset {
265 * @timeset: Last set of synchronisation statistics. 266 * @timeset: Last set of synchronisation statistics.
266 */ 267 */
267struct efx_ptp_data { 268struct efx_ptp_data {
269 struct efx_nic *efx;
268 struct efx_channel *channel; 270 struct efx_channel *channel;
269 struct sk_buff_head rxq; 271 struct sk_buff_head rxq;
270 struct sk_buff_head txq; 272 struct sk_buff_head txq;
@@ -319,7 +321,8 @@ static int efx_ptp_enable(struct efx_nic *efx)
319 MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ENABLE); 321 MCDI_SET_DWORD(inbuf, PTP_IN_OP, MC_CMD_PTP_OP_ENABLE);
320 MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0); 322 MCDI_SET_DWORD(inbuf, PTP_IN_PERIPH_ID, 0);
321 MCDI_SET_DWORD(inbuf, PTP_IN_ENABLE_QUEUE, 323 MCDI_SET_DWORD(inbuf, PTP_IN_ENABLE_QUEUE,
322 efx->ptp_data->channel->channel); 324 efx->ptp_data->channel ?
325 efx->ptp_data->channel->channel : 0);
323 MCDI_SET_DWORD(inbuf, PTP_IN_ENABLE_MODE, efx->ptp_data->mode); 326 MCDI_SET_DWORD(inbuf, PTP_IN_ENABLE_MODE, efx->ptp_data->mode);
324 327
325 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_PTP, inbuf, sizeof(inbuf), 328 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_PTP, inbuf, sizeof(inbuf),
@@ -774,7 +777,7 @@ static int efx_ptp_insert_multicast_filters(struct efx_nic *efx)
774 struct efx_filter_spec rxfilter; 777 struct efx_filter_spec rxfilter;
775 int rc; 778 int rc;
776 779
777 if (ptp->rxfilter_installed) 780 if (!ptp->channel || ptp->rxfilter_installed)
778 return 0; 781 return 0;
779 782
780 /* Must filter on both event and general ports to ensure 783 /* Must filter on both event and general ports to ensure
@@ -882,7 +885,7 @@ static void efx_ptp_pps_worker(struct work_struct *work)
882{ 885{
883 struct efx_ptp_data *ptp = 886 struct efx_ptp_data *ptp =
884 container_of(work, struct efx_ptp_data, pps_work); 887 container_of(work, struct efx_ptp_data, pps_work);
885 struct efx_nic *efx = ptp->channel->efx; 888 struct efx_nic *efx = ptp->efx;
886 struct ptp_clock_event ptp_evt; 889 struct ptp_clock_event ptp_evt;
887 890
888 if (efx_ptp_synchronize(efx, PTP_SYNC_ATTEMPTS)) 891 if (efx_ptp_synchronize(efx, PTP_SYNC_ATTEMPTS))
@@ -899,7 +902,7 @@ static void efx_ptp_worker(struct work_struct *work)
899{ 902{
900 struct efx_ptp_data *ptp_data = 903 struct efx_ptp_data *ptp_data =
901 container_of(work, struct efx_ptp_data, work); 904 container_of(work, struct efx_ptp_data, work);
902 struct efx_nic *efx = ptp_data->channel->efx; 905 struct efx_nic *efx = ptp_data->efx;
903 struct sk_buff *skb; 906 struct sk_buff *skb;
904 struct sk_buff_head tempq; 907 struct sk_buff_head tempq;
905 908
@@ -923,31 +926,25 @@ static void efx_ptp_worker(struct work_struct *work)
923 efx_ptp_process_rx(efx, skb); 926 efx_ptp_process_rx(efx, skb);
924} 927}
925 928
926/* Initialise PTP channel and state. 929/* Initialise PTP state. */
927 * 930int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel)
928 * Setting core_index to zero causes the queue to be initialised and doesn't
929 * overlap with 'rxq0' because ptp.c doesn't use skb_record_rx_queue.
930 */
931static int efx_ptp_probe_channel(struct efx_channel *channel)
932{ 931{
933 struct efx_nic *efx = channel->efx;
934 struct efx_ptp_data *ptp; 932 struct efx_ptp_data *ptp;
935 int rc = 0; 933 int rc = 0;
936 unsigned int pos; 934 unsigned int pos;
937 935
938 channel->irq_moderation = 0;
939 channel->rx_queue.core_index = 0;
940
941 ptp = kzalloc(sizeof(struct efx_ptp_data), GFP_KERNEL); 936 ptp = kzalloc(sizeof(struct efx_ptp_data), GFP_KERNEL);
942 efx->ptp_data = ptp; 937 efx->ptp_data = ptp;
943 if (!efx->ptp_data) 938 if (!efx->ptp_data)
944 return -ENOMEM; 939 return -ENOMEM;
945 940
941 ptp->efx = efx;
942 ptp->channel = channel;
943
946 rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL); 944 rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL);
947 if (rc != 0) 945 if (rc != 0)
948 goto fail1; 946 goto fail1;
949 947
950 ptp->channel = channel;
951 skb_queue_head_init(&ptp->rxq); 948 skb_queue_head_init(&ptp->rxq);
952 skb_queue_head_init(&ptp->txq); 949 skb_queue_head_init(&ptp->txq);
953 ptp->workwq = create_singlethread_workqueue("sfc_ptp"); 950 ptp->workwq = create_singlethread_workqueue("sfc_ptp");
@@ -1014,14 +1011,27 @@ fail1:
1014 return rc; 1011 return rc;
1015} 1012}
1016 1013
1017static void efx_ptp_remove_channel(struct efx_channel *channel) 1014/* Initialise PTP channel.
1015 *
1016 * Setting core_index to zero causes the queue to be initialised and doesn't
1017 * overlap with 'rxq0' because ptp.c doesn't use skb_record_rx_queue.
1018 */
1019static int efx_ptp_probe_channel(struct efx_channel *channel)
1018{ 1020{
1019 struct efx_nic *efx = channel->efx; 1021 struct efx_nic *efx = channel->efx;
1020 1022
1023 channel->irq_moderation = 0;
1024 channel->rx_queue.core_index = 0;
1025
1026 return efx_ptp_probe(efx, channel);
1027}
1028
1029void efx_ptp_remove(struct efx_nic *efx)
1030{
1021 if (!efx->ptp_data) 1031 if (!efx->ptp_data)
1022 return; 1032 return;
1023 1033
1024 (void)efx_ptp_disable(channel->efx); 1034 (void)efx_ptp_disable(efx);
1025 1035
1026 cancel_work_sync(&efx->ptp_data->work); 1036 cancel_work_sync(&efx->ptp_data->work);
1027 cancel_work_sync(&efx->ptp_data->pps_work); 1037 cancel_work_sync(&efx->ptp_data->pps_work);
@@ -1038,6 +1048,11 @@ static void efx_ptp_remove_channel(struct efx_channel *channel)
1038 kfree(efx->ptp_data); 1048 kfree(efx->ptp_data);
1039} 1049}
1040 1050
1051static void efx_ptp_remove_channel(struct efx_channel *channel)
1052{
1053 efx_ptp_remove(channel->efx);
1054}
1055
1041static void efx_ptp_get_channel_name(struct efx_channel *channel, 1056static void efx_ptp_get_channel_name(struct efx_channel *channel,
1042 char *buf, size_t len) 1057 char *buf, size_t len)
1043{ 1058{
@@ -1449,7 +1464,7 @@ static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
1449 struct efx_ptp_data *ptp_data = container_of(ptp, 1464 struct efx_ptp_data *ptp_data = container_of(ptp,
1450 struct efx_ptp_data, 1465 struct efx_ptp_data,
1451 phc_clock_info); 1466 phc_clock_info);
1452 struct efx_nic *efx = ptp_data->channel->efx; 1467 struct efx_nic *efx = ptp_data->efx;
1453 MCDI_DECLARE_BUF(inadj, MC_CMD_PTP_IN_ADJUST_LEN); 1468 MCDI_DECLARE_BUF(inadj, MC_CMD_PTP_IN_ADJUST_LEN);
1454 s64 adjustment_ns; 1469 s64 adjustment_ns;
1455 int rc; 1470 int rc;
@@ -1482,7 +1497,7 @@ static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
1482 struct efx_ptp_data *ptp_data = container_of(ptp, 1497 struct efx_ptp_data *ptp_data = container_of(ptp,
1483 struct efx_ptp_data, 1498 struct efx_ptp_data,
1484 phc_clock_info); 1499 phc_clock_info);
1485 struct efx_nic *efx = ptp_data->channel->efx; 1500 struct efx_nic *efx = ptp_data->efx;
1486 struct timespec delta_ts = ns_to_timespec(delta); 1501 struct timespec delta_ts = ns_to_timespec(delta);
1487 MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_ADJUST_LEN); 1502 MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_ADJUST_LEN);
1488 1503
@@ -1500,7 +1515,7 @@ static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
1500 struct efx_ptp_data *ptp_data = container_of(ptp, 1515 struct efx_ptp_data *ptp_data = container_of(ptp,
1501 struct efx_ptp_data, 1516 struct efx_ptp_data,
1502 phc_clock_info); 1517 phc_clock_info);
1503 struct efx_nic *efx = ptp_data->channel->efx; 1518 struct efx_nic *efx = ptp_data->efx;
1504 MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_READ_NIC_TIME_LEN); 1519 MCDI_DECLARE_BUF(inbuf, MC_CMD_PTP_IN_READ_NIC_TIME_LEN);
1505 MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_READ_NIC_TIME_LEN); 1520 MCDI_DECLARE_BUF(outbuf, MC_CMD_PTP_OUT_READ_NIC_TIME_LEN);
1506 int rc; 1521 int rc;
@@ -1566,7 +1581,7 @@ static const struct efx_channel_type efx_ptp_channel_type = {
1566 .keep_eventq = false, 1581 .keep_eventq = false,
1567}; 1582};
1568 1583
1569void efx_ptp_probe(struct efx_nic *efx) 1584void efx_ptp_defer_probe_with_channel(struct efx_nic *efx)
1570{ 1585{
1571 /* Check whether PTP is implemented on this NIC. The DISABLE 1586 /* Check whether PTP is implemented on this NIC. The DISABLE
1572 * operation will succeed if and only if it is implemented. 1587 * operation will succeed if and only if it is implemented.
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index f2a7ad4c76aa..53b4ce67be0e 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -259,7 +259,7 @@ static int siena_probe_nic(struct efx_nic *efx)
259 goto fail5; 259 goto fail5;
260 260
261 efx_sriov_probe(efx); 261 efx_sriov_probe(efx);
262 efx_ptp_probe(efx); 262 efx_ptp_defer_probe_with_channel(efx);
263 263
264 return 0; 264 return 0;
265 265