diff options
| -rw-r--r-- | drivers/net/ethernet/sfc/nic.h | 4 | ||||
| -rw-r--r-- | drivers/net/ethernet/sfc/ptp.c | 59 | ||||
| -rw-r--r-- | drivers/net/ethernet/sfc/siena.c | 2 |
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 | ||
| 556 | struct ethtool_ts_info; | 556 | struct ethtool_ts_info; |
| 557 | void efx_ptp_probe(struct efx_nic *efx); | 557 | int efx_ptp_probe(struct efx_nic *efx, struct efx_channel *channel); |
| 558 | void efx_ptp_defer_probe_with_channel(struct efx_nic *efx); | ||
| 559 | void efx_ptp_remove(struct efx_nic *efx); | ||
| 558 | int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr); | 560 | int efx_ptp_set_ts_config(struct efx_nic *efx, struct ifreq *ifr); |
| 559 | int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr); | 561 | int efx_ptp_get_ts_config(struct efx_nic *efx, struct ifreq *ifr); |
| 560 | void efx_ptp_get_ts_info(struct efx_nic *efx, struct ethtool_ts_info *ts_info); | 562 | void 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 | */ |
| 267 | struct efx_ptp_data { | 268 | struct 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 | * | 930 | int 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 | */ | ||
| 931 | static 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 | ||
| 1017 | static 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 | */ | ||
| 1019 | static 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 | |||
| 1029 | void 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 | ||
| 1051 | static void efx_ptp_remove_channel(struct efx_channel *channel) | ||
| 1052 | { | ||
| 1053 | efx_ptp_remove(channel->efx); | ||
| 1054 | } | ||
| 1055 | |||
| 1041 | static void efx_ptp_get_channel_name(struct efx_channel *channel, | 1056 | static 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 | ||
| 1569 | void efx_ptp_probe(struct efx_nic *efx) | 1584 | void 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 | ||
