Commit 9f361f7a authored by Alexander Viro's avatar Alexander Viro Committed by Stephen Hemminger

[wan hdlc] new private struct pointer in hdlc_device, and helpers for it

New field in hdlc_device: void *priv;
New helpers:
        struct net_device *alloc_hdlcdev(priv) allocates hdlc, sets ->priv and
returns pointer to hdlc->netdev
        free_hdlcdev(dev) takes such pointer and frees its hdlc.

wanxl switched to use of those; instead of embedding hdlc into card->ports[]
we allocate it separately right after card had been allocated and store pointer
to hdlc->netdev in card->ports[]->dev.  Freeing is done just before freeing
card.  Pointer back to card->ports[] is stored in hdlc->priv.  port_to_dev()
and dev_to_port() rewritten in the obvious way; by now the rest of driver
doesn't care whether hdlc is embedded or not - everything uses port_to_dev()
and dev_to_port().

That killed embedded hdlc replacing it with pointer to net_device.  Fairly
similar work will be done in the next few patches for other drivers.

Additionally, setup-after-register and free_irq()-before-unregister races
had been fixed.
parent 070c8cb2
......@@ -226,7 +226,15 @@ int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
}
}
struct net_device *alloc_hdlcdev(void *priv)
{
void *p = kmalloc(sizeof(hdlc_device), GFP_KERNEL);
if (p) {
memset(p, 0, sizeof(hdlc_device));
dev_to_hdlc(p)->priv = priv;
}
return p;
}
int register_hdlc_device(struct net_device *dev)
{
......@@ -279,6 +287,7 @@ EXPORT_SYMBOL(hdlc_open);
EXPORT_SYMBOL(hdlc_close);
EXPORT_SYMBOL(hdlc_set_carrier);
EXPORT_SYMBOL(hdlc_ioctl);
EXPORT_SYMBOL(alloc_hdlcdev);
EXPORT_SYMBOL(register_hdlc_device);
EXPORT_SYMBOL(unregister_hdlc_device);
......
......@@ -51,7 +51,7 @@ static const char* version = "wanXL serial card driver version: 0.47";
typedef struct {
hdlc_device hdlc; /* HDLC device struct - must be first */
struct net_device *dev;
struct card_t *card;
spinlock_t lock; /* for wanxl_xmit */
int node; /* physical port #0 - 3 */
......@@ -78,19 +78,20 @@ typedef struct card_t {
struct sk_buff *rx_skbs[RX_QUEUE_LENGTH];
card_status_t *status; /* shared between host and card */
dma_addr_t status_address;
port_t __ports[0];
}card_t;
static inline port_t* dev_to_port(struct net_device *dev)
{
return (port_t *)(dev_to_hdlc(dev));
return (port_t *)dev_to_hdlc(dev)->priv;
}
static inline struct net_device *port_to_dev(port_t* port)
{
return hdlc_to_dev(&port->hdlc);
return port->dev;
}
......@@ -527,16 +528,16 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev)
card_t *card = pci_get_drvdata(pdev);
int i;
/* unregister and free all host resources */
if (card->irq)
free_irq(card->irq, card);
for (i = 0; i < 4; i++)
if (card->ports[i]) {
struct net_device *dev = port_to_dev(card->ports[i]);
unregister_hdlc_device(dev);
}
/* unregister and free all host resources */
if (card->irq)
free_irq(card->irq, card);
wanxl_reset(card);
for (i = 0; i < RX_QUEUE_LENGTH; i++)
......@@ -554,6 +555,10 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev)
pci_free_consistent(pdev, sizeof(card_status_t),
card->status, card->status_address);
for (i = 0; i < card->n_ports; i++)
if (card->__ports[i].dev)
free_hdlcdev(card->__ports[i].dev);
pci_set_drvdata(pdev, NULL);
kfree(card);
pci_release_regions(pdev);
......@@ -622,6 +627,16 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
card->pdev = pdev;
card->n_ports = ports;
for (i = 0; i < ports; i++) {
card->__ports[i].dev = alloc_hdlcdev(&card->__ports[i]);
if (!card->__ports[i].dev) {
printk(KERN_ERR "wanXL %s: unable to allocate memory\n",
card_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENOMEM;
}
}
card->status = pci_alloc_consistent(pdev, sizeof(card_status_t),
&card->status_address);
if (card->status == NULL) {
......@@ -702,32 +717,6 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
return -ENODEV;
}
for (i = 0; i < ports; i++) {
port_t *port = (void *)card + sizeof(card_t) +
i * sizeof(port_t);
struct net_device *dev = port_to_dev(port);
hdlc_device *hdlc = dev_to_hdlc(dev);
spin_lock_init(&port->lock);
SET_MODULE_OWNER(dev);
dev->tx_queue_len = 50;
dev->do_ioctl = wanxl_ioctl;
dev->open = wanxl_open;
dev->stop = wanxl_close;
hdlc->attach = wanxl_attach;
hdlc->xmit = wanxl_xmit;
if (register_hdlc_device(dev)) {
printk(KERN_ERR "wanXL %s: unable to register hdlc"
" device\n", card_name(pdev));
wanxl_pci_remove_one(pdev);
return -ENOBUFS;
}
card->ports[i] = port;
dev->get_stats = wanxl_get_stats;
port->card = card;
port->node = i;
get_status(port)->clocking = CLOCK_EXT;
}
for (i = 0; i < RX_QUEUE_LENGTH; i++) {
struct sk_buff *skb = dev_alloc_skb(BUFFER_LENGTH);
card->rx_skbs[i] = skb;
......@@ -796,6 +785,32 @@ static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
}
card->irq = pdev->irq;
for (i = 0; i < ports; i++) {
port_t *port = &card->__ports[i];
struct net_device *dev = port_to_dev(port);
hdlc_device *hdlc = dev_to_hdlc(dev);
spin_lock_init(&port->lock);
SET_MODULE_OWNER(dev);
dev->tx_queue_len = 50;
dev->do_ioctl = wanxl_ioctl;
dev->open = wanxl_open;
dev->stop = wanxl_close;
hdlc->attach = wanxl_attach;
hdlc->xmit = wanxl_xmit;
card->ports[i] = port;
dev->get_stats = wanxl_get_stats;
port->card = card;
port->node = i;
get_status(port)->clocking = CLOCK_EXT;
if (register_hdlc_device(dev)) {
printk(KERN_ERR "wanXL %s: unable to register hdlc"
" device\n", card_name(pdev));
card->ports[i] = NULL;
wanxl_pci_remove_one(pdev);
return -ENOBUFS;
}
}
return 0;
}
......
......@@ -167,6 +167,7 @@ typedef struct hdlc_device_struct {
int new_mtu);
}ppp;
}state;
void *priv;
}hdlc_device;
......@@ -188,6 +189,12 @@ int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
int register_hdlc_device(struct net_device *dev);
void unregister_hdlc_device(struct net_device *dev);
struct net_device *alloc_hdlcdev(void *priv);
static inline void free_hdlcdev(struct net_device *dev)
{
kfree(dev);
}
static __inline__ struct net_device* hdlc_to_dev(hdlc_device *hdlc)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment