Commit 0dc80d7c authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: network driver.

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

s390 network driver changes:
 - ctc/lcs/qeth: prevent a ccw-device to be grouped multiple times.
 - icuv: clear correct field in iucv_register_program if no userid is specified.
 - lcs: fix online/offline cycle again.
 - lcs: fix ungrouping of lcs group device. The channels of the lcs card
   should be offline afterwards.
 - lcs: don't do netif_stop_queue if no tx buffer is available, just
   return -EBUSY and drop the packets.
parent ba0ce578
/* /*
* drivers/s390/cio/ccwgroup.c * drivers/s390/cio/ccwgroup.c
* bus driver for ccwgroup * bus driver for ccwgroup
* $Revision: 1.24 $ * $Revision: 1.25 $
* *
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation * IBM Corporation
...@@ -102,8 +102,10 @@ ccwgroup_release (struct device *dev) ...@@ -102,8 +102,10 @@ ccwgroup_release (struct device *dev)
gdev = to_ccwgroupdev(dev); gdev = to_ccwgroupdev(dev);
for (i = 0; i < gdev->count; i++) for (i = 0; i < gdev->count; i++) {
gdev->cdev[i]->dev.driver_data = NULL;
put_device(&gdev->cdev[i]->dev); put_device(&gdev->cdev[i]->dev);
}
kfree(gdev); kfree(gdev);
} }
...@@ -155,6 +157,7 @@ ccwgroup_create(struct device *root, ...@@ -155,6 +157,7 @@ ccwgroup_create(struct device *root,
struct ccwgroup_device *gdev; struct ccwgroup_device *gdev;
int i; int i;
int rc; int rc;
int del_drvdata;
if (argc > 256) /* disallow dumb users */ if (argc > 256) /* disallow dumb users */
return -EINVAL; return -EINVAL;
...@@ -166,6 +169,7 @@ ccwgroup_create(struct device *root, ...@@ -166,6 +169,7 @@ ccwgroup_create(struct device *root,
memset(gdev, 0, sizeof(*gdev) + argc*sizeof(gdev->cdev[0])); memset(gdev, 0, sizeof(*gdev) + argc*sizeof(gdev->cdev[0]));
atomic_set(&gdev->onoff, 0); atomic_set(&gdev->onoff, 0);
del_drvdata = 0;
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]); gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]);
...@@ -177,7 +181,15 @@ ccwgroup_create(struct device *root, ...@@ -177,7 +181,15 @@ ccwgroup_create(struct device *root,
rc = -EINVAL; rc = -EINVAL;
goto error; goto error;
} }
/* Don't allow a device to belong to more than one group. */
if (gdev->cdev[i]->dev.driver_data) {
rc = -EINVAL;
goto error;
}
} }
for (i = 0; i < argc; i++)
gdev->cdev[i]->dev.driver_data = gdev;
del_drvdata = 1;
*gdev = (struct ccwgroup_device) { *gdev = (struct ccwgroup_device) {
.creator_id = creator_id, .creator_id = creator_id,
...@@ -212,9 +224,11 @@ ccwgroup_create(struct device *root, ...@@ -212,9 +224,11 @@ ccwgroup_create(struct device *root,
device_unregister(&gdev->dev); device_unregister(&gdev->dev);
error: error:
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
if (gdev->cdev[i]) if (gdev->cdev[i]) {
put_device(&gdev->cdev[i]->dev); put_device(&gdev->cdev[i]->dev);
if (del_drvdata)
gdev->cdev[i]->dev.driver_data = NULL;
}
kfree(gdev); kfree(gdev);
return rc; return rc;
...@@ -399,40 +413,14 @@ static inline struct ccwgroup_device * ...@@ -399,40 +413,14 @@ static inline struct ccwgroup_device *
__ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev) __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
{ {
struct ccwgroup_device *gdev; struct ccwgroup_device *gdev;
struct list_head *entry;
struct device *dev;
int i, found;
/*
* Find groupdevice cdev belongs to.
* Unfortunately, we can't use bus_for_each_dev() because of the
* semaphore (and return value of fn() is int).
*/
if (!get_bus(&ccwgroup_bus_type))
return NULL;
gdev = NULL; if (cdev->dev.driver_data) {
down_read(&ccwgroup_bus_type.subsys.rwsem); gdev = (struct ccwgroup_device *)cdev->dev.driver_data;
if (get_device(&gdev->dev))
list_for_each(entry, &ccwgroup_bus_type.devices.list) { return gdev;
dev = get_device(container_of(entry, struct device, bus_list)); return NULL;
found = 0;
if (!dev)
continue;
gdev = to_ccwgroupdev(dev);
for (i = 0; i < gdev->count && (!found); i++) {
if (gdev->cdev[i] == cdev)
found = 1;
}
if (found)
break;
put_device(dev);
gdev = NULL;
} }
up_read(&ccwgroup_bus_type.subsys.rwsem); return NULL;
put_bus(&ccwgroup_bus_type);
return gdev;
} }
void void
......
/* /*
* $Id: ctcmain.c,v 1.57 2004/03/02 15:34:01 mschwide Exp $ * $Id: ctcmain.c,v 1.58 2004/03/24 10:51:56 ptiedem Exp $
* *
* CTC / ESCON network driver * CTC / ESCON network driver
* *
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* RELEASE-TAG: CTC/ESCON network driver $Revision: 1.57 $ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.58 $
* *
*/ */
...@@ -319,7 +319,7 @@ static void ...@@ -319,7 +319,7 @@ static void
print_banner(void) print_banner(void)
{ {
static int printed = 0; static int printed = 0;
char vbuf[] = "$Revision: 1.57 $"; char vbuf[] = "$Revision: 1.58 $";
char *version = vbuf; char *version = vbuf;
if (printed) if (printed)
...@@ -2067,7 +2067,8 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) ...@@ -2067,7 +2067,8 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
return; return;
} }
priv = cdev->dev.driver_data; priv = ((struct ccwgroup_device *)cdev->dev.driver_data)
->dev.driver_data;
/* Try to extract channel from driver data. */ /* Try to extract channel from driver data. */
if (priv->channel[READ]->cdev == cdev) if (priv->channel[READ]->cdev == cdev)
...@@ -2963,8 +2964,6 @@ ctc_probe_device(struct ccwgroup_device *cgdev) ...@@ -2963,8 +2964,6 @@ ctc_probe_device(struct ccwgroup_device *cgdev)
cgdev->cdev[0]->handler = ctc_irq_handler; cgdev->cdev[0]->handler = ctc_irq_handler;
cgdev->cdev[1]->handler = ctc_irq_handler; cgdev->cdev[1]->handler = ctc_irq_handler;
cgdev->dev.driver_data = priv; cgdev->dev.driver_data = priv;
cgdev->cdev[0]->dev.driver_data = priv;
cgdev->cdev[1]->dev.driver_data = priv;
return 0; return 0;
} }
......
/* /*
* $Id: iucv.c,v 1.26 2004/03/10 11:55:31 braunu Exp $ * $Id: iucv.c,v 1.27 2004/03/22 07:43:43 braunu Exp $
* *
* IUCV network driver * IUCV network driver
* *
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* RELEASE-TAG: IUCV lowlevel driver $Revision: 1.26 $ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.27 $
* *
*/ */
...@@ -351,7 +351,7 @@ do { \ ...@@ -351,7 +351,7 @@ do { \
static void static void
iucv_banner(void) iucv_banner(void)
{ {
char vbuf[] = "$Revision: 1.26 $"; char vbuf[] = "$Revision: 1.27 $";
char *version = vbuf; char *version = vbuf;
if ((version = strchr(version, ':'))) { if ((version = strchr(version, ':'))) {
...@@ -374,14 +374,14 @@ iucv_init(void) ...@@ -374,14 +374,14 @@ iucv_init(void)
{ {
int ret; int ret;
if (iucv_external_int_buffer)
return 0;
if (!MACHINE_IS_VM) { if (!MACHINE_IS_VM) {
printk(KERN_ERR "IUCV: IUCV connection needs VM as base\n"); printk(KERN_ERR "IUCV: IUCV connection needs VM as base\n");
return -EPROTONOSUPPORT; return -EPROTONOSUPPORT;
} }
if (iucv_external_int_buffer)
return 0;
ret = bus_register(&iucv_bus); ret = bus_register(&iucv_bus);
if (ret != 0) { if (ret != 0) {
printk(KERN_ERR "IUCV: failed to register bus.\n"); printk(KERN_ERR "IUCV: failed to register bus.\n");
...@@ -830,7 +830,7 @@ iucv_register_program (__u8 pgmname[16], ...@@ -830,7 +830,7 @@ iucv_register_program (__u8 pgmname[16],
memset (new_handler->id.mask, 0xFF, memset (new_handler->id.mask, 0xFF,
sizeof (new_handler->id.mask)); sizeof (new_handler->id.mask));
} }
memset (new_handler->id.mask, 0x00, memset (new_handler->id.userid, 0x00,
sizeof (new_handler->id.userid)); sizeof (new_handler->id.userid));
} }
/* fill in the rest of handler */ /* fill in the rest of handler */
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and * Frank Pavlic (pavlic@de.ibm.com) and
* Martin Schwidefsky <schwidefsky@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com>
* *
* $Revision: 1.68 $ $Date: 2004/03/02 15:34:01 $ * $Revision: 1.72 $ $Date: 2004/03/22 09:34:27 $
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -58,9 +58,10 @@ ...@@ -58,9 +58,10 @@
/** /**
* initialization string for output * initialization string for output
*/ */
#define VERSION_LCS_C "$Revision: 1.68 $" #define VERSION_LCS_C "$Revision: 1.72 $"
static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
static char debug_buffer[255];
/** /**
* Some prototypes. * Some prototypes.
...@@ -112,7 +113,7 @@ lcs_alloc_channel(struct lcs_channel *channel) ...@@ -112,7 +113,7 @@ lcs_alloc_channel(struct lcs_channel *channel)
{ {
int cnt; int cnt;
LCS_DBF_TEXT(3, setup, "ichalloc"); LCS_DBF_TEXT(2, setup, "ichalloc");
for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) { for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) {
/* alloc memory fo iobuffer */ /* alloc memory fo iobuffer */
channel->iob[cnt].data = (void *) channel->iob[cnt].data = (void *)
...@@ -124,7 +125,7 @@ lcs_alloc_channel(struct lcs_channel *channel) ...@@ -124,7 +125,7 @@ lcs_alloc_channel(struct lcs_channel *channel)
} }
if (cnt < LCS_NUM_BUFFS) { if (cnt < LCS_NUM_BUFFS) {
/* Not all io buffers could be allocated. */ /* Not all io buffers could be allocated. */
LCS_DBF_TEXT(3, setup, "echalloc"); LCS_DBF_TEXT(2, setup, "echalloc");
while (cnt-- > 0) while (cnt-- > 0)
kfree(channel->iob[cnt].data); kfree(channel->iob[cnt].data);
return -ENOMEM; return -ENOMEM;
...@@ -140,7 +141,7 @@ lcs_free_channel(struct lcs_channel *channel) ...@@ -140,7 +141,7 @@ lcs_free_channel(struct lcs_channel *channel)
{ {
int cnt; int cnt;
LCS_DBF_TEXT(3, setup, "ichfree"); LCS_DBF_TEXT(2, setup, "ichfree");
for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) { for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) {
if (channel->iob[cnt].data != NULL) if (channel->iob[cnt].data != NULL)
kfree(channel->iob[cnt].data); kfree(channel->iob[cnt].data);
...@@ -148,6 +149,30 @@ lcs_free_channel(struct lcs_channel *channel) ...@@ -148,6 +149,30 @@ lcs_free_channel(struct lcs_channel *channel)
} }
} }
/*
* Cleanup channel.
*/
static void
lcs_cleanup_channel(struct lcs_channel *channel)
{
LCS_DBF_TEXT(3, setup, "cleanch");
/* Kill write channel tasklets. */
tasklet_kill(&channel->irq_tasklet);
/* Free channel buffers. */
lcs_free_channel(channel);
}
/**
* LCS free memory for card and channels.
*/
static void
lcs_free_card(struct lcs_card *card)
{
LCS_DBF_TEXT(2, setup, "remcard");
LCS_DBF_HEX(2, setup, &card, sizeof(void*));
kfree(card);
}
/** /**
* LCS alloc memory for card and channels * LCS alloc memory for card and channels
*/ */
...@@ -155,25 +180,34 @@ static struct lcs_card * ...@@ -155,25 +180,34 @@ static struct lcs_card *
lcs_alloc_card(void) lcs_alloc_card(void)
{ {
struct lcs_card *card; struct lcs_card *card;
int rc;
LCS_DBF_TEXT(2, setup, "alloclcs");
LCS_DBF_TEXT(3, setup, "alloclcs");
card = kmalloc(sizeof(struct lcs_card), GFP_KERNEL | GFP_DMA); card = kmalloc(sizeof(struct lcs_card), GFP_KERNEL | GFP_DMA);
if (card == NULL) if (card == NULL)
return NULL; return NULL;
memset(card, 0, sizeof(struct lcs_card)); memset(card, 0, sizeof(struct lcs_card));
card->lan_type = LCS_FRAME_TYPE_AUTO; card->lan_type = LCS_FRAME_TYPE_AUTO;
card->lancmd_timeout = LCS_LANCMD_TIMEOUT_DEFAULT; card->lancmd_timeout = LCS_LANCMD_TIMEOUT_DEFAULT;
return card; /* Allocate io buffers for the read channel. */
} rc = lcs_alloc_channel(&card->read);
if (rc){
LCS_DBF_TEXT(2, setup, "iccwerr");
lcs_free_card(card);
return NULL;
}
/* Allocate io buffers for the write channel. */
rc = lcs_alloc_channel(&card->write);
if (rc) {
LCS_DBF_TEXT(2, setup, "iccwerr");
lcs_cleanup_channel(&card->read);
lcs_free_card(card);
return NULL;
}
/** LCS_DBF_HEX(2, setup, &card, sizeof(void*));
* LCS free memory for card and channels. return card;
*/
static void
lcs_free_card(struct lcs_card *card)
{
LCS_DBF_TEXT(2, setup, "remcard");
kfree(card);
} }
/* /*
...@@ -218,25 +252,17 @@ lcs_setup_read_ccws(struct lcs_card *card) ...@@ -218,25 +252,17 @@ lcs_setup_read_ccws(struct lcs_card *card)
card->read.buf_idx = 0; card->read.buf_idx = 0;
} }
static int static void
lcs_setup_read(struct lcs_card *card) lcs_setup_read(struct lcs_card *card)
{ {
int rc; LCS_DBF_TEXT(3, setup, "initread");
LCS_DBF_TEXT(3, setup, "readirq");
/* Allocate io buffers for the read channel. */
rc = lcs_alloc_channel(&card->read);
if (rc){
LCS_DBF_TEXT(3, setup, "iccwerr");
return rc;
}
lcs_setup_read_ccws(card); lcs_setup_read_ccws(card);
/* Initialize read channel tasklet. */ /* Initialize read channel tasklet. */
card->read.irq_tasklet.data = (unsigned long) &card->read; card->read.irq_tasklet.data = (unsigned long) &card->read;
card->read.irq_tasklet.func = lcs_tasklet; card->read.irq_tasklet.func = lcs_tasklet;
/* Initialize waitqueue. */ /* Initialize waitqueue. */
init_waitqueue_head(&card->read.wait_q); init_waitqueue_head(&card->read.wait_q);
return 0;
} }
/* /*
...@@ -247,7 +273,7 @@ lcs_setup_write_ccws(struct lcs_card *card) ...@@ -247,7 +273,7 @@ lcs_setup_write_ccws(struct lcs_card *card)
{ {
int cnt; int cnt;
LCS_DBF_TEXT(2, setup, "iwritccw"); LCS_DBF_TEXT(3, setup, "iwritccw");
/* Setup write ccws. */ /* Setup write ccws. */
memset(card->write.ccws, 0, sizeof(struct ccw1) * LCS_NUM_BUFFS + 1); memset(card->write.ccws, 0, sizeof(struct ccw1) * LCS_NUM_BUFFS + 1);
for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) { for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) {
...@@ -273,61 +299,32 @@ lcs_setup_write_ccws(struct lcs_card *card) ...@@ -273,61 +299,32 @@ lcs_setup_write_ccws(struct lcs_card *card)
card->write.buf_idx = 0; card->write.buf_idx = 0;
} }
static int static void
lcs_setup_write(struct lcs_card *card) lcs_setup_write(struct lcs_card *card)
{ {
int rc; LCS_DBF_TEXT(3, setup, "initwrit");
LCS_DBF_TEXT(3, setup, "writeirq");
/* Allocate io buffers for the write channel. */
rc = lcs_alloc_channel(&card->write);
if (rc) {
LCS_DBF_TEXT(3, setup, "iccwerr");
return rc;
}
lcs_setup_write_ccws(card); lcs_setup_write_ccws(card);
/* Initialize write channel tasklet. */ /* Initialize write channel tasklet. */
card->write.irq_tasklet.data = (unsigned long) &card->write; card->write.irq_tasklet.data = (unsigned long) &card->write;
card->write.irq_tasklet.func = lcs_tasklet; card->write.irq_tasklet.func = lcs_tasklet;
/* Initialize waitqueue. */ /* Initialize waitqueue. */
init_waitqueue_head(&card->write.wait_q); init_waitqueue_head(&card->write.wait_q);
return 0;
} }
/*
* Cleanup channel.
*/
static void
lcs_cleanup_channel(struct lcs_channel *channel)
{
LCS_DBF_TEXT(3, setup, "cleanch");
/* Kill write channel tasklets. */
tasklet_kill(&channel->irq_tasklet);
/* Free channel buffers. */
lcs_free_channel(channel);
}
/** /**
* Initialize channels,card and state machines. * Initialize channels,card and state machines.
*/ */
static int static void
lcs_setup_card(struct lcs_card *card) lcs_setup_card(struct lcs_card *card)
{ {
int rc; LCS_DBF_TEXT(2, setup, "initcard");
LCS_DBF_HEX(2, setup, &card, sizeof(void*));
LCS_DBF_TEXT(3, setup, "initcard");
rc = lcs_setup_read(card); lcs_setup_read(card);
if (rc) { lcs_setup_write(card);
PRINT_ERR("Could not initialize read channel\n");
return rc;
}
rc = lcs_setup_write(card);
if (rc) {
PRINT_ERR("Could not initialize write channel\n");
lcs_cleanup_channel(&card->read);
return rc;
}
/* Set cards initial state. */ /* Set cards initial state. */
card->state = DEV_STATE_DOWN; card->state = DEV_STATE_DOWN;
card->tx_buffer = NULL; card->tx_buffer = NULL;
...@@ -342,7 +339,6 @@ lcs_setup_card(struct lcs_card *card) ...@@ -342,7 +339,6 @@ lcs_setup_card(struct lcs_card *card)
INIT_LIST_HEAD(&card->ipm_list); INIT_LIST_HEAD(&card->ipm_list);
#endif #endif
INIT_LIST_HEAD(&card->lancmd_waiters); INIT_LIST_HEAD(&card->lancmd_waiters);
return 0;
} }
/** /**
...@@ -355,6 +351,7 @@ lcs_cleanup_card(struct lcs_card *card) ...@@ -355,6 +351,7 @@ lcs_cleanup_card(struct lcs_card *card)
struct lcs_ipm_list *ipm_list; struct lcs_ipm_list *ipm_list;
LCS_DBF_TEXT(3, setup, "cleancrd"); LCS_DBF_TEXT(3, setup, "cleancrd");
LCS_DBF_HEX(2,setup,&card,sizeof(void*));
#ifdef CONFIG_IP_MULTICAST #ifdef CONFIG_IP_MULTICAST
/* Free multicast list. */ /* Free multicast list. */
list_for_each_safe(l, n, &card->ipm_list) { list_for_each_safe(l, n, &card->ipm_list) {
...@@ -376,12 +373,10 @@ lcs_cleanup_card(struct lcs_card *card) ...@@ -376,12 +373,10 @@ lcs_cleanup_card(struct lcs_card *card)
static int static int
lcs_start_channel(struct lcs_channel *channel) lcs_start_channel(struct lcs_channel *channel)
{ {
char dbf_text[15];
unsigned long flags; unsigned long flags;
int rc; int rc;
sprintf(dbf_text,"ssch%s", channel->ccwdev->dev.bus_id); LCS_DBF_TEXT_(4,trace,"ssch%s", channel->ccwdev->dev.bus_id);
LCS_DBF_TEXT(4, trace, dbf_text);
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_start(channel->ccwdev, rc = ccw_device_start(channel->ccwdev,
channel->ccws + channel->io_idx, 0, 0, channel->ccws + channel->io_idx, 0, 0,
...@@ -390,37 +385,56 @@ lcs_start_channel(struct lcs_channel *channel) ...@@ -390,37 +385,56 @@ lcs_start_channel(struct lcs_channel *channel)
channel->state = CH_STATE_RUNNING; channel->state = CH_STATE_RUNNING;
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
if (rc) { if (rc) {
sprintf(dbf_text,"essc%s", channel->ccwdev->dev.bus_id); LCS_DBF_TEXT_(4,trace,"essh%s", channel->ccwdev->dev.bus_id);
LCS_DBF_TEXT(4, trace, dbf_text);
PRINT_ERR("Error in starting channel, rc=%d!\n", rc); PRINT_ERR("Error in starting channel, rc=%d!\n", rc);
} }
return rc; return rc;
} }
static int
lcs_clear_channel(struct lcs_channel *channel)
{
unsigned long flags;
int rc;
LCS_DBF_TEXT(4,trace,"clearch");
LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id);
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_clear(channel->ccwdev, (addr_t) channel);
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
if (rc) {
LCS_DBF_TEXT_(4,trace,"ecsc%s", channel->ccwdev->dev.bus_id);
return rc;
}
wait_event(channel->wait_q, (channel->state == CH_STATE_CLEARED));
channel->state = CH_STATE_STOPPED;
return rc;
}
/** /**
* Stop channel. * Stop channel.
*/ */
static int static int
lcs_stop_channel(struct lcs_channel *channel) lcs_stop_channel(struct lcs_channel *channel)
{ {
char dbf_text[15];
unsigned long flags; unsigned long flags;
int rc; int rc;
if (channel->state == CH_STATE_STOPPED) if (channel->state == CH_STATE_STOPPED)
return 0; return 0;
sprintf(dbf_text,"hsch%s", channel->ccwdev->dev.bus_id); LCS_DBF_TEXT(4,trace,"haltsch");
LCS_DBF_TEXT(4, trace, dbf_text); LCS_DBF_TEXT_(4,trace,"%s", channel->ccwdev->dev.bus_id);
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
rc = ccw_device_halt(channel->ccwdev, (addr_t) channel); rc = ccw_device_halt(channel->ccwdev, (addr_t) channel);
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
if (rc) { if (rc) {
sprintf(dbf_text,"ehsc%s", channel->ccwdev->dev.bus_id); LCS_DBF_TEXT_(4,trace,"ehsc%s", channel->ccwdev->dev.bus_id);
LCS_DBF_TEXT(4, trace, dbf_text);
return rc; return rc;
} }
/* Asynchronous halt initialted. Wait for its completion. */ /* Asynchronous halt initialted. Wait for its completion. */
wait_event(channel->wait_q, (channel->state == CH_STATE_HALTED)); wait_event(channel->wait_q, (channel->state == CH_STATE_HALTED));
lcs_clear_channel(channel);
return 0; return 0;
} }
...@@ -464,6 +478,7 @@ __lcs_get_buffer(struct lcs_channel *channel) ...@@ -464,6 +478,7 @@ __lcs_get_buffer(struct lcs_channel *channel)
{ {
int index; int index;
LCS_DBF_TEXT(5, trace, "_getbuff");
index = channel->io_idx; index = channel->io_idx;
do { do {
if (channel->iob[index].state == BUF_STATE_EMPTY) { if (channel->iob[index].state == BUF_STATE_EMPTY) {
...@@ -481,6 +496,7 @@ lcs_get_buffer(struct lcs_channel *channel) ...@@ -481,6 +496,7 @@ lcs_get_buffer(struct lcs_channel *channel)
struct lcs_buffer *buffer; struct lcs_buffer *buffer;
unsigned long flags; unsigned long flags;
LCS_DBF_TEXT(5, trace, "getbuff");
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
buffer = __lcs_get_buffer(channel); buffer = __lcs_get_buffer(channel);
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
...@@ -493,19 +509,16 @@ lcs_get_buffer(struct lcs_channel *channel) ...@@ -493,19 +509,16 @@ lcs_get_buffer(struct lcs_channel *channel)
static int static int
__lcs_resume_channel(struct lcs_channel *channel) __lcs_resume_channel(struct lcs_channel *channel)
{ {
char dbf_text[15];
int rc; int rc;
if (channel->state != CH_STATE_SUSPENDED) if (channel->state != CH_STATE_SUSPENDED)
return 0; return 0;
if (channel->ccws[channel->io_idx].flags & CCW_FLAG_SUSPEND) if (channel->ccws[channel->io_idx].flags & CCW_FLAG_SUSPEND)
return 0; return 0;
sprintf(dbf_text,"rsch%s", channel->ccwdev->dev.bus_id); LCS_DBF_TEXT_(5, trace, "rsch%s", channel->ccwdev->dev.bus_id);
LCS_DBF_TEXT(4, trace, dbf_text);
rc = ccw_device_resume(channel->ccwdev); rc = ccw_device_resume(channel->ccwdev);
if (rc) { if (rc) {
sprintf(dbf_text,"ersc%s", channel->ccwdev->dev.bus_id); LCS_DBF_TEXT_(4, trace, "ersc%s", channel->ccwdev->dev.bus_id);
LCS_DBF_TEXT(4, trace, dbf_text);
PRINT_ERR("Error in lcs_resume_channel: rc=%d\n",rc); PRINT_ERR("Error in lcs_resume_channel: rc=%d\n",rc);
} else } else
channel->state = CH_STATE_RUNNING; channel->state = CH_STATE_RUNNING;
...@@ -521,6 +534,7 @@ __lcs_ready_buffer_bits(struct lcs_channel *channel, int index) ...@@ -521,6 +534,7 @@ __lcs_ready_buffer_bits(struct lcs_channel *channel, int index)
{ {
int prev, next; int prev, next;
LCS_DBF_TEXT(5, trace, "rdybits");
prev = (index - 1) & (LCS_NUM_BUFFS - 1); prev = (index - 1) & (LCS_NUM_BUFFS - 1);
next = (index + 1) & (LCS_NUM_BUFFS - 1); next = (index + 1) & (LCS_NUM_BUFFS - 1);
/* Check if we may clear the suspend bit of this buffer. */ /* Check if we may clear the suspend bit of this buffer. */
...@@ -540,6 +554,7 @@ lcs_ready_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) ...@@ -540,6 +554,7 @@ lcs_ready_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer)
unsigned long flags; unsigned long flags;
int index, rc; int index, rc;
LCS_DBF_TEXT(5, trace, "rdybuff");
if (buffer->state != BUF_STATE_LOCKED && if (buffer->state != BUF_STATE_LOCKED &&
buffer->state != BUF_STATE_PROCESSED) buffer->state != BUF_STATE_PROCESSED)
BUG(); BUG();
...@@ -565,6 +580,7 @@ __lcs_processed_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) ...@@ -565,6 +580,7 @@ __lcs_processed_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer)
{ {
int index, prev, next; int index, prev, next;
LCS_DBF_TEXT(5, trace, "prcsbuff");
if (buffer->state != BUF_STATE_READY) if (buffer->state != BUF_STATE_READY)
BUG(); BUG();
buffer->state = BUF_STATE_PROCESSED; buffer->state = BUF_STATE_PROCESSED;
...@@ -597,6 +613,7 @@ lcs_release_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) ...@@ -597,6 +613,7 @@ lcs_release_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer)
{ {
unsigned long flags; unsigned long flags;
LCS_DBF_TEXT(5, trace, "relbuff");
if (buffer->state != BUF_STATE_LOCKED && if (buffer->state != BUF_STATE_LOCKED &&
buffer->state != BUF_STATE_PROCESSED) buffer->state != BUF_STATE_PROCESSED)
BUG(); BUG();
...@@ -614,6 +631,7 @@ lcs_get_lancmd(struct lcs_card *card, int count) ...@@ -614,6 +631,7 @@ lcs_get_lancmd(struct lcs_card *card, int count)
struct lcs_buffer *buffer; struct lcs_buffer *buffer;
struct lcs_cmd *cmd; struct lcs_cmd *cmd;
LCS_DBF_TEXT(4, trace, "getlncmd");
/* Get buffer and wait if none is available. */ /* Get buffer and wait if none is available. */
wait_event(card->write.wait_q, wait_event(card->write.wait_q,
((buffer = lcs_get_buffer(&card->write)) != NULL)); ((buffer = lcs_get_buffer(&card->write)) != NULL));
...@@ -637,6 +655,7 @@ lcs_notify_lancmd_waiters(struct lcs_card *card, struct lcs_cmd *cmd) ...@@ -637,6 +655,7 @@ lcs_notify_lancmd_waiters(struct lcs_card *card, struct lcs_cmd *cmd)
struct list_head *l, *n; struct list_head *l, *n;
struct lcs_reply *reply; struct lcs_reply *reply;
LCS_DBF_TEXT(4, trace, "notiwait");
spin_lock(&card->lock); spin_lock(&card->lock);
list_for_each_safe(l, n, &card->lancmd_waiters) { list_for_each_safe(l, n, &card->lancmd_waiters) {
reply = list_entry(l, struct lcs_reply, list); reply = list_entry(l, struct lcs_reply, list);
...@@ -661,6 +680,7 @@ lcs_lancmd_timeout(unsigned long data) ...@@ -661,6 +680,7 @@ lcs_lancmd_timeout(unsigned long data)
{ {
struct lcs_reply *reply; struct lcs_reply *reply;
LCS_DBF_TEXT(4, trace, "timeout");
reply = (struct lcs_reply *) data; reply = (struct lcs_reply *) data;
list_del(&reply->list); list_del(&reply->list);
reply->received = 1; reply->received = 1;
...@@ -676,8 +696,8 @@ lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer, ...@@ -676,8 +696,8 @@ lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer,
struct lcs_cmd *cmd; struct lcs_cmd *cmd;
struct timer_list timer; struct timer_list timer;
int rc; int rc;
char buf[16];
LCS_DBF_TEXT(4, trace, "sendcmd");
cmd = (struct lcs_cmd *) buffer->data; cmd = (struct lcs_cmd *) buffer->data;
cmd->sequence_no = ++card->sequence_no; cmd->sequence_no = ++card->sequence_no;
cmd->return_code = 0; cmd->return_code = 0;
...@@ -700,9 +720,7 @@ lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer, ...@@ -700,9 +720,7 @@ lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer,
add_timer(&timer); add_timer(&timer);
wait_event(reply.wait_q, reply.received); wait_event(reply.wait_q, reply.received);
del_timer(&timer); del_timer(&timer);
LCS_DBF_TEXT(5, trace, "sendcmd"); LCS_DBF_TEXT_(4, trace, "rc:%d",reply.rc);
sprintf(buf, "rc:%d", reply.rc);
LCS_DBF_TEXT(5, trace, buf);
return reply.rc ? -EIO : 0; return reply.rc ? -EIO : 0;
} }
...@@ -747,6 +765,7 @@ lcs_send_shutdown(struct lcs_card *card) ...@@ -747,6 +765,7 @@ lcs_send_shutdown(struct lcs_card *card)
static void static void
__lcs_lanstat_cb(struct lcs_card *card, struct lcs_cmd *cmd) __lcs_lanstat_cb(struct lcs_card *card, struct lcs_cmd *cmd)
{ {
LCS_DBF_TEXT(2, trace, "statcb");
memcpy(card->mac, cmd->cmd.lcs_lanstat_cmd.mac_addr, LCS_MAC_LENGTH); memcpy(card->mac, cmd->cmd.lcs_lanstat_cmd.mac_addr, LCS_MAC_LENGTH);
} }
...@@ -756,7 +775,7 @@ lcs_send_lanstat(struct lcs_card *card) ...@@ -756,7 +775,7 @@ lcs_send_lanstat(struct lcs_card *card)
struct lcs_buffer *buffer; struct lcs_buffer *buffer;
struct lcs_cmd *cmd; struct lcs_cmd *cmd;
LCS_DBF_TEXT(2, trace, "cmdstat"); LCS_DBF_TEXT(2,trace, "cmdstat");
buffer = lcs_get_lancmd(card, LCS_STD_CMD_SIZE); buffer = lcs_get_lancmd(card, LCS_STD_CMD_SIZE);
cmd = (struct lcs_cmd *) buffer->data; cmd = (struct lcs_cmd *) buffer->data;
/* Setup lanstat command. */ /* Setup lanstat command. */
...@@ -792,6 +811,7 @@ lcs_send_stoplan(struct lcs_card *card, __u8 initiator) ...@@ -792,6 +811,7 @@ lcs_send_stoplan(struct lcs_card *card, __u8 initiator)
static void static void
__lcs_send_startlan_cb(struct lcs_card *card, struct lcs_cmd *cmd) __lcs_send_startlan_cb(struct lcs_card *card, struct lcs_cmd *cmd)
{ {
LCS_DBF_TEXT(2, trace, "srtlancb");
card->lan_type = cmd->cmd.lcs_std_cmd.lan_type; card->lan_type = cmd->cmd.lcs_std_cmd.lan_type;
card->portno = cmd->cmd.lcs_std_cmd.portno; card->portno = cmd->cmd.lcs_std_cmd.portno;
} }
...@@ -833,6 +853,7 @@ lcs_send_setipm(struct lcs_card *card,struct lcs_ipm_list *ipm_list) ...@@ -833,6 +853,7 @@ lcs_send_setipm(struct lcs_card *card,struct lcs_ipm_list *ipm_list)
cmd->cmd.lcs_qipassist.num_ip_pairs = 1; cmd->cmd.lcs_qipassist.num_ip_pairs = 1;
memcpy(cmd->cmd.lcs_qipassist.lcs_ipass_ctlmsg.ip_mac_pair, memcpy(cmd->cmd.lcs_qipassist.lcs_ipass_ctlmsg.ip_mac_pair,
&ipm_list->ipm, sizeof (struct lcs_ip_mac_pair)); &ipm_list->ipm, sizeof (struct lcs_ip_mac_pair));
LCS_DBF_TEXT_(2, trace, "%x",ipm_list->ipm.ip_addr);
return lcs_send_lancmd(card, buffer, NULL); return lcs_send_lancmd(card, buffer, NULL);
} }
...@@ -856,6 +877,7 @@ lcs_send_delipm(struct lcs_card *card,struct lcs_ipm_list *ipm_list) ...@@ -856,6 +877,7 @@ lcs_send_delipm(struct lcs_card *card,struct lcs_ipm_list *ipm_list)
cmd->cmd.lcs_qipassist.num_ip_pairs = 1; cmd->cmd.lcs_qipassist.num_ip_pairs = 1;
memcpy(cmd->cmd.lcs_qipassist.lcs_ipass_ctlmsg.ip_mac_pair, memcpy(cmd->cmd.lcs_qipassist.lcs_ipass_ctlmsg.ip_mac_pair,
&ipm_list->ipm, sizeof (struct lcs_ip_mac_pair)); &ipm_list->ipm, sizeof (struct lcs_ip_mac_pair));
LCS_DBF_TEXT_(2, trace, "%x",ipm_list->ipm.ip_addr);
return lcs_send_lancmd(card, buffer, NULL); return lcs_send_lancmd(card, buffer, NULL);
} }
...@@ -865,6 +887,7 @@ lcs_send_delipm(struct lcs_card *card,struct lcs_ipm_list *ipm_list) ...@@ -865,6 +887,7 @@ lcs_send_delipm(struct lcs_card *card,struct lcs_ipm_list *ipm_list)
static void static void
__lcs_check_multicast_cb(struct lcs_card *card, struct lcs_cmd *cmd) __lcs_check_multicast_cb(struct lcs_card *card, struct lcs_cmd *cmd)
{ {
LCS_DBF_TEXT(2, trace, "chkmccb");
card->ip_assists_supported = card->ip_assists_supported =
cmd->cmd.lcs_qipassist.ip_assists_supported; cmd->cmd.lcs_qipassist.ip_assists_supported;
card->ip_assists_enabled = card->ip_assists_enabled =
...@@ -919,7 +942,7 @@ lcs_fix_multicast_list(void *data) ...@@ -919,7 +942,7 @@ lcs_fix_multicast_list(void *data)
card = (struct lcs_card *) data; card = (struct lcs_card *) data;
daemonize("fixipm"); daemonize("fixipm");
LCS_DBF_TEXT(5, trace, "fixipm"); LCS_DBF_TEXT(4,trace, "fixipm");
spin_lock(&card->lock); spin_lock(&card->lock);
list_for_each_safe(l, n, &card->ipm_list) { list_for_each_safe(l, n, &card->ipm_list) {
ipm = list_entry(l, struct lcs_ipm_list, list); ipm = list_entry(l, struct lcs_ipm_list, list);
...@@ -952,6 +975,7 @@ lcs_fix_multicast_list(void *data) ...@@ -952,6 +975,7 @@ lcs_fix_multicast_list(void *data)
static void static void
lcs_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev) lcs_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev)
{ {
LCS_DBF_TEXT(4,trace, "getmac");
if (dev->type == ARPHRD_IEEE802_TR) if (dev->type == ARPHRD_IEEE802_TR)
ip_tr_mc_map(ipm, mac); ip_tr_mc_map(ipm, mac);
else else
...@@ -971,7 +995,7 @@ lcs_set_multicast_list(struct net_device *dev) ...@@ -971,7 +995,7 @@ lcs_set_multicast_list(struct net_device *dev)
struct lcs_ipm_list *ipm, *tmp; struct lcs_ipm_list *ipm, *tmp;
struct lcs_card *card; struct lcs_card *card;
LCS_DBF_TEXT(5, trace, "setmulti"); LCS_DBF_TEXT(4, trace, "setmulti");
in4_dev = in_dev_get(dev); in4_dev = in_dev_get(dev);
if (in4_dev == NULL) if (in4_dev == NULL)
return; return;
...@@ -1033,21 +1057,18 @@ lcs_set_multicast_list(struct net_device *dev) ...@@ -1033,21 +1057,18 @@ lcs_set_multicast_list(struct net_device *dev)
static void static void
lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
{ {
char dbf_text[15];
struct lcs_card *card; struct lcs_card *card;
struct lcs_channel *channel; struct lcs_channel *channel;
int index; int index;
card = (struct lcs_card *)cdev->dev.driver_data; card = CARD_FROM_DEV(cdev);
if (card->read.ccwdev == cdev) if (card->read.ccwdev == cdev)
channel = &card->read; channel = &card->read;
else else
channel = &card->write; channel = &card->write;
sprintf(dbf_text, "Rint%s", cdev->dev.bus_id); LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id);
LCS_DBF_TEXT(5, trace, dbf_text); LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.cstat, irb->scsw.dstat);
sprintf(dbf_text, "%4x%4x", irb->scsw.cstat, irb->scsw.dstat);
LCS_DBF_TEXT(5, trace, dbf_text);
/* How far in the ccw chain have we processed? */ /* How far in the ccw chain have we processed? */
if ((channel->state != CH_STATE_INIT) && if ((channel->state != CH_STATE_INIT) &&
...@@ -1084,6 +1105,9 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) ...@@ -1084,6 +1105,9 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
channel->state = CH_STATE_HALTED; channel->state = CH_STATE_HALTED;
} }
if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
channel->state = CH_STATE_CLEARED;
}
/* Do the rest in the tasklet. */ /* Do the rest in the tasklet. */
tasklet_schedule(&channel->irq_tasklet); tasklet_schedule(&channel->irq_tasklet);
} }
...@@ -1094,7 +1118,6 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) ...@@ -1094,7 +1118,6 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
static void static void
lcs_tasklet(unsigned long data) lcs_tasklet(unsigned long data)
{ {
char dbf_text[15];
unsigned long flags; unsigned long flags;
struct lcs_channel *channel; struct lcs_channel *channel;
struct lcs_buffer *iob; struct lcs_buffer *iob;
...@@ -1102,8 +1125,7 @@ lcs_tasklet(unsigned long data) ...@@ -1102,8 +1125,7 @@ lcs_tasklet(unsigned long data)
int rc; int rc;
channel = (struct lcs_channel *) data; channel = (struct lcs_channel *) data;
sprintf(dbf_text, "tlet%s", channel->ccwdev->dev.bus_id); LCS_DBF_TEXT_(5, trace, "tlet%s",channel->ccwdev->dev.bus_id);
LCS_DBF_TEXT(5, trace, dbf_text);
/* Check for processed buffers. */ /* Check for processed buffers. */
iob = channel->iob; iob = channel->iob;
...@@ -1137,6 +1159,7 @@ lcs_tasklet(unsigned long data) ...@@ -1137,6 +1159,7 @@ lcs_tasklet(unsigned long data)
static void static void
__lcs_emit_txbuffer(struct lcs_card *card) __lcs_emit_txbuffer(struct lcs_card *card)
{ {
LCS_DBF_TEXT(5, trace, "emittx");
*(__u16 *)(card->tx_buffer->data + card->tx_buffer->count) = 0; *(__u16 *)(card->tx_buffer->data + card->tx_buffer->count) = 0;
card->tx_buffer->count += 2; card->tx_buffer->count += 2;
lcs_ready_buffer(&card->write, card->tx_buffer); lcs_ready_buffer(&card->write, card->tx_buffer);
...@@ -1152,6 +1175,7 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer) ...@@ -1152,6 +1175,7 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer)
{ {
struct lcs_card *card; struct lcs_card *card;
LCS_DBF_TEXT(5, trace, "txbuffcb");
/* Put buffer back to pool. */ /* Put buffer back to pool. */
lcs_release_buffer(channel, buffer); lcs_release_buffer(channel, buffer);
card = (struct lcs_card *) card = (struct lcs_card *)
...@@ -1176,6 +1200,7 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, ...@@ -1176,6 +1200,7 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
{ {
struct lcs_header *header; struct lcs_header *header;
LCS_DBF_TEXT(5, trace, "hardxmit");
if (skb == NULL) { if (skb == NULL) {
card->stats.tx_dropped++; card->stats.tx_dropped++;
card->stats.tx_errors++; card->stats.tx_errors++;
...@@ -1201,7 +1226,6 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb, ...@@ -1201,7 +1226,6 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
/* Get new tx buffer */ /* Get new tx buffer */
card->tx_buffer = lcs_get_buffer(&card->write); card->tx_buffer = lcs_get_buffer(&card->write);
if (card->tx_buffer == NULL) { if (card->tx_buffer == NULL) {
netif_stop_queue(dev);
card->stats.tx_dropped++; card->stats.tx_dropped++;
return -EBUSY; return -EBUSY;
} }
...@@ -1246,6 +1270,7 @@ lcs_startlan_auto(struct lcs_card *card) ...@@ -1246,6 +1270,7 @@ lcs_startlan_auto(struct lcs_card *card)
{ {
int rc; int rc;
LCS_DBF_TEXT(2, trace, "strtauto");
#ifdef CONFIG_NET_ETHERNET #ifdef CONFIG_NET_ETHERNET
card->lan_type = LCS_FRAME_TYPE_ENET; card->lan_type = LCS_FRAME_TYPE_ENET;
rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP); rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP);
...@@ -1307,7 +1332,7 @@ lcs_detect(struct lcs_card *card) ...@@ -1307,7 +1332,7 @@ lcs_detect(struct lcs_card *card)
{ {
int rc = 0; int rc = 0;
LCS_DBF_TEXT(3, setup," lcsdetct"); LCS_DBF_TEXT(2, setup, "lcsdetct");
/* start/reset card */ /* start/reset card */
if (card->dev) if (card->dev)
netif_stop_queue(card->dev); netif_stop_queue(card->dev);
...@@ -1340,7 +1365,7 @@ lcs_resetcard(struct lcs_card *card) ...@@ -1340,7 +1365,7 @@ lcs_resetcard(struct lcs_card *card)
{ {
int retries; int retries;
LCS_DBF_TEXT(4, trace, "rescard"); LCS_DBF_TEXT(2, trace, "rescard");
for (retries = 0; retries < 10; retries++) { for (retries = 0; retries < 10; retries++) {
if (lcs_detect(card) == 0) { if (lcs_detect(card) == 0) {
netif_wake_queue(card->dev); netif_wake_queue(card->dev);
...@@ -1364,13 +1389,16 @@ lcs_stopcard(struct lcs_card *card) ...@@ -1364,13 +1389,16 @@ lcs_stopcard(struct lcs_card *card)
int rc; int rc;
LCS_DBF_TEXT(3, setup, "stopcard"); LCS_DBF_TEXT(3, setup, "stopcard");
if (card->read.state != CH_STATE_STOPPED && if (card->read.state != CH_STATE_STOPPED &&
card->write.state != CH_STATE_STOPPED && card->write.state != CH_STATE_STOPPED &&
card->state == DEV_STATE_UP) card->state == DEV_STATE_UP) {
rc = lcs_send_stoplan(card,LCS_INITIATOR_TCPIP); rc = lcs_send_stoplan(card,LCS_INITIATOR_TCPIP);
rc = lcs_send_shutdown(card); rc = lcs_send_shutdown(card);
}
rc = lcs_stop_channels(card); rc = lcs_stop_channels(card);
card->state = DEV_STATE_DOWN; card->state = DEV_STATE_DOWN;
return rc; return rc;
} }
...@@ -1492,6 +1520,7 @@ lcs_start_kernel_thread(struct lcs_card *card) ...@@ -1492,6 +1520,7 @@ lcs_start_kernel_thread(struct lcs_card *card)
static void static void
lcs_get_control(struct lcs_card *card, struct lcs_cmd *cmd) lcs_get_control(struct lcs_card *card, struct lcs_cmd *cmd)
{ {
LCS_DBF_TEXT(5, trace, "getctrl");
if (cmd->initiator == LCS_INITIATOR_LGW) { if (cmd->initiator == LCS_INITIATOR_LGW) {
switch(cmd->cmd_code) { switch(cmd->cmd_code) {
case LCS_CMD_STARTUP: case LCS_CMD_STARTUP:
...@@ -1522,6 +1551,7 @@ lcs_get_skb(struct lcs_card *card, char *skb_data, unsigned int skb_len) ...@@ -1522,6 +1551,7 @@ lcs_get_skb(struct lcs_card *card, char *skb_data, unsigned int skb_len)
{ {
struct sk_buff *skb; struct sk_buff *skb;
LCS_DBF_TEXT(5, trace, "getskb");
if (card->dev == NULL || if (card->dev == NULL ||
card->state != DEV_STATE_UP) card->state != DEV_STATE_UP)
/* The card isn't up. Ignore the packet. */ /* The card isn't up. Ignore the packet. */
...@@ -1619,6 +1649,7 @@ lcs_stop_device(struct net_device *dev) ...@@ -1619,6 +1649,7 @@ lcs_stop_device(struct net_device *dev)
LCS_DBF_TEXT(2, trace, "stopdev"); LCS_DBF_TEXT(2, trace, "stopdev");
card = (struct lcs_card *) dev->priv; card = (struct lcs_card *) dev->priv;
netif_stop_queue(dev); netif_stop_queue(dev);
dev->flags &= ~IFF_UP;
rc = lcs_stopcard(card); rc = lcs_stopcard(card);
if (rc) if (rc)
PRINT_ERR("Try it again!\n "); PRINT_ERR("Try it again!\n ");
...@@ -1643,6 +1674,7 @@ lcs_open_device(struct net_device *dev) ...@@ -1643,6 +1674,7 @@ lcs_open_device(struct net_device *dev)
PRINT_ERR("LCS:Error in opening device!\n"); PRINT_ERR("LCS:Error in opening device!\n");
} else { } else {
dev->flags |= IFF_UP;
netif_wake_queue(dev); netif_wake_queue(dev);
card->state = DEV_STATE_UP; card->state = DEV_STATE_UP;
} }
...@@ -1757,7 +1789,7 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev) ...@@ -1757,7 +1789,7 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
if (!get_device(&ccwgdev->dev)) if (!get_device(&ccwgdev->dev))
return -ENODEV; return -ENODEV;
LCS_DBF_TEXT(3, setup, "add_dev"); LCS_DBF_TEXT(2, setup, "add_dev");
card = lcs_alloc_card(); card = lcs_alloc_card();
if (!card) { if (!card) {
PRINT_ERR("Allocation of lcs card failed\n"); PRINT_ERR("Allocation of lcs card failed\n");
...@@ -1772,46 +1804,62 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev) ...@@ -1772,46 +1804,62 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
return ret; return ret;
} }
ccwgdev->dev.driver_data = card; ccwgdev->dev.driver_data = card;
ccwgdev->cdev[0]->dev.driver_data = card;
ccwgdev->cdev[0]->handler = lcs_irq; ccwgdev->cdev[0]->handler = lcs_irq;
ccwgdev->cdev[1]->dev.driver_data = card;
ccwgdev->cdev[1]->handler = lcs_irq; ccwgdev->cdev[1]->handler = lcs_irq;
return 0; return 0;
} }
static int
lcs_register_netdev(struct ccwgroup_device *ccwgdev)
{
struct lcs_card *card;
LCS_DBF_TEXT(2, setup, "regnetdv");
card = (struct lcs_card *)ccwgdev->dev.driver_data;
if (card->dev->reg_state != NETREG_UNINITIALIZED)
return 0;
SET_NETDEV_DEV(card->dev, &ccwgdev->dev);
return register_netdev(card->dev);
}
/** /**
* lcs_new_device will be called by setting the group device online. * lcs_new_device will be called by setting the group device online.
*/ */
static int static int
lcs_new_device(struct ccwgroup_device *ccwgdev) lcs_new_device(struct ccwgroup_device *ccwgdev)
{ {
struct lcs_card *card; struct lcs_card *card;
struct net_device *dev; struct net_device *dev=NULL;
enum lcs_dev_states recover_state;
int rc; int rc;
card = (struct lcs_card *)ccwgdev->dev.driver_data; card = (struct lcs_card *)ccwgdev->dev.driver_data;
if (!card) if (!card)
return -ENODEV; return -ENODEV;
LCS_DBF_TEXT(2, setup, "newdev");
LCS_DBF_HEX(3, setup, &card, sizeof(void*));
card->read.ccwdev = ccwgdev->cdev[0]; card->read.ccwdev = ccwgdev->cdev[0];
card->write.ccwdev = ccwgdev->cdev[1]; card->write.ccwdev = ccwgdev->cdev[1];
recover_state = card->state;
ccw_device_set_online(card->read.ccwdev); ccw_device_set_online(card->read.ccwdev);
ccw_device_set_online(card->write.ccwdev); ccw_device_set_online(card->write.ccwdev);
LCS_DBF_TEXT(3, setup, "lcsnewdv"); LCS_DBF_TEXT(3, setup, "lcsnewdv");
rc = lcs_setup_card(card);
if (rc) {
LCS_DBF_TEXT(3, setup, "errinit");
PRINT_ERR("LCS card Initialization failed\n");
return rc;
}
lcs_setup_card(card);
rc = lcs_detect(card); rc = lcs_detect(card);
if (rc) { if (rc) {
lcs_stopcard(card); lcs_stopcard(card);
lcs_cleanup_card(card); lcs_cleanup_card(card);
return -ENODEV; goto out;
}
if (card->dev) {
LCS_DBF_TEXT(2, setup, "samedev");
LCS_DBF_HEX(3, setup, &card, sizeof(void*));
goto netdev_out;
} }
switch (card->lan_type) { switch (card->lan_type) {
#ifdef CONFIG_NET_ETHERNET #ifdef CONFIG_NET_ETHERNET
...@@ -1840,27 +1888,34 @@ lcs_new_device(struct ccwgroup_device *ccwgdev) ...@@ -1840,27 +1888,34 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
} }
if (!dev) if (!dev)
goto out; goto out;
memcpy(dev->dev_addr, card->mac, LCS_MAC_LENGTH);
card->dev = dev; card->dev = dev;
dev->priv = card; netdev_out:
dev->open = lcs_open_device; card->dev->priv = card;
dev->stop = lcs_stop_device; card->dev->open = lcs_open_device;
dev->hard_start_xmit = lcs_start_xmit; card->dev->stop = lcs_stop_device;
card->dev->hard_start_xmit = lcs_start_xmit;
card->dev->get_stats = lcs_getstats;
SET_MODULE_OWNER(dev);
if (lcs_register_netdev(ccwgdev) != 0)
goto out;
memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH);
#ifdef CONFIG_IP_MULTICAST #ifdef CONFIG_IP_MULTICAST
if (lcs_check_multicast_support(card)) if (lcs_check_multicast_support(card))
dev->set_multicast_list = lcs_set_multicast_list; card->dev->set_multicast_list = lcs_set_multicast_list;
#endif #endif
dev->get_stats = lcs_getstats; netif_stop_queue(card->dev);
SET_MODULE_OWNER(dev); if (recover_state == DEV_STATE_RECOVER) {
if (register_netdev(dev) != 0) card->dev->flags |= IFF_UP;
goto out; netif_wake_queue(card->dev);
/* Create symlinks. */ card->state = DEV_STATE_UP;
SET_NETDEV_DEV(dev, &ccwgdev->dev); } else
lcs_stopcard(card);
netif_stop_queue(dev);
lcs_stopcard(card);
return 0; return 0;
out: out:
ccw_device_set_offline(card->read.ccwdev);
ccw_device_set_offline(card->write.ccwdev);
lcs_cleanup_card(card); lcs_cleanup_card(card);
return -ENODEV; return -ENODEV;
} }
...@@ -1872,6 +1927,7 @@ static int ...@@ -1872,6 +1927,7 @@ static int
lcs_shutdown_device(struct ccwgroup_device *ccwgdev) lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
{ {
struct lcs_card *card; struct lcs_card *card;
enum lcs_dev_states recover_state;
int ret; int ret;
LCS_DBF_TEXT(3, setup, "shtdndev"); LCS_DBF_TEXT(3, setup, "shtdndev");
...@@ -1879,10 +1935,17 @@ lcs_shutdown_device(struct ccwgroup_device *ccwgdev) ...@@ -1879,10 +1935,17 @@ lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
if (!card) if (!card)
return -ENODEV; return -ENODEV;
LCS_DBF_HEX(3, setup, &card, sizeof(void*));
recover_state = card->state;
ret = lcs_stop_device(card->dev); ret = lcs_stop_device(card->dev);
ret = ccw_device_set_offline(card->read.ccwdev);
ret = ccw_device_set_offline(card->write.ccwdev);
if (recover_state == DEV_STATE_UP) {
card->state = DEV_STATE_RECOVER;
}
if (ret) if (ret)
return ret; return ret;
unregister_netdev(card->dev);
return 0; return 0;
} }
...@@ -1894,14 +1957,17 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev) ...@@ -1894,14 +1957,17 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev)
{ {
struct lcs_card *card; struct lcs_card *card;
LCS_DBF_TEXT(3, setup, "remdev");
card = (struct lcs_card *)ccwgdev->dev.driver_data; card = (struct lcs_card *)ccwgdev->dev.driver_data;
if (!card) if (!card)
return; return;
PRINT_INFO("Removing lcs group device ....\n");
LCS_DBF_TEXT(3, setup, "remdev");
LCS_DBF_HEX(3, setup, &card, sizeof(void*));
if (ccwgdev->state == CCWGROUP_ONLINE) { if (ccwgdev->state == CCWGROUP_ONLINE) {
lcs_stop_device(card->dev); /* Ignore rc. */ lcs_shutdown_device(ccwgdev);
unregister_netdev(card->dev);
} }
unregister_netdev(card->dev);
sysfs_remove_group(&ccwgdev->dev.kobj, &lcs_attr_group); sysfs_remove_group(&ccwgdev->dev.kobj, &lcs_attr_group);
lcs_cleanup_card(card); lcs_cleanup_card(card);
lcs_free_card(card); lcs_free_card(card);
......
...@@ -6,18 +6,35 @@ ...@@ -6,18 +6,35 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <asm/ccwdev.h> #include <asm/ccwdev.h>
#define VERSION_LCS_H "$Revision: 1.13 $" #define VERSION_LCS_H "$Revision: 1.15 $"
#define LCS_DBF_TEXT(level, name, text) \ #define LCS_DBF_TEXT(level, name, text) \
do { \ do { \
debug_text_event(lcs_dbf_##name, level, text); \ debug_text_event(lcs_dbf_##name, level, text); \
} while (0) } while (0)
#define LCS_DBF_HEX(level,name,addr,len) \
do { \
debug_event(lcs_dbf_##name,level,(void*)(addr),len); \
} while (0)
#define LCS_DBF_TEXT_(level,name,text...) \
do { \
sprintf(debug_buffer, text); \
debug_text_event(lcs_dbf_##name,level, debug_buffer);\
} while (0)
/** /**
* some more definitions for debug or output stuff * some more definitions for debug or output stuff
*/ */
#define PRINTK_HEADER " lcs: " #define PRINTK_HEADER " lcs: "
/**
* sysfs related stuff
*/
#define CARD_FROM_DEV(cdev) \
(struct lcs_card *) \
((struct ccwgroup_device *)cdev->dev.driver_data)->dev.driver_data;
/** /**
* CCW commands used in this driver * CCW commands used in this driver
*/ */
...@@ -123,6 +140,7 @@ enum lcs_channel_states { ...@@ -123,6 +140,7 @@ enum lcs_channel_states {
CH_STATE_STOPPED, CH_STATE_STOPPED,
CH_STATE_RUNNING, CH_STATE_RUNNING,
CH_STATE_SUSPENDED, CH_STATE_SUSPENDED,
CH_STATE_CLEARED,
}; };
/** /**
...@@ -131,6 +149,7 @@ enum lcs_channel_states { ...@@ -131,6 +149,7 @@ enum lcs_channel_states {
enum lcs_dev_states { enum lcs_dev_states {
DEV_STATE_DOWN, DEV_STATE_DOWN,
DEV_STATE_UP, DEV_STATE_UP,
DEV_STATE_RECOVER,
}; };
/** /**
......
/* /*
* $Id: netiucv.c,v 1.45 2004/03/15 08:48:48 braunu Exp $ * $Id: netiucv.c,v 1.47 2004/03/22 07:41:42 braunu Exp $
* *
* IUCV network driver * IUCV network driver
* *
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *
* RELEASE-TAG: IUCV network driver $Revision: 1.45 $ * RELEASE-TAG: IUCV network driver $Revision: 1.47 $
* *
*/ */
...@@ -764,7 +764,7 @@ conn_action_start(fsm_instance *fi, int event, void *arg) ...@@ -764,7 +764,7 @@ conn_action_start(fsm_instance *fi, int event, void *arg)
{ {
struct iucv_event *ev = (struct iucv_event *)arg; struct iucv_event *ev = (struct iucv_event *)arg;
struct iucv_connection *conn = ev->conn; struct iucv_connection *conn = ev->conn;
__u16 msglimit;
int rc; int rc;
pr_debug("%s() called\n", __FUNCTION__); pr_debug("%s() called\n", __FUNCTION__);
...@@ -793,10 +793,11 @@ conn_action_start(fsm_instance *fi, int event, void *arg) ...@@ -793,10 +793,11 @@ conn_action_start(fsm_instance *fi, int event, void *arg)
fsm_newstate(fi, CONN_STATE_SETUPWAIT); fsm_newstate(fi, CONN_STATE_SETUPWAIT);
rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic, rc = iucv_connect(&(conn->pathid), NETIUCV_QUEUELEN_DEFAULT, iucvMagic,
conn->userid, iucv_host, 0, NULL, NULL, conn->handle, conn->userid, iucv_host, 0, NULL, &msglimit, conn->handle,
conn); conn);
switch (rc) { switch (rc) {
case 0: case 0:
conn->netdev->tx_queue_len = msglimit;
return; return;
case 11: case 11:
printk(KERN_NOTICE printk(KERN_NOTICE
...@@ -1911,7 +1912,7 @@ static struct device_driver netiucv_driver = { ...@@ -1911,7 +1912,7 @@ static struct device_driver netiucv_driver = {
static void static void
netiucv_banner(void) netiucv_banner(void)
{ {
char vbuf[] = "$Revision: 1.45 $"; char vbuf[] = "$Revision: 1.47 $";
char *version = vbuf; char *version = vbuf;
if ((version = strchr(version, ':'))) { if ((version = strchr(version, ':'))) {
......
...@@ -755,7 +755,7 @@ qeth_get_cards_problem(struct ccw_device *cdev, unsigned char *buffer, ...@@ -755,7 +755,7 @@ qeth_get_cards_problem(struct ccw_device *cdev, unsigned char *buffer,
int problem = 0; int problem = 0;
struct qeth_card *card; struct qeth_card *card;
card = cdev->dev.driver_data; card = CARD_FROM_CDEV(cdev);
if (atomic_read(&card->shutdown_phase)) if (atomic_read(&card->shutdown_phase))
return 0; return 0;
...@@ -6105,7 +6105,7 @@ qeth_interrupt_handler_read(struct ccw_device *cdev, unsigned long intparm, ...@@ -6105,7 +6105,7 @@ qeth_interrupt_handler_read(struct ccw_device *cdev, unsigned long intparm,
sprintf(dbf_text, "%4x", rqparam); sprintf(dbf_text, "%4x", rqparam);
QETH_DBF_TEXT4(0, trace, dbf_text); QETH_DBF_TEXT4(0, trace, dbf_text);
card = cdev->dev.driver_data; card = CARD_FROM_CDEV(cdev);
if (!card) if (!card)
return; return;
...@@ -6231,7 +6231,7 @@ qeth_interrupt_handler_write(struct ccw_device *cdev, unsigned long intparm, ...@@ -6231,7 +6231,7 @@ qeth_interrupt_handler_write(struct ccw_device *cdev, unsigned long intparm,
sprintf(dbf_text, "%4x", rqparam); sprintf(dbf_text, "%4x", rqparam);
QETH_DBF_TEXT4(0, trace, dbf_text); QETH_DBF_TEXT4(0, trace, dbf_text);
card = cdev->dev.driver_data; card = CARD_FROM_CDEV(cdev);
if (!card) if (!card)
return; return;
...@@ -6343,7 +6343,7 @@ qeth_interrupt_handler_qdio(struct ccw_device *cdev, unsigned long intparm, ...@@ -6343,7 +6343,7 @@ qeth_interrupt_handler_qdio(struct ccw_device *cdev, unsigned long intparm,
sprintf(dbf_text, "%4x", rqparam); sprintf(dbf_text, "%4x", rqparam);
QETH_DBF_TEXT4(0, trace, dbf_text); QETH_DBF_TEXT4(0, trace, dbf_text);
card = cdev->dev.driver_data; card = CARD_FROM_CDEV(cdev);
if (!card) if (!card)
return; return;
...@@ -10620,13 +10620,10 @@ qeth_probe_device(struct ccwgroup_device *gdev) ...@@ -10620,13 +10620,10 @@ qeth_probe_device(struct ccwgroup_device *gdev)
card->gdev = gdev; card->gdev = gdev;
gdev->cdev[0]->handler = qeth_interrupt_handler_read; gdev->cdev[0]->handler = qeth_interrupt_handler_read;
gdev->cdev[0]->dev.driver_data = card;
gdev->cdev[1]->handler = qeth_interrupt_handler_write; gdev->cdev[1]->handler = qeth_interrupt_handler_write;
gdev->cdev[1]->dev.driver_data = card;
gdev->cdev[2]->handler = qeth_interrupt_handler_qdio; gdev->cdev[2]->handler = qeth_interrupt_handler_qdio;
gdev->cdev[2]->dev.driver_data = card;
ret = __qeth_create_attributes(&gdev->dev); ret = __qeth_create_attributes(&gdev->dev);
if (ret != 0) if (ret != 0)
......
...@@ -696,6 +696,8 @@ struct sparebufs { ...@@ -696,6 +696,8 @@ struct sparebufs {
#define CARD_RDEV_ID(card) card->gdev->cdev[0]->dev.bus_id #define CARD_RDEV_ID(card) card->gdev->cdev[0]->dev.bus_id
#define CARD_WDEV_ID(card) card->gdev->cdev[1]->dev.bus_id #define CARD_WDEV_ID(card) card->gdev->cdev[1]->dev.bus_id
#define CARD_DDEV_ID(card) card->gdev->cdev[2]->dev.bus_id #define CARD_DDEV_ID(card) card->gdev->cdev[2]->dev.bus_id
#define CARD_FROM_CDEV(cdev) (struct qeth_card *) \
((struct ccwgroup_device *) cdev->dev.driver_data)->dev.driver_data
#define SENSE_COMMAND_REJECT_BYTE 0 #define SENSE_COMMAND_REJECT_BYTE 0
#define SENSE_COMMAND_REJECT_FLAG 0x80 #define SENSE_COMMAND_REJECT_FLAG 0x80
......
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