Ejemplo n.º 1
0
static void c_can_handle_lost_msg_obj(struct net_device *dev,
					int iface, int objno)
{
	struct c_can_priv *priv = netdev_priv(dev);
	struct net_device_stats *stats = &dev->stats;
	struct sk_buff *skb;
	struct can_frame *frame;

	netdev_err(dev, "msg lost in buffer %d\n", objno);

	c_can_object_get(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST);

	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
			IF_MCONT_CLR_MSGLST);

	c_can_object_put(dev, 0, objno, IF_COMM_CONTROL);

	/* create an error msg */
	skb = alloc_can_err_skb(dev, &frame);
	if (unlikely(!skb))
		return;

	frame->can_id |= CAN_ERR_CRTL;
	frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
	stats->rx_errors++;
	stats->rx_over_errors++;

	netif_receive_skb(skb);
}
Ejemplo n.º 2
0
static void c_can_setup_receive_object(struct net_device *dev, int iface,
					int objno, unsigned int mask,
					unsigned int id, unsigned int mcont)
{
	struct c_can_priv *priv = netdev_priv(dev);

	priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface),
			IFX_WRITE_LOW_16BIT(mask));

	/* According to C_CAN documentation, the reserved bit
	 * in IFx_MASK2 register is fixed 1
	 */
	priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface),
			IFX_WRITE_HIGH_16BIT(mask) | BIT(13));

	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface),
			IFX_WRITE_LOW_16BIT(id));
	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface),
			(IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id)));

	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), mcont);
	c_can_object_put(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST);

	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
			c_can_read_reg32(priv, C_CAN_MSGVAL1_REG));
}
Ejemplo n.º 3
0
static int c_can_handle_lost_msg_obj(struct net_device *dev,
				     int iface, int objno, u32 ctrl)
{
	struct net_device_stats *stats = &dev->stats;
	struct c_can_priv *priv = netdev_priv(dev);
	struct can_frame *frame;
	struct sk_buff *skb;

	ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT);
	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
	c_can_object_put(dev, iface, objno, IF_COMM_CONTROL);

	stats->rx_errors++;
	stats->rx_over_errors++;

	/* create an error msg */
	skb = alloc_can_err_skb(dev, &frame);
	if (unlikely(!skb))
		return 0;

	frame->can_id |= CAN_ERR_CRTL;
	frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;

	netif_receive_skb(skb);
	return 1;
}
Ejemplo n.º 4
0
static void c_can_write_msg_object(struct net_device *dev,
			int iface, struct can_frame *frame, int objno)
{
	int i;
	u16 flags = 0;
	unsigned int id;
	struct c_can_priv *priv = netdev_priv(dev);

	if (!(frame->can_id & CAN_RTR_FLAG))
		flags |= IF_ARB_TRANSMIT;

	if (frame->can_id & CAN_EFF_FLAG) {
		id = frame->can_id & CAN_EFF_MASK;
		flags |= IF_ARB_MSGXTD;
	} else
		id = ((frame->can_id & CAN_SFF_MASK) << 18);

	flags |= IF_ARB_MSGVAL;

	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface),
				IFX_WRITE_LOW_16BIT(id));
	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), flags |
				IFX_WRITE_HIGH_16BIT(id));

	for (i = 0; i < frame->can_dlc; i += 2) {
		priv->write_reg(priv, C_CAN_IFACE(DATA1_REG, iface) + i / 2,
				frame->data[i] | (frame->data[i + 1] << 8));
	}

	/* enable interrupt for this message object */
	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
			IF_MCONT_TXIE | IF_MCONT_TXRQST | IF_MCONT_EOB |
			frame->can_dlc);
	c_can_object_put(dev, iface, objno, IF_COMM_ALL);
}
Ejemplo n.º 5
0
static void c_can_setup_receive_object(struct net_device *dev, int iface,
					int objno, unsigned int mask,
					unsigned int id, unsigned int mcont)
{
	struct c_can_priv *priv = netdev_priv(dev);

	priv->write_reg(priv, &priv->regs->ifregs[iface].mask1,
			IFX_WRITE_LOW_16BIT(mask));

	/* According to C_CAN documentation, the reserved bit
	 * in IFx_MASK2 register is fixed 1
	 */
	priv->write_reg(priv, &priv->regs->ifregs[iface].mask2,
			IFX_WRITE_HIGH_16BIT(mask) | BIT(13));

	priv->write_reg(priv, &priv->regs->ifregs[iface].arb1,
			IFX_WRITE_LOW_16BIT(id));
	priv->write_reg(priv, &priv->regs->ifregs[iface].arb2,
			(IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id)));

	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, mcont);
	c_can_object_put(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST);

	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
			c_can_read_reg32(priv, &priv->regs->msgval1));
}
Ejemplo n.º 6
0
/*
 * Note: According to documentation clearing TXIE while MSGVAL is set
 * is not allowed, but works nicely on C/DCAN. And that lowers the I/O
 * load significantly.
 */
static void c_can_inval_tx_object(struct net_device *dev, int iface, int obj)
{
	struct c_can_priv *priv = netdev_priv(dev);

	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0);
	c_can_object_put(dev, iface, obj, IF_COMM_INVAL);
}
Ejemplo n.º 7
0
static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
				    struct net_device *dev)
{
	struct can_frame *frame = (struct can_frame *)skb->data;
	struct c_can_priv *priv = netdev_priv(dev);
	u32 idx, obj;

	if (can_dropped_invalid_skb(dev, skb))
		return NETDEV_TX_OK;
	/*
	 * This is not a FIFO. C/D_CAN sends out the buffers
	 * prioritized. The lowest buffer number wins.
	 */
	idx = fls(atomic_read(&priv->tx_active));
	obj = idx + C_CAN_MSG_OBJ_TX_FIRST;

	/* If this is the last buffer, stop the xmit queue */
	if (idx == C_CAN_MSG_OBJ_TX_NUM - 1)
		netif_stop_queue(dev);
	/*
	 * Store the message in the interface so we can call
	 * can_put_echo_skb(). We must do this before we enable
	 * transmit as we might race against do_tx().
	 */
	c_can_setup_tx_object(dev, IF_TX, frame, idx);
	priv->dlc[idx] = frame->can_dlc;
	can_put_echo_skb(skb, dev, idx);

	/* Update the active bits */
	atomic_add((1 << idx), &priv->tx_active);
	/* Start transmission */
	c_can_object_put(dev, IF_TX, obj, IF_COMM_TX);

	return NETDEV_TX_OK;
}
Ejemplo n.º 8
0
static inline void c_can_activate_rx_msg_obj(struct net_device *dev,
						int iface, int ctrl_mask,
						int obj)
{
	struct c_can_priv *priv = netdev_priv(dev);

	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
			ctrl_mask & ~(IF_MCONT_MSGLST |
				IF_MCONT_INTPND | IF_MCONT_NEWDAT));
	c_can_object_put(dev, iface, obj, IF_COMM_CONTROL);
}
Ejemplo n.º 9
0
static inline void c_can_activate_rx_msg_obj(struct net_device *dev,
						int iface, int ctrl_mask,
						int obj)
{
	struct c_can_priv *priv = netdev_priv(dev);

	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl,
			ctrl_mask & ~(IF_MCONT_MSGLST |
				IF_MCONT_INTPND | IF_MCONT_NEWDAT));
	c_can_object_put(dev, iface, obj, IF_COMM_CONTROL);
}
Ejemplo n.º 10
0
static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno)
{
	struct c_can_priv *priv = netdev_priv(dev);

	priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), 0);
	priv->write_reg(priv, C_CAN_IFACE(ARB2_REG, iface), 0);
	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), 0);

	c_can_object_put(dev, iface, objno, IF_COMM_ARB | IF_COMM_CONTROL);

	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
			c_can_read_reg32(priv, C_CAN_MSGVAL1_REG));
}
Ejemplo n.º 11
0
static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno)
{
	struct c_can_priv *priv = netdev_priv(dev);

	priv->write_reg(priv, &priv->regs->ifregs[iface].arb1, 0);
	priv->write_reg(priv, &priv->regs->ifregs[iface].arb2, 0);
	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, 0);

	c_can_object_put(dev, iface, objno, IF_COMM_ARB | IF_COMM_CONTROL);

	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
			c_can_read_reg32(priv, &priv->regs->msgval1));
}
Ejemplo n.º 12
0
static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
						int iface,
						int ctrl_mask)
{
	int i;
	struct c_can_priv *priv = netdev_priv(dev);

	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) {
		priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
				ctrl_mask & ~(IF_MCONT_MSGLST |
					IF_MCONT_INTPND | IF_MCONT_NEWDAT));
		c_can_object_put(dev, iface, i, IF_COMM_CONTROL);
	}
}
Ejemplo n.º 13
0
static void c_can_setup_receive_object(struct net_device *dev, int iface,
				       u32 obj, u32 mask, u32 id, u32 mcont)
{
	struct c_can_priv *priv = netdev_priv(dev);

	mask |= BIT(29);
	priv->write_reg32(priv, C_CAN_IFACE(MASK1_REG, iface), mask);

	id |= IF_ARB_MSGVAL;
	priv->write_reg32(priv, C_CAN_IFACE(ARB1_REG, iface), id);

	priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), mcont);
	c_can_object_put(dev, iface, obj, IF_COMM_RCV_SETUP);
}
Ejemplo n.º 14
0
static void c_can_setup_receive_object(struct net_device *dev, int iface,
					int objno, unsigned int mask,
					unsigned int id, unsigned int mcont)
{
	struct c_can_priv *priv = netdev_priv(dev);

	priv->write_reg(priv, &priv->regs->ifregs[iface].mask1,
			IFX_WRITE_LOW_16BIT(mask));
	priv->write_reg(priv, &priv->regs->ifregs[iface].mask2,
			IFX_WRITE_HIGH_16BIT(mask));

	priv->write_reg(priv, &priv->regs->ifregs[iface].arb1,
			IFX_WRITE_LOW_16BIT(id));
	priv->write_reg(priv, &priv->regs->ifregs[iface].arb2,
			(IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id)));

	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, mcont);
	c_can_object_put(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST);

	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
			c_can_read_reg32(priv, &priv->regs->msgval1));
}