Skip to content

Commit

Permalink
Merge tag 'arcnet-for-4.4-rc1' of git://git.pengutronix.de/git/mgr/linux
Browse files Browse the repository at this point in the history
Michael Grzeschik says:

====================
This series includes code simplifaction. The main changes are the correct
xceiver handling (enable/disable) of the com20020 cards. The driver now handles
link status change detection. The EAE PCI-ARCNET cards now make use of the
rotary encoded subdevice indexing and got support for led triggers on transmit
and reconnection events.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Oct 27, 2015
2 parents 4b3418f + 59fbcbc commit 61b9da9
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 18 deletions.
21 changes: 21 additions & 0 deletions drivers/net/arcnet/arcdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ struct Outgoing {
numsegs; /* number of segments */
};

#define ARCNET_LED_NAME_SZ (IFNAMSIZ + 6)

struct arcnet_local {
uint8_t config, /* current value of CONFIG register */
timeout, /* Extended timeout for COM20020 */
Expand All @@ -260,6 +262,13 @@ struct arcnet_local {
/* On preemtive and SMB a lock is needed */
spinlock_t lock;

struct led_trigger *tx_led_trig;
char tx_led_trig_name[ARCNET_LED_NAME_SZ];
struct led_trigger *recon_led_trig;
char recon_led_trig_name[ARCNET_LED_NAME_SZ];

struct timer_list timer;

/*
* Buffer management: an ARCnet card has 4 x 512-byte buffers, each of
* which can be used for either sending or receiving. The new dynamic
Expand Down Expand Up @@ -309,6 +318,8 @@ struct arcnet_local {
int (*reset)(struct net_device *dev, int really_reset);
void (*open)(struct net_device *dev);
void (*close)(struct net_device *dev);
void (*datatrigger) (struct net_device * dev, int enable);
void (*recontrigger) (struct net_device * dev, int enable);

void (*copy_to_card)(struct net_device *dev, int bufnum,
int offset, void *buf, int count);
Expand All @@ -319,6 +330,16 @@ struct arcnet_local {
void __iomem *mem_start; /* pointer to ioremap'ed MMIO */
};

enum arcnet_led_event {
ARCNET_LED_EVENT_RECON,
ARCNET_LED_EVENT_OPEN,
ARCNET_LED_EVENT_STOP,
ARCNET_LED_EVENT_TX,
};

void arcnet_led_event(struct net_device *netdev, enum arcnet_led_event event);
void devm_arcnet_led_init(struct net_device *netdev, int index, int subid);

#if ARCNET_DEBUG_MAX & D_SKB
void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc);
#else
Expand Down
107 changes: 99 additions & 8 deletions drivers/net/arcnet/arcnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
#include <linux/init.h>
#include <linux/jiffies.h>

#include <linux/leds.h>

#include "arcdevice.h"
#include "com9026.h"

Expand Down Expand Up @@ -189,6 +191,71 @@ static void arcnet_dump_packet(struct net_device *dev, int bufnum,

#endif

/* Trigger a LED event in response to a ARCNET device event */
void arcnet_led_event(struct net_device *dev, enum arcnet_led_event event)
{
struct arcnet_local *lp = netdev_priv(dev);
unsigned long led_delay = 350;
unsigned long tx_delay = 50;

switch (event) {
case ARCNET_LED_EVENT_RECON:
led_trigger_blink_oneshot(lp->recon_led_trig,
&led_delay, &led_delay, 0);
break;
case ARCNET_LED_EVENT_OPEN:
led_trigger_event(lp->tx_led_trig, LED_OFF);
led_trigger_event(lp->recon_led_trig, LED_OFF);
break;
case ARCNET_LED_EVENT_STOP:
led_trigger_event(lp->tx_led_trig, LED_OFF);
led_trigger_event(lp->recon_led_trig, LED_OFF);
break;
case ARCNET_LED_EVENT_TX:
led_trigger_blink_oneshot(lp->tx_led_trig,
&tx_delay, &tx_delay, 0);
break;
}
}
EXPORT_SYMBOL_GPL(arcnet_led_event);

static void arcnet_led_release(struct device *gendev, void *res)
{
struct arcnet_local *lp = netdev_priv(to_net_dev(gendev));

led_trigger_unregister_simple(lp->tx_led_trig);
led_trigger_unregister_simple(lp->recon_led_trig);
}

/* Register ARCNET LED triggers for a arcnet device
*
* This is normally called from a driver's probe function
*/
void devm_arcnet_led_init(struct net_device *netdev, int index, int subid)
{
struct arcnet_local *lp = netdev_priv(netdev);
void *res;

res = devres_alloc(arcnet_led_release, 0, GFP_KERNEL);
if (!res) {
netdev_err(netdev, "cannot register LED triggers\n");
return;
}

snprintf(lp->tx_led_trig_name, sizeof(lp->tx_led_trig_name),
"arc%d-%d-tx", index, subid);
snprintf(lp->recon_led_trig_name, sizeof(lp->recon_led_trig_name),
"arc%d-%d-recon", index, subid);

led_trigger_register_simple(lp->tx_led_trig_name,
&lp->tx_led_trig);
led_trigger_register_simple(lp->recon_led_trig_name,
&lp->recon_led_trig);

devres_add(&netdev->dev, res);
}
EXPORT_SYMBOL_GPL(devm_arcnet_led_init);

/* Unregister a protocol driver from the arc_proto_map. Protocol drivers
* are responsible for registering themselves, but the unregister routine
* is pretty generic so we'll do it here.
Expand Down Expand Up @@ -314,6 +381,16 @@ static void arcdev_setup(struct net_device *dev)
dev->flags = IFF_BROADCAST;
}

static void arcnet_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;

if (!netif_carrier_ok(dev)) {
netif_carrier_on(dev);
netdev_info(dev, "link up\n");
}
}

struct net_device *alloc_arcdev(const char *name)
{
struct net_device *dev;
Expand All @@ -325,6 +402,9 @@ struct net_device *alloc_arcdev(const char *name)
struct arcnet_local *lp = netdev_priv(dev);

spin_lock_init(&lp->lock);
init_timer(&lp->timer);
lp->timer.data = (unsigned long) dev;
lp->timer.function = arcnet_timer;
}

return dev;
Expand Down Expand Up @@ -423,8 +503,11 @@ int arcnet_open(struct net_device *dev)
lp->hw.intmask(dev, lp->intmask);
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);

netif_carrier_off(dev);
netif_start_queue(dev);
mod_timer(&lp->timer, jiffies + msecs_to_jiffies(1000));

arcnet_led_event(dev, ARCNET_LED_EVENT_OPEN);
return 0;

out_module_put:
Expand All @@ -438,7 +521,11 @@ int arcnet_close(struct net_device *dev)
{
struct arcnet_local *lp = netdev_priv(dev);

arcnet_led_event(dev, ARCNET_LED_EVENT_STOP);
del_timer_sync(&lp->timer);

netif_stop_queue(dev);
netif_carrier_off(dev);

/* flush TX and disable RX */
lp->hw.intmask(dev, 0);
Expand Down Expand Up @@ -515,7 +602,7 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
struct ArcProto *proto;
int txbuf;
unsigned long flags;
int freeskb, retval;
int retval;

arc_printk(D_DURING, dev,
"transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",
Expand Down Expand Up @@ -554,15 +641,13 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
* the package later - forget about it now
*/
dev->stats.tx_bytes += skb->len;
freeskb = 1;
dev_kfree_skb(skb);
} else {
/* do it the 'split' way */
lp->outgoing.proto = proto;
lp->outgoing.skb = skb;
lp->outgoing.pkt = pkt;

freeskb = 0;

if (proto->continue_tx &&
proto->continue_tx(dev, txbuf)) {
arc_printk(D_NORMAL, dev,
Expand All @@ -574,7 +659,6 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
lp->next_tx = txbuf;
} else {
retval = NETDEV_TX_BUSY;
freeskb = 0;
}

arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n",
Expand All @@ -588,10 +672,9 @@ netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
arc_printk(D_DEBUG, dev, "%s: %d: %s, status: %x\n",
__FILE__, __LINE__, __func__, lp->hw.status(dev));

spin_unlock_irqrestore(&lp->lock, flags);
if (freeskb)
dev_kfree_skb(skb);
arcnet_led_event(dev, ARCNET_LED_EVENT_TX);

spin_unlock_irqrestore(&lp->lock, flags);
return retval; /* no need to try again */
}
EXPORT_SYMBOL(arcnet_send_packet);
Expand Down Expand Up @@ -843,6 +926,13 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)

arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n",
status);
if (netif_carrier_ok(dev)) {
netif_carrier_off(dev);
netdev_info(dev, "link down\n");
}
mod_timer(&lp->timer, jiffies + msecs_to_jiffies(1000));

arcnet_led_event(dev, ARCNET_LED_EVENT_RECON);
/* MYRECON bit is at bit 7 of diagstatus */
if (diagstatus & 0x80)
arc_printk(D_RECON, dev, "Put out that recon myself\n");
Expand Down Expand Up @@ -893,6 +983,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
lp->num_recons = lp->network_down = 0;

arc_printk(D_DURING, dev, "not recon: clearing counters anyway.\n");
netif_carrier_on(dev);
}

if (didsomething)
Expand Down
Loading

0 comments on commit 61b9da9

Please sign in to comment.