Merge branch 'upstream-fixes' into upstream
Conflicts: drivers/s390/net/ctctty.c
This commit is contained in:
commit
983f27d37d
15 changed files with 632 additions and 624 deletions
|
@ -20,7 +20,7 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
@ -77,7 +77,7 @@ group_write(struct device_driver *drv, const char *buf, size_t count)
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (!(end = strchr(start, delim[i])))
|
if (!(end = strchr(start, delim[i])))
|
||||||
return count;
|
return -EINVAL;
|
||||||
len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start + 1);
|
len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start + 1);
|
||||||
strlcpy (bus_ids[i], start, len);
|
strlcpy (bus_ids[i], start, len);
|
||||||
argv[i] = bus_ids[i];
|
argv[i] = bus_ids[i];
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* #define DEBUG */
|
/* #define DEBUG */
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -297,7 +297,7 @@ MODULE_LICENSE("GPL");
|
||||||
/*
|
/*
|
||||||
* Debugging stuff
|
* Debugging stuff
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static int debuglevel = 0;
|
static int debuglevel = 0;
|
||||||
|
@ -344,7 +344,7 @@ do { \
|
||||||
/*
|
/*
|
||||||
* Internal functions
|
* Internal functions
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* print start banner
|
* print start banner
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -68,6 +68,7 @@ static void lcs_tasklet(unsigned long);
|
||||||
static void lcs_start_kernel_thread(struct lcs_card *card);
|
static void lcs_start_kernel_thread(struct lcs_card *card);
|
||||||
static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *);
|
static void lcs_get_frames_cb(struct lcs_channel *, struct lcs_buffer *);
|
||||||
static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *);
|
static int lcs_send_delipm(struct lcs_card *, struct lcs_ipm_list *);
|
||||||
|
static int lcs_recovery(void *ptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug Facility Stuff
|
* Debug Facility Stuff
|
||||||
|
@ -429,12 +430,6 @@ lcs_setup_card(struct lcs_card *card)
|
||||||
card->tx_buffer = NULL;
|
card->tx_buffer = NULL;
|
||||||
card->tx_emitted = 0;
|
card->tx_emitted = 0;
|
||||||
|
|
||||||
/* Initialize kernel thread task used for LGW commands. */
|
|
||||||
INIT_WORK(&card->kernel_thread_starter,
|
|
||||||
(void *)lcs_start_kernel_thread,card);
|
|
||||||
card->thread_start_mask = 0;
|
|
||||||
card->thread_allowed_mask = 0;
|
|
||||||
card->thread_running_mask = 0;
|
|
||||||
init_waitqueue_head(&card->wait_q);
|
init_waitqueue_head(&card->wait_q);
|
||||||
spin_lock_init(&card->lock);
|
spin_lock_init(&card->lock);
|
||||||
spin_lock_init(&card->ipm_lock);
|
spin_lock_init(&card->ipm_lock);
|
||||||
|
@ -675,8 +670,9 @@ lcs_ready_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer)
|
||||||
int index, rc;
|
int index, rc;
|
||||||
|
|
||||||
LCS_DBF_TEXT(5, trace, "rdybuff");
|
LCS_DBF_TEXT(5, trace, "rdybuff");
|
||||||
BUG_ON(buffer->state != BUF_STATE_LOCKED &&
|
if (buffer->state != BUF_STATE_LOCKED &&
|
||||||
buffer->state != BUF_STATE_PROCESSED);
|
buffer->state != BUF_STATE_PROCESSED)
|
||||||
|
BUG();
|
||||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
||||||
buffer->state = BUF_STATE_READY;
|
buffer->state = BUF_STATE_READY;
|
||||||
index = buffer - channel->iob;
|
index = buffer - channel->iob;
|
||||||
|
@ -700,7 +696,8 @@ __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");
|
LCS_DBF_TEXT(5, trace, "prcsbuff");
|
||||||
BUG_ON(buffer->state != BUF_STATE_READY);
|
if (buffer->state != BUF_STATE_READY)
|
||||||
|
BUG();
|
||||||
buffer->state = BUF_STATE_PROCESSED;
|
buffer->state = BUF_STATE_PROCESSED;
|
||||||
index = buffer - channel->iob;
|
index = buffer - channel->iob;
|
||||||
prev = (index - 1) & (LCS_NUM_BUFFS - 1);
|
prev = (index - 1) & (LCS_NUM_BUFFS - 1);
|
||||||
|
@ -732,8 +729,9 @@ lcs_release_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
LCS_DBF_TEXT(5, trace, "relbuff");
|
LCS_DBF_TEXT(5, trace, "relbuff");
|
||||||
BUG_ON(buffer->state != BUF_STATE_LOCKED &&
|
if (buffer->state != BUF_STATE_LOCKED &&
|
||||||
buffer->state != BUF_STATE_PROCESSED);
|
buffer->state != BUF_STATE_PROCESSED)
|
||||||
|
BUG();
|
||||||
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags);
|
||||||
buffer->state = BUF_STATE_EMPTY;
|
buffer->state = BUF_STATE_EMPTY;
|
||||||
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags);
|
||||||
|
@ -1147,8 +1145,6 @@ list_modified:
|
||||||
list_add_tail(&ipm->list, &card->ipm_list);
|
list_add_tail(&ipm->list, &card->ipm_list);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&card->ipm_lock, flags);
|
spin_unlock_irqrestore(&card->ipm_lock, flags);
|
||||||
if (card->state == DEV_STATE_UP)
|
|
||||||
netif_wake_queue(card->dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1231,17 +1227,17 @@ lcs_set_mc_addresses(struct lcs_card *card, struct in_device *in4_dev)
|
||||||
if (ipm != NULL)
|
if (ipm != NULL)
|
||||||
continue; /* Address already in list. */
|
continue; /* Address already in list. */
|
||||||
ipm = (struct lcs_ipm_list *)
|
ipm = (struct lcs_ipm_list *)
|
||||||
kmalloc(sizeof(struct lcs_ipm_list), GFP_ATOMIC);
|
kzalloc(sizeof(struct lcs_ipm_list), GFP_ATOMIC);
|
||||||
if (ipm == NULL) {
|
if (ipm == NULL) {
|
||||||
PRINT_INFO("Not enough memory to add "
|
PRINT_INFO("Not enough memory to add "
|
||||||
"new multicast entry!\n");
|
"new multicast entry!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
memset(ipm, 0, sizeof(struct lcs_ipm_list));
|
|
||||||
memcpy(&ipm->ipm.mac_addr, buf, LCS_MAC_LENGTH);
|
memcpy(&ipm->ipm.mac_addr, buf, LCS_MAC_LENGTH);
|
||||||
ipm->ipm.ip_addr = im4->multiaddr;
|
ipm->ipm.ip_addr = im4->multiaddr;
|
||||||
ipm->ipm_state = LCS_IPM_STATE_SET_REQUIRED;
|
ipm->ipm_state = LCS_IPM_STATE_SET_REQUIRED;
|
||||||
spin_lock_irqsave(&card->ipm_lock, flags);
|
spin_lock_irqsave(&card->ipm_lock, flags);
|
||||||
|
LCS_DBF_HEX(2,trace,&ipm->ipm.ip_addr,4);
|
||||||
list_add(&ipm->list, &card->ipm_list);
|
list_add(&ipm->list, &card->ipm_list);
|
||||||
spin_unlock_irqrestore(&card->ipm_lock, flags);
|
spin_unlock_irqrestore(&card->ipm_lock, flags);
|
||||||
}
|
}
|
||||||
|
@ -1269,7 +1265,15 @@ lcs_register_mc_addresses(void *data)
|
||||||
read_unlock(&in4_dev->mc_list_lock);
|
read_unlock(&in4_dev->mc_list_lock);
|
||||||
in_dev_put(in4_dev);
|
in_dev_put(in4_dev);
|
||||||
|
|
||||||
|
netif_carrier_off(card->dev);
|
||||||
|
netif_tx_disable(card->dev);
|
||||||
|
wait_event(card->write.wait_q,
|
||||||
|
(card->write.state != CH_STATE_RUNNING));
|
||||||
lcs_fix_multicast_list(card);
|
lcs_fix_multicast_list(card);
|
||||||
|
if (card->state == DEV_STATE_UP) {
|
||||||
|
netif_carrier_on(card->dev);
|
||||||
|
netif_wake_queue(card->dev);
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
lcs_clear_thread_running_bit(card, LCS_SET_MC_THREAD);
|
lcs_clear_thread_running_bit(card, LCS_SET_MC_THREAD);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1318,6 +1322,53 @@ lcs_check_irb_error(struct ccw_device *cdev, struct irb *irb)
|
||||||
return PTR_ERR(irb);
|
return PTR_ERR(irb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lcs_get_problem(struct ccw_device *cdev, struct irb *irb)
|
||||||
|
{
|
||||||
|
int dstat, cstat;
|
||||||
|
char *sense;
|
||||||
|
|
||||||
|
sense = (char *) irb->ecw;
|
||||||
|
cstat = irb->scsw.cstat;
|
||||||
|
dstat = irb->scsw.dstat;
|
||||||
|
|
||||||
|
if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
|
||||||
|
SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
|
||||||
|
SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) {
|
||||||
|
LCS_DBF_TEXT(2, trace, "CGENCHK");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (dstat & DEV_STAT_UNIT_CHECK) {
|
||||||
|
if (sense[LCS_SENSE_BYTE_1] &
|
||||||
|
LCS_SENSE_RESETTING_EVENT) {
|
||||||
|
LCS_DBF_TEXT(2, trace, "REVIND");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (sense[LCS_SENSE_BYTE_0] &
|
||||||
|
LCS_SENSE_CMD_REJECT) {
|
||||||
|
LCS_DBF_TEXT(2, trace, "CMDREJ");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ((!sense[LCS_SENSE_BYTE_0]) &&
|
||||||
|
(!sense[LCS_SENSE_BYTE_1]) &&
|
||||||
|
(!sense[LCS_SENSE_BYTE_2]) &&
|
||||||
|
(!sense[LCS_SENSE_BYTE_3])) {
|
||||||
|
LCS_DBF_TEXT(2, trace, "ZEROSEN");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LCS_DBF_TEXT(2, trace, "DGENCHK");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lcs_schedule_recovery(struct lcs_card *card)
|
||||||
|
{
|
||||||
|
LCS_DBF_TEXT(2, trace, "startrec");
|
||||||
|
if (!lcs_set_thread_start_bit(card, LCS_RECOVERY_THREAD))
|
||||||
|
schedule_work(&card->kernel_thread_starter);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IRQ Handler for LCS channels
|
* IRQ Handler for LCS channels
|
||||||
|
@ -1327,7 +1378,8 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||||
{
|
{
|
||||||
struct lcs_card *card;
|
struct lcs_card *card;
|
||||||
struct lcs_channel *channel;
|
struct lcs_channel *channel;
|
||||||
int index;
|
int rc, index;
|
||||||
|
int cstat, dstat;
|
||||||
|
|
||||||
if (lcs_check_irb_error(cdev, irb))
|
if (lcs_check_irb_error(cdev, irb))
|
||||||
return;
|
return;
|
||||||
|
@ -1338,10 +1390,23 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||||
else
|
else
|
||||||
channel = &card->write;
|
channel = &card->write;
|
||||||
|
|
||||||
|
cstat = irb->scsw.cstat;
|
||||||
|
dstat = irb->scsw.dstat;
|
||||||
LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id);
|
LCS_DBF_TEXT_(5, trace, "Rint%s",cdev->dev.bus_id);
|
||||||
LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.cstat, irb->scsw.dstat);
|
LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.cstat, irb->scsw.dstat);
|
||||||
LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.fctl, irb->scsw.actl);
|
LCS_DBF_TEXT_(5, trace, "%4x%4x",irb->scsw.fctl, irb->scsw.actl);
|
||||||
|
|
||||||
|
/* Check for channel and device errors presented */
|
||||||
|
rc = lcs_get_problem(cdev, irb);
|
||||||
|
if (rc || (dstat & DEV_STAT_UNIT_EXCEP)) {
|
||||||
|
PRINT_WARN("check on device %s, dstat=0x%X, cstat=0x%X \n",
|
||||||
|
cdev->dev.bus_id, dstat, cstat);
|
||||||
|
if (rc) {
|
||||||
|
lcs_schedule_recovery(card);
|
||||||
|
wake_up(&card->wait_q);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
/* 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) &&
|
||||||
(irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
|
(irb->scsw.fctl & SCSW_FCTL_START_FUNC)) {
|
||||||
|
@ -1367,7 +1432,6 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||||
else if (irb->scsw.actl & SCSW_ACTL_SUSPENDED)
|
else if (irb->scsw.actl & SCSW_ACTL_SUSPENDED)
|
||||||
/* CCW execution stopped on a suspend bit. */
|
/* CCW execution stopped on a suspend bit. */
|
||||||
channel->state = CH_STATE_SUSPENDED;
|
channel->state = CH_STATE_SUSPENDED;
|
||||||
|
|
||||||
if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
|
if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) {
|
||||||
if (irb->scsw.cc != 0) {
|
if (irb->scsw.cc != 0) {
|
||||||
ccw_device_halt(channel->ccwdev, (addr_t) channel);
|
ccw_device_halt(channel->ccwdev, (addr_t) channel);
|
||||||
|
@ -1376,7 +1440,6 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
|
||||||
/* The channel has been stopped by halt_IO. */
|
/* The channel has been stopped by halt_IO. */
|
||||||
channel->state = CH_STATE_HALTED;
|
channel->state = CH_STATE_HALTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
|
if (irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) {
|
||||||
channel->state = CH_STATE_CLEARED;
|
channel->state = CH_STATE_CLEARED;
|
||||||
}
|
}
|
||||||
|
@ -1452,7 +1515,7 @@ lcs_txbuffer_cb(struct lcs_channel *channel, struct lcs_buffer *buffer)
|
||||||
lcs_release_buffer(channel, buffer);
|
lcs_release_buffer(channel, buffer);
|
||||||
card = (struct lcs_card *)
|
card = (struct lcs_card *)
|
||||||
((char *) channel - offsetof(struct lcs_card, write));
|
((char *) channel - offsetof(struct lcs_card, write));
|
||||||
if (netif_queue_stopped(card->dev))
|
if (netif_queue_stopped(card->dev) && netif_carrier_ok(card->dev))
|
||||||
netif_wake_queue(card->dev);
|
netif_wake_queue(card->dev);
|
||||||
spin_lock(&card->lock);
|
spin_lock(&card->lock);
|
||||||
card->tx_emitted--;
|
card->tx_emitted--;
|
||||||
|
@ -1488,6 +1551,10 @@ __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
|
||||||
card->stats.tx_carrier_errors++;
|
card->stats.tx_carrier_errors++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (skb->protocol == htons(ETH_P_IPV6)) {
|
||||||
|
dev_kfree_skb(skb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
netif_stop_queue(card->dev);
|
netif_stop_queue(card->dev);
|
||||||
spin_lock(&card->lock);
|
spin_lock(&card->lock);
|
||||||
if (card->tx_buffer != NULL &&
|
if (card->tx_buffer != NULL &&
|
||||||
|
@ -1632,30 +1699,6 @@ lcs_detect(struct lcs_card *card)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* reset card
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
lcs_resetcard(struct lcs_card *card)
|
|
||||||
{
|
|
||||||
int retries;
|
|
||||||
|
|
||||||
LCS_DBF_TEXT(2, trace, "rescard");
|
|
||||||
for (retries = 0; retries < 10; retries++) {
|
|
||||||
if (lcs_detect(card) == 0) {
|
|
||||||
netif_wake_queue(card->dev);
|
|
||||||
card->state = DEV_STATE_UP;
|
|
||||||
PRINT_INFO("LCS device %s successfully restarted!\n",
|
|
||||||
card->dev->name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
msleep(3000);
|
|
||||||
}
|
|
||||||
PRINT_ERR("Error in Reseting LCS card!\n");
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LCS Stop card
|
* LCS Stop card
|
||||||
*/
|
*/
|
||||||
|
@ -1679,111 +1722,6 @@ lcs_stopcard(struct lcs_card *card)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* LGW initiated commands
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
lcs_lgw_startlan_thread(void *data)
|
|
||||||
{
|
|
||||||
struct lcs_card *card;
|
|
||||||
|
|
||||||
card = (struct lcs_card *) data;
|
|
||||||
daemonize("lgwstpln");
|
|
||||||
|
|
||||||
if (!lcs_do_run_thread(card, LCS_STARTLAN_THREAD))
|
|
||||||
return 0;
|
|
||||||
LCS_DBF_TEXT(4, trace, "lgwstpln");
|
|
||||||
if (card->dev)
|
|
||||||
netif_stop_queue(card->dev);
|
|
||||||
if (lcs_startlan(card) == 0) {
|
|
||||||
netif_wake_queue(card->dev);
|
|
||||||
card->state = DEV_STATE_UP;
|
|
||||||
PRINT_INFO("LCS Startlan for device %s succeeded!\n",
|
|
||||||
card->dev->name);
|
|
||||||
|
|
||||||
} else
|
|
||||||
PRINT_ERR("LCS Startlan for device %s failed!\n",
|
|
||||||
card->dev->name);
|
|
||||||
lcs_clear_thread_running_bit(card, LCS_STARTLAN_THREAD);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send startup command initiated by Lan Gateway
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
lcs_lgw_startup_thread(void *data)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
struct lcs_card *card;
|
|
||||||
|
|
||||||
card = (struct lcs_card *) data;
|
|
||||||
daemonize("lgwstaln");
|
|
||||||
|
|
||||||
if (!lcs_do_run_thread(card, LCS_STARTUP_THREAD))
|
|
||||||
return 0;
|
|
||||||
LCS_DBF_TEXT(4, trace, "lgwstaln");
|
|
||||||
if (card->dev)
|
|
||||||
netif_stop_queue(card->dev);
|
|
||||||
rc = lcs_send_startup(card, LCS_INITIATOR_LGW);
|
|
||||||
if (rc != 0) {
|
|
||||||
PRINT_ERR("Startup for LCS device %s initiated " \
|
|
||||||
"by LGW failed!\nReseting card ...\n",
|
|
||||||
card->dev->name);
|
|
||||||
/* do a card reset */
|
|
||||||
rc = lcs_resetcard(card);
|
|
||||||
if (rc == 0)
|
|
||||||
goto Done;
|
|
||||||
}
|
|
||||||
rc = lcs_startlan(card);
|
|
||||||
if (rc == 0) {
|
|
||||||
netif_wake_queue(card->dev);
|
|
||||||
card->state = DEV_STATE_UP;
|
|
||||||
}
|
|
||||||
Done:
|
|
||||||
if (rc == 0)
|
|
||||||
PRINT_INFO("LCS Startup for device %s succeeded!\n",
|
|
||||||
card->dev->name);
|
|
||||||
else
|
|
||||||
PRINT_ERR("LCS Startup for device %s failed!\n",
|
|
||||||
card->dev->name);
|
|
||||||
lcs_clear_thread_running_bit(card, LCS_STARTUP_THREAD);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* send stoplan command initiated by Lan Gateway
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
lcs_lgw_stoplan_thread(void *data)
|
|
||||||
{
|
|
||||||
struct lcs_card *card;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
card = (struct lcs_card *) data;
|
|
||||||
daemonize("lgwstop");
|
|
||||||
|
|
||||||
if (!lcs_do_run_thread(card, LCS_STOPLAN_THREAD))
|
|
||||||
return 0;
|
|
||||||
LCS_DBF_TEXT(4, trace, "lgwstop");
|
|
||||||
if (card->dev)
|
|
||||||
netif_stop_queue(card->dev);
|
|
||||||
if (lcs_send_stoplan(card, LCS_INITIATOR_LGW) == 0)
|
|
||||||
PRINT_INFO("Stoplan for %s initiated by LGW succeeded!\n",
|
|
||||||
card->dev->name);
|
|
||||||
else
|
|
||||||
PRINT_ERR("Stoplan %s initiated by LGW failed!\n",
|
|
||||||
card->dev->name);
|
|
||||||
/*Try to reset the card, stop it on failure */
|
|
||||||
rc = lcs_resetcard(card);
|
|
||||||
if (rc != 0)
|
|
||||||
rc = lcs_stopcard(card);
|
|
||||||
lcs_clear_thread_running_bit(card, LCS_STOPLAN_THREAD);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kernel Thread helper functions for LGW initiated commands
|
* Kernel Thread helper functions for LGW initiated commands
|
||||||
*/
|
*/
|
||||||
|
@ -1791,15 +1729,12 @@ static void
|
||||||
lcs_start_kernel_thread(struct lcs_card *card)
|
lcs_start_kernel_thread(struct lcs_card *card)
|
||||||
{
|
{
|
||||||
LCS_DBF_TEXT(5, trace, "krnthrd");
|
LCS_DBF_TEXT(5, trace, "krnthrd");
|
||||||
if (lcs_do_start_thread(card, LCS_STARTUP_THREAD))
|
if (lcs_do_start_thread(card, LCS_RECOVERY_THREAD))
|
||||||
kernel_thread(lcs_lgw_startup_thread, (void *) card, SIGCHLD);
|
kernel_thread(lcs_recovery, (void *) card, SIGCHLD);
|
||||||
if (lcs_do_start_thread(card, LCS_STARTLAN_THREAD))
|
|
||||||
kernel_thread(lcs_lgw_startlan_thread, (void *) card, SIGCHLD);
|
|
||||||
if (lcs_do_start_thread(card, LCS_STOPLAN_THREAD))
|
|
||||||
kernel_thread(lcs_lgw_stoplan_thread, (void *) card, SIGCHLD);
|
|
||||||
#ifdef CONFIG_IP_MULTICAST
|
#ifdef CONFIG_IP_MULTICAST
|
||||||
if (lcs_do_start_thread(card, LCS_SET_MC_THREAD))
|
if (lcs_do_start_thread(card, LCS_SET_MC_THREAD))
|
||||||
kernel_thread(lcs_register_mc_addresses, (void *) card, SIGCHLD);
|
kernel_thread(lcs_register_mc_addresses,
|
||||||
|
(void *) card, SIGCHLD);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1813,19 +1748,14 @@ lcs_get_control(struct lcs_card *card, struct lcs_cmd *cmd)
|
||||||
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:
|
||||||
if (!lcs_set_thread_start_bit(card,
|
|
||||||
LCS_STARTUP_THREAD))
|
|
||||||
schedule_work(&card->kernel_thread_starter);
|
|
||||||
break;
|
|
||||||
case LCS_CMD_STARTLAN:
|
case LCS_CMD_STARTLAN:
|
||||||
if (!lcs_set_thread_start_bit(card,
|
lcs_schedule_recovery(card);
|
||||||
LCS_STARTLAN_THREAD))
|
|
||||||
schedule_work(&card->kernel_thread_starter);
|
|
||||||
break;
|
break;
|
||||||
case LCS_CMD_STOPLAN:
|
case LCS_CMD_STOPLAN:
|
||||||
if (!lcs_set_thread_start_bit(card,
|
PRINT_WARN("Stoplan for %s initiated by LGW.\n",
|
||||||
LCS_STOPLAN_THREAD))
|
card->dev->name);
|
||||||
schedule_work(&card->kernel_thread_starter);
|
if (card->dev)
|
||||||
|
netif_carrier_off(card->dev);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PRINT_INFO("UNRECOGNIZED LGW COMMAND\n");
|
PRINT_INFO("UNRECOGNIZED LGW COMMAND\n");
|
||||||
|
@ -1941,8 +1871,11 @@ 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_carrier_off(dev);
|
||||||
|
netif_tx_disable(dev);
|
||||||
dev->flags &= ~IFF_UP;
|
dev->flags &= ~IFF_UP;
|
||||||
|
wait_event(card->write.wait_q,
|
||||||
|
(card->write.state != CH_STATE_RUNNING));
|
||||||
rc = lcs_stopcard(card);
|
rc = lcs_stopcard(card);
|
||||||
if (rc)
|
if (rc)
|
||||||
PRINT_ERR("Try it again!\n ");
|
PRINT_ERR("Try it again!\n ");
|
||||||
|
@ -1968,6 +1901,7 @@ lcs_open_device(struct net_device *dev)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dev->flags |= IFF_UP;
|
dev->flags |= IFF_UP;
|
||||||
|
netif_carrier_on(dev);
|
||||||
netif_wake_queue(dev);
|
netif_wake_queue(dev);
|
||||||
card->state = DEV_STATE_UP;
|
card->state = DEV_STATE_UP;
|
||||||
}
|
}
|
||||||
|
@ -2059,10 +1993,31 @@ lcs_timeout_store (struct device *dev, struct device_attribute *attr, const char
|
||||||
|
|
||||||
DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store);
|
DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store);
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
lcs_dev_recover_store(struct device *dev, struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct lcs_card *card = dev->driver_data;
|
||||||
|
char *tmp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!card)
|
||||||
|
return -EINVAL;
|
||||||
|
if (card->state != DEV_STATE_UP)
|
||||||
|
return -EPERM;
|
||||||
|
i = simple_strtoul(buf, &tmp, 16);
|
||||||
|
if (i == 1)
|
||||||
|
lcs_schedule_recovery(card);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(recover, 0200, NULL, lcs_dev_recover_store);
|
||||||
|
|
||||||
static struct attribute * lcs_attrs[] = {
|
static struct attribute * lcs_attrs[] = {
|
||||||
&dev_attr_portno.attr,
|
&dev_attr_portno.attr,
|
||||||
&dev_attr_type.attr,
|
&dev_attr_type.attr,
|
||||||
&dev_attr_lancmd_timeout.attr,
|
&dev_attr_lancmd_timeout.attr,
|
||||||
|
&dev_attr_recover.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2099,6 +2054,12 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev)
|
||||||
ccwgdev->dev.driver_data = card;
|
ccwgdev->dev.driver_data = card;
|
||||||
ccwgdev->cdev[0]->handler = lcs_irq;
|
ccwgdev->cdev[0]->handler = lcs_irq;
|
||||||
ccwgdev->cdev[1]->handler = lcs_irq;
|
ccwgdev->cdev[1]->handler = lcs_irq;
|
||||||
|
card->gdev = ccwgdev;
|
||||||
|
INIT_WORK(&card->kernel_thread_starter,
|
||||||
|
(void *) lcs_start_kernel_thread, card);
|
||||||
|
card->thread_start_mask = 0;
|
||||||
|
card->thread_allowed_mask = 0;
|
||||||
|
card->thread_running_mask = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2200,6 +2161,7 @@ netdev_out:
|
||||||
if (recover_state == DEV_STATE_RECOVER) {
|
if (recover_state == DEV_STATE_RECOVER) {
|
||||||
lcs_set_multicast_list(card->dev);
|
lcs_set_multicast_list(card->dev);
|
||||||
card->dev->flags |= IFF_UP;
|
card->dev->flags |= IFF_UP;
|
||||||
|
netif_carrier_on(card->dev);
|
||||||
netif_wake_queue(card->dev);
|
netif_wake_queue(card->dev);
|
||||||
card->state = DEV_STATE_UP;
|
card->state = DEV_STATE_UP;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2229,7 +2191,7 @@ out:
|
||||||
* lcs_shutdown_device, called when setting the group device offline.
|
* lcs_shutdown_device, called when setting the group device offline.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
|
__lcs_shutdown_device(struct ccwgroup_device *ccwgdev, int recovery_mode)
|
||||||
{
|
{
|
||||||
struct lcs_card *card;
|
struct lcs_card *card;
|
||||||
enum lcs_dev_states recover_state;
|
enum lcs_dev_states recover_state;
|
||||||
|
@ -2239,9 +2201,11 @@ lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
|
||||||
card = (struct lcs_card *)ccwgdev->dev.driver_data;
|
card = (struct lcs_card *)ccwgdev->dev.driver_data;
|
||||||
if (!card)
|
if (!card)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
if (recovery_mode == 0) {
|
||||||
lcs_set_allowed_threads(card, 0);
|
lcs_set_allowed_threads(card, 0);
|
||||||
if (lcs_wait_for_threads(card, LCS_SET_MC_THREAD))
|
if (lcs_wait_for_threads(card, LCS_SET_MC_THREAD))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
|
}
|
||||||
LCS_DBF_HEX(3, setup, &card, sizeof(void*));
|
LCS_DBF_HEX(3, setup, &card, sizeof(void*));
|
||||||
recover_state = card->state;
|
recover_state = card->state;
|
||||||
|
|
||||||
|
@ -2256,6 +2220,43 @@ lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lcs_shutdown_device(struct ccwgroup_device *ccwgdev)
|
||||||
|
{
|
||||||
|
return __lcs_shutdown_device(ccwgdev, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drive lcs recovery after startup and startlan initiated by Lan Gateway
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
lcs_recovery(void *ptr)
|
||||||
|
{
|
||||||
|
struct lcs_card *card;
|
||||||
|
struct ccwgroup_device *gdev;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
card = (struct lcs_card *) ptr;
|
||||||
|
daemonize("lcs_recover");
|
||||||
|
|
||||||
|
LCS_DBF_TEXT(4, trace, "recover1");
|
||||||
|
if (!lcs_do_run_thread(card, LCS_RECOVERY_THREAD))
|
||||||
|
return 0;
|
||||||
|
LCS_DBF_TEXT(4, trace, "recover2");
|
||||||
|
gdev = card->gdev;
|
||||||
|
PRINT_WARN("Recovery of device %s started...\n", gdev->dev.bus_id);
|
||||||
|
rc = __lcs_shutdown_device(gdev, 1);
|
||||||
|
rc = lcs_new_device(gdev);
|
||||||
|
if (!rc)
|
||||||
|
PRINT_INFO("Device %s successfully recovered!\n",
|
||||||
|
card->dev->name);
|
||||||
|
else
|
||||||
|
PRINT_INFO("Device %s could not be recovered!\n",
|
||||||
|
card->dev->name);
|
||||||
|
lcs_clear_thread_running_bit(card, LCS_RECOVERY_THREAD);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lcs_remove_device, free buffers and card
|
* lcs_remove_device, free buffers and card
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -73,13 +73,17 @@ do { \
|
||||||
/**
|
/**
|
||||||
* LCS sense byte definitions
|
* LCS sense byte definitions
|
||||||
*/
|
*/
|
||||||
|
#define LCS_SENSE_BYTE_0 0
|
||||||
|
#define LCS_SENSE_BYTE_1 1
|
||||||
|
#define LCS_SENSE_BYTE_2 2
|
||||||
|
#define LCS_SENSE_BYTE_3 3
|
||||||
#define LCS_SENSE_INTERFACE_DISCONNECT 0x01
|
#define LCS_SENSE_INTERFACE_DISCONNECT 0x01
|
||||||
#define LCS_SENSE_EQUIPMENT_CHECK 0x10
|
#define LCS_SENSE_EQUIPMENT_CHECK 0x10
|
||||||
#define LCS_SENSE_BUS_OUT_CHECK 0x20
|
#define LCS_SENSE_BUS_OUT_CHECK 0x20
|
||||||
#define LCS_SENSE_INTERVENTION_REQUIRED 0x40
|
#define LCS_SENSE_INTERVENTION_REQUIRED 0x40
|
||||||
#define LCS_SENSE_CMD_REJECT 0x80
|
#define LCS_SENSE_CMD_REJECT 0x80
|
||||||
#define LCS_SENSE_RESETTING_EVENT 0x0080
|
#define LCS_SENSE_RESETTING_EVENT 0x80
|
||||||
#define LCS_SENSE_DEVICE_ONLINE 0x0020
|
#define LCS_SENSE_DEVICE_ONLINE 0x20
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LCS packet type definitions
|
* LCS packet type definitions
|
||||||
|
@ -152,10 +156,9 @@ enum lcs_dev_states {
|
||||||
|
|
||||||
enum lcs_threads {
|
enum lcs_threads {
|
||||||
LCS_SET_MC_THREAD = 1,
|
LCS_SET_MC_THREAD = 1,
|
||||||
LCS_STARTLAN_THREAD = 2,
|
LCS_RECOVERY_THREAD = 2,
|
||||||
LCS_STOPLAN_THREAD = 4,
|
|
||||||
LCS_STARTUP_THREAD = 8,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LCS struct declarations
|
* LCS struct declarations
|
||||||
*/
|
*/
|
||||||
|
@ -286,6 +289,7 @@ struct lcs_card {
|
||||||
struct net_device_stats stats;
|
struct net_device_stats stats;
|
||||||
unsigned short (*lan_type_trans)(struct sk_buff *skb,
|
unsigned short (*lan_type_trans)(struct sk_buff *skb,
|
||||||
struct net_device *dev);
|
struct net_device *dev);
|
||||||
|
struct ccwgroup_device *gdev;
|
||||||
struct lcs_channel read;
|
struct lcs_channel read;
|
||||||
struct lcs_channel write;
|
struct lcs_channel write;
|
||||||
struct lcs_buffer *tx_buffer;
|
struct lcs_buffer *tx_buffer;
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#undef DEBUG
|
#undef DEBUG
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -65,7 +65,7 @@ MODULE_AUTHOR
|
||||||
("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
|
("(C) 2001 IBM Corporation by Fritz Elfert (felfert@millenux.com)");
|
||||||
MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
|
MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
|
||||||
|
|
||||||
|
|
||||||
#define PRINTK_HEADER " iucv: " /* for debugging */
|
#define PRINTK_HEADER " iucv: " /* for debugging */
|
||||||
|
|
||||||
static struct device_driver netiucv_driver = {
|
static struct device_driver netiucv_driver = {
|
||||||
|
@ -202,7 +202,7 @@ netiucv_printname(char *name)
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* States of the interface statemachine.
|
* States of the interface statemachine.
|
||||||
*/
|
*/
|
||||||
|
@ -244,7 +244,7 @@ static const char *dev_event_names[] = {
|
||||||
"Connection up",
|
"Connection up",
|
||||||
"Connection down",
|
"Connection down",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Events of the connection statemachine
|
* Events of the connection statemachine
|
||||||
*/
|
*/
|
||||||
|
@ -364,7 +364,7 @@ static const char *conn_state_names[] = {
|
||||||
"Connect error",
|
"Connect error",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug Facility Stuff
|
* Debug Facility Stuff
|
||||||
*/
|
*/
|
||||||
|
@ -516,7 +516,7 @@ static void
|
||||||
fsm_action_nop(fsm_instance *fi, int event, void *arg)
|
fsm_action_nop(fsm_instance *fi, int event, void *arg)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actions of the connection statemachine
|
* Actions of the connection statemachine
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -993,7 +993,7 @@ static const fsm_node conn_fsm[] = {
|
||||||
|
|
||||||
static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
|
static const int CONN_FSM_LEN = sizeof(conn_fsm) / sizeof(fsm_node);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actions for interface - statemachine.
|
* Actions for interface - statemachine.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
@ -1220,7 +1220,7 @@ netiucv_transmit_skb(struct iucv_connection *conn, struct sk_buff *skb) {
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface API for upper network layers
|
* Interface API for upper network layers
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -1099,7 +1099,7 @@ qeth_string_to_ipaddr4(const char *buf, __u8 *addr)
|
||||||
|
|
||||||
rc = sscanf(buf, "%d.%d.%d.%d%n",
|
rc = sscanf(buf, "%d.%d.%d.%d%n",
|
||||||
&in[0], &in[1], &in[2], &in[3], &count);
|
&in[0], &in[1], &in[2], &in[3], &count);
|
||||||
if (rc != 4 || count)
|
if (rc != 4 || count<=0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
for (count = 0; count < 4; count++) {
|
for (count = 0; count < 4; count++) {
|
||||||
if (in[count] > 255)
|
if (in[count] > 255)
|
||||||
|
|
|
@ -3798,10 +3798,10 @@ qeth_open(struct net_device *dev)
|
||||||
QETH_DBF_TEXT(trace,4,"nomacadr");
|
QETH_DBF_TEXT(trace,4,"nomacadr");
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
card->dev->flags |= IFF_UP;
|
|
||||||
netif_start_queue(dev);
|
|
||||||
card->data.state = CH_STATE_UP;
|
card->data.state = CH_STATE_UP;
|
||||||
card->state = CARD_STATE_UP;
|
card->state = CARD_STATE_UP;
|
||||||
|
card->dev->flags |= IFF_UP;
|
||||||
|
netif_start_queue(dev);
|
||||||
|
|
||||||
if (!card->lan_online && netif_carrier_ok(dev))
|
if (!card->lan_online && netif_carrier_ok(dev))
|
||||||
netif_carrier_off(dev);
|
netif_carrier_off(dev);
|
||||||
|
@ -3817,7 +3817,7 @@ qeth_stop(struct net_device *dev)
|
||||||
|
|
||||||
card = (struct qeth_card *) dev->priv;
|
card = (struct qeth_card *) dev->priv;
|
||||||
|
|
||||||
netif_stop_queue(dev);
|
netif_tx_disable(dev);
|
||||||
card->dev->flags &= ~IFF_UP;
|
card->dev->flags &= ~IFF_UP;
|
||||||
if (card->state == CARD_STATE_UP)
|
if (card->state == CARD_STATE_UP)
|
||||||
card->state = CARD_STATE_SOFTSETUP;
|
card->state = CARD_STATE_SOFTSETUP;
|
||||||
|
@ -3958,7 +3958,7 @@ qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
|
||||||
#endif
|
#endif
|
||||||
*hdr = (struct qeth_hdr *)
|
*hdr = (struct qeth_hdr *)
|
||||||
qeth_push_skb(card, skb, sizeof(struct qeth_hdr));
|
qeth_push_skb(card, skb, sizeof(struct qeth_hdr));
|
||||||
if (hdr == NULL)
|
if (*hdr == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4416,6 +4416,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
|
||||||
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
|
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
|
||||||
struct qeth_eddp_context *ctx = NULL;
|
struct qeth_eddp_context *ctx = NULL;
|
||||||
int tx_bytes = skb->len;
|
int tx_bytes = skb->len;
|
||||||
|
unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
|
||||||
|
unsigned short tso_size = skb_shinfo(skb)->tso_size;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
QETH_DBF_TEXT(trace, 6, "sendpkt");
|
QETH_DBF_TEXT(trace, 6, "sendpkt");
|
||||||
|
@ -4498,16 +4500,16 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
|
||||||
card->stats.tx_packets++;
|
card->stats.tx_packets++;
|
||||||
card->stats.tx_bytes += tx_bytes;
|
card->stats.tx_bytes += tx_bytes;
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
#ifdef CONFIG_QETH_PERF_STATS
|
||||||
if (skb_shinfo(skb)->tso_size &&
|
if (tso_size &&
|
||||||
!(large_send == QETH_LARGE_SEND_NO)) {
|
!(large_send == QETH_LARGE_SEND_NO)) {
|
||||||
card->perf_stats.large_send_bytes += skb->len;
|
card->perf_stats.large_send_bytes += tx_bytes;
|
||||||
card->perf_stats.large_send_cnt++;
|
card->perf_stats.large_send_cnt++;
|
||||||
}
|
}
|
||||||
if (skb_shinfo(skb)->nr_frags > 0){
|
if (nr_frags > 0){
|
||||||
card->perf_stats.sg_skbs_sent++;
|
card->perf_stats.sg_skbs_sent++;
|
||||||
/* nr_frags + skb->data */
|
/* nr_frags + skb->data */
|
||||||
card->perf_stats.sg_frags_sent +=
|
card->perf_stats.sg_frags_sent +=
|
||||||
skb_shinfo(skb)->nr_frags + 1;
|
nr_frags + 1;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_QETH_PERF_STATS */
|
#endif /* CONFIG_QETH_PERF_STATS */
|
||||||
}
|
}
|
||||||
|
@ -6359,12 +6361,9 @@ qeth_netdev_init(struct net_device *dev)
|
||||||
dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
|
dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid;
|
||||||
dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid;
|
dev->vlan_rx_add_vid = qeth_vlan_rx_add_vid;
|
||||||
#endif
|
#endif
|
||||||
dev->hard_header = card->orig_hard_header;
|
|
||||||
if (qeth_get_netdev_flags(card) & IFF_NOARP) {
|
if (qeth_get_netdev_flags(card) & IFF_NOARP) {
|
||||||
dev->rebuild_header = NULL;
|
dev->rebuild_header = NULL;
|
||||||
dev->hard_header = NULL;
|
dev->hard_header = NULL;
|
||||||
if (card->options.fake_ll)
|
|
||||||
dev->hard_header = qeth_fake_header;
|
|
||||||
dev->header_cache_update = NULL;
|
dev->header_cache_update = NULL;
|
||||||
dev->hard_header_cache = NULL;
|
dev->hard_header_cache = NULL;
|
||||||
}
|
}
|
||||||
|
@ -6373,6 +6372,9 @@ qeth_netdev_init(struct net_device *dev)
|
||||||
if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
|
if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
|
||||||
card->dev->dev_id = card->info.unique_id & 0xffff;
|
card->dev->dev_id = card->info.unique_id & 0xffff;
|
||||||
#endif
|
#endif
|
||||||
|
if (card->options.fake_ll &&
|
||||||
|
(qeth_get_netdev_flags(card) & IFF_NOARP))
|
||||||
|
dev->hard_header = qeth_fake_header;
|
||||||
dev->hard_header_parse = NULL;
|
dev->hard_header_parse = NULL;
|
||||||
dev->set_mac_address = qeth_layer2_set_mac_address;
|
dev->set_mac_address = qeth_layer2_set_mac_address;
|
||||||
dev->flags |= qeth_get_netdev_flags(card);
|
dev->flags |= qeth_get_netdev_flags(card);
|
||||||
|
@ -6477,6 +6479,9 @@ retry:
|
||||||
/*network device will be recovered*/
|
/*network device will be recovered*/
|
||||||
if (card->dev) {
|
if (card->dev) {
|
||||||
card->dev->hard_header = card->orig_hard_header;
|
card->dev->hard_header = card->orig_hard_header;
|
||||||
|
if (card->options.fake_ll &&
|
||||||
|
(qeth_get_netdev_flags(card) & IFF_NOARP))
|
||||||
|
card->dev->hard_header = qeth_fake_header;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* at first set_online allocate netdev */
|
/* at first set_online allocate netdev */
|
||||||
|
@ -7031,14 +7036,12 @@ qeth_softsetup_ipv6(struct qeth_card *card)
|
||||||
|
|
||||||
QETH_DBF_TEXT(trace,3,"softipv6");
|
QETH_DBF_TEXT(trace,3,"softipv6");
|
||||||
|
|
||||||
netif_stop_queue(card->dev);
|
|
||||||
rc = qeth_send_startlan(card, QETH_PROT_IPV6);
|
rc = qeth_send_startlan(card, QETH_PROT_IPV6);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
PRINT_ERR("IPv6 startlan failed on %s\n",
|
PRINT_ERR("IPv6 startlan failed on %s\n",
|
||||||
QETH_CARD_IFNAME(card));
|
QETH_CARD_IFNAME(card));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
netif_wake_queue(card->dev);
|
|
||||||
rc = qeth_query_ipassists(card,QETH_PROT_IPV6);
|
rc = qeth_query_ipassists(card,QETH_PROT_IPV6);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
PRINT_ERR("IPv6 query ipassist failed on %s\n",
|
PRINT_ERR("IPv6 query ipassist failed on %s\n",
|
||||||
|
@ -7352,7 +7355,8 @@ qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
|
||||||
card->options.large_send = type;
|
card->options.large_send = type;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
netif_stop_queue(card->dev);
|
if (card->state == CARD_STATE_UP)
|
||||||
|
netif_tx_disable(card->dev);
|
||||||
card->options.large_send = type;
|
card->options.large_send = type;
|
||||||
switch (card->options.large_send) {
|
switch (card->options.large_send) {
|
||||||
case QETH_LARGE_SEND_EDDP:
|
case QETH_LARGE_SEND_EDDP:
|
||||||
|
@ -7374,6 +7378,7 @@ qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
|
||||||
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
|
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (card->state == CARD_STATE_UP)
|
||||||
netif_wake_queue(card->dev);
|
netif_wake_queue(card->dev);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -7427,7 +7432,7 @@ qeth_softsetup_card(struct qeth_card *card)
|
||||||
if ((rc = qeth_setrouting_v6(card)))
|
if ((rc = qeth_setrouting_v6(card)))
|
||||||
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
|
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
|
||||||
out:
|
out:
|
||||||
netif_stop_queue(card->dev);
|
netif_tx_disable(card->dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7736,10 +7741,8 @@ static int
|
||||||
qeth_register_netdev(struct qeth_card *card)
|
qeth_register_netdev(struct qeth_card *card)
|
||||||
{
|
{
|
||||||
QETH_DBF_TEXT(setup, 3, "regnetd");
|
QETH_DBF_TEXT(setup, 3, "regnetd");
|
||||||
if (card->dev->reg_state != NETREG_UNINITIALIZED) {
|
if (card->dev->reg_state != NETREG_UNINITIALIZED)
|
||||||
qeth_netdev_init(card->dev);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
/* sysfs magic */
|
/* sysfs magic */
|
||||||
SET_NETDEV_DEV(card->dev, &card->gdev->dev);
|
SET_NETDEV_DEV(card->dev, &card->gdev->dev);
|
||||||
return register_netdev(card->dev);
|
return register_netdev(card->dev);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue