Merge branch 's390-net-next'
Julian Wiedmann says: ==================== s390/net: updates 2018-09-26 please apply one more series of cleanups and small improvements for qeth to net-next. Note that one patch needs to touch both af_iucv and qeth, in order to untangle their receive paths. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
37ac5db6e6
|
@ -582,7 +582,8 @@ struct qeth_cmd_buffer {
|
|||
struct qeth_channel *channel;
|
||||
unsigned char *data;
|
||||
int rc;
|
||||
void (*callback) (struct qeth_channel *, struct qeth_cmd_buffer *);
|
||||
void (*callback)(struct qeth_card *card, struct qeth_channel *channel,
|
||||
struct qeth_cmd_buffer *iob);
|
||||
};
|
||||
|
||||
static inline struct qeth_ipa_cmd *__ipa_cmd(struct qeth_cmd_buffer *iob)
|
||||
|
@ -671,6 +672,12 @@ struct qeth_card_info {
|
|||
__u32 hwtrap;
|
||||
};
|
||||
|
||||
enum qeth_discipline_id {
|
||||
QETH_DISCIPLINE_UNDETERMINED = -1,
|
||||
QETH_DISCIPLINE_LAYER3 = 0,
|
||||
QETH_DISCIPLINE_LAYER2 = 1,
|
||||
};
|
||||
|
||||
struct qeth_card_options {
|
||||
struct qeth_routing_info route4;
|
||||
struct qeth_ipa_info ipa4;
|
||||
|
@ -680,7 +687,7 @@ struct qeth_card_options {
|
|||
struct qeth_sbp_info sbp; /* SETBRIDGEPORT options */
|
||||
struct qeth_vnicc_info vnicc; /* VNICC options */
|
||||
int fake_broadcast;
|
||||
int layer2;
|
||||
enum qeth_discipline_id layer;
|
||||
int performance_stats;
|
||||
int rx_sg_cb;
|
||||
enum qeth_ipa_isolation_modes isolation;
|
||||
|
@ -690,6 +697,9 @@ struct qeth_card_options {
|
|||
char hsuid[9];
|
||||
};
|
||||
|
||||
#define IS_LAYER2(card) ((card)->options.layer == QETH_DISCIPLINE_LAYER2)
|
||||
#define IS_LAYER3(card) ((card)->options.layer == QETH_DISCIPLINE_LAYER3)
|
||||
|
||||
/*
|
||||
* thread bits for qeth_card thread masks
|
||||
*/
|
||||
|
@ -702,12 +712,6 @@ struct qeth_osn_info {
|
|||
int (*data_cb)(struct sk_buff *skb);
|
||||
};
|
||||
|
||||
enum qeth_discipline_id {
|
||||
QETH_DISCIPLINE_UNDETERMINED = -1,
|
||||
QETH_DISCIPLINE_LAYER3 = 0,
|
||||
QETH_DISCIPLINE_LAYER2 = 1,
|
||||
};
|
||||
|
||||
struct qeth_discipline {
|
||||
const struct device_type *devtype;
|
||||
int (*process_rx_buffer)(struct qeth_card *card, int budget, int *done);
|
||||
|
@ -759,7 +763,6 @@ struct qeth_switch_info {
|
|||
struct qeth_card {
|
||||
struct list_head list;
|
||||
enum qeth_card_states state;
|
||||
int lan_online;
|
||||
spinlock_t lock;
|
||||
struct ccwgroup_device *gdev;
|
||||
struct qeth_channel read;
|
||||
|
|
|
@ -62,10 +62,10 @@ static struct kmem_cache *qeth_qdio_outbuf_cache;
|
|||
|
||||
static struct device *qeth_core_root_dev;
|
||||
static struct lock_class_key qdio_out_skb_queue_key;
|
||||
static struct mutex qeth_mod_mutex;
|
||||
|
||||
static void qeth_send_control_data_cb(struct qeth_channel *,
|
||||
struct qeth_cmd_buffer *);
|
||||
static void qeth_send_control_data_cb(struct qeth_card *card,
|
||||
struct qeth_channel *channel,
|
||||
struct qeth_cmd_buffer *iob);
|
||||
static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *);
|
||||
static void qeth_free_buffer_pool(struct qeth_card *);
|
||||
static int qeth_qdio_establish(struct qeth_card *);
|
||||
|
@ -626,80 +626,61 @@ static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
|
|||
}
|
||||
|
||||
static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
|
||||
struct qeth_cmd_buffer *iob)
|
||||
struct qeth_ipa_cmd *cmd)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd = NULL;
|
||||
|
||||
QETH_CARD_TEXT(card, 5, "chkipad");
|
||||
if (IS_IPA(iob->data)) {
|
||||
cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
|
||||
if (IS_IPA_REPLY(cmd)) {
|
||||
if (cmd->hdr.command != IPA_CMD_SETCCID &&
|
||||
cmd->hdr.command != IPA_CMD_DELCCID &&
|
||||
cmd->hdr.command != IPA_CMD_MODCCID &&
|
||||
cmd->hdr.command != IPA_CMD_SET_DIAG_ASS)
|
||||
qeth_issue_ipa_msg(cmd,
|
||||
cmd->hdr.return_code, card);
|
||||
return cmd;
|
||||
} else {
|
||||
switch (cmd->hdr.command) {
|
||||
case IPA_CMD_STOPLAN:
|
||||
if (cmd->hdr.return_code ==
|
||||
IPA_RC_VEPA_TO_VEB_TRANSITION) {
|
||||
dev_err(&card->gdev->dev,
|
||||
"Interface %s is down because the "
|
||||
"adjacent port is no longer in "
|
||||
"reflective relay mode\n",
|
||||
QETH_CARD_IFNAME(card));
|
||||
qeth_close_dev(card);
|
||||
} else {
|
||||
dev_warn(&card->gdev->dev,
|
||||
"The link for interface %s on CHPID"
|
||||
" 0x%X failed\n",
|
||||
QETH_CARD_IFNAME(card),
|
||||
card->info.chpid);
|
||||
qeth_issue_ipa_msg(cmd,
|
||||
cmd->hdr.return_code, card);
|
||||
}
|
||||
card->lan_online = 0;
|
||||
netif_carrier_off(card->dev);
|
||||
return NULL;
|
||||
case IPA_CMD_STARTLAN:
|
||||
dev_info(&card->gdev->dev,
|
||||
"The link for %s on CHPID 0x%X has"
|
||||
" been restored\n",
|
||||
QETH_CARD_IFNAME(card),
|
||||
card->info.chpid);
|
||||
netif_carrier_on(card->dev);
|
||||
card->lan_online = 1;
|
||||
if (card->info.hwtrap)
|
||||
card->info.hwtrap = 2;
|
||||
qeth_schedule_recovery(card);
|
||||
return NULL;
|
||||
case IPA_CMD_SETBRIDGEPORT_IQD:
|
||||
case IPA_CMD_SETBRIDGEPORT_OSA:
|
||||
case IPA_CMD_ADDRESS_CHANGE_NOTIF:
|
||||
if (card->discipline->control_event_handler
|
||||
(card, cmd))
|
||||
return cmd;
|
||||
else
|
||||
return NULL;
|
||||
case IPA_CMD_MODCCID:
|
||||
return cmd;
|
||||
case IPA_CMD_REGISTER_LOCAL_ADDR:
|
||||
QETH_CARD_TEXT(card, 3, "irla");
|
||||
break;
|
||||
case IPA_CMD_UNREGISTER_LOCAL_ADDR:
|
||||
QETH_CARD_TEXT(card, 3, "urla");
|
||||
break;
|
||||
default:
|
||||
QETH_DBF_MESSAGE(2, "Received data is IPA "
|
||||
"but not a reply!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_IPA_REPLY(cmd)) {
|
||||
if (cmd->hdr.command != IPA_CMD_SETCCID &&
|
||||
cmd->hdr.command != IPA_CMD_DELCCID &&
|
||||
cmd->hdr.command != IPA_CMD_MODCCID &&
|
||||
cmd->hdr.command != IPA_CMD_SET_DIAG_ASS)
|
||||
qeth_issue_ipa_msg(cmd, cmd->hdr.return_code, card);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/* handle unsolicited event: */
|
||||
switch (cmd->hdr.command) {
|
||||
case IPA_CMD_STOPLAN:
|
||||
if (cmd->hdr.return_code == IPA_RC_VEPA_TO_VEB_TRANSITION) {
|
||||
dev_err(&card->gdev->dev,
|
||||
"Interface %s is down because the adjacent port is no longer in reflective relay mode\n",
|
||||
QETH_CARD_IFNAME(card));
|
||||
qeth_close_dev(card);
|
||||
} else {
|
||||
dev_warn(&card->gdev->dev,
|
||||
"The link for interface %s on CHPID 0x%X failed\n",
|
||||
QETH_CARD_IFNAME(card), card->info.chpid);
|
||||
qeth_issue_ipa_msg(cmd, cmd->hdr.return_code, card);
|
||||
netif_carrier_off(card->dev);
|
||||
}
|
||||
return NULL;
|
||||
case IPA_CMD_STARTLAN:
|
||||
dev_info(&card->gdev->dev,
|
||||
"The link for %s on CHPID 0x%X has been restored\n",
|
||||
QETH_CARD_IFNAME(card), card->info.chpid);
|
||||
if (card->info.hwtrap)
|
||||
card->info.hwtrap = 2;
|
||||
qeth_schedule_recovery(card);
|
||||
return NULL;
|
||||
case IPA_CMD_SETBRIDGEPORT_IQD:
|
||||
case IPA_CMD_SETBRIDGEPORT_OSA:
|
||||
case IPA_CMD_ADDRESS_CHANGE_NOTIF:
|
||||
if (card->discipline->control_event_handler(card, cmd))
|
||||
return cmd;
|
||||
return NULL;
|
||||
case IPA_CMD_MODCCID:
|
||||
return cmd;
|
||||
case IPA_CMD_REGISTER_LOCAL_ADDR:
|
||||
QETH_CARD_TEXT(card, 3, "irla");
|
||||
return NULL;
|
||||
case IPA_CMD_UNREGISTER_LOCAL_ADDR:
|
||||
QETH_CARD_TEXT(card, 3, "urla");
|
||||
return NULL;
|
||||
default:
|
||||
QETH_DBF_MESSAGE(2, "Received data is IPA but not a reply!\n");
|
||||
return cmd;
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void qeth_clear_ipacmd_list(struct qeth_card *card)
|
||||
|
@ -746,18 +727,10 @@ static int qeth_check_idx_response(struct qeth_card *card,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct qeth_card *CARD_FROM_CDEV(struct ccw_device *cdev)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(&((struct ccwgroup_device *)
|
||||
dev_get_drvdata(&cdev->dev))->dev);
|
||||
return card;
|
||||
}
|
||||
|
||||
static struct qeth_cmd_buffer *__qeth_get_buffer(struct qeth_channel *channel)
|
||||
{
|
||||
__u8 index;
|
||||
|
||||
QETH_CARD_TEXT(CARD_FROM_CDEV(channel->ccwdev), 6, "getbuff");
|
||||
index = channel->io_buf_no;
|
||||
do {
|
||||
if (channel->iob[index].state == BUF_STATE_FREE) {
|
||||
|
@ -778,7 +751,6 @@ void qeth_release_buffer(struct qeth_channel *channel,
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
QETH_CARD_TEXT(CARD_FROM_CDEV(channel->ccwdev), 6, "relbuff");
|
||||
spin_lock_irqsave(&channel->iob_lock, flags);
|
||||
iob->state = BUF_STATE_FREE;
|
||||
iob->callback = qeth_send_control_data_cb;
|
||||
|
@ -788,6 +760,13 @@ void qeth_release_buffer(struct qeth_channel *channel,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_release_buffer);
|
||||
|
||||
static void qeth_release_buffer_cb(struct qeth_card *card,
|
||||
struct qeth_channel *channel,
|
||||
struct qeth_cmd_buffer *iob)
|
||||
{
|
||||
qeth_release_buffer(channel, iob);
|
||||
}
|
||||
|
||||
static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel)
|
||||
{
|
||||
struct qeth_cmd_buffer *buffer = NULL;
|
||||
|
@ -818,17 +797,16 @@ void qeth_clear_cmd_buffers(struct qeth_channel *channel)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_clear_cmd_buffers);
|
||||
|
||||
static void qeth_send_control_data_cb(struct qeth_channel *channel,
|
||||
struct qeth_cmd_buffer *iob)
|
||||
static void qeth_send_control_data_cb(struct qeth_card *card,
|
||||
struct qeth_channel *channel,
|
||||
struct qeth_cmd_buffer *iob)
|
||||
{
|
||||
struct qeth_card *card;
|
||||
struct qeth_ipa_cmd *cmd = NULL;
|
||||
struct qeth_reply *reply, *r;
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
unsigned long flags;
|
||||
int keep_reply;
|
||||
int rc = 0;
|
||||
|
||||
card = CARD_FROM_CDEV(channel->ccwdev);
|
||||
QETH_CARD_TEXT(card, 4, "sndctlcb");
|
||||
rc = qeth_check_idx_response(card, iob->data);
|
||||
switch (rc) {
|
||||
|
@ -842,16 +820,20 @@ static void qeth_send_control_data_cb(struct qeth_channel *channel,
|
|||
goto out;
|
||||
}
|
||||
|
||||
cmd = qeth_check_ipa_data(card, iob);
|
||||
if ((cmd == NULL) && (card->state != CARD_STATE_DOWN))
|
||||
goto out;
|
||||
/*in case of OSN : check if cmd is set */
|
||||
if (card->info.type == QETH_CARD_TYPE_OSN &&
|
||||
cmd &&
|
||||
cmd->hdr.command != IPA_CMD_STARTLAN &&
|
||||
card->osn_info.assist_cb != NULL) {
|
||||
card->osn_info.assist_cb(card->dev, cmd);
|
||||
goto out;
|
||||
if (IS_IPA(iob->data)) {
|
||||
cmd = (struct qeth_ipa_cmd *) PDU_ENCAPSULATION(iob->data);
|
||||
cmd = qeth_check_ipa_data(card, cmd);
|
||||
if (!cmd)
|
||||
goto out;
|
||||
if (IS_OSN(card) && card->osn_info.assist_cb &&
|
||||
cmd->hdr.command != IPA_CMD_STARTLAN) {
|
||||
card->osn_info.assist_cb(card->dev, cmd);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* non-IPA commands should only flow during initialization */
|
||||
if (card->state != CARD_STATE_DOWN)
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
|
@ -974,16 +956,15 @@ void qeth_schedule_recovery(struct qeth_card *card)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_schedule_recovery);
|
||||
|
||||
static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
|
||||
static int qeth_get_problem(struct qeth_card *card, struct ccw_device *cdev,
|
||||
struct irb *irb)
|
||||
{
|
||||
int dstat, cstat;
|
||||
char *sense;
|
||||
struct qeth_card *card;
|
||||
|
||||
sense = (char *) irb->ecw;
|
||||
cstat = irb->scsw.cmd.cstat;
|
||||
dstat = irb->scsw.cmd.dstat;
|
||||
card = CARD_FROM_CDEV(cdev);
|
||||
|
||||
if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK |
|
||||
SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK |
|
||||
|
@ -1023,14 +1004,11 @@ static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static long __qeth_check_irb_error(struct ccw_device *cdev,
|
||||
unsigned long intparm, struct irb *irb)
|
||||
static long qeth_check_irb_error(struct qeth_card *card,
|
||||
struct ccw_device *cdev, unsigned long intparm,
|
||||
struct irb *irb)
|
||||
{
|
||||
struct qeth_card *card;
|
||||
|
||||
card = CARD_FROM_CDEV(cdev);
|
||||
|
||||
if (!card || !IS_ERR(irb))
|
||||
if (!IS_ERR(irb))
|
||||
return 0;
|
||||
|
||||
switch (PTR_ERR(irb)) {
|
||||
|
@ -1067,10 +1045,13 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|||
int rc;
|
||||
int cstat, dstat;
|
||||
struct qeth_cmd_buffer *iob = NULL;
|
||||
struct ccwgroup_device *gdev;
|
||||
struct qeth_channel *channel;
|
||||
struct qeth_card *card;
|
||||
|
||||
card = CARD_FROM_CDEV(cdev);
|
||||
/* while we hold the ccwdev lock, this stays valid: */
|
||||
gdev = dev_get_drvdata(&cdev->dev);
|
||||
card = dev_get_drvdata(&gdev->dev);
|
||||
if (!card)
|
||||
return;
|
||||
|
||||
|
@ -1090,7 +1071,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|||
if (qeth_intparm_is_iob(intparm))
|
||||
iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
|
||||
|
||||
if (__qeth_check_irb_error(cdev, intparm, irb)) {
|
||||
if (qeth_check_irb_error(card, cdev, intparm, irb)) {
|
||||
/* IO was terminated, free its resources. */
|
||||
if (iob)
|
||||
qeth_release_buffer(iob->channel, iob);
|
||||
|
@ -1145,7 +1126,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|||
channel->state = CH_STATE_DOWN;
|
||||
goto out;
|
||||
}
|
||||
rc = qeth_get_problem(cdev, irb);
|
||||
rc = qeth_get_problem(card, cdev, irb);
|
||||
if (rc) {
|
||||
card->read_or_write_problem = 1;
|
||||
qeth_clear_ipacmd_list(card);
|
||||
|
@ -1165,7 +1146,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
|
|||
__qeth_issue_next_read(card);
|
||||
|
||||
if (iob && iob->callback)
|
||||
iob->callback(iob->channel, iob);
|
||||
iob->callback(card, iob->channel, iob);
|
||||
|
||||
out:
|
||||
wake_up(&card->wait_q);
|
||||
|
@ -1178,54 +1159,23 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *q,
|
|||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (skb_queue_empty(&buf->skb_list))
|
||||
goto out;
|
||||
skb = skb_peek(&buf->skb_list);
|
||||
while (skb) {
|
||||
skb_queue_walk(&buf->skb_list, skb) {
|
||||
QETH_CARD_TEXT_(q->card, 5, "skbn%d", notification);
|
||||
QETH_CARD_TEXT_(q->card, 5, "%lx", (long) skb);
|
||||
if (be16_to_cpu(skb->protocol) == ETH_P_AF_IUCV) {
|
||||
if (skb->sk) {
|
||||
struct iucv_sock *iucv = iucv_sk(skb->sk);
|
||||
iucv->sk_txnotify(skb, notification);
|
||||
}
|
||||
}
|
||||
if (skb_queue_is_last(&buf->skb_list, skb))
|
||||
skb = NULL;
|
||||
else
|
||||
skb = skb_queue_next(&buf->skb_list, skb);
|
||||
if (skb->protocol == htons(ETH_P_AF_IUCV) && skb->sk)
|
||||
iucv_sk(skb->sk)->sk_txnotify(skb, notification);
|
||||
}
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct iucv_sock *iucv;
|
||||
int notify_general_error = 0;
|
||||
|
||||
if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING)
|
||||
notify_general_error = 1;
|
||||
|
||||
/* release may never happen from within CQ tasklet scope */
|
||||
WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
|
||||
|
||||
skb = skb_dequeue(&buf->skb_list);
|
||||
while (skb) {
|
||||
QETH_CARD_TEXT(buf->q->card, 5, "skbr");
|
||||
QETH_CARD_TEXT_(buf->q->card, 5, "%lx", (long) skb);
|
||||
if (notify_general_error &&
|
||||
be16_to_cpu(skb->protocol) == ETH_P_AF_IUCV) {
|
||||
if (skb->sk) {
|
||||
iucv = iucv_sk(skb->sk);
|
||||
iucv->sk_txnotify(skb, TX_NOTIFY_GENERALERROR);
|
||||
}
|
||||
}
|
||||
refcount_dec(&skb->users);
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = skb_dequeue(&buf->skb_list);
|
||||
}
|
||||
if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING)
|
||||
qeth_notify_skbs(buf->q, buf, TX_NOTIFY_GENERALERROR);
|
||||
|
||||
__skb_queue_purge(&buf->skb_list);
|
||||
}
|
||||
|
||||
static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
|
||||
|
@ -1429,6 +1379,7 @@ static void qeth_set_initial_options(struct qeth_card *card)
|
|||
card->options.rx_sg_cb = QETH_RX_SG_CB;
|
||||
card->options.isolation = ISOLATION_MODE_NONE;
|
||||
card->options.cq = QETH_CQ_DISABLED;
|
||||
card->options.layer = QETH_DISCIPLINE_UNDETERMINED;
|
||||
}
|
||||
|
||||
static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread)
|
||||
|
@ -1513,6 +1464,7 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev)
|
|||
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
|
||||
|
||||
card->gdev = gdev;
|
||||
dev_set_drvdata(&gdev->dev, card);
|
||||
CARD_RDEV(card) = gdev->cdev[0];
|
||||
CARD_WDEV(card) = gdev->cdev[1];
|
||||
CARD_DDEV(card) = gdev->cdev[2];
|
||||
|
@ -1522,7 +1474,6 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev)
|
|||
goto out_channel;
|
||||
if (qeth_setup_channel(&card->data, false))
|
||||
goto out_data;
|
||||
card->options.layer2 = -1;
|
||||
card->qeth_service_level.seq_print = qeth_core_sl_print;
|
||||
register_service_level(&card->qeth_service_level);
|
||||
return card;
|
||||
|
@ -1532,17 +1483,17 @@ out_data:
|
|||
out_channel:
|
||||
qeth_clean_channel(&card->read);
|
||||
out_ip:
|
||||
dev_set_drvdata(&gdev->dev, NULL);
|
||||
kfree(card);
|
||||
out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int qeth_clear_channel(struct qeth_channel *channel)
|
||||
static int qeth_clear_channel(struct qeth_card *card,
|
||||
struct qeth_channel *channel)
|
||||
{
|
||||
struct qeth_card *card;
|
||||
int rc;
|
||||
|
||||
card = CARD_FROM_CDEV(channel->ccwdev);
|
||||
QETH_CARD_TEXT(card, 3, "clearch");
|
||||
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||
rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
|
||||
|
@ -1560,12 +1511,11 @@ static int qeth_clear_channel(struct qeth_channel *channel)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int qeth_halt_channel(struct qeth_channel *channel)
|
||||
static int qeth_halt_channel(struct qeth_card *card,
|
||||
struct qeth_channel *channel)
|
||||
{
|
||||
struct qeth_card *card;
|
||||
int rc;
|
||||
|
||||
card = CARD_FROM_CDEV(channel->ccwdev);
|
||||
QETH_CARD_TEXT(card, 3, "haltch");
|
||||
spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
|
||||
rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
|
||||
|
@ -1587,9 +1537,9 @@ static int qeth_halt_channels(struct qeth_card *card)
|
|||
int rc1 = 0, rc2 = 0, rc3 = 0;
|
||||
|
||||
QETH_CARD_TEXT(card, 3, "haltchs");
|
||||
rc1 = qeth_halt_channel(&card->read);
|
||||
rc2 = qeth_halt_channel(&card->write);
|
||||
rc3 = qeth_halt_channel(&card->data);
|
||||
rc1 = qeth_halt_channel(card, &card->read);
|
||||
rc2 = qeth_halt_channel(card, &card->write);
|
||||
rc3 = qeth_halt_channel(card, &card->data);
|
||||
if (rc1)
|
||||
return rc1;
|
||||
if (rc2)
|
||||
|
@ -1602,9 +1552,9 @@ static int qeth_clear_channels(struct qeth_card *card)
|
|||
int rc1 = 0, rc2 = 0, rc3 = 0;
|
||||
|
||||
QETH_CARD_TEXT(card, 3, "clearchs");
|
||||
rc1 = qeth_clear_channel(&card->read);
|
||||
rc2 = qeth_clear_channel(&card->write);
|
||||
rc3 = qeth_clear_channel(&card->data);
|
||||
rc1 = qeth_clear_channel(card, &card->read);
|
||||
rc2 = qeth_clear_channel(card, &card->write);
|
||||
rc3 = qeth_clear_channel(card, &card->data);
|
||||
if (rc1)
|
||||
return rc1;
|
||||
if (rc2)
|
||||
|
@ -1833,20 +1783,20 @@ static void qeth_init_func_level(struct qeth_card *card)
|
|||
}
|
||||
}
|
||||
|
||||
static int qeth_idx_activate_get_answer(struct qeth_channel *channel,
|
||||
void (*idx_reply_cb)(struct qeth_channel *,
|
||||
struct qeth_cmd_buffer *))
|
||||
static int qeth_idx_activate_get_answer(struct qeth_card *card,
|
||||
struct qeth_channel *channel,
|
||||
void (*reply_cb)(struct qeth_card *,
|
||||
struct qeth_channel *,
|
||||
struct qeth_cmd_buffer *))
|
||||
{
|
||||
struct qeth_cmd_buffer *iob;
|
||||
int rc;
|
||||
struct qeth_card *card;
|
||||
|
||||
QETH_DBF_TEXT(SETUP, 2, "idxanswr");
|
||||
card = CARD_FROM_CDEV(channel->ccwdev);
|
||||
iob = qeth_get_buffer(channel);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
iob->callback = idx_reply_cb;
|
||||
iob->callback = reply_cb;
|
||||
qeth_setup_ccw(channel->ccw, CCW_CMD_READ, QETH_BUFSIZE, iob->data);
|
||||
|
||||
wait_event(card->wait_q,
|
||||
|
@ -1876,25 +1826,24 @@ static int qeth_idx_activate_get_answer(struct qeth_channel *channel,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_idx_activate_channel(struct qeth_channel *channel,
|
||||
void (*idx_reply_cb)(struct qeth_channel *,
|
||||
struct qeth_cmd_buffer *))
|
||||
static int qeth_idx_activate_channel(struct qeth_card *card,
|
||||
struct qeth_channel *channel,
|
||||
void (*reply_cb)(struct qeth_card *,
|
||||
struct qeth_channel *,
|
||||
struct qeth_cmd_buffer *))
|
||||
{
|
||||
struct qeth_card *card;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
__u16 temp;
|
||||
__u8 tmp;
|
||||
int rc;
|
||||
struct ccw_dev_id temp_devid;
|
||||
|
||||
card = CARD_FROM_CDEV(channel->ccwdev);
|
||||
|
||||
QETH_DBF_TEXT(SETUP, 2, "idxactch");
|
||||
|
||||
iob = qeth_get_buffer(channel);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
iob->callback = idx_reply_cb;
|
||||
iob->callback = reply_cb;
|
||||
qeth_setup_ccw(channel->ccw, CCW_CMD_WRITE, IDX_ACTIVATE_SIZE,
|
||||
iob->data);
|
||||
if (channel == &card->write) {
|
||||
|
@ -1946,7 +1895,7 @@ static int qeth_idx_activate_channel(struct qeth_channel *channel,
|
|||
QETH_DBF_TEXT_(SETUP, 2, "2err%d", -ETIME);
|
||||
return -ETIME;
|
||||
}
|
||||
return qeth_idx_activate_get_answer(channel, idx_reply_cb);
|
||||
return qeth_idx_activate_get_answer(card, channel, reply_cb);
|
||||
}
|
||||
|
||||
static int qeth_peer_func_level(int level)
|
||||
|
@ -1958,10 +1907,10 @@ static int qeth_peer_func_level(int level)
|
|||
return level;
|
||||
}
|
||||
|
||||
static void qeth_idx_write_cb(struct qeth_channel *channel,
|
||||
struct qeth_cmd_buffer *iob)
|
||||
static void qeth_idx_write_cb(struct qeth_card *card,
|
||||
struct qeth_channel *channel,
|
||||
struct qeth_cmd_buffer *iob)
|
||||
{
|
||||
struct qeth_card *card;
|
||||
__u16 temp;
|
||||
|
||||
QETH_DBF_TEXT(SETUP , 2, "idxwrcb");
|
||||
|
@ -1970,7 +1919,6 @@ static void qeth_idx_write_cb(struct qeth_channel *channel,
|
|||
channel->state = CH_STATE_ACTIVATING;
|
||||
goto out;
|
||||
}
|
||||
card = CARD_FROM_CDEV(channel->ccwdev);
|
||||
|
||||
if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
|
||||
if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == QETH_IDX_ACT_ERR_EXCL)
|
||||
|
@ -1996,10 +1944,10 @@ out:
|
|||
qeth_release_buffer(channel, iob);
|
||||
}
|
||||
|
||||
static void qeth_idx_read_cb(struct qeth_channel *channel,
|
||||
struct qeth_cmd_buffer *iob)
|
||||
static void qeth_idx_read_cb(struct qeth_card *card,
|
||||
struct qeth_channel *channel,
|
||||
struct qeth_cmd_buffer *iob)
|
||||
{
|
||||
struct qeth_card *card;
|
||||
__u16 temp;
|
||||
|
||||
QETH_DBF_TEXT(SETUP , 2, "idxrdcb");
|
||||
|
@ -2008,7 +1956,6 @@ static void qeth_idx_read_cb(struct qeth_channel *channel,
|
|||
goto out;
|
||||
}
|
||||
|
||||
card = CARD_FROM_CDEV(channel->ccwdev);
|
||||
if (qeth_check_idx_response(card, iob->data))
|
||||
goto out;
|
||||
|
||||
|
@ -2057,7 +2004,7 @@ void qeth_prepare_control_data(struct qeth_card *card, int len,
|
|||
struct qeth_cmd_buffer *iob)
|
||||
{
|
||||
qeth_setup_ccw(iob->channel->ccw, CCW_CMD_WRITE, len, iob->data);
|
||||
iob->callback = qeth_release_buffer;
|
||||
iob->callback = qeth_release_buffer_cb;
|
||||
|
||||
memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(iob->data),
|
||||
&card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH);
|
||||
|
@ -2205,7 +2152,6 @@ static int qeth_cm_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
|
|||
memcpy(&card->token.cm_filter_r,
|
||||
QETH_CM_ENABLE_RESP_FILTER_TOKEN(iob->data),
|
||||
QETH_MPC_TOKEN_LENGTH);
|
||||
QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2231,7 +2177,6 @@ static int qeth_cm_enable(struct qeth_card *card)
|
|||
static int qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
|
||||
unsigned long data)
|
||||
{
|
||||
|
||||
struct qeth_cmd_buffer *iob;
|
||||
|
||||
QETH_DBF_TEXT(SETUP, 2, "cmsetpcb");
|
||||
|
@ -2240,7 +2185,6 @@ static int qeth_cm_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
|
|||
memcpy(&card->token.cm_connection_r,
|
||||
QETH_CM_SETUP_RESP_DEST_ADDR(iob->data),
|
||||
QETH_MPC_TOKEN_LENGTH);
|
||||
QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2262,7 +2206,6 @@ static int qeth_cm_setup(struct qeth_card *card)
|
|||
rc = qeth_send_control_data(card, CM_SETUP_SIZE, iob,
|
||||
qeth_cm_setup_cb, NULL);
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
static int qeth_update_max_mtu(struct qeth_card *card, unsigned int max_mtu)
|
||||
|
@ -2291,7 +2234,7 @@ static int qeth_update_max_mtu(struct qeth_card *card, unsigned int max_mtu)
|
|||
if (dev->mtu)
|
||||
new_mtu = dev->mtu;
|
||||
/* default MTUs for first setup: */
|
||||
else if (card->options.layer2)
|
||||
else if (IS_LAYER2(card))
|
||||
new_mtu = ETH_DATA_LEN;
|
||||
else
|
||||
new_mtu = ETH_DATA_LEN - 8; /* allow for LLC + SNAP */
|
||||
|
@ -2322,7 +2265,6 @@ static int qeth_get_mtu_outof_framesize(int framesize)
|
|||
static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
|
||||
unsigned long data)
|
||||
{
|
||||
|
||||
__u16 mtu, framesize;
|
||||
__u16 len;
|
||||
__u8 link_type;
|
||||
|
@ -2350,7 +2292,6 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
|
|||
} else
|
||||
card->info.link_type = 0;
|
||||
QETH_DBF_TEXT_(SETUP, 2, "link%d", card->info.link_type);
|
||||
QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2358,7 +2299,7 @@ static u8 qeth_mpc_select_prot_type(struct qeth_card *card)
|
|||
{
|
||||
if (IS_OSN(card))
|
||||
return QETH_PROT_OSN2;
|
||||
return (card->options.layer2 == 1) ? QETH_PROT_LAYER2 : QETH_PROT_TCPIP;
|
||||
return IS_LAYER2(card) ? QETH_PROT_LAYER2 : QETH_PROT_TCPIP;
|
||||
}
|
||||
|
||||
static int qeth_ulp_enable(struct qeth_card *card)
|
||||
|
@ -2896,10 +2837,7 @@ static void qeth_fill_ipacmd_header(struct qeth_card *card,
|
|||
/* cmd->hdr.seqno is set by qeth_send_control_data() */
|
||||
cmd->hdr.adapter_type = qeth_get_ipa_adp_type(card->info.link_type);
|
||||
cmd->hdr.rel_adapter_no = (u8) card->dev->dev_port;
|
||||
if (card->options.layer2)
|
||||
cmd->hdr.prim_version_no = 2;
|
||||
else
|
||||
cmd->hdr.prim_version_no = 1;
|
||||
cmd->hdr.prim_version_no = IS_LAYER2(card) ? 2 : 1;
|
||||
cmd->hdr.param_count = 1;
|
||||
cmd->hdr.prot_version = prot;
|
||||
}
|
||||
|
@ -4001,8 +3939,7 @@ static int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
|
|||
bool is_first_elem = true;
|
||||
int flush_cnt = 0;
|
||||
|
||||
refcount_inc(&skb->users);
|
||||
skb_queue_tail(&buf->skb_list, skb);
|
||||
__skb_queue_tail(&buf->skb_list, skb);
|
||||
|
||||
/* build dedicated header element */
|
||||
if (hd_len) {
|
||||
|
@ -4278,8 +4215,7 @@ static int qeth_setadpparms_change_macaddr_cb(struct qeth_card *card,
|
|||
if (qeth_setadpparms_inspect_rc(cmd))
|
||||
return 0;
|
||||
|
||||
if (!card->options.layer2 ||
|
||||
!(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
|
||||
if (IS_LAYER3(card) || !(card->info.mac_bits & QETH_LAYER2_MAC_READ)) {
|
||||
ether_addr_copy(card->dev->dev_addr,
|
||||
cmd->data.setadapterparms.data.change_addr.addr);
|
||||
card->info.mac_bits |= QETH_LAYER2_MAC_READ;
|
||||
|
@ -4633,9 +4569,9 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)
|
|||
return -EOPNOTSUPP;
|
||||
|
||||
if ((!qeth_adp_supported(card, IPA_SETADP_SET_SNMP_CONTROL)) &&
|
||||
(!card->options.layer2)) {
|
||||
IS_LAYER3(card))
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* skip 4 bytes (data_len struct member) to get req_len */
|
||||
if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
@ -5079,6 +5015,7 @@ static void qeth_core_free_card(struct qeth_card *card)
|
|||
qeth_clean_channel(&card->data);
|
||||
qeth_free_qdio_buffers(card);
|
||||
unregister_service_level(&card->qeth_service_level);
|
||||
dev_set_drvdata(&card->gdev->dev, NULL);
|
||||
kfree(card);
|
||||
}
|
||||
|
||||
|
@ -5158,7 +5095,7 @@ retriable:
|
|||
qeth_determine_capabilities(card);
|
||||
qeth_init_tokens(card);
|
||||
qeth_init_func_level(card);
|
||||
rc = qeth_idx_activate_channel(&card->read, qeth_idx_read_cb);
|
||||
rc = qeth_idx_activate_channel(card, &card->read, qeth_idx_read_cb);
|
||||
if (rc == -ERESTARTSYS) {
|
||||
QETH_DBF_TEXT(SETUP, 2, "break2");
|
||||
return rc;
|
||||
|
@ -5169,7 +5106,7 @@ retriable:
|
|||
else
|
||||
goto retry;
|
||||
}
|
||||
rc = qeth_idx_activate_channel(&card->write, qeth_idx_write_cb);
|
||||
rc = qeth_idx_activate_channel(card, &card->write, qeth_idx_write_cb);
|
||||
if (rc == -ERESTARTSYS) {
|
||||
QETH_DBF_TEXT(SETUP, 2, "break3");
|
||||
return rc;
|
||||
|
@ -5193,13 +5130,14 @@ retriable:
|
|||
if (rc == IPA_RC_LAN_OFFLINE) {
|
||||
dev_warn(&card->gdev->dev,
|
||||
"The LAN is offline\n");
|
||||
card->lan_online = 0;
|
||||
netif_carrier_off(card->dev);
|
||||
} else {
|
||||
rc = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
card->lan_online = 1;
|
||||
} else {
|
||||
netif_carrier_on(card->dev);
|
||||
}
|
||||
|
||||
card->options.ipa4.supported_funcs = 0;
|
||||
card->options.ipa6.supported_funcs = 0;
|
||||
|
@ -5593,11 +5531,11 @@ static int qeth_register_dbf_views(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static DEFINE_MUTEX(qeth_mod_mutex); /* for synchronized module loading */
|
||||
|
||||
int qeth_core_load_discipline(struct qeth_card *card,
|
||||
enum qeth_discipline_id discipline)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
mutex_lock(&qeth_mod_mutex);
|
||||
switch (discipline) {
|
||||
case QETH_DISCIPLINE_LAYER3:
|
||||
|
@ -5611,22 +5549,25 @@ int qeth_core_load_discipline(struct qeth_card *card,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&qeth_mod_mutex);
|
||||
|
||||
if (!card->discipline) {
|
||||
dev_err(&card->gdev->dev, "There is no kernel module to "
|
||||
"support discipline %d\n", discipline);
|
||||
rc = -EINVAL;
|
||||
return -EINVAL;
|
||||
}
|
||||
mutex_unlock(&qeth_mod_mutex);
|
||||
return rc;
|
||||
|
||||
card->options.layer = discipline;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qeth_core_free_discipline(struct qeth_card *card)
|
||||
{
|
||||
if (card->options.layer2)
|
||||
if (IS_LAYER2(card))
|
||||
symbol_put(qeth_l2_discipline);
|
||||
else
|
||||
symbol_put(qeth_l3_discipline);
|
||||
card->options.layer = QETH_DISCIPLINE_UNDETERMINED;
|
||||
card->discipline = NULL;
|
||||
}
|
||||
|
||||
|
@ -5790,7 +5731,6 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
|
|||
goto err_card;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&gdev->dev, card);
|
||||
qeth_setup_card(card);
|
||||
qeth_update_from_chp_desc(card);
|
||||
|
||||
|
@ -5853,7 +5793,6 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev)
|
|||
write_unlock_irq(&qeth_core_card_list.rwlock);
|
||||
free_netdev(card->dev);
|
||||
qeth_core_free_card(card);
|
||||
dev_set_drvdata(&gdev->dev, NULL);
|
||||
put_device(&gdev->dev);
|
||||
}
|
||||
|
||||
|
@ -6146,7 +6085,7 @@ void qeth_core_get_drvinfo(struct net_device *dev,
|
|||
{
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
|
||||
strlcpy(info->driver, card->options.layer2 ? "qeth_l2" : "qeth_l3",
|
||||
strlcpy(info->driver, IS_LAYER2(card) ? "qeth_l2" : "qeth_l3",
|
||||
sizeof(info->driver));
|
||||
strlcpy(info->version, "1.0", sizeof(info->version));
|
||||
strlcpy(info->fw_version, card->info.mcl_level,
|
||||
|
@ -6625,9 +6564,7 @@ static int __init qeth_core_init(void)
|
|||
|
||||
pr_info("loading core functions\n");
|
||||
INIT_LIST_HEAD(&qeth_core_card_list.list);
|
||||
INIT_LIST_HEAD(&qeth_dbf_list);
|
||||
rwlock_init(&qeth_core_card_list.rwlock);
|
||||
mutex_init(&qeth_mod_mutex);
|
||||
|
||||
qeth_wq = create_singlethread_workqueue("qeth_wq");
|
||||
if (!qeth_wq) {
|
||||
|
|
|
@ -31,10 +31,9 @@ static ssize_t qeth_dev_state_show(struct device *dev,
|
|||
case CARD_STATE_SOFTSETUP:
|
||||
return sprintf(buf, "SOFTSETUP\n");
|
||||
case CARD_STATE_UP:
|
||||
if (card->lan_online)
|
||||
return sprintf(buf, "UP (LAN ONLINE)\n");
|
||||
else
|
||||
return sprintf(buf, "UP (LAN OFFLINE)\n");
|
||||
return sprintf(buf, "UP (LAN %s)\n",
|
||||
netif_carrier_ok(card->dev) ? "ONLINE" :
|
||||
"OFFLINE");
|
||||
case CARD_STATE_RECOVER:
|
||||
return sprintf(buf, "RECOVER\n");
|
||||
default:
|
||||
|
@ -228,7 +227,7 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev,
|
|||
card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_TOS;
|
||||
card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
|
||||
} else if (sysfs_streq(buf, "prio_queueing_vlan")) {
|
||||
if (!card->options.layer2) {
|
||||
if (IS_LAYER3(card)) {
|
||||
rc = -ENOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
@ -379,7 +378,7 @@ static ssize_t qeth_dev_layer2_show(struct device *dev,
|
|||
if (!card)
|
||||
return -EINVAL;
|
||||
|
||||
return sprintf(buf, "%i\n", card->options.layer2);
|
||||
return sprintf(buf, "%i\n", card->options.layer);
|
||||
}
|
||||
|
||||
static ssize_t qeth_dev_layer2_store(struct device *dev,
|
||||
|
@ -413,7 +412,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (card->options.layer2 == newdis)
|
||||
if (card->options.layer == newdis)
|
||||
goto out;
|
||||
if (card->info.layer_enforced) {
|
||||
/* fixed layer, can't switch */
|
||||
|
@ -432,8 +431,6 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
|
|||
|
||||
card->discipline->remove(card->gdev);
|
||||
qeth_core_free_discipline(card);
|
||||
card->options.layer2 = -1;
|
||||
|
||||
free_netdev(card->dev);
|
||||
card->dev = ndev;
|
||||
}
|
||||
|
|
|
@ -694,7 +694,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
|
|||
int tx_bytes = skb->len;
|
||||
int rc;
|
||||
|
||||
if ((card->state != CARD_STATE_UP) || !card->lan_online) {
|
||||
if (card->state != CARD_STATE_UP) {
|
||||
card->stats.tx_carrier_errors++;
|
||||
goto tx_drop;
|
||||
}
|
||||
|
@ -806,7 +806,6 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
|
|||
}
|
||||
INIT_LIST_HEAD(&card->vid_list);
|
||||
hash_init(card->mac_htable);
|
||||
card->options.layer2 = 1;
|
||||
card->info.hwtrap = 0;
|
||||
qeth_l2_vnicc_set_defaults(card);
|
||||
return 0;
|
||||
|
@ -998,10 +997,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
goto out_remove;
|
||||
}
|
||||
card->state = CARD_STATE_SOFTSETUP;
|
||||
if (card->lan_online)
|
||||
netif_carrier_on(card->dev);
|
||||
else
|
||||
netif_carrier_off(card->dev);
|
||||
|
||||
qeth_set_allowed_threads(card, 0xffffffff, 0);
|
||||
|
||||
|
@ -1147,9 +1142,6 @@ static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
|
|||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||
int rc = 0;
|
||||
|
||||
if (gdev->state == CCWGROUP_OFFLINE)
|
||||
goto out;
|
||||
|
||||
if (card->state == CARD_STATE_RECOVER) {
|
||||
rc = __qeth_l2_set_online(card->gdev, 1);
|
||||
if (rc) {
|
||||
|
@ -1159,7 +1151,7 @@ static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
|
|||
}
|
||||
} else
|
||||
rc = __qeth_l2_set_online(card->gdev, 0);
|
||||
out:
|
||||
|
||||
qeth_set_allowed_threads(card, 0xffffffff, 0);
|
||||
netif_device_attach(card->dev);
|
||||
if (rc)
|
||||
|
|
|
@ -1348,6 +1348,7 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
|
|||
static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
|
||||
int budget, int *done)
|
||||
{
|
||||
struct net_device *dev = card->dev;
|
||||
int work_done = 0;
|
||||
struct sk_buff *skb;
|
||||
struct qeth_hdr *hdr;
|
||||
|
@ -1369,11 +1370,10 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
|
|||
magic = *(__u16 *)skb->data;
|
||||
if ((card->info.type == QETH_CARD_TYPE_IQD) &&
|
||||
(magic == ETH_P_AF_IUCV)) {
|
||||
skb->protocol = cpu_to_be16(ETH_P_AF_IUCV);
|
||||
len = skb->len;
|
||||
card->dev->header_ops->create(skb, card->dev, 0,
|
||||
card->dev->dev_addr, "FAKELL", len);
|
||||
skb_reset_mac_header(skb);
|
||||
dev_hard_header(skb, dev, ETH_P_AF_IUCV,
|
||||
dev->dev_addr, "FAKELL", len);
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
netif_receive_skb(skb);
|
||||
} else {
|
||||
qeth_l3_rebuild_skb(card, skb, hdr);
|
||||
|
@ -2005,17 +2005,15 @@ static void qeth_l3_fill_af_iucv_hdr(struct qeth_hdr *hdr, struct sk_buff *skb,
|
|||
unsigned int data_len)
|
||||
{
|
||||
char daddr[16];
|
||||
struct af_iucv_trans_hdr *iucv_hdr;
|
||||
|
||||
hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
|
||||
hdr->hdr.l3.length = data_len;
|
||||
hdr->hdr.l3.flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST;
|
||||
|
||||
iucv_hdr = (struct af_iucv_trans_hdr *)(skb_mac_header(skb) + ETH_HLEN);
|
||||
memset(daddr, 0, sizeof(daddr));
|
||||
daddr[0] = 0xfe;
|
||||
daddr[1] = 0x80;
|
||||
memcpy(&daddr[8], iucv_hdr->destUserID, 8);
|
||||
memcpy(&daddr[8], iucv_trans_hdr(skb)->destUserID, 8);
|
||||
memcpy(hdr->hdr.l3.next_hop.ipv6_addr, daddr, 16);
|
||||
}
|
||||
|
||||
|
@ -2235,7 +2233,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
|
|||
goto tx_drop;
|
||||
}
|
||||
|
||||
if (card->state != CARD_STATE_UP || !card->lan_online) {
|
||||
if (card->state != CARD_STATE_UP) {
|
||||
card->stats.tx_carrier_errors++;
|
||||
goto tx_drop;
|
||||
}
|
||||
|
@ -2489,7 +2487,6 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
|
|||
}
|
||||
hash_init(card->ip_htable);
|
||||
hash_init(card->ip_mc_htable);
|
||||
card->options.layer2 = 0;
|
||||
card->info.hwtrap = 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2576,10 +2573,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
|
||||
qeth_set_allowed_threads(card, 0xffffffff, 0);
|
||||
qeth_l3_recover_ip(card);
|
||||
if (card->lan_online)
|
||||
netif_carrier_on(card->dev);
|
||||
else
|
||||
netif_carrier_off(card->dev);
|
||||
|
||||
qeth_enable_hw_features(card->dev);
|
||||
if (recover_flag == CARD_STATE_RECOVER) {
|
||||
|
@ -2717,9 +2710,6 @@ static int qeth_l3_pm_resume(struct ccwgroup_device *gdev)
|
|||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||
int rc = 0;
|
||||
|
||||
if (gdev->state == CCWGROUP_OFFLINE)
|
||||
goto out;
|
||||
|
||||
if (card->state == CARD_STATE_RECOVER) {
|
||||
rc = __qeth_l3_set_online(card->gdev, 1);
|
||||
if (rc) {
|
||||
|
@ -2729,7 +2719,7 @@ static int qeth_l3_pm_resume(struct ccwgroup_device *gdev)
|
|||
}
|
||||
} else
|
||||
rc = __qeth_l3_set_online(card->gdev, 0);
|
||||
out:
|
||||
|
||||
qeth_set_allowed_threads(card, 0xffffffff, 0);
|
||||
netif_device_attach(card->dev);
|
||||
if (rc)
|
||||
|
|
|
@ -80,6 +80,11 @@ struct af_iucv_trans_hdr {
|
|||
u8 pad; /* total 104 bytes */
|
||||
} __packed;
|
||||
|
||||
static inline struct af_iucv_trans_hdr *iucv_trans_hdr(struct sk_buff *skb)
|
||||
{
|
||||
return (struct af_iucv_trans_hdr *)skb_network_header(skb);
|
||||
}
|
||||
|
||||
enum iucv_tx_notify {
|
||||
/* transmission of skb is completed and was successful */
|
||||
TX_NOTIFY_OK = 0,
|
||||
|
|
|
@ -320,13 +320,9 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
|
|||
struct sk_buff *nskb;
|
||||
int err, confirm_recv = 0;
|
||||
|
||||
memset(skb->head, 0, ETH_HLEN);
|
||||
phs_hdr = skb_push(skb, sizeof(struct af_iucv_trans_hdr));
|
||||
skb_reset_mac_header(skb);
|
||||
phs_hdr = skb_push(skb, sizeof(*phs_hdr));
|
||||
memset(phs_hdr, 0, sizeof(*phs_hdr));
|
||||
skb_reset_network_header(skb);
|
||||
skb_push(skb, ETH_HLEN);
|
||||
skb_reset_mac_header(skb);
|
||||
memset(phs_hdr, 0, sizeof(struct af_iucv_trans_hdr));
|
||||
|
||||
phs_hdr->magic = ETH_P_AF_IUCV;
|
||||
phs_hdr->version = 1;
|
||||
|
@ -350,6 +346,9 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
|
|||
if (imsg)
|
||||
memcpy(&phs_hdr->iucv_hdr, imsg, sizeof(struct iucv_message));
|
||||
|
||||
skb_push(skb, ETH_HLEN);
|
||||
memset(skb->data, 0, ETH_HLEN);
|
||||
|
||||
skb->dev = iucv->hs_dev;
|
||||
if (!skb->dev) {
|
||||
err = -ENODEV;
|
||||
|
@ -1943,8 +1942,7 @@ static void iucv_callback_shutdown(struct iucv_path *path, u8 ipuser[16])
|
|||
/***************** HiperSockets transport callbacks ********************/
|
||||
static void afiucv_swap_src_dest(struct sk_buff *skb)
|
||||
{
|
||||
struct af_iucv_trans_hdr *trans_hdr =
|
||||
(struct af_iucv_trans_hdr *)skb->data;
|
||||
struct af_iucv_trans_hdr *trans_hdr = iucv_trans_hdr(skb);
|
||||
char tmpID[8];
|
||||
char tmpName[8];
|
||||
|
||||
|
@ -1967,13 +1965,12 @@ static void afiucv_swap_src_dest(struct sk_buff *skb)
|
|||
**/
|
||||
static int afiucv_hs_callback_syn(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct af_iucv_trans_hdr *trans_hdr = iucv_trans_hdr(skb);
|
||||
struct sock *nsk;
|
||||
struct iucv_sock *iucv, *niucv;
|
||||
struct af_iucv_trans_hdr *trans_hdr;
|
||||
int err;
|
||||
|
||||
iucv = iucv_sk(sk);
|
||||
trans_hdr = (struct af_iucv_trans_hdr *)skb->data;
|
||||
if (!iucv) {
|
||||
/* no sock - connection refused */
|
||||
afiucv_swap_src_dest(skb);
|
||||
|
@ -2034,15 +2031,13 @@ out:
|
|||
static int afiucv_hs_callback_synack(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct iucv_sock *iucv = iucv_sk(sk);
|
||||
struct af_iucv_trans_hdr *trans_hdr =
|
||||
(struct af_iucv_trans_hdr *)skb->data;
|
||||
|
||||
if (!iucv)
|
||||
goto out;
|
||||
if (sk->sk_state != IUCV_BOUND)
|
||||
goto out;
|
||||
bh_lock_sock(sk);
|
||||
iucv->msglimit_peer = trans_hdr->window;
|
||||
iucv->msglimit_peer = iucv_trans_hdr(skb)->window;
|
||||
sk->sk_state = IUCV_CONNECTED;
|
||||
sk->sk_state_change(sk);
|
||||
bh_unlock_sock(sk);
|
||||
|
@ -2098,8 +2093,6 @@ out:
|
|||
static int afiucv_hs_callback_win(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct iucv_sock *iucv = iucv_sk(sk);
|
||||
struct af_iucv_trans_hdr *trans_hdr =
|
||||
(struct af_iucv_trans_hdr *)skb->data;
|
||||
|
||||
if (!iucv)
|
||||
return NET_RX_SUCCESS;
|
||||
|
@ -2107,7 +2100,7 @@ static int afiucv_hs_callback_win(struct sock *sk, struct sk_buff *skb)
|
|||
if (sk->sk_state != IUCV_CONNECTED)
|
||||
return NET_RX_SUCCESS;
|
||||
|
||||
atomic_sub(trans_hdr->window, &iucv->msg_sent);
|
||||
atomic_sub(iucv_trans_hdr(skb)->window, &iucv->msg_sent);
|
||||
iucv_sock_wake_msglim(sk);
|
||||
return NET_RX_SUCCESS;
|
||||
}
|
||||
|
@ -2170,22 +2163,13 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
|
|||
int err = NET_RX_SUCCESS;
|
||||
char nullstring[8];
|
||||
|
||||
if (skb->len < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr))) {
|
||||
WARN_ONCE(1, "AF_IUCV too short skb, len=%d, min=%d",
|
||||
(int)skb->len,
|
||||
(int)(ETH_HLEN + sizeof(struct af_iucv_trans_hdr)));
|
||||
if (!pskb_may_pull(skb, sizeof(*trans_hdr))) {
|
||||
WARN_ONCE(1, "AF_IUCV failed to receive skb, len=%u", skb->len);
|
||||
kfree_skb(skb);
|
||||
return NET_RX_SUCCESS;
|
||||
}
|
||||
if (skb_headlen(skb) < (ETH_HLEN + sizeof(struct af_iucv_trans_hdr)))
|
||||
if (skb_linearize(skb)) {
|
||||
WARN_ONCE(1, "AF_IUCV skb_linearize failed, len=%d",
|
||||
(int)skb->len);
|
||||
kfree_skb(skb);
|
||||
return NET_RX_SUCCESS;
|
||||
}
|
||||
skb_pull(skb, ETH_HLEN);
|
||||
trans_hdr = (struct af_iucv_trans_hdr *)skb->data;
|
||||
|
||||
trans_hdr = iucv_trans_hdr(skb);
|
||||
EBCASC(trans_hdr->destAppName, sizeof(trans_hdr->destAppName));
|
||||
EBCASC(trans_hdr->destUserID, sizeof(trans_hdr->destUserID));
|
||||
EBCASC(trans_hdr->srcAppName, sizeof(trans_hdr->srcAppName));
|
||||
|
|
Loading…
Reference in New Issue