static int ines_hwtstamp()

in ptp_ines.c [331:397]


static int ines_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr)
{
	struct ines_port *port = container_of(mii_ts, struct ines_port, mii_ts);
	u32 cm_one_step = 0, port_conf, ts_stat_rx, ts_stat_tx;
	struct hwtstamp_config cfg;
	unsigned long flags;

	if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
		return -EFAULT;

	switch (cfg.tx_type) {
	case HWTSTAMP_TX_OFF:
		ts_stat_tx = 0;
		break;
	case HWTSTAMP_TX_ON:
		ts_stat_tx = TS_ENABLE;
		break;
	case HWTSTAMP_TX_ONESTEP_P2P:
		ts_stat_tx = TS_ENABLE;
		cm_one_step = CM_ONE_STEP;
		break;
	default:
		return -ERANGE;
	}

	switch (cfg.rx_filter) {
	case HWTSTAMP_FILTER_NONE:
		ts_stat_rx = 0;
		break;
	case HWTSTAMP_FILTER_ALL:
	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
		return -ERANGE;
	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
	case HWTSTAMP_FILTER_PTP_V2_EVENT:
	case HWTSTAMP_FILTER_PTP_V2_SYNC:
	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
		ts_stat_rx = TS_ENABLE;
		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
		break;
	default:
		return -ERANGE;
	}

	spin_lock_irqsave(&port->lock, flags);

	port_conf = ines_read32(port, port_conf);
	port_conf &= ~CM_ONE_STEP;
	port_conf |= cm_one_step;

	ines_write32(port, port_conf, port_conf);
	ines_write32(port, ts_stat_rx, ts_stat_rx);
	ines_write32(port, ts_stat_tx, ts_stat_tx);

	port->rxts_enabled = ts_stat_rx == TS_ENABLE;
	port->txts_enabled = ts_stat_tx == TS_ENABLE;

	spin_unlock_irqrestore(&port->lock, flags);

	return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
}