summaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-20 21:04:44 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-20 21:04:44 -0700
commitf8965467f366fd18f01feafb5db10512d7b4422c (patch)
tree3706a9cd779859271ca61b85c63a1bc3f82d626e /drivers/s390
parenta26272e5200765691e67d6780e52b32498fdb659 (diff)
parent2ec8c6bb5d8f3a62a79f463525054bae1e3d4487 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1674 commits) qlcnic: adding co maintainer ixgbe: add support for active DA cables ixgbe: dcb, do not tag tc_prio_control frames ixgbe: fix ixgbe_tx_is_paused logic ixgbe: always enable vlan strip/insert when DCB is enabled ixgbe: remove some redundant code in setting FCoE FIP filter ixgbe: fix wrong offset to fc_frame_header in ixgbe_fcoe_ddp ixgbe: fix header len when unsplit packet overflows to data buffer ipv6: Never schedule DAD timer on dead address ipv6: Use POSTDAD state ipv6: Use state_lock to protect ifa state ipv6: Replace inet6_ifaddr->dead with state cxgb4: notify upper drivers if the device is already up when they load cxgb4: keep interrupts available when the ports are brought down cxgb4: fix initial addition of MAC address cnic: Return SPQ credit to bnx2x after ring setup and shutdown. cnic: Convert cnic_local_flags to atomic ops. can: Fix SJA1000 command register writes on SMP systems bridge: fix build for CONFIG_SYSFS disabled ARCNET: Limit com20020 PCI ID matches for SOHARD cards ... Fix up various conflicts with pcmcia tree drivers/net/ {pcmcia/3c589_cs.c, wireless/orinoco/orinoco_cs.c and wireless/orinoco/spectrum_cs.c} and feature removal (Documentation/feature-removal-schedule.txt). Also fix a non-content conflict due to pm_qos_requirement getting renamed in the PM tree (now pm_qos_request) in net/mac80211/scan.c
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/net/ctcm_main.c6
-rw-r--r--drivers/s390/net/ctcm_mpc.c6
-rw-r--r--drivers/s390/net/lcs.c3
-rw-r--r--drivers/s390/net/qeth_core.h32
-rw-r--r--drivers/s390/net/qeth_core_main.c237
-rw-r--r--drivers/s390/net/qeth_core_mpc.h10
-rw-r--r--drivers/s390/net/qeth_core_sys.c151
-rw-r--r--drivers/s390/net/qeth_l2_main.c47
-rw-r--r--drivers/s390/net/qeth_l3_main.c108
-rw-r--r--drivers/s390/net/qeth_l3_sys.c244
10 files changed, 523 insertions, 321 deletions
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index e35713dd050..4ecafbf9121 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -1364,8 +1364,7 @@ static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type,
ch->protocol = priv->protocol;
if (IS_MPC(priv)) {
- ch->discontact_th = (struct th_header *)
- kzalloc(TH_HEADER_LENGTH, gfp_type());
+ ch->discontact_th = kzalloc(TH_HEADER_LENGTH, gfp_type());
if (ch->discontact_th == NULL)
goto nomem_return;
@@ -1379,8 +1378,7 @@ static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type,
} else
ccw_num = 8;
- ch->ccw = (struct ccw1 *)
- kzalloc(ccw_num * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
+ ch->ccw = kzalloc(ccw_num * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
if (ch->ccw == NULL)
goto nomem_return;
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c
index 5978b390153..87c24d2936d 100644
--- a/drivers/s390/net/ctcm_mpc.c
+++ b/drivers/s390/net/ctcm_mpc.c
@@ -669,8 +669,7 @@ static void ctcmpc_send_sweep_resp(struct channel *rch)
goto done;
}
- header = (struct th_sweep *)
- kmalloc(sizeof(struct th_sweep), gfp_type());
+ header = kmalloc(sizeof(struct th_sweep), gfp_type());
if (!header) {
dev_kfree_skb_any(sweep_skb);
@@ -1191,8 +1190,7 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
skb_pull(pskb, new_len); /* point to next PDU */
}
} else {
- mpcginfo = (struct mpcg_info *)
- kmalloc(sizeof(struct mpcg_info), gfp_type());
+ mpcginfo = kmalloc(sizeof(struct mpcg_info), gfp_type());
if (mpcginfo == NULL)
goto done;
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 9b19ea13b4d..0f19d540b65 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1238,8 +1238,7 @@ lcs_set_mc_addresses(struct lcs_card *card, struct in_device *in4_dev)
ipm = lcs_check_addr_entry(card, im4, buf);
if (ipm != NULL)
continue; /* Address already in list. */
- ipm = (struct lcs_ipm_list *)
- kzalloc(sizeof(struct lcs_ipm_list), GFP_ATOMIC);
+ ipm = kzalloc(sizeof(struct lcs_ipm_list), GFP_ATOMIC);
if (ipm == NULL) {
pr_info("Not enough memory to add"
" new multicast entry!\n");
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index fcd005aad98..7a44c38aaf6 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -179,25 +179,23 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
((prot == QETH_PROT_IPV6) ? \
qeth_is_enabled6(c, f) : qeth_is_enabled(c, f))
-#define QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT 0x0101
-#define QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT 0x0101
+#define QETH_IDX_FUNC_LEVEL_OSD 0x0101
#define QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT 0x4108
#define QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT 0x5108
#define QETH_MODELLIST_ARRAY \
- {{0x1731, 0x01, 0x1732, 0x01, QETH_CARD_TYPE_OSAE, 1, \
- QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
- QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
- QETH_MAX_QUEUES, 0}, \
- {0x1731, 0x05, 0x1732, 0x05, QETH_CARD_TYPE_IQD, 0, \
- QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \
- QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \
- QETH_MAX_QUEUES, 0x103}, \
- {0x1731, 0x06, 0x1732, 0x06, QETH_CARD_TYPE_OSN, 0, \
- QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \
- QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \
- QETH_MAX_QUEUES, 0}, \
- {0, 0, 0, 0, 0, 0, 0, 0, 0} }
+ {{0x1731, 0x01, 0x1732, QETH_CARD_TYPE_OSD, QETH_MAX_QUEUES, 0}, \
+ {0x1731, 0x05, 0x1732, QETH_CARD_TYPE_IQD, QETH_MAX_QUEUES, 0x103}, \
+ {0x1731, 0x06, 0x1732, QETH_CARD_TYPE_OSN, QETH_MAX_QUEUES, 0}, \
+ {0x1731, 0x02, 0x1732, QETH_CARD_TYPE_OSM, QETH_MAX_QUEUES, 0}, \
+ {0x1731, 0x02, 0x1732, QETH_CARD_TYPE_OSX, QETH_MAX_QUEUES, 0}, \
+ {0, 0, 0, 0, 0, 0} }
+#define QETH_CU_TYPE_IND 0
+#define QETH_CU_MODEL_IND 1
+#define QETH_DEV_TYPE_IND 2
+#define QETH_DEV_MODEL_IND 3
+#define QETH_QUEUE_NO_IND 4
+#define QETH_MULTICAST_IND 5
#define QETH_REAL_CARD 1
#define QETH_VLAN_CARD 2
@@ -351,7 +349,7 @@ enum qeth_header_ids {
#define QETH_HDR_EXT_SRC_MAC_ADDR 0x08
#define QETH_HDR_EXT_CSUM_HDR_REQ 0x10
#define QETH_HDR_EXT_CSUM_TRANSP_REQ 0x20
-#define QETH_HDR_EXT_UDP_TSO 0x40 /*bit off for TCP*/
+#define QETH_HDR_EXT_UDP 0x40 /*bit off for TCP*/
static inline int qeth_is_last_sbale(struct qdio_buffer_element *sbale)
{
@@ -630,6 +628,7 @@ struct qeth_card_info {
int unique_id;
struct qeth_card_blkt blkt;
__u32 csum_mask;
+ __u32 tx_csum_mask;
enum qeth_ipa_promisc_modes promisc_mode;
};
@@ -739,6 +738,7 @@ struct qeth_card {
atomic_t force_alloc_skb;
struct service_level qeth_service_level;
struct qdio_ssqd_desc ssqd;
+ struct mutex conf_mutex;
};
struct qeth_card_list_struct {
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 28f71349fde..13ef46b9d38 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -53,7 +53,7 @@ struct kmem_cache *qeth_core_header_cache;
EXPORT_SYMBOL_GPL(qeth_core_header_cache);
static struct device *qeth_core_root_dev;
-static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY;
+static unsigned int known_devices[][6] = QETH_MODELLIST_ARRAY;
static struct lock_class_key qdio_out_skb_queue_key;
static void qeth_send_control_data_cb(struct qeth_channel *,
@@ -111,21 +111,29 @@ static inline const char *qeth_get_cardname(struct qeth_card *card)
{
if (card->info.guestlan) {
switch (card->info.type) {
- case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSD:
return " Guest LAN QDIO";
case QETH_CARD_TYPE_IQD:
return " Guest LAN Hiper";
+ case QETH_CARD_TYPE_OSM:
+ return " Guest LAN QDIO - OSM";
+ case QETH_CARD_TYPE_OSX:
+ return " Guest LAN QDIO - OSX";
default:
return " unknown";
}
} else {
switch (card->info.type) {
- case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSD:
return " OSD Express";
case QETH_CARD_TYPE_IQD:
return " HiperSockets";
case QETH_CARD_TYPE_OSN:
return " OSN QDIO";
+ case QETH_CARD_TYPE_OSM:
+ return " OSM QDIO";
+ case QETH_CARD_TYPE_OSX:
+ return " OSX QDIO";
default:
return " unknown";
}
@@ -138,16 +146,20 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
{
if (card->info.guestlan) {
switch (card->info.type) {
- case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSD:
return "GuestLAN QDIO";
case QETH_CARD_TYPE_IQD:
return "GuestLAN Hiper";
+ case QETH_CARD_TYPE_OSM:
+ return "GuestLAN OSM";
+ case QETH_CARD_TYPE_OSX:
+ return "GuestLAN OSX";
default:
return "unknown";
}
} else {
switch (card->info.type) {
- case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSD:
switch (card->info.link_type) {
case QETH_LINK_TYPE_FAST_ETH:
return "OSD_100";
@@ -172,6 +184,10 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
return "HiperSockets";
case QETH_CARD_TYPE_OSN:
return "OSN";
+ case QETH_CARD_TYPE_OSM:
+ return "OSM_1000";
+ case QETH_CARD_TYPE_OSX:
+ return "OSX_10GIG";
default:
return "unknown";
}
@@ -419,7 +435,8 @@ void qeth_clear_ipacmd_list(struct qeth_card *card)
}
EXPORT_SYMBOL_GPL(qeth_clear_ipacmd_list);
-static int qeth_check_idx_response(unsigned char *buffer)
+static int qeth_check_idx_response(struct qeth_card *card,
+ unsigned char *buffer)
{
if (!buffer)
return 0;
@@ -434,6 +451,12 @@ static int qeth_check_idx_response(unsigned char *buffer)
QETH_DBF_TEXT(TRACE, 2, "ckidxres");
QETH_DBF_TEXT(TRACE, 2, " idxterm");
QETH_DBF_TEXT_(TRACE, 2, " rc%d", -EIO);
+ if (buffer[4] == 0xf6) {
+ dev_err(&card->gdev->dev,
+ "The qeth device is not configured "
+ "for the OSI layer required by z/VM\n");
+ return -EPERM;
+ }
return -EIO;
}
return 0;
@@ -528,18 +551,19 @@ static void qeth_send_control_data_cb(struct qeth_channel *channel,
struct qeth_ipa_cmd *cmd;
unsigned long flags;
int keep_reply;
+ int rc = 0;
QETH_DBF_TEXT(TRACE, 4, "sndctlcb");
card = CARD_FROM_CDEV(channel->ccwdev);
- if (qeth_check_idx_response(iob->data)) {
+ rc = qeth_check_idx_response(card, iob->data);
+ switch (rc) {
+ case 0:
+ break;
+ case -EIO:
qeth_clear_ipacmd_list(card);
- if (((iob->data[2] & 0xc0) == 0xc0) && iob->data[4] == 0xf6)
- dev_err(&card->gdev->dev,
- "The qeth device is not configured "
- "for the OSI layer required by z/VM\n");
- else
- qeth_schedule_recovery(card);
+ qeth_schedule_recovery(card);
+ default:
goto out;
}
@@ -606,7 +630,7 @@ static int qeth_setup_channel(struct qeth_channel *channel)
QETH_DBF_TEXT(SETUP, 2, "setupch");
for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) {
- channel->iob[cnt].data = (char *)
+ channel->iob[cnt].data =
kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL);
if (channel->iob[cnt].data == NULL)
break;
@@ -719,7 +743,7 @@ static int qeth_get_problem(struct ccw_device *cdev, struct irb *irb)
QETH_DBF_TEXT(TRACE, 2, "CGENCHK");
dev_warn(&cdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
- QETH_DBF_MESSAGE(2, "%s check on device dstat=x%x, cstat=x%x ",
+ QETH_DBF_MESSAGE(2, "%s check on device dstat=x%x, cstat=x%x\n",
dev_name(&cdev->dev), dstat, cstat);
print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET,
16, 1, irb, 64, 1);
@@ -998,9 +1022,8 @@ static void qeth_clean_channel(struct qeth_channel *channel)
kfree(channel->iob[cnt].data);
}
-static int qeth_is_1920_device(struct qeth_card *card)
+static void qeth_get_channel_path_desc(struct qeth_card *card)
{
- int single_queue = 0;
struct ccw_device *ccwdev;
struct channelPath_dsc {
u8 flags;
@@ -1013,17 +1036,25 @@ static int qeth_is_1920_device(struct qeth_card *card)
u8 chpp;
} *chp_dsc;
- QETH_DBF_TEXT(SETUP, 2, "chk_1920");
+ QETH_DBF_TEXT(SETUP, 2, "chp_desc");
ccwdev = card->data.ccwdev;
chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0);
if (chp_dsc != NULL) {
/* CHPP field bit 6 == 1 -> single queue */
- single_queue = ((chp_dsc->chpp & 0x02) == 0x02);
+ if ((chp_dsc->chpp & 0x02) == 0x02)
+ card->qdio.no_out_queues = 1;
+ card->info.func_level = 0x4100 + chp_dsc->desc;
kfree(chp_dsc);
}
- QETH_DBF_TEXT_(SETUP, 2, "rc:%x", single_queue);
- return single_queue;
+ if (card->qdio.no_out_queues == 1) {
+ card->qdio.default_out_queue = 0;
+ dev_info(&card->gdev->dev,
+ "Priority Queueing not supported\n");
+ }
+ QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues);
+ QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level);
+ return;
}
static void qeth_init_qdio_info(struct qeth_card *card)
@@ -1100,6 +1131,7 @@ static int qeth_setup_card(struct qeth_card *card)
spin_lock_init(&card->lock);
spin_lock_init(&card->ip_lock);
spin_lock_init(&card->thread_mask_lock);
+ mutex_init(&card->conf_mutex);
card->thread_start_mask = 0;
card->thread_allowed_mask = 0;
card->thread_running_mask = 0;
@@ -1170,18 +1202,17 @@ static int qeth_determine_card_type(struct qeth_card *card)
card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
- while (known_devices[i][4]) {
- if ((CARD_RDEV(card)->id.dev_type == known_devices[i][2]) &&
- (CARD_RDEV(card)->id.dev_model == known_devices[i][3])) {
- card->info.type = known_devices[i][4];
- card->qdio.no_out_queues = known_devices[i][8];
- card->info.is_multicast_different = known_devices[i][9];
- if (qeth_is_1920_device(card)) {
- dev_info(&card->gdev->dev,
- "Priority Queueing not supported\n");
- card->qdio.no_out_queues = 1;
- card->qdio.default_out_queue = 0;
- }
+ while (known_devices[i][QETH_DEV_MODEL_IND]) {
+ if ((CARD_RDEV(card)->id.dev_type ==
+ known_devices[i][QETH_DEV_TYPE_IND]) &&
+ (CARD_RDEV(card)->id.dev_model ==
+ known_devices[i][QETH_DEV_MODEL_IND])) {
+ card->info.type = known_devices[i][QETH_DEV_MODEL_IND];
+ card->qdio.no_out_queues =
+ known_devices[i][QETH_QUEUE_NO_IND];
+ card->info.is_multicast_different =
+ known_devices[i][QETH_MULTICAST_IND];
+ qeth_get_channel_path_desc(card);
return 0;
}
i++;
@@ -1399,22 +1430,20 @@ static void qeth_init_tokens(struct qeth_card *card)
static void qeth_init_func_level(struct qeth_card *card)
{
- if (card->ipato.enabled) {
- if (card->info.type == QETH_CARD_TYPE_IQD)
- card->info.func_level =
- QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT;
- else
- card->info.func_level =
- QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT;
- } else {
- if (card->info.type == QETH_CARD_TYPE_IQD)
- /*FIXME:why do we have same values for dis and ena for
- osae??? */
+ switch (card->info.type) {
+ case QETH_CARD_TYPE_IQD:
+ if (card->ipato.enabled)
card->info.func_level =
- QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
+ QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT;
else
card->info.func_level =
- QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT;
+ QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT;
+ break;
+ case QETH_CARD_TYPE_OSD:
+ card->info.func_level = QETH_IDX_FUNC_LEVEL_OSD;
+ break;
+ default:
+ break;
}
}
@@ -1561,7 +1590,7 @@ static void qeth_idx_write_cb(struct qeth_channel *channel,
card = CARD_FROM_CDEV(channel->ccwdev);
if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
- if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+ if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == QETH_IDX_ACT_ERR_EXCL)
dev_err(&card->write.ccwdev->dev,
"The adapter is used exclusively by another "
"host\n");
@@ -1597,27 +1626,35 @@ static void qeth_idx_read_cb(struct qeth_channel *channel,
}
card = CARD_FROM_CDEV(channel->ccwdev);
- if (qeth_check_idx_response(iob->data))
+ if (qeth_check_idx_response(card, iob->data))
goto out;
if (!(QETH_IS_IDX_ACT_POS_REPLY(iob->data))) {
- if (QETH_IDX_ACT_CAUSE_CODE(iob->data) == 0x19)
+ switch (QETH_IDX_ACT_CAUSE_CODE(iob->data)) {
+ case QETH_IDX_ACT_ERR_EXCL:
dev_err(&card->write.ccwdev->dev,
"The adapter is used exclusively by another "
"host\n");
- else
+ break;
+ case QETH_IDX_ACT_ERR_AUTH:
+ dev_err(&card->read.ccwdev->dev,
+ "Setting the device online failed because of "
+ "insufficient LPAR authorization\n");
+ break;
+ default:
QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on read channel:"
" negative reply\n",
dev_name(&card->read.ccwdev->dev));
+ }
goto out;
}
/**
- * temporary fix for microcode bug
- * to revert it,replace OR by AND
- */
+ * * temporary fix for microcode bug
+ * * to revert it,replace OR by AND
+ * */
if ((!QETH_IDX_NO_PORTNAME_REQUIRED(iob->data)) ||
- (card->info.type == QETH_CARD_TYPE_OSAE))
+ (card->info.type == QETH_CARD_TYPE_OSD))
card->info.portname_required = 1;
memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);
@@ -1826,7 +1863,7 @@ static inline int qeth_get_initial_mtu_for_card(struct qeth_card *card)
return 1500;
case QETH_CARD_TYPE_IQD:
return card->info.max_mtu;
- case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSD:
switch (card->info.link_type) {
case QETH_LINK_TYPE_HSTR:
case QETH_LINK_TYPE_LANE_TR:
@@ -1834,6 +1871,9 @@ static inline int qeth_get_initial_mtu_for_card(struct qeth_card *card)
default:
return 1492;
}
+ case QETH_CARD_TYPE_OSM:
+ case QETH_CARD_TYPE_OSX:
+ return 1492;
default:
return 1500;
}
@@ -1844,8 +1884,10 @@ static inline int qeth_get_max_mtu_for_card(int cardtype)
switch (cardtype) {
case QETH_CARD_TYPE_UNKNOWN:
- case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSD:
case QETH_CARD_TYPE_OSN:
+ case QETH_CARD_TYPE_OSM:
+ case QETH_CARD_TYPE_OSX:
return 61440;
case QETH_CARD_TYPE_IQD:
return 57344;
@@ -1883,7 +1925,9 @@ static inline int qeth_get_mtu_outof_framesize(int framesize)
static inline int qeth_mtu_is_valid(struct qeth_card *card, int mtu)
{
switch (card->info.type) {
- case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSD:
+ case QETH_CARD_TYPE_OSM:
+ case QETH_CARD_TYPE_OSX:
return ((mtu >= 576) && (mtu <= 61440));
case QETH_CARD_TYPE_IQD:
return ((mtu >= 576) &&
@@ -1934,6 +1978,7 @@ static int qeth_ulp_enable_cb(struct qeth_card *card, struct qeth_reply *reply,
card->info.link_type = link_type;
} else
card->info.link_type = 0;
+ QETH_DBF_TEXT_(SETUP, 2, "link%d", link_type);
QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
return 0;
}
@@ -1977,6 +2022,7 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
unsigned long data)
{
struct qeth_cmd_buffer *iob;
+ int rc = 0;
QETH_DBF_TEXT(SETUP, 2, "ulpstpcb");
@@ -1984,8 +2030,15 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
memcpy(&card->token.ulp_connection_r,
QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
QETH_MPC_TOKEN_LENGTH);
+ if (!strncmp("00S", QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(iob->data),
+ 3)) {
+ QETH_DBF_TEXT(SETUP, 2, "olmlimit");
+ dev_err(&card->gdev->dev, "A connection could not be "
+ "established because of an OLM limit\n");
+ rc = -EMLINK;
+ }
QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc);
- return 0;
+ return rc;
}
static int qeth_ulp_setup(struct qeth_card *card)
@@ -2238,7 +2291,9 @@ static void qeth_print_status_no_portname(struct qeth_card *card)
void qeth_print_status_message(struct qeth_card *card)
{
switch (card->info.type) {
- case QETH_CARD_TYPE_OSAE:
+ case QETH_CARD_TYPE_OSD:
+ case QETH_CARD_TYPE_OSM:
+ case QETH_CARD_TYPE_OSX:
/* VM will use a non-zero first character
* to indicate a HiperSockets like reporting
* of the level OSA sets the first character to zero
@@ -2545,9 +2600,11 @@ static int qeth_query_setadapterparms_cb(struct qeth_card *card,
QETH_DBF_TEXT(TRACE, 3, "quyadpcb");
cmd = (struct qeth_ipa_cmd *) data;
- if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f)
+ if (cmd->data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f) {
card->info.link_type =
cmd->data.setadapterparms.data.query_cmds_supp.lan_type;
+ QETH_DBF_TEXT_(SETUP, 2, "lnk %d", card->info.link_type);
+ }
card->options.adp.supported_funcs =
cmd->data.setadapterparms.data.query_cmds_supp.supported_cmds;
return qeth_default_setadapterparms_cb(card, reply, (unsigned long)cmd);
@@ -2937,7 +2994,8 @@ EXPORT_SYMBOL_GPL(qeth_qdio_output_handler);
int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
int ipv, int cast_type)
{
- if (!ipv && (card->info.type == QETH_CARD_TYPE_OSAE))
+ if (!ipv && (card->info.type == QETH_CARD_TYPE_OSD ||
+ card->info.type == QETH_CARD_TYPE_OSX))
return card->qdio.default_out_queue;
switch (card->qdio.no_out_queues) {
case 4:
@@ -3499,13 +3557,14 @@ int qeth_set_access_ctrl_online(struct qeth_card *card)
QETH_DBF_TEXT(TRACE, 4, "setactlo");
- if (card->info.type == QETH_CARD_TYPE_OSAE &&
- qeth_adp_supported(card, IPA_SETADP_SET_ACCESS_CONTROL)) {
+ if ((card->info.type == QETH_CARD_TYPE_OSD ||
+ card->info.type == QETH_CARD_TYPE_OSX) &&
+ qeth_adp_supported(card, IPA_SETADP_SET_ACCESS_CONTROL)) {
rc = qeth_setadpparms_set_access_ctrl(card,
card->options.isolation);
if (rc) {
QETH_DBF_MESSAGE(3,
- "IPA(SET_ACCESS_CTRL,%s,%d) sent failed",
+ "IPA(SET_ACCESS_CTRL,%s,%d) sent failed\n",
card->gdev->dev.kobj.name,
rc);
}
@@ -3845,9 +3904,16 @@ static void qeth_core_free_card(struct qeth_card *card)
}
static struct ccw_device_id qeth_ids[] = {
- {CCW_DEVICE(0x1731, 0x01), .driver_info = QETH_CARD_TYPE_OSAE},
- {CCW_DEVICE(0x1731, 0x05), .driver_info = QETH_CARD_TYPE_IQD},
- {CCW_DEVICE(0x1731, 0x06), .driver_info = QETH_CARD_TYPE_OSN},
+ {CCW_DEVICE_DEVTYPE(0x1731, 0x01, 0x1732, 0x01),
+ .driver_info = QETH_CARD_TYPE_OSD},
+ {CCW_DEVICE_DEVTYPE(0x1731, 0x05, 0x1732, 0x05),
+ .driver_info = QETH_CARD_TYPE_IQD},
+ {CCW_DEVICE_DEVTYPE(0x1731, 0x06, 0x1732, 0x06),
+ .driver_info = QETH_CARD_TYPE_OSN},
+ {CCW_DEVICE_DEVTYPE(0x1731, 0x02, 0x1732, 0x03),
+ .driver_info = QETH_CARD_TYPE_OSM},
+ {CCW_DEVICE_DEVTYPE(0x1731, 0x02, 0x1732, 0x02),
+ .driver_info = QETH_CARD_TYPE_OSX},
{},
};
MODULE_DEVICE_TABLE(ccw, qeth_ids);
@@ -4251,25 +4317,25 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
goto err_card;
}
- if (card->info.type == QETH_CARD_TYPE_OSN) {
+ if (card->info.type == QETH_CARD_TYPE_OSN)
rc = qeth_core_create_osn_attributes(dev);
- if (rc)
- goto err_card;
+ else
+ rc = qeth_core_create_device_attributes(dev);
+ if (rc)
+ goto err_card;
+ switch (card->info.type) {
+ case QETH_CARD_TYPE_OSN:
+ case QETH_CARD_TYPE_OSM:
rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
- if (rc) {
- qeth_core_remove_osn_attributes(dev);
- goto err_card;
- }
+ if (rc)
+ goto err_attr;
rc = card->discipline.ccwgdriver->probe(card->gdev);
- if (rc) {
- qeth_core_free_discipline(card);
- qeth_core_remove_osn_attributes(dev);
- goto err_card;
- }
- } else {
- rc = qeth_core_create_device_attributes(dev);
if (rc)
- goto err_card;
+ goto err_disc;
+ case QETH_CARD_TYPE_OSD:
+ case QETH_CARD_TYPE_OSX:
+ default:
+ break;
}
write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
@@ -4279,6 +4345,13 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
qeth_determine_capabilities(card);
return 0;
+err_disc:
+ qeth_core_free_discipline(card);
+err_attr:
+ if (card->info.type == QETH_CARD_TYPE_OSN)
+ qeth_core_remove_osn_attributes(dev);
+ else
+ qeth_core_remove_device_attributes(dev);
err_card:
qeth_core_free_card(card);
err_dev:
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
index 104a3351e02..f9ed24de751 100644
--- a/drivers/s390/net/qeth_core_mpc.h
+++ b/drivers/s390/net/qeth_core_mpc.h
@@ -48,9 +48,11 @@ extern unsigned char IPA_PDU_HEADER[];
enum qeth_card_types {
QETH_CARD_TYPE_UNKNOWN = 0,
- QETH_CARD_TYPE_OSAE = 10,
- QETH_CARD_TYPE_IQD = 1234,
- QETH_CARD_TYPE_OSN = 11,
+ QETH_CARD_TYPE_OSD = 1,
+ QETH_CARD_TYPE_IQD = 5,
+ QETH_CARD_TYPE_OSN = 6,
+ QETH_CARD_TYPE_OSM = 3,
+ QETH_CARD_TYPE_OSX = 2,
};
#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18
@@ -614,6 +616,8 @@ extern unsigned char IDX_ACTIVATE_WRITE[];
#define QETH_IS_IDX_ACT_POS_REPLY(buffer) (((buffer)[0x08] & 3) == 2)
#define QETH_IDX_REPLY_LEVEL(buffer) (buffer + 0x12)
#define QETH_IDX_ACT_CAUSE_CODE(buffer) (buffer)[0x09]
+#define QETH_IDX_ACT_ERR_EXCL 0x19
+#define QETH_IDX_ACT_ERR_AUTH 0x1E
#define PDU_ENCAPSULATION(buffer) \
(buffer + *(buffer + (*(buffer + 0x0b)) + \
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index 25dfd5abd19..2eb022ff261 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -122,23 +122,32 @@ static ssize_t qeth_dev_portno_store(struct device *dev,
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
unsigned int portno, limit;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
portno = simple_strtoul(buf, &tmp, 16);
- if (portno > QETH_MAX_PORTNO)
- return -EINVAL;
+ if (portno > QETH_MAX_PORTNO) {
+ rc = -EINVAL;
+ goto out;
+ }
limit = (card->ssqd.pcnt ? card->ssqd.pcnt - 1 : card->ssqd.pcnt);
- if (portno > limit)
- return -EINVAL;
-
+ if (portno > limit) {
+ rc = -EINVAL;
+ goto out;
+ }
card->info.portno = portno;
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
@@ -165,18 +174,23 @@ static ssize_t qeth_dev_portname_store(struct device *dev,
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
- int i;
+ int i, rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
tmp = strsep((char **) &buf, "\n");
- if ((strlen(tmp) > 8) || (strlen(tmp) == 0))
- return -EINVAL;
+ if ((strlen(tmp) > 8) || (strlen(tmp) == 0)) {
+ rc = -EINVAL;
+ goto out;
+ }
card->info.portname[0] = strlen(tmp);
/* for beauty reasons */
@@ -184,8 +198,9 @@ static ssize_t qeth_dev_portname_store(struct device *dev,
card->info.portname[i] = ' ';
strcpy(card->info.portname + 1, tmp);
ASCEBC(card->info.portname + 1, 8);
-
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
@@ -215,20 +230,25 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev,
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
/* check if 1920 devices are supported ,
* if though we have to permit priority queueing
*/
if (card->qdio.no_out_queues == 1) {
card->qdio.do_prio_queueing = QETH_PRIOQ_DEFAULT;
- return -EPERM;
+ rc = -EPERM;
+ goto out;
}
tmp = strsep((char **) &buf, "\n");
@@ -251,10 +271,11 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev,
} else if (!strcmp(tmp, "no_prio_queueing")) {
card->qdio.do_prio_queueing = QETH_NO_PRIO_QUEUEING;
card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
- } else {
- return -EINVAL;
- }
- return count;
+ } else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
@@ -277,14 +298,17 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev,
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
int cnt, old_cnt;
- int rc;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
old_cnt = card->qdio.in_buf_pool.buf_count;
cnt = simple_strtoul(buf, &tmp, 10);
@@ -293,7 +317,9 @@ static ssize_t qeth_dev_bufcnt_store(struct device *dev,
if (old_cnt != cnt) {
rc = qeth_realloc_buffer_pool(card, cnt);
}
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show,
@@ -337,25 +363,27 @@ static ssize_t qeth_dev_performance_stats_store(struct device *dev,
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
- int i;
+ int i, rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
i = simple_strtoul(buf, &tmp, 16);
if ((i == 0) || (i == 1)) {
if (i == card->options.performance_stats)
- return count;
+ goto out;;
card->options.performance_stats = i;
if (i == 0)
memset(&card->perf_stats, 0,
sizeof(struct qeth_perf_stats));
card->perf_stats.initial_rx_packets = card->stats.rx_packets;
card->perf_stats.initial_tx_packets = card->stats.tx_packets;
- } else {
- return -EINVAL;
- }
- return count;
+ } else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
@@ -377,15 +405,17 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
- int i, rc;
+ int i, rc = 0;
enum qeth_discipline_id newdis;
if (!card)
return -EINVAL;
- if (((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)))
- return -EPERM;
+ mutex_lock(&card->conf_mutex);
+ if (card->state != CARD_STATE_DOWN) {
+ rc = -EPERM;
+ goto out;
+ }
i = simple_strtoul(buf, &tmp, 16);
switch (i) {
@@ -396,12 +426,13 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
newdis = QETH_DISCIPLINE_LAYER2;
break;
default:
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
- if (card->options.layer2 == newdis) {
- return count;
- } else {
+ if (card->options.layer2 == newdis)
+ goto out;
+ else {
if (card->discipline.ccwgdriver) {
card->discipline.ccwgdriver->remove(card->gdev);
qeth_core_free_discipline(card);
@@ -410,12 +441,12 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
rc = qeth_core_load_discipline(card, newdis);
if (rc)
- return rc;
+ goto out;
rc = card->discipline.ccwgdriver->probe(card->gdev);
- if (rc)
- return rc;
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
@@ -454,13 +485,13 @@ static ssize_t qeth_dev_isolation_store(struct device *dev,
char *tmp, *curtoken;
curtoken = (char *) buf;
- if (!card) {
- rc = -EINVAL;
- goto out;
- }
+ if (!card)
+ return -EINVAL;
+ mutex_lock(&card->conf_mutex);
/* check for unknown, too, in case we do not yet know who we are */
- if (card->info.type != QETH_CARD_TYPE_OSAE &&
+ if (card->info.type != QETH_CARD_TYPE_OSD &&
+ card->info.type != QETH_CARD_TYPE_OSX &&
card->info.type != QETH_CARD_TYPE_UNKNOWN) {
rc = -EOPNOTSUPP;
dev_err(&card->gdev->dev, "Adapter does not "
@@ -491,6 +522,7 @@ static ssize_t qeth_dev_isolation_store(struct device *dev,
rc = ipa_rc;
}
out:
+ mutex_unlock(&card->conf_mutex);
return rc;
}
@@ -510,22 +542,25 @@ static ssize_t qeth_dev_blkt_store(struct qeth_card *card,
const char *buf, size_t count, int *value, int max_value)
{
char *tmp;
- int i;
+ int i, rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
-
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
i = simple_strtoul(buf, &tmp, 10);
- if (i <= max_value) {
+ if (i <= max_value)
*value = i;
- } else {
- return -EINVAL;
- }
- return count;
+ else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_dev_blkt_total_show(struct device *dev,
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 6a801dc3bf8..d43f57a4ac6 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -56,7 +56,9 @@ static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
break;
case SIOC_QETH_GET_CARD_TYPE:
- if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
+ if ((card->info.type == QETH_CARD_TYPE_OSD ||
+ card->info.type == QETH_CARD_TYPE_OSM ||
+ card->info.type == QETH_CARD_TYPE_OSX) &&
!card->info.guestlan)
return 1;
return 0;
@@ -309,6 +311,10 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
struct qeth_vlan_vid *id;
QETH_DBF_TEXT_(TRACE, 4, "aid:%d", vid);
+ if (card->info.type == QETH_CARD_TYPE_OSM) {
+ QETH_DBF_TEXT(TRACE, 3, "aidOSM");
+ return;
+ }
if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
QETH_DBF_TEXT(TRACE, 3, "aidREC");
return;
@@ -329,6 +335,10 @@ static void qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
struct qeth_card *card = dev->ml_priv;
QETH_DBF_TEXT_(TRACE, 4, "kid:%d", vid);
+ if (card->info.type == QETH_CARD_TYPE_OSM) {
+ QETH_DBF_TEXT(TRACE, 3, "kidOSM");
+ return;
+ }
if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
QETH_DBF_TEXT(TRACE, 3, "kidREC");
return;
@@ -559,8 +569,10 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
"device %s: x%x\n", CARD_BUS_ID(card), rc);
}
- if ((card->info.type == QETH_CARD_TYPE_IQD) ||
- (card->info.guestlan)) {
+ if (card->info.type == QETH_CARD_TYPE_IQD ||
+ card->info.type == QETH_CARD_TYPE_OSM ||
+ card->info.type == QETH_CARD_TYPE_OSX ||
+ card->info.guestlan) {
rc = qeth_setadpparms_change_macaddr(card);
if (rc) {
QETH_DBF_MESSAGE(2, "couldn't get MAC address on "
@@ -589,8 +601,10 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
return -EOPNOTSUPP;
}
- if (card->info.type == QETH_CARD_TYPE_OSN) {
- QETH_DBF_TEXT(TRACE, 3, "setmcOSN");
+ if (card->info.type == QETH_CARD_TYPE_OSN ||
+ card->info.type == QETH_CARD_TYPE_OSM ||
+ card->info.type == QETH_CARD_TYPE_OSX) {
+ QETH_DBF_TEXT(TRACE, 3, "setmcTYP");
return -EOPNOTSUPP;
}
QETH_DBF_TEXT_(TRACE, 3, "%s", CARD_BUS_ID(card));
@@ -608,7 +622,6 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
static void qeth_l2_set_multicast_list(struct net_device *dev)
{
struct qeth_card *card = dev->ml_priv;
- struct dev_addr_list *dm;
struct netdev_hw_addr *ha;
if (card->info.type == QETH_CARD_TYPE_OSN)
@@ -620,8 +633,8 @@ static void qeth_l2_set_multicast_list(struct net_device *dev)
return;
qeth_l2_del_all_mc(card);
spin_lock_bh(&card->mclock);
- for (dm = dev->mc_list; dm; dm = dm->next)
- qeth_l2_add_mc(card, dm->da_addr, 0);
+ netdev_for_each_mc_addr(ha, dev)
+ qeth_l2_add_mc(card, ha->addr, 0);
netdev_for_each_uc_addr(ha, dev)
qeth_l2_add_mc(card, ha->addr, 1);
@@ -886,9 +899,6 @@ static const struct net_device_ops qeth_l2_netdev_ops = {
static int qeth_l2_setup_netdev(struct qeth_card *card)
{
switch (card->info.type) {
- case QETH_CARD_TYPE_OSAE:
- card->dev = alloc_etherdev(0);
- break;
case QETH_CARD_TYPE_IQD:
card->dev = alloc_netdev(0, "hsi%d", ether_setup);
break;
@@ -925,6 +935,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
enum qeth_card_states recover_flag;
BUG_ON(!card);
+ mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 2, "setonlin");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
@@ -957,18 +968,21 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
dev_warn(&card->gdev->dev,
"The LAN is offline\n");
card->lan_online = 0;
- return 0;
+ goto out;
}
rc = -ENODEV;
goto out_remove;
} else
card->lan_online = 1;
- if (card->info.type != QETH_CARD_TYPE_OSN) {
+ if ((card->info.type == QETH_CARD_TYPE_OSD) ||
+ (card->info.type == QETH_CARD_TYPE_OSX))
/* configure isolation level */
qeth_set_access_ctrl_online(card);
+
+ if (card->info.type != QETH_CARD_TYPE_OSN &&
+ card->info.type != QETH_CARD_TYPE_OSM)
qeth_l2_process_vlans(card, 0);
- }
netif_tx_disable(card->dev);
@@ -996,6 +1010,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
}
/* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
+out:
+ mutex_unlock(&card->conf_mutex);
return 0;
out_remove:
@@ -1008,6 +1024,7 @@ out_remove:
card->state = CARD_STATE_RECOVER;
else
card->state = CARD_STATE_DOWN;
+ mutex_unlock(&card->conf_mutex);
return rc;
}
@@ -1023,6 +1040,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
int rc = 0, rc2 = 0, rc3 = 0;
enum qeth_card_states recover_flag;
+ mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 3, "setoffl");
QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
@@ -1041,6 +1059,7 @@ static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
card->state = CARD_STATE_RECOVER;
/* let user_space know that device is offline */
kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
+ mutex_unlock(&card->conf_mutex);
return 0;
}
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index fc6ca1da8b9..61adae21a46 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -54,16 +54,16 @@ int qeth_l3_set_large_send(struct qeth_card *card,
if (card->options.large_send == QETH_LARGE_SEND_TSO) {
if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
- NETIF_F_HW_CSUM;
+ NETIF_F_IP_CSUM;
} else {
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
- NETIF_F_HW_CSUM);
+ NETIF_F_IP_CSUM);
card->options.large_send = QETH_LARGE_SEND_NO;
rc = -EOPNOTSUPP;
}
} else {
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
- NETIF_F_HW_CSUM);
+ NETIF_F_IP_CSUM);
card->options.large_send = QETH_LARGE_SEND_NO;
}
return rc;
@@ -1108,6 +1108,13 @@ static int qeth_l3_default_setassparms_cb(struct qeth_card *card,
card->info.csum_mask = cmd->data.setassparms.data.flags_32bit;
QETH_DBF_TEXT_(TRACE, 3, "csum:%d", card->info.csum_mask);
}
+ if (cmd->data.setassparms.hdr.assist_no == IPA_OUTBOUND_CHECKSUM &&
+ cmd->data.setassparms.hdr.command_code == IPA_CMD_ASS_START) {
+ card->info.tx_csum_mask =
+ cmd->data.setassparms.data.flags_32bit;
+ QETH_DBF_TEXT_(TRACE, 3, "tcsu:%d", card->info.tx_csum_mask);
+ }
+
return 0;
}
@@ -1536,6 +1543,28 @@ static int qeth_l3_start_ipa_checksum(struct qeth_card *card)
return rc;
}
+static int qeth_l3_start_ipa_tx_checksum(struct qeth_card *card)
+{
+ int rc = 0;
+
+ if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
+ return rc;
+ rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_CHECKSUM,
+ IPA_CMD_ASS_START, 0);
+ if (rc)
+ goto err_out;
+ rc = qeth_l3_send_simple_setassparms(card, IPA_OUTBOUND_CHECKSUM,
+ IPA_CMD_ASS_ENABLE, card->info.tx_csum_mask);
+ if (rc)
+ goto err_out;
+ dev_info(&card->gdev->dev, "HW TX Checksumming enabled\n");
+ return rc;
+err_out:
+ dev_warn(&card->gdev->dev, "Enabling HW TX checksumming for %s "
+ "failed, using SW TX checksumming\n", QETH_CARD_IFNAME(card));
+ return rc;
+}
+
static int qeth_l3_start_ipa_tso(struct qeth_card *card)
{
int rc;
@@ -1578,6 +1607,7 @@ static int qeth_l3_start_ipassists(struct qeth_card *card)
qeth_l3_start_ipa_ipv6(card); /* go on*/
qeth_l3_start_ipa_broadcast(card); /* go on*/
qeth_l3_start_ipa_checksum(card); /* go on*/
+ qeth_l3_start_ipa_tx_checksum(card);
qeth_l3_start_ipa_tso(card); /* go on*/
return 0;
}
@@ -1929,7 +1959,7 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
in6_dev = in6_dev_get(vlan_group_get_device(card->vlangrp, vid));
if (!in6_dev)
return;
- for (ifa = in6_dev->addr_list; ifa; ifa = ifa->lst_next) {
+ list_for_each_entry(ifa, &in6_dev->addr_list, if_list) {
addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
if (addr) {
memcpy(&addr->u.a6.addr, &ifa->addr,
@@ -2681,7 +2711,8 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
break;
case SIOC_QETH_GET_CARD_TYPE:
- if ((card->info.type == QETH_CARD_TYPE_OSAE) &&
+ if ((card->info.type == QETH_CARD_TYPE_OSD ||
+ card->info.type == QETH_CARD_TYPE_OSX) &&
!card->info.guestlan)
return 1;
return 0;
@@ -2817,6 +2848,21 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
}
}
+static inline void qeth_l3_hdr_csum(struct qeth_card *card,
+ struct qeth_hdr *hdr, struct sk_buff *skb)
+{
+ struct iphdr *iph = ip_hdr(skb);
+
+ /* tcph->check contains already the pseudo hdr checksum
+ * so just set the header flags
+ */
+ if (iph->protocol == IPPROTO_UDP)
+ hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_UDP;
+ hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ;
+ if (card->options.performance_stats)
+ card->perf_stats.tx_csum++;
+}
+
static void qeth_tso_fill_header(struct qeth_card *card,
struct qeth_hdr *qhdr, struct sk_buff *skb)
{
@@ -2852,21 +2898,6 @@ static void qeth_tso_fill_header(struct qeth_card *card,
}
}
-static void qeth_tx_csum(struct sk_buff *skb)
-{
- __wsum csum;
- int offset;
-
- skb_set_transport_header(skb, skb->csum_start - skb_headroom(skb));
- offset = skb->csum_start - skb_headroom(skb);
- BUG_ON(offset >= skb_headlen(skb));
- csum = skb_checksum(skb, offset, skb->len - offset, 0);
-
- offset += skb->csum_offset;
- BUG_ON(offset + sizeof(__sum16) > skb_headlen(skb));
- *(__sum16 *)(skb->data + offset) = csum_fold(csum);
-}
-
static inline int qeth_l3_tso_elements(struct sk_buff *skb)
{
unsigned long tcpd = (unsigned long)tcp_hdr(skb) +
@@ -2923,12 +2954,6 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb_is_gso(skb))
large_send = card->options.large_send;
- else
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- qeth_tx_csum(skb);
- if (card->options.performance_stats)
- card->perf_stats.tx_csum++;
- }
if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) &&
(skb_shinfo(skb)->nr_frags == 0)) {
@@ -3007,6 +3032,9 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
cast_type);
hdr->hdr.l3.length = new_skb->len - data_offset;
}
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL)
+ qeth_l3_hdr_csum(card, hdr, new_skb);
}
elems = qeth_get_elements_no(card, (void *)hdr, new_skb,
@@ -3132,10 +3160,25 @@ static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data)
return rc;
}
+static int qeth_l3_ethtool_set_tx_csum(struct net_device *dev, u32 data)
+{
+ struct qeth_card *card = dev->ml_priv;
+
+ if (data) {
+ if (qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
+ dev->features |= NETIF_F_IP_CSUM;
+ else
+ return -EPERM;
+ } else
+ dev->features &= ~NETIF_F_IP_CSUM;
+
+ return 0;
+}
+
static const struct ethtool_ops qeth_l3_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_tx_csum = ethtool_op_get_tx_csum,
- .set_tx_csum = ethtool_op_set_tx_hw_csum,
+ .set_tx_csum = qeth_l3_ethtool_set_tx_csum,
.get_rx_csum = qeth_l3_ethtool_get_rx_csum,
.set_rx_csum = qeth_l3_ethtool_set_rx_csum,
.get_sg = ethtool_op_get_sg,
@@ -3206,7 +3249,8 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = {
static int qeth_l3_setup_netdev(struct qeth_card *card)
{
- if (card->info.type == QETH_CARD_TYPE_OSAE) {
+ if (card->info.type == QETH_CARD_TYPE_OSD ||
+ card->info.type == QETH_CARD_TYPE_OSX) {
if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) ||
(card->info.link_type == QETH_LINK_TYPE_HSTR)) {
#ifdef CONFIG_TR
@@ -3336,6 +3380,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
enum qeth_card_states recover_flag;
BUG_ON(!card);
+ mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 2, "setonlin");
QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
@@ -3367,7 +3412,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
dev_warn(&card->gdev->dev,
"The LAN is offline\n");
card->lan_online = 0;
- return 0;
+ goto out;
}
rc = -ENODEV;
goto out_remove;
@@ -3414,6 +3459,8 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
}
/* let user_space know that device is online */
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
+out:
+ mutex_unlock(&card->conf_mutex);
return 0;
out_remove:
card->use_hard_stop = 1;
@@ -3425,6 +3472,7 @@ out_remove:
card->state = CARD_STATE_RECOVER;
else
card->state = CARD_STATE_DOWN;
+ mutex_unlock(&card->conf_mutex);
return rc;
}
@@ -3440,6 +3488,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
int rc = 0, rc2 = 0, rc3 = 0;
enum qeth_card_states recover_flag;
+ mutex_lock(&card->conf_mutex);
QETH_DBF_TEXT(SETUP, 3, "setoffl");
QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
@@ -3458,6 +3507,7 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev,
card->state = CARD_STATE_RECOVER;
/* let user_space know that device is offline */
kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
+ mutex_unlock(&card->conf_mutex);
return 0;
}
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c
index 25b3e7aae44..fb5318b30e9 100644
--- a/drivers/s390/net/qeth_l3_sys.c
+++ b/drivers/s390/net/qeth_l3_sys.c
@@ -70,10 +70,10 @@ static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
{
enum qeth_routing_types old_route_type = route->type;
char *tmp;
- int rc;
+ int rc = 0;
tmp = strsep((char **) &buf, "\n");
-
+ mutex_lock(&card->conf_mutex);
if (!strcmp(tmp, "no_router")) {
route->type = NO_ROUTER;
} else if (!strcmp(tmp, "primary_connector")) {
@@ -87,7 +87,8 @@ static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
} else if (!strcmp(tmp, "multicast_router")) {
route->type = MULTICAST_ROUTER;
} else {
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
if (((card->state == CARD_STATE_SOFTSETUP) ||
(card->state == CARD_STATE_UP)) &&
@@ -97,7 +98,9 @@ static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
else if (prot == QETH_PROT_IPV6)
rc = qeth_l3_setrouting_v6(card);
}
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_route4_store(struct device *dev,
@@ -157,22 +160,26 @@ static ssize_t qeth_l3_dev_fake_broadcast_store(struct device *dev,
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
- int i;
+ int i, rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
i = simple_strtoul(buf, &tmp, 16);
if ((i == 0) || (i == 1))
card->options.fake_broadcast = i;
- else {
- return -EINVAL;
- }
- return count;
+ else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show,
@@ -200,31 +207,35 @@ static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev,
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
(card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
tmp = strsep((char **) &buf, "\n");
- if (!strcmp(tmp, "local")) {
+ if (!strcmp(tmp, "local"))
card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL;
- return count;
- } else if (!strcmp(tmp, "all_rings")) {
+ else if (!strcmp(tmp, "all_rings"))
card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS;
- return count;
- } else {
- return -EINVAL;
- }
- return count;
+ else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show,
@@ -251,18 +262,22 @@ static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev,
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
- int i;
+ int i, rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) ||
(card->info.link_type == QETH_LINK_TYPE_LANE_TR))) {
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
i = simple_strtoul(buf, &tmp, 16);
@@ -270,10 +285,11 @@ static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev,
card->options.macaddr_mode = i?
QETH_TR_MACADDR_CANONICAL :
QETH_TR_MACADDR_NONCANONICAL;
- else {
- return -EINVAL;
- }
- return count;
+ else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show,
@@ -297,11 +313,12 @@ static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
struct qeth_card *card = dev_get_drvdata(dev);
enum qeth_checksum_types csum_type;
char *tmp;
- int rc;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "sw_checksumming"))
csum_type = SW_CHECKSUMMING;
@@ -309,13 +326,15 @@ static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
csum_type = HW_CHECKSUMMING;
else if (!strcmp(tmp, "no_checksumming"))
csum_type = NO_CHECKSUMMING;
- else
- return -EINVAL;
+ else {
+ rc = -EINVAL;
+ goto out;
+ }
rc = qeth_l3_set_rx_csum(card, csum_type);
- if (rc)
- return rc;
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
@@ -336,7 +355,7 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev_get_drvdata(dev);
- int ret;
+ int rc = 0;
unsigned long i;
if (!card)
@@ -345,19 +364,24 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
if (card->info.type != QETH_CARD_TYPE_IQD)
return -EPERM;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
- ret = strict_strtoul(buf, 16, &i);
- if (ret)
- return -EINVAL;
+ rc = strict_strtoul(buf, 16, &i);
+ if (rc) {
+ rc = -EINVAL;
+ goto out;
+ }
switch (i) {
case 0:
card->options.sniffer = i;
break;
case 1:
- ret = qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd);
+ qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd);
if (card->ssqd.qdioac2 & QETH_SNIFF_AVAIL) {
card->options.sniffer = i;
if (card->qdio.init_pool.buf_count !=
@@ -366,11 +390,13 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
QETH_IN_BUF_COUNT_MAX);
break;
} else
- return -EPERM;
+ rc = -EPERM;
default: /* fall through */
- return -EINVAL;
+ rc = -EINVAL;
}
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show,
@@ -412,12 +438,11 @@ static ssize_t qeth_l3_dev_large_send_store(struct device *dev,
else
return -EINVAL;
- if (card->options.large_send == type)
- return count;
- rc = qeth_l3_set_large_send(card, type);
- if (rc)
- return rc;
- return count;
+ mutex_lock(&card->conf_mutex);
+ if (card->options.large_send != type)
+ rc = qeth_l3_set_large_send(card, type);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static DEVICE_ATTR(large_send, 0644, qeth_l3_dev_large_send_show,
@@ -455,13 +480,17 @@ static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
if ((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER))
- return -EPERM;
+ (card->state != CARD_STATE_RECOVER)) {
+ rc = -EPERM;
+ goto out;
+ }
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")) {
@@ -470,10 +499,11 @@ static ssize_t qeth_l3_dev_ipato_enable_store(struct device *dev,
card->ipato.enabled = 1;
} else if (!strcmp(tmp, "0")) {
card->ipato.enabled = 0;
- } else {
- return -EINVAL;
- }
- return count;
+ } else
+ rc = -EINVAL;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
@@ -497,10 +527,12 @@ static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")) {
card->ipato.invert4 = (card->ipato.invert4)? 0 : 1;
@@ -508,10 +540,10 @@ static ssize_t qeth_l3_dev_ipato_invert4_store(struct device *dev,
card->ipato.invert4 = 1;
} else if (!strcmp(tmp, "0")) {
card->ipato.invert4 = 0;
- } else {
- return -EINVAL;
- }
- return count;
+ } else
+ rc = -EINVAL;
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644,
@@ -593,27 +625,28 @@ static ssize_t qeth_l3_dev_ipato_add_store(const char *buf, size_t count,
struct qeth_ipato_entry *ipatoe;
u8 addr[16];
int mask_bits;
- int rc;
+ int rc = 0;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
if (rc)
- return rc;
+ goto out;
ipatoe = kzalloc(sizeof(struct qeth_ipato_entry), GFP_KERNEL);
if (!ipatoe) {
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto out;
}
ipatoe->proto = proto;
memcpy(ipatoe->addr, addr, (proto == QETH_PROT_IPV4)? 4:16);
ipatoe->mask_bits = mask_bits;
rc = qeth_l3_add_ipato_entry(card, ipatoe);
- if (rc) {
+ if (rc)
kfree(ipatoe);
- return rc;
- }
-
- return count;
+out:
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_ipato_add4_store(struct device *dev,
@@ -636,15 +669,14 @@ static ssize_t qeth_l3_dev_ipato_del_store(const char *buf, size_t count,
{
u8 addr[16];
int mask_bits;
- int rc;
+ int rc = 0;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_ipatoe(buf, proto, addr, &mask_bits);
- if (rc)
- return rc;
-
- qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
-
- return count;
+ if (!rc)
+ qeth_l3_del_ipato_entry(card, proto, addr, mask_bits);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_ipato_del4_store(struct device *dev,
@@ -677,10 +709,12 @@ static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
{
struct qeth_card *card = dev_get_drvdata(dev);
char *tmp;
+ int rc = 0;
if (!card)
return -EINVAL;
+ mutex_lock(&card->conf_mutex);
tmp = strsep((char **) &buf, "\n");
if (!strcmp(tmp, "toggle")) {
card->ipato.invert6 = (card->ipato.invert6)? 0 : 1;
@@ -688,10 +722,10 @@ static ssize_t qeth_l3_dev_ipato_invert6_store(struct device *dev,
card->ipato.invert6 = 1;
} else if (!strcmp(tmp, "0")) {
card->ipato.invert6 = 0;
- } else {
- return -EINVAL;
- }
- return count;
+ } else
+ rc = -EINVAL;
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
@@ -813,15 +847,12 @@ static ssize_t qeth_l3_dev_vipa_add_store(const char *buf, size_t count,
u8 addr[16] = {0, };
int rc;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_vipae(buf, proto, addr);
- if (rc)
- return rc;
-
- rc = qeth_l3_add_vipa(card, proto, addr);
- if (rc)
- return rc;
-
- return count;
+ if (!rc)
+ rc = qeth_l3_add_vipa(card, proto, addr);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_vipa_add4_store(struct device *dev,
@@ -845,13 +876,12 @@ static ssize_t qeth_l3_dev_vipa_del_store(const char *buf, size_t count,
u8 addr[16];
int rc;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_vipae(buf, proto, addr);
- if (rc)
- return rc;
-
- qeth_l3_del_vipa(card, proto, addr);
-
- return count;
+ if (!rc)
+ qeth_l3_del_vipa(card, proto, addr);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_vipa_del4_store(struct device *dev,
@@ -979,15 +1009,12 @@ static ssize_t qeth_l3_dev_rxip_add_store(const char *buf, size_t count,
u8 addr[16] = {0, };
int rc;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_rxipe(buf, proto, addr);
- if (rc)
- return rc;
-
- rc = qeth_l3_add_rxip(card, proto, addr);
- if (rc)
- return rc;
-
- return count;
+ if (!rc)
+ rc = qeth_l3_add_rxip(card, proto, addr);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_rxip_add4_store(struct device *dev,
@@ -1011,13 +1038,12 @@ static ssize_t qeth_l3_dev_rxip_del_store(const char *buf, size_t count,
u8 addr[16];
int rc;
+ mutex_lock(&card->conf_mutex);
rc = qeth_l3_parse_rxipe(buf, proto, addr);
- if (rc)
- return rc;
-
- qeth_l3_del_rxip(card, proto, addr);
-
- return count;
+ if (!rc)
+ qeth_l3_del_rxip(card, proto, addr);
+ mutex_unlock(&card->conf_mutex);
+ return rc ? rc : count;
}
static ssize_t qeth_l3_dev_rxip_del4_store(struct device *dev,