aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth_core_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/net/qeth_core_main.c')
-rw-r--r--drivers/s390/net/qeth_core_main.c373
1 files changed, 155 insertions, 218 deletions
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 89e09e7b8fff..0078b5d217cc 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -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;
+
+ 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 {
- 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;
- }
+ 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) {