Skip to content

Commit

Permalink
Merge tag 'linux-can-fixes-for-4.0-20150322' of git://git.kernel.org/…
Browse files Browse the repository at this point in the history
…pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2015-03-22

this is a pull-request of 7 patches for net/master.

Ahmed S. Darwish fixes another two problems in the kvaser_usb driver. A patch
by Colin Ian King for the gs_usb driver adds a missing check for kzalloc
allocation failures. Two patches by Stephane Grosjean for the peak_usb driver
add missing support for ISO / non-ISO mode switching. Andri Yngvason
contributes a patch to fix the state handling in the flexcan driver. The last
patch by Andreas Werner for the flexcan driver add missing EPROBE_DEFER
handling for the transceiver regulator.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 24, 2015
2 parents 90a5a89 + 555828e commit 7ef70aa
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 64 deletions.
18 changes: 11 additions & 7 deletions drivers/net/can/flexcan.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,13 +592,12 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr)
rx_state = unlikely(reg_esr & FLEXCAN_ESR_RX_WRN) ?
CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
new_state = max(tx_state, rx_state);
} else if (unlikely(flt == FLEXCAN_ESR_FLT_CONF_PASSIVE)) {
} else {
__flexcan_get_berr_counter(dev, &bec);
new_state = CAN_STATE_ERROR_PASSIVE;
new_state = flt == FLEXCAN_ESR_FLT_CONF_PASSIVE ?
CAN_STATE_ERROR_PASSIVE : CAN_STATE_BUS_OFF;
rx_state = bec.rxerr >= bec.txerr ? new_state : 0;
tx_state = bec.rxerr <= bec.txerr ? new_state : 0;
} else {
new_state = CAN_STATE_BUS_OFF;
}

/* state hasn't changed */
Expand Down Expand Up @@ -1158,12 +1157,19 @@ static int flexcan_probe(struct platform_device *pdev)
const struct flexcan_devtype_data *devtype_data;
struct net_device *dev;
struct flexcan_priv *priv;
struct regulator *reg_xceiver;
struct resource *mem;
struct clk *clk_ipg = NULL, *clk_per = NULL;
void __iomem *base;
int err, irq;
u32 clock_freq = 0;

reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER)
return -EPROBE_DEFER;
else if (IS_ERR(reg_xceiver))
reg_xceiver = NULL;

if (pdev->dev.of_node)
of_property_read_u32(pdev->dev.of_node,
"clock-frequency", &clock_freq);
Expand Down Expand Up @@ -1224,9 +1230,7 @@ static int flexcan_probe(struct platform_device *pdev)
priv->pdata = dev_get_platdata(&pdev->dev);
priv->devtype_data = devtype_data;

priv->reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
if (IS_ERR(priv->reg_xceiver))
priv->reg_xceiver = NULL;
priv->reg_xceiver = reg_xceiver;

netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);

Expand Down
2 changes: 2 additions & 0 deletions drivers/net/can/usb/gs_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,8 @@ static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *
}

dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
init_usb_anchor(&dev->rx_submitted);

atomic_set(&dev->active_channels, 0);
Expand Down
69 changes: 42 additions & 27 deletions drivers/net/can/usb/kvaser_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include <linux/can/dev.h>
#include <linux/can/error.h>

#define MAX_TX_URBS 16
#define MAX_RX_URBS 4
#define START_TIMEOUT 1000 /* msecs */
#define STOP_TIMEOUT 1000 /* msecs */
Expand Down Expand Up @@ -443,6 +442,7 @@ struct kvaser_usb_error_summary {
};
};

/* Context for an outstanding, not yet ACKed, transmission */
struct kvaser_usb_tx_urb_context {
struct kvaser_usb_net_priv *priv;
u32 echo_index;
Expand All @@ -456,8 +456,13 @@ struct kvaser_usb {
struct usb_endpoint_descriptor *bulk_in, *bulk_out;
struct usb_anchor rx_submitted;

/* @max_tx_urbs: Firmware-reported maximum number of oustanding,
* not yet ACKed, transmissions on this device. This value is
* also used as a sentinel for marking free tx contexts.
*/
u32 fw_version;
unsigned int nchannels;
unsigned int max_tx_urbs;
enum kvaser_usb_family family;

bool rxinitdone;
Expand All @@ -467,19 +472,18 @@ struct kvaser_usb {

struct kvaser_usb_net_priv {
struct can_priv can;

spinlock_t tx_contexts_lock;
int active_tx_contexts;
struct kvaser_usb_tx_urb_context tx_contexts[MAX_TX_URBS];

struct usb_anchor tx_submitted;
struct completion start_comp, stop_comp;
struct can_berr_counter bec;

struct kvaser_usb *dev;
struct net_device *netdev;
int channel;

struct can_berr_counter bec;
struct completion start_comp, stop_comp;
struct usb_anchor tx_submitted;

spinlock_t tx_contexts_lock;
int active_tx_contexts;
struct kvaser_usb_tx_urb_context tx_contexts[];
};

static const struct usb_device_id kvaser_usb_table[] = {
Expand Down Expand Up @@ -592,8 +596,8 @@ static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,
* for further details.
*/
if (tmp->len == 0) {
pos = round_up(pos,
dev->bulk_in->wMaxPacketSize);
pos = round_up(pos, le16_to_cpu(dev->bulk_in->
wMaxPacketSize));
continue;
}

Expand Down Expand Up @@ -657,9 +661,13 @@ static int kvaser_usb_get_software_info(struct kvaser_usb *dev)
switch (dev->family) {
case KVASER_LEAF:
dev->fw_version = le32_to_cpu(msg.u.leaf.softinfo.fw_version);
dev->max_tx_urbs =
le16_to_cpu(msg.u.leaf.softinfo.max_outstanding_tx);
break;
case KVASER_USBCAN:
dev->fw_version = le32_to_cpu(msg.u.usbcan.softinfo.fw_version);
dev->max_tx_urbs =
le16_to_cpu(msg.u.usbcan.softinfo.max_outstanding_tx);
break;
}

Expand Down Expand Up @@ -715,7 +723,7 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,

stats = &priv->netdev->stats;

context = &priv->tx_contexts[tid % MAX_TX_URBS];
context = &priv->tx_contexts[tid % dev->max_tx_urbs];

/* Sometimes the state change doesn't come after a bus-off event */
if (priv->can.restart_ms &&
Expand Down Expand Up @@ -744,7 +752,7 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
spin_lock_irqsave(&priv->tx_contexts_lock, flags);

can_get_echo_skb(priv->netdev, context->echo_index);
context->echo_index = MAX_TX_URBS;
context->echo_index = dev->max_tx_urbs;
--priv->active_tx_contexts;
netif_wake_queue(priv->netdev);

Expand Down Expand Up @@ -1329,7 +1337,8 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb)
* number of events in case of a heavy rx load on the bus.
*/
if (msg->len == 0) {
pos = round_up(pos, dev->bulk_in->wMaxPacketSize);
pos = round_up(pos, le16_to_cpu(dev->bulk_in->
wMaxPacketSize));
continue;
}

Expand Down Expand Up @@ -1512,11 +1521,13 @@ static int kvaser_usb_open(struct net_device *netdev)

static void kvaser_usb_reset_tx_urb_contexts(struct kvaser_usb_net_priv *priv)
{
int i;
int i, max_tx_urbs;

max_tx_urbs = priv->dev->max_tx_urbs;

priv->active_tx_contexts = 0;
for (i = 0; i < MAX_TX_URBS; i++)
priv->tx_contexts[i].echo_index = MAX_TX_URBS;
for (i = 0; i < max_tx_urbs; i++)
priv->tx_contexts[i].echo_index = max_tx_urbs;
}

/* This method might sleep. Do not call it in the atomic context
Expand Down Expand Up @@ -1702,14 +1713,14 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
*msg_tx_can_flags |= MSG_FLAG_REMOTE_FRAME;

spin_lock_irqsave(&priv->tx_contexts_lock, flags);
for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) {
if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
for (i = 0; i < dev->max_tx_urbs; i++) {
if (priv->tx_contexts[i].echo_index == dev->max_tx_urbs) {
context = &priv->tx_contexts[i];

context->echo_index = i;
can_put_echo_skb(skb, netdev, context->echo_index);
++priv->active_tx_contexts;
if (priv->active_tx_contexts >= MAX_TX_URBS)
if (priv->active_tx_contexts >= dev->max_tx_urbs)
netif_stop_queue(netdev);

break;
Expand Down Expand Up @@ -1743,7 +1754,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
spin_lock_irqsave(&priv->tx_contexts_lock, flags);

can_free_echo_skb(netdev, context->echo_index);
context->echo_index = MAX_TX_URBS;
context->echo_index = dev->max_tx_urbs;
--priv->active_tx_contexts;
netif_wake_queue(netdev);

Expand Down Expand Up @@ -1881,7 +1892,9 @@ static int kvaser_usb_init_one(struct usb_interface *intf,
if (err)
return err;

netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
netdev = alloc_candev(sizeof(*priv) +
dev->max_tx_urbs * sizeof(*priv->tx_contexts),
dev->max_tx_urbs);
if (!netdev) {
dev_err(&intf->dev, "Cannot alloc candev\n");
return -ENOMEM;
Expand Down Expand Up @@ -2009,18 +2022,20 @@ static int kvaser_usb_probe(struct usb_interface *intf,
return err;
}

dev_dbg(&intf->dev, "Firmware version: %d.%d.%d\n",
((dev->fw_version >> 24) & 0xff),
((dev->fw_version >> 16) & 0xff),
(dev->fw_version & 0xffff));

dev_dbg(&intf->dev, "Max oustanding tx = %d URBs\n", dev->max_tx_urbs);

err = kvaser_usb_get_card_info(dev);
if (err) {
dev_err(&intf->dev,
"Cannot get card infos, error %d\n", err);
return err;
}

dev_dbg(&intf->dev, "Firmware version: %d.%d.%d\n",
((dev->fw_version >> 24) & 0xff),
((dev->fw_version >> 16) & 0xff),
(dev->fw_version & 0xffff));

for (i = 0; i < dev->nchannels; i++) {
err = kvaser_usb_init_one(intf, id, i);
if (err) {
Expand Down
15 changes: 8 additions & 7 deletions drivers/net/can/usb/peak_usb/pcan_ucan.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
#define PUCAN_CMD_FILTER_STD 0x008
#define PUCAN_CMD_TX_ABORT 0x009
#define PUCAN_CMD_WR_ERR_CNT 0x00a
#define PUCAN_CMD_RX_FRAME_ENABLE 0x00b
#define PUCAN_CMD_RX_FRAME_DISABLE 0x00c
#define PUCAN_CMD_SET_EN_OPTION 0x00b
#define PUCAN_CMD_CLR_DIS_OPTION 0x00c
#define PUCAN_CMD_END_OF_COLLECTION 0x3ff

/* uCAN received messages list */
Expand Down Expand Up @@ -101,14 +101,15 @@ struct __packed pucan_wr_err_cnt {
u16 unused;
};

/* uCAN RX_FRAME_ENABLE command fields */
#define PUCAN_FLTEXT_ERROR 0x0001
#define PUCAN_FLTEXT_BUSLOAD 0x0002
/* uCAN SET_EN/CLR_DIS _OPTION command fields */
#define PUCAN_OPTION_ERROR 0x0001
#define PUCAN_OPTION_BUSLOAD 0x0002
#define PUCAN_OPTION_CANDFDISO 0x0004

struct __packed pucan_filter_ext {
struct __packed pucan_options {
__le16 opcode_channel;

__le16 ext_mask;
__le16 options;
u32 unused;
};

Expand Down
Loading

0 comments on commit 7ef70aa

Please sign in to comment.