diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 10:55:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 10:55:01 -0500 |
commit | d7fc02c7bae7b1cf69269992cf880a43a350cdaa (patch) | |
tree | a43d56fa72913a1cc98a0bbebe054d08581b3a7c /drivers/s390 | |
parent | ee1262dbc65ce0b6234a915d8432171e8d77f518 (diff) | |
parent | 28b4d5cc17c20786848cdc07b7ea237a309776bb (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: (1815 commits)
mac80211: fix reorder buffer release
iwmc3200wifi: Enable wimax core through module parameter
iwmc3200wifi: Add wifi-wimax coexistence mode as a module parameter
iwmc3200wifi: Coex table command does not expect a response
iwmc3200wifi: Update wiwi priority table
iwlwifi: driver version track kernel version
iwlwifi: indicate uCode type when fail dump error/event log
iwl3945: remove duplicated event logging code
b43: fix two warnings
ipw2100: fix rebooting hang with driver loaded
cfg80211: indent regulatory messages with spaces
iwmc3200wifi: fix NULL pointer dereference in pmkid update
mac80211: Fix TX status reporting for injected data frames
ath9k: enable 2GHz band only if the device supports it
airo: Fix integer overflow warning
rt2x00: Fix padding bug on L2PAD devices.
WE: Fix set events not propagated
b43legacy: avoid PPC fault during resume
b43: avoid PPC fault during resume
tcp: fix a timewait refcnt race
...
Fix up conflicts due to sysctl cleanups (dead sysctl_check code and
CTL_UNNUMBERED removed) in
kernel/sysctl_check.c
net/ipv4/sysctl_net_ipv4.c
net/ipv6/addrconf.c
net/sctp/sysctl.c
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/net/Makefile | 6 | ||||
-rw-r--r-- | drivers/s390/net/claw.c | 82 | ||||
-rw-r--r-- | drivers/s390/net/claw.h | 12 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_fsms.c | 1 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_fsms.h | 1 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_main.c | 168 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_main.h | 20 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_mpc.c | 1 | ||||
-rw-r--r-- | drivers/s390/net/ctcm_sysfs.c | 11 | ||||
-rw-r--r-- | drivers/s390/net/cu3088.c | 148 | ||||
-rw-r--r-- | drivers/s390/net/cu3088.h | 41 | ||||
-rw-r--r-- | drivers/s390/net/fsm.c | 1 | ||||
-rw-r--r-- | drivers/s390/net/fsm.h | 2 | ||||
-rw-r--r-- | drivers/s390/net/lcs.c | 115 | ||||
-rw-r--r-- | drivers/s390/net/lcs.h | 18 | ||||
-rw-r--r-- | drivers/s390/net/netiucv.c | 4 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core.h | 8 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 225 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_mpc.h | 45 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_sys.c | 83 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 33 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3.h | 2 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 144 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_sys.c | 67 |
24 files changed, 806 insertions, 432 deletions
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile index 96eddb3b1d08..6cab5a62f99e 100644 --- a/drivers/s390/net/Makefile +++ b/drivers/s390/net/Makefile | |||
@@ -3,11 +3,11 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o | 5 | ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o |
6 | obj-$(CONFIG_CTCM) += ctcm.o fsm.o cu3088.o | 6 | obj-$(CONFIG_CTCM) += ctcm.o fsm.o |
7 | obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o | 7 | obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o |
8 | obj-$(CONFIG_SMSGIUCV) += smsgiucv.o | 8 | obj-$(CONFIG_SMSGIUCV) += smsgiucv.o |
9 | obj-$(CONFIG_LCS) += lcs.o cu3088.o | 9 | obj-$(CONFIG_LCS) += lcs.o |
10 | obj-$(CONFIG_CLAW) += claw.o cu3088.o | 10 | obj-$(CONFIG_CLAW) += claw.o |
11 | qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o | 11 | qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o |
12 | obj-$(CONFIG_QETH) += qeth.o | 12 | obj-$(CONFIG_QETH) += qeth.o |
13 | qeth_l2-y += qeth_l2_main.o | 13 | qeth_l2-y += qeth_l2_main.o |
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index c63babefb698..3c77bfe0764c 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c | |||
@@ -90,7 +90,6 @@ | |||
90 | #include <linux/timer.h> | 90 | #include <linux/timer.h> |
91 | #include <linux/types.h> | 91 | #include <linux/types.h> |
92 | 92 | ||
93 | #include "cu3088.h" | ||
94 | #include "claw.h" | 93 | #include "claw.h" |
95 | 94 | ||
96 | /* | 95 | /* |
@@ -258,6 +257,9 @@ static int claw_pm_prepare(struct ccwgroup_device *gdev) | |||
258 | return -EPERM; | 257 | return -EPERM; |
259 | } | 258 | } |
260 | 259 | ||
260 | /* the root device for claw group devices */ | ||
261 | static struct device *claw_root_dev; | ||
262 | |||
261 | /* ccwgroup table */ | 263 | /* ccwgroup table */ |
262 | 264 | ||
263 | static struct ccwgroup_driver claw_group_driver = { | 265 | static struct ccwgroup_driver claw_group_driver = { |
@@ -272,6 +274,47 @@ static struct ccwgroup_driver claw_group_driver = { | |||
272 | .prepare = claw_pm_prepare, | 274 | .prepare = claw_pm_prepare, |
273 | }; | 275 | }; |
274 | 276 | ||
277 | static struct ccw_device_id claw_ids[] = { | ||
278 | {CCW_DEVICE(0x3088, 0x61), .driver_info = claw_channel_type_claw}, | ||
279 | {}, | ||
280 | }; | ||
281 | MODULE_DEVICE_TABLE(ccw, claw_ids); | ||
282 | |||
283 | static struct ccw_driver claw_ccw_driver = { | ||
284 | .owner = THIS_MODULE, | ||
285 | .name = "claw", | ||
286 | .ids = claw_ids, | ||
287 | .probe = ccwgroup_probe_ccwdev, | ||
288 | .remove = ccwgroup_remove_ccwdev, | ||
289 | }; | ||
290 | |||
291 | static ssize_t | ||
292 | claw_driver_group_store(struct device_driver *ddrv, const char *buf, | ||
293 | size_t count) | ||
294 | { | ||
295 | int err; | ||
296 | err = ccwgroup_create_from_string(claw_root_dev, | ||
297 | claw_group_driver.driver_id, | ||
298 | &claw_ccw_driver, 3, buf); | ||
299 | return err ? err : count; | ||
300 | } | ||
301 | |||
302 | static DRIVER_ATTR(group, 0200, NULL, claw_driver_group_store); | ||
303 | |||
304 | static struct attribute *claw_group_attrs[] = { | ||
305 | &driver_attr_group.attr, | ||
306 | NULL, | ||
307 | }; | ||
308 | |||
309 | static struct attribute_group claw_group_attr_group = { | ||
310 | .attrs = claw_group_attrs, | ||
311 | }; | ||
312 | |||
313 | static const struct attribute_group *claw_group_attr_groups[] = { | ||
314 | &claw_group_attr_group, | ||
315 | NULL, | ||
316 | }; | ||
317 | |||
275 | /* | 318 | /* |
276 | * Key functions | 319 | * Key functions |
277 | */ | 320 | */ |
@@ -3326,7 +3369,11 @@ claw_remove_files(struct device *dev) | |||
3326 | static void __exit | 3369 | static void __exit |
3327 | claw_cleanup(void) | 3370 | claw_cleanup(void) |
3328 | { | 3371 | { |
3329 | unregister_cu3088_discipline(&claw_group_driver); | 3372 | driver_remove_file(&claw_group_driver.driver, |
3373 | &driver_attr_group); | ||
3374 | ccwgroup_driver_unregister(&claw_group_driver); | ||
3375 | ccw_driver_unregister(&claw_ccw_driver); | ||
3376 | root_device_unregister(claw_root_dev); | ||
3330 | claw_unregister_debug_facility(); | 3377 | claw_unregister_debug_facility(); |
3331 | pr_info("Driver unloaded\n"); | 3378 | pr_info("Driver unloaded\n"); |
3332 | 3379 | ||
@@ -3348,16 +3395,31 @@ claw_init(void) | |||
3348 | if (ret) { | 3395 | if (ret) { |
3349 | pr_err("Registering with the S/390 debug feature" | 3396 | pr_err("Registering with the S/390 debug feature" |
3350 | " failed with error code %d\n", ret); | 3397 | " failed with error code %d\n", ret); |
3351 | return ret; | 3398 | goto out_err; |
3352 | } | 3399 | } |
3353 | CLAW_DBF_TEXT(2, setup, "init_mod"); | 3400 | CLAW_DBF_TEXT(2, setup, "init_mod"); |
3354 | ret = register_cu3088_discipline(&claw_group_driver); | 3401 | claw_root_dev = root_device_register("qeth"); |
3355 | if (ret) { | 3402 | ret = IS_ERR(claw_root_dev) ? PTR_ERR(claw_root_dev) : 0; |
3356 | CLAW_DBF_TEXT(2, setup, "init_bad"); | 3403 | if (ret) |
3357 | claw_unregister_debug_facility(); | 3404 | goto register_err; |
3358 | pr_err("Registering with the cu3088 device driver failed " | 3405 | ret = ccw_driver_register(&claw_ccw_driver); |
3359 | "with error code %d\n", ret); | 3406 | if (ret) |
3360 | } | 3407 | goto ccw_err; |
3408 | claw_group_driver.driver.groups = claw_group_attr_groups; | ||
3409 | ret = ccwgroup_driver_register(&claw_group_driver); | ||
3410 | if (ret) | ||
3411 | goto ccwgroup_err; | ||
3412 | return 0; | ||
3413 | |||
3414 | ccwgroup_err: | ||
3415 | ccw_driver_unregister(&claw_ccw_driver); | ||
3416 | ccw_err: | ||
3417 | root_device_unregister(claw_root_dev); | ||
3418 | register_err: | ||
3419 | CLAW_DBF_TEXT(2, setup, "init_bad"); | ||
3420 | claw_unregister_debug_facility(); | ||
3421 | out_err: | ||
3422 | pr_err("Initializing the claw device driver failed\n"); | ||
3361 | return ret; | 3423 | return ret; |
3362 | } | 3424 | } |
3363 | 3425 | ||
diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h index 005072c420d3..46d59a13db12 100644 --- a/drivers/s390/net/claw.h +++ b/drivers/s390/net/claw.h | |||
@@ -129,6 +129,18 @@ static inline int claw_dbf_passes(debug_info_t *dbf_grp, int level) | |||
129 | } \ | 129 | } \ |
130 | } while (0) | 130 | } while (0) |
131 | 131 | ||
132 | /** | ||
133 | * Enum for classifying detected devices. | ||
134 | */ | ||
135 | enum claw_channel_types { | ||
136 | /* Device is not a channel */ | ||
137 | claw_channel_type_none, | ||
138 | |||
139 | /* Device is a CLAW channel device */ | ||
140 | claw_channel_type_claw | ||
141 | }; | ||
142 | |||
143 | |||
132 | /******************************************************* | 144 | /******************************************************* |
133 | * Define Control Blocks * | 145 | * Define Control Blocks * |
134 | * * | 146 | * * |
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c index 4ded9ac2c5ef..70eb7f138414 100644 --- a/drivers/s390/net/ctcm_fsms.c +++ b/drivers/s390/net/ctcm_fsms.c | |||
@@ -44,7 +44,6 @@ | |||
44 | #include <asm/idals.h> | 44 | #include <asm/idals.h> |
45 | 45 | ||
46 | #include "fsm.h" | 46 | #include "fsm.h" |
47 | #include "cu3088.h" | ||
48 | 47 | ||
49 | #include "ctcm_dbug.h" | 48 | #include "ctcm_dbug.h" |
50 | #include "ctcm_main.h" | 49 | #include "ctcm_main.h" |
diff --git a/drivers/s390/net/ctcm_fsms.h b/drivers/s390/net/ctcm_fsms.h index 2326aba9807a..046d077fabbb 100644 --- a/drivers/s390/net/ctcm_fsms.h +++ b/drivers/s390/net/ctcm_fsms.h | |||
@@ -39,7 +39,6 @@ | |||
39 | #include <asm/idals.h> | 39 | #include <asm/idals.h> |
40 | 40 | ||
41 | #include "fsm.h" | 41 | #include "fsm.h" |
42 | #include "cu3088.h" | ||
43 | #include "ctcm_main.h" | 42 | #include "ctcm_main.h" |
44 | 43 | ||
45 | /* | 44 | /* |
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index c5b83874500c..e35713dd0504 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c | |||
@@ -51,12 +51,16 @@ | |||
51 | 51 | ||
52 | #include <asm/idals.h> | 52 | #include <asm/idals.h> |
53 | 53 | ||
54 | #include "cu3088.h" | ||
55 | #include "ctcm_fsms.h" | 54 | #include "ctcm_fsms.h" |
56 | #include "ctcm_main.h" | 55 | #include "ctcm_main.h" |
57 | 56 | ||
58 | /* Some common global variables */ | 57 | /* Some common global variables */ |
59 | 58 | ||
59 | /** | ||
60 | * The root device for ctcm group devices | ||
61 | */ | ||
62 | static struct device *ctcm_root_dev; | ||
63 | |||
60 | /* | 64 | /* |
61 | * Linked list of all detected channels. | 65 | * Linked list of all detected channels. |
62 | */ | 66 | */ |
@@ -246,7 +250,7 @@ static void channel_remove(struct channel *ch) | |||
246 | * | 250 | * |
247 | * returns Pointer to a channel or NULL if no matching channel available. | 251 | * returns Pointer to a channel or NULL if no matching channel available. |
248 | */ | 252 | */ |
249 | static struct channel *channel_get(enum channel_types type, | 253 | static struct channel *channel_get(enum ctcm_channel_types type, |
250 | char *id, int direction) | 254 | char *id, int direction) |
251 | { | 255 | { |
252 | struct channel *ch = channels; | 256 | struct channel *ch = channels; |
@@ -1342,7 +1346,7 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev) | |||
1342 | * | 1346 | * |
1343 | * returns 0 on success, !0 on error. | 1347 | * returns 0 on success, !0 on error. |
1344 | */ | 1348 | */ |
1345 | static int add_channel(struct ccw_device *cdev, enum channel_types type, | 1349 | static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type, |
1346 | struct ctcm_priv *priv) | 1350 | struct ctcm_priv *priv) |
1347 | { | 1351 | { |
1348 | struct channel **c = &channels; | 1352 | struct channel **c = &channels; |
@@ -1501,13 +1505,13 @@ free_return: /* note that all channel pointers are 0 or valid */ | |||
1501 | /* | 1505 | /* |
1502 | * Return type of a detected device. | 1506 | * Return type of a detected device. |
1503 | */ | 1507 | */ |
1504 | static enum channel_types get_channel_type(struct ccw_device_id *id) | 1508 | static enum ctcm_channel_types get_channel_type(struct ccw_device_id *id) |
1505 | { | 1509 | { |
1506 | enum channel_types type; | 1510 | enum ctcm_channel_types type; |
1507 | type = (enum channel_types)id->driver_info; | 1511 | type = (enum ctcm_channel_types)id->driver_info; |
1508 | 1512 | ||
1509 | if (type == channel_type_ficon) | 1513 | if (type == ctcm_channel_type_ficon) |
1510 | type = channel_type_escon; | 1514 | type = ctcm_channel_type_escon; |
1511 | 1515 | ||
1512 | return type; | 1516 | return type; |
1513 | } | 1517 | } |
@@ -1525,16 +1529,21 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1525 | char read_id[CTCM_ID_SIZE]; | 1529 | char read_id[CTCM_ID_SIZE]; |
1526 | char write_id[CTCM_ID_SIZE]; | 1530 | char write_id[CTCM_ID_SIZE]; |
1527 | int direction; | 1531 | int direction; |
1528 | enum channel_types type; | 1532 | enum ctcm_channel_types type; |
1529 | struct ctcm_priv *priv; | 1533 | struct ctcm_priv *priv; |
1530 | struct net_device *dev; | 1534 | struct net_device *dev; |
1531 | struct ccw_device *cdev0; | 1535 | struct ccw_device *cdev0; |
1532 | struct ccw_device *cdev1; | 1536 | struct ccw_device *cdev1; |
1537 | struct channel *readc; | ||
1538 | struct channel *writec; | ||
1533 | int ret; | 1539 | int ret; |
1540 | int result; | ||
1534 | 1541 | ||
1535 | priv = dev_get_drvdata(&cgdev->dev); | 1542 | priv = dev_get_drvdata(&cgdev->dev); |
1536 | if (!priv) | 1543 | if (!priv) { |
1537 | return -ENODEV; | 1544 | result = -ENODEV; |
1545 | goto out_err_result; | ||
1546 | } | ||
1538 | 1547 | ||
1539 | cdev0 = cgdev->cdev[0]; | 1548 | cdev0 = cgdev->cdev[0]; |
1540 | cdev1 = cgdev->cdev[1]; | 1549 | cdev1 = cgdev->cdev[1]; |
@@ -1545,31 +1554,40 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1545 | snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev)); | 1554 | snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev)); |
1546 | 1555 | ||
1547 | ret = add_channel(cdev0, type, priv); | 1556 | ret = add_channel(cdev0, type, priv); |
1548 | if (ret) | 1557 | if (ret) { |
1549 | return ret; | 1558 | result = ret; |
1559 | goto out_err_result; | ||
1560 | } | ||
1550 | ret = add_channel(cdev1, type, priv); | 1561 | ret = add_channel(cdev1, type, priv); |
1551 | if (ret) | 1562 | if (ret) { |
1552 | return ret; | 1563 | result = ret; |
1564 | goto out_remove_channel1; | ||
1565 | } | ||
1553 | 1566 | ||
1554 | ret = ccw_device_set_online(cdev0); | 1567 | ret = ccw_device_set_online(cdev0); |
1555 | if (ret != 0) { | 1568 | if (ret != 0) { |
1556 | /* may be ok to fail now - can be done later */ | ||
1557 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE, | 1569 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE, |
1558 | "%s(%s) set_online rc=%d", | 1570 | "%s(%s) set_online rc=%d", |
1559 | CTCM_FUNTAIL, read_id, ret); | 1571 | CTCM_FUNTAIL, read_id, ret); |
1572 | result = -EIO; | ||
1573 | goto out_remove_channel2; | ||
1560 | } | 1574 | } |
1561 | 1575 | ||
1562 | ret = ccw_device_set_online(cdev1); | 1576 | ret = ccw_device_set_online(cdev1); |
1563 | if (ret != 0) { | 1577 | if (ret != 0) { |
1564 | /* may be ok to fail now - can be done later */ | ||
1565 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE, | 1578 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE, |
1566 | "%s(%s) set_online rc=%d", | 1579 | "%s(%s) set_online rc=%d", |
1567 | CTCM_FUNTAIL, write_id, ret); | 1580 | CTCM_FUNTAIL, write_id, ret); |
1581 | |||
1582 | result = -EIO; | ||
1583 | goto out_ccw1; | ||
1568 | } | 1584 | } |
1569 | 1585 | ||
1570 | dev = ctcm_init_netdevice(priv); | 1586 | dev = ctcm_init_netdevice(priv); |
1571 | if (dev == NULL) | 1587 | if (dev == NULL) { |
1572 | goto out; | 1588 | result = -ENODEV; |
1589 | goto out_ccw2; | ||
1590 | } | ||
1573 | 1591 | ||
1574 | for (direction = READ; direction <= WRITE; direction++) { | 1592 | for (direction = READ; direction <= WRITE; direction++) { |
1575 | priv->channel[direction] = | 1593 | priv->channel[direction] = |
@@ -1587,12 +1605,14 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1587 | /* sysfs magic */ | 1605 | /* sysfs magic */ |
1588 | SET_NETDEV_DEV(dev, &cgdev->dev); | 1606 | SET_NETDEV_DEV(dev, &cgdev->dev); |
1589 | 1607 | ||
1590 | if (register_netdev(dev)) | 1608 | if (register_netdev(dev)) { |
1591 | goto out_dev; | 1609 | result = -ENODEV; |
1610 | goto out_dev; | ||
1611 | } | ||
1592 | 1612 | ||
1593 | if (ctcm_add_attributes(&cgdev->dev)) { | 1613 | if (ctcm_add_attributes(&cgdev->dev)) { |
1594 | unregister_netdev(dev); | 1614 | result = -ENODEV; |
1595 | goto out_dev; | 1615 | goto out_unregister; |
1596 | } | 1616 | } |
1597 | 1617 | ||
1598 | strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name)); | 1618 | strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name)); |
@@ -1608,13 +1628,22 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1608 | priv->channel[WRITE]->id, priv->protocol); | 1628 | priv->channel[WRITE]->id, priv->protocol); |
1609 | 1629 | ||
1610 | return 0; | 1630 | return 0; |
1631 | out_unregister: | ||
1632 | unregister_netdev(dev); | ||
1611 | out_dev: | 1633 | out_dev: |
1612 | ctcm_free_netdevice(dev); | 1634 | ctcm_free_netdevice(dev); |
1613 | out: | 1635 | out_ccw2: |
1614 | ccw_device_set_offline(cgdev->cdev[1]); | 1636 | ccw_device_set_offline(cgdev->cdev[1]); |
1637 | out_ccw1: | ||
1615 | ccw_device_set_offline(cgdev->cdev[0]); | 1638 | ccw_device_set_offline(cgdev->cdev[0]); |
1616 | 1639 | out_remove_channel2: | |
1617 | return -ENODEV; | 1640 | readc = channel_get(type, read_id, READ); |
1641 | channel_remove(readc); | ||
1642 | out_remove_channel1: | ||
1643 | writec = channel_get(type, write_id, WRITE); | ||
1644 | channel_remove(writec); | ||
1645 | out_err_result: | ||
1646 | return result; | ||
1618 | } | 1647 | } |
1619 | 1648 | ||
1620 | /** | 1649 | /** |
@@ -1695,6 +1724,11 @@ static int ctcm_pm_suspend(struct ccwgroup_device *gdev) | |||
1695 | return 0; | 1724 | return 0; |
1696 | netif_device_detach(priv->channel[READ]->netdev); | 1725 | netif_device_detach(priv->channel[READ]->netdev); |
1697 | ctcm_close(priv->channel[READ]->netdev); | 1726 | ctcm_close(priv->channel[READ]->netdev); |
1727 | if (!wait_event_timeout(priv->fsm->wait_q, | ||
1728 | fsm_getstate(priv->fsm) == DEV_STATE_STOPPED, CTCM_TIME_5_SEC)) { | ||
1729 | netif_device_attach(priv->channel[READ]->netdev); | ||
1730 | return -EBUSY; | ||
1731 | } | ||
1698 | ccw_device_set_offline(gdev->cdev[1]); | 1732 | ccw_device_set_offline(gdev->cdev[1]); |
1699 | ccw_device_set_offline(gdev->cdev[0]); | 1733 | ccw_device_set_offline(gdev->cdev[0]); |
1700 | return 0; | 1734 | return 0; |
@@ -1719,6 +1753,22 @@ err_out: | |||
1719 | return rc; | 1753 | return rc; |
1720 | } | 1754 | } |
1721 | 1755 | ||
1756 | static struct ccw_device_id ctcm_ids[] = { | ||
1757 | {CCW_DEVICE(0x3088, 0x08), .driver_info = ctcm_channel_type_parallel}, | ||
1758 | {CCW_DEVICE(0x3088, 0x1e), .driver_info = ctcm_channel_type_ficon}, | ||
1759 | {CCW_DEVICE(0x3088, 0x1f), .driver_info = ctcm_channel_type_escon}, | ||
1760 | {}, | ||
1761 | }; | ||
1762 | MODULE_DEVICE_TABLE(ccw, ctcm_ids); | ||
1763 | |||
1764 | static struct ccw_driver ctcm_ccw_driver = { | ||
1765 | .owner = THIS_MODULE, | ||
1766 | .name = "ctcm", | ||
1767 | .ids = ctcm_ids, | ||
1768 | .probe = ccwgroup_probe_ccwdev, | ||
1769 | .remove = ccwgroup_remove_ccwdev, | ||
1770 | }; | ||
1771 | |||
1722 | static struct ccwgroup_driver ctcm_group_driver = { | 1772 | static struct ccwgroup_driver ctcm_group_driver = { |
1723 | .owner = THIS_MODULE, | 1773 | .owner = THIS_MODULE, |
1724 | .name = CTC_DRIVER_NAME, | 1774 | .name = CTC_DRIVER_NAME, |
@@ -1733,6 +1783,33 @@ static struct ccwgroup_driver ctcm_group_driver = { | |||
1733 | .restore = ctcm_pm_resume, | 1783 | .restore = ctcm_pm_resume, |
1734 | }; | 1784 | }; |
1735 | 1785 | ||
1786 | static ssize_t | ||
1787 | ctcm_driver_group_store(struct device_driver *ddrv, const char *buf, | ||
1788 | size_t count) | ||
1789 | { | ||
1790 | int err; | ||
1791 | |||
1792 | err = ccwgroup_create_from_string(ctcm_root_dev, | ||
1793 | ctcm_group_driver.driver_id, | ||
1794 | &ctcm_ccw_driver, 2, buf); | ||
1795 | return err ? err : count; | ||
1796 | } | ||
1797 | |||
1798 | static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store); | ||
1799 | |||
1800 | static struct attribute *ctcm_group_attrs[] = { | ||
1801 | &driver_attr_group.attr, | ||
1802 | NULL, | ||
1803 | }; | ||
1804 | |||
1805 | static struct attribute_group ctcm_group_attr_group = { | ||
1806 | .attrs = ctcm_group_attrs, | ||
1807 | }; | ||
1808 | |||
1809 | static const struct attribute_group *ctcm_group_attr_groups[] = { | ||
1810 | &ctcm_group_attr_group, | ||
1811 | NULL, | ||
1812 | }; | ||
1736 | 1813 | ||
1737 | /* | 1814 | /* |
1738 | * Module related routines | 1815 | * Module related routines |
@@ -1746,7 +1823,10 @@ static struct ccwgroup_driver ctcm_group_driver = { | |||
1746 | */ | 1823 | */ |
1747 | static void __exit ctcm_exit(void) | 1824 | static void __exit ctcm_exit(void) |
1748 | { | 1825 | { |
1749 | unregister_cu3088_discipline(&ctcm_group_driver); | 1826 | driver_remove_file(&ctcm_group_driver.driver, &driver_attr_group); |
1827 | ccwgroup_driver_unregister(&ctcm_group_driver); | ||
1828 | ccw_driver_unregister(&ctcm_ccw_driver); | ||
1829 | root_device_unregister(ctcm_root_dev); | ||
1750 | ctcm_unregister_dbf_views(); | 1830 | ctcm_unregister_dbf_views(); |
1751 | pr_info("CTCM driver unloaded\n"); | 1831 | pr_info("CTCM driver unloaded\n"); |
1752 | } | 1832 | } |
@@ -1772,17 +1852,31 @@ static int __init ctcm_init(void) | |||
1772 | channels = NULL; | 1852 | channels = NULL; |
1773 | 1853 | ||
1774 | ret = ctcm_register_dbf_views(); | 1854 | ret = ctcm_register_dbf_views(); |
1775 | if (ret) { | 1855 | if (ret) |
1776 | return ret; | 1856 | goto out_err; |
1777 | } | 1857 | ctcm_root_dev = root_device_register("ctcm"); |
1778 | ret = register_cu3088_discipline(&ctcm_group_driver); | 1858 | ret = IS_ERR(ctcm_root_dev) ? PTR_ERR(ctcm_root_dev) : 0; |
1779 | if (ret) { | 1859 | if (ret) |
1780 | ctcm_unregister_dbf_views(); | 1860 | goto register_err; |
1781 | pr_err("%s / register_cu3088_discipline failed, ret = %d\n", | 1861 | ret = ccw_driver_register(&ctcm_ccw_driver); |
1782 | __func__, ret); | 1862 | if (ret) |
1783 | return ret; | 1863 | goto ccw_err; |
1784 | } | 1864 | ctcm_group_driver.driver.groups = ctcm_group_attr_groups; |
1865 | ret = ccwgroup_driver_register(&ctcm_group_driver); | ||
1866 | if (ret) | ||
1867 | goto ccwgroup_err; | ||
1785 | print_banner(); | 1868 | print_banner(); |
1869 | return 0; | ||
1870 | |||
1871 | ccwgroup_err: | ||
1872 | ccw_driver_unregister(&ctcm_ccw_driver); | ||
1873 | ccw_err: | ||
1874 | root_device_unregister(ctcm_root_dev); | ||
1875 | register_err: | ||
1876 | ctcm_unregister_dbf_views(); | ||
1877 | out_err: | ||
1878 | pr_err("%s / Initializing the ctcm device driver failed, ret = %d\n", | ||
1879 | __func__, ret); | ||
1786 | return ret; | 1880 | return ret; |
1787 | } | 1881 | } |
1788 | 1882 | ||
diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h index d925e732b7d8..d34fa14f44e7 100644 --- a/drivers/s390/net/ctcm_main.h +++ b/drivers/s390/net/ctcm_main.h | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
17 | 17 | ||
18 | #include "fsm.h" | 18 | #include "fsm.h" |
19 | #include "cu3088.h" | ||
20 | #include "ctcm_dbug.h" | 19 | #include "ctcm_dbug.h" |
21 | #include "ctcm_mpc.h" | 20 | #include "ctcm_mpc.h" |
22 | 21 | ||
@@ -66,6 +65,23 @@ | |||
66 | ctcmpc_dumpit(buf, len); \ | 65 | ctcmpc_dumpit(buf, len); \ |
67 | } while (0) | 66 | } while (0) |
68 | 67 | ||
68 | /** | ||
69 | * Enum for classifying detected devices | ||
70 | */ | ||
71 | enum ctcm_channel_types { | ||
72 | /* Device is not a channel */ | ||
73 | ctcm_channel_type_none, | ||
74 | |||
75 | /* Device is a CTC/A */ | ||
76 | ctcm_channel_type_parallel, | ||
77 | |||
78 | /* Device is a FICON channel */ | ||
79 | ctcm_channel_type_ficon, | ||
80 | |||
81 | /* Device is a ESCON channel */ | ||
82 | ctcm_channel_type_escon | ||
83 | }; | ||
84 | |||
69 | /* | 85 | /* |
70 | * CCW commands, used in this driver. | 86 | * CCW commands, used in this driver. |
71 | */ | 87 | */ |
@@ -121,7 +137,7 @@ struct channel { | |||
121 | * Type of this channel. | 137 | * Type of this channel. |
122 | * CTC/A or Escon for valid channels. | 138 | * CTC/A or Escon for valid channels. |
123 | */ | 139 | */ |
124 | enum channel_types type; | 140 | enum ctcm_channel_types type; |
125 | /* | 141 | /* |
126 | * Misc. flags. See CHANNEL_FLAGS_... below | 142 | * Misc. flags. See CHANNEL_FLAGS_... below |
127 | */ | 143 | */ |
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index 781e18be7e8f..5978b390153f 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c | |||
@@ -53,7 +53,6 @@ | |||
53 | #include <linux/moduleparam.h> | 53 | #include <linux/moduleparam.h> |
54 | #include <asm/idals.h> | 54 | #include <asm/idals.h> |
55 | 55 | ||
56 | #include "cu3088.h" | ||
57 | #include "ctcm_mpc.h" | 56 | #include "ctcm_mpc.h" |
58 | #include "ctcm_main.h" | 57 | #include "ctcm_main.h" |
59 | #include "ctcm_fsms.h" | 58 | #include "ctcm_fsms.h" |
diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c index 8452bb052d68..738ad26c74a7 100644 --- a/drivers/s390/net/ctcm_sysfs.c +++ b/drivers/s390/net/ctcm_sysfs.c | |||
@@ -158,6 +158,15 @@ static ssize_t ctcm_proto_store(struct device *dev, | |||
158 | return count; | 158 | return count; |
159 | } | 159 | } |
160 | 160 | ||
161 | const char *ctcm_type[] = { | ||
162 | "not a channel", | ||
163 | "CTC/A", | ||
164 | "FICON channel", | ||
165 | "ESCON channel", | ||
166 | "unknown channel type", | ||
167 | "unsupported channel type", | ||
168 | }; | ||
169 | |||
161 | static ssize_t ctcm_type_show(struct device *dev, | 170 | static ssize_t ctcm_type_show(struct device *dev, |
162 | struct device_attribute *attr, char *buf) | 171 | struct device_attribute *attr, char *buf) |
163 | { | 172 | { |
@@ -168,7 +177,7 @@ static ssize_t ctcm_type_show(struct device *dev, | |||
168 | return -ENODEV; | 177 | return -ENODEV; |
169 | 178 | ||
170 | return sprintf(buf, "%s\n", | 179 | return sprintf(buf, "%s\n", |
171 | cu3088_type[cgdev->cdev[0]->id.driver_info]); | 180 | ctcm_type[cgdev->cdev[0]->id.driver_info]); |
172 | } | 181 | } |
173 | 182 | ||
174 | static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write); | 183 | static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write); |
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c deleted file mode 100644 index 48383459e99b..000000000000 --- a/drivers/s390/net/cu3088.c +++ /dev/null | |||
@@ -1,148 +0,0 @@ | |||
1 | /* | ||
2 | * CTC / LCS ccw_device driver | ||
3 | * | ||
4 | * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation | ||
5 | * Author(s): Arnd Bergmann <arndb@de.ibm.com> | ||
6 | * Cornelia Huck <cornelia.huck@de.ibm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/init.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/err.h> | ||
27 | |||
28 | #include <asm/ccwdev.h> | ||
29 | #include <asm/ccwgroup.h> | ||
30 | |||
31 | #include "cu3088.h" | ||
32 | |||
33 | const char *cu3088_type[] = { | ||
34 | "not a channel", | ||
35 | "CTC/A", | ||
36 | "ESCON channel", | ||
37 | "FICON channel", | ||
38 | "OSA LCS card", | ||
39 | "CLAW channel device", | ||
40 | "unknown channel type", | ||
41 | "unsupported channel type", | ||
42 | }; | ||
43 | |||
44 | /* static definitions */ | ||
45 | |||
46 | static struct ccw_device_id cu3088_ids[] = { | ||
47 | { CCW_DEVICE(0x3088, 0x08), .driver_info = channel_type_parallel }, | ||
48 | { CCW_DEVICE(0x3088, 0x1f), .driver_info = channel_type_escon }, | ||
49 | { CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon }, | ||
50 | { CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 }, | ||
51 | { CCW_DEVICE(0x3088, 0x61), .driver_info = channel_type_claw }, | ||
52 | { /* end of list */ } | ||
53 | }; | ||
54 | |||
55 | static struct ccw_driver cu3088_driver; | ||
56 | |||
57 | static struct device *cu3088_root_dev; | ||
58 | |||
59 | static ssize_t | ||
60 | group_write(struct device_driver *drv, const char *buf, size_t count) | ||
61 | { | ||
62 | int ret; | ||
63 | struct ccwgroup_driver *cdrv; | ||
64 | |||
65 | cdrv = to_ccwgroupdrv(drv); | ||
66 | if (!cdrv) | ||
67 | return -EINVAL; | ||
68 | ret = ccwgroup_create_from_string(cu3088_root_dev, cdrv->driver_id, | ||
69 | &cu3088_driver, 2, buf); | ||
70 | |||
71 | return (ret == 0) ? count : ret; | ||
72 | } | ||
73 | |||
74 | static DRIVER_ATTR(group, 0200, NULL, group_write); | ||
75 | |||
76 | /* Register-unregister for ctc&lcs */ | ||
77 | int | ||
78 | register_cu3088_discipline(struct ccwgroup_driver *dcp) | ||
79 | { | ||
80 | int rc; | ||
81 | |||
82 | if (!dcp) | ||
83 | return -EINVAL; | ||
84 | |||
85 | /* Register discipline.*/ | ||
86 | rc = ccwgroup_driver_register(dcp); | ||
87 | if (rc) | ||
88 | return rc; | ||
89 | |||
90 | rc = driver_create_file(&dcp->driver, &driver_attr_group); | ||
91 | if (rc) | ||
92 | ccwgroup_driver_unregister(dcp); | ||
93 | |||
94 | return rc; | ||
95 | |||
96 | } | ||
97 | |||
98 | void | ||
99 | unregister_cu3088_discipline(struct ccwgroup_driver *dcp) | ||
100 | { | ||
101 | if (!dcp) | ||
102 | return; | ||
103 | |||
104 | driver_remove_file(&dcp->driver, &driver_attr_group); | ||
105 | ccwgroup_driver_unregister(dcp); | ||
106 | } | ||
107 | |||
108 | static struct ccw_driver cu3088_driver = { | ||
109 | .owner = THIS_MODULE, | ||
110 | .ids = cu3088_ids, | ||
111 | .name = "cu3088", | ||
112 | .probe = ccwgroup_probe_ccwdev, | ||
113 | .remove = ccwgroup_remove_ccwdev, | ||
114 | }; | ||
115 | |||
116 | /* module setup */ | ||
117 | static int __init | ||
118 | cu3088_init (void) | ||
119 | { | ||
120 | int rc; | ||
121 | |||
122 | cu3088_root_dev = root_device_register("cu3088"); | ||
123 | if (IS_ERR(cu3088_root_dev)) | ||
124 | return PTR_ERR(cu3088_root_dev); | ||
125 | rc = ccw_driver_register(&cu3088_driver); | ||
126 | if (rc) | ||
127 | root_device_unregister(cu3088_root_dev); | ||
128 | |||
129 | return rc; | ||
130 | } | ||
131 | |||
132 | static void __exit | ||
133 | cu3088_exit (void) | ||
134 | { | ||
135 | ccw_driver_unregister(&cu3088_driver); | ||
136 | root_device_unregister(cu3088_root_dev); | ||
137 | } | ||
138 | |||
139 | MODULE_DEVICE_TABLE(ccw,cu3088_ids); | ||
140 | MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>"); | ||
141 | MODULE_LICENSE("GPL"); | ||
142 | |||
143 | module_init(cu3088_init); | ||
144 | module_exit(cu3088_exit); | ||
145 | |||
146 | EXPORT_SYMBOL_GPL(cu3088_type); | ||
147 | EXPORT_SYMBOL_GPL(register_cu3088_discipline); | ||
148 | EXPORT_SYMBOL_GPL(unregister_cu3088_discipline); | ||
diff --git a/drivers/s390/net/cu3088.h b/drivers/s390/net/cu3088.h deleted file mode 100644 index d8558a7105a5..000000000000 --- a/drivers/s390/net/cu3088.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | #ifndef _CU3088_H | ||
2 | #define _CU3088_H | ||
3 | |||
4 | /** | ||
5 | * Enum for classifying detected devices. | ||
6 | */ | ||
7 | enum channel_types { | ||
8 | /* Device is not a channel */ | ||
9 | channel_type_none, | ||
10 | |||
11 | /* Device is a CTC/A */ | ||
12 | channel_type_parallel, | ||
13 | |||
14 | /* Device is a ESCON channel */ | ||
15 | channel_type_escon, | ||
16 | |||
17 | /* Device is a FICON channel */ | ||
18 | channel_type_ficon, | ||
19 | |||
20 | /* Device is a OSA2 card */ | ||
21 | channel_type_osa2, | ||
22 | |||
23 | /* Device is a CLAW channel device */ | ||
24 | channel_type_claw, | ||
25 | |||
26 | /* Device is a channel, but we don't know | ||
27 | * anything about it */ | ||
28 | channel_type_unknown, | ||
29 | |||
30 | /* Device is an unsupported model */ | ||
31 | channel_type_unsupported, | ||
32 | |||
33 | /* number of type entries */ | ||
34 | num_channel_types | ||
35 | }; | ||
36 | |||
37 | extern const char *cu3088_type[num_channel_types]; | ||
38 | extern int register_cu3088_discipline(struct ccwgroup_driver *); | ||
39 | extern void unregister_cu3088_discipline(struct ccwgroup_driver *); | ||
40 | |||
41 | #endif | ||
diff --git a/drivers/s390/net/fsm.c b/drivers/s390/net/fsm.c index 2c1db8036b7c..cae48cbc5e96 100644 --- a/drivers/s390/net/fsm.c +++ b/drivers/s390/net/fsm.c | |||
@@ -27,6 +27,7 @@ init_fsm(char *name, const char **state_names, const char **event_names, int nr_ | |||
27 | return NULL; | 27 | return NULL; |
28 | } | 28 | } |
29 | strlcpy(this->name, name, sizeof(this->name)); | 29 | strlcpy(this->name, name, sizeof(this->name)); |
30 | init_waitqueue_head(&this->wait_q); | ||
30 | 31 | ||
31 | f = kzalloc(sizeof(fsm), order); | 32 | f = kzalloc(sizeof(fsm), order); |
32 | if (f == NULL) { | 33 | if (f == NULL) { |
diff --git a/drivers/s390/net/fsm.h b/drivers/s390/net/fsm.h index af679c10f1bd..1e8b235d95b5 100644 --- a/drivers/s390/net/fsm.h +++ b/drivers/s390/net/fsm.h | |||
@@ -66,6 +66,7 @@ typedef struct fsm_instance_t { | |||
66 | char name[16]; | 66 | char name[16]; |
67 | void *userdata; | 67 | void *userdata; |
68 | int userint; | 68 | int userint; |
69 | wait_queue_head_t wait_q; | ||
69 | #if FSM_DEBUG_HISTORY | 70 | #if FSM_DEBUG_HISTORY |
70 | int history_index; | 71 | int history_index; |
71 | int history_size; | 72 | int history_size; |
@@ -197,6 +198,7 @@ fsm_newstate(fsm_instance *fi, int newstate) | |||
197 | printk(KERN_DEBUG "fsm(%s): New state %s\n", fi->name, | 198 | printk(KERN_DEBUG "fsm(%s): New state %s\n", fi->name, |
198 | fi->f->state_names[newstate]); | 199 | fi->f->state_names[newstate]); |
199 | #endif | 200 | #endif |
201 | wake_up(&fi->wait_q); | ||
200 | } | 202 | } |
201 | 203 | ||
202 | /** | 204 | /** |
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index a70de9b4bf29..f6cc46dc0501 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include <asm/ccwgroup.h> | 47 | #include <asm/ccwgroup.h> |
48 | 48 | ||
49 | #include "lcs.h" | 49 | #include "lcs.h" |
50 | #include "cu3088.h" | ||
51 | 50 | ||
52 | 51 | ||
53 | #if !defined(CONFIG_NET_ETHERNET) && \ | 52 | #if !defined(CONFIG_NET_ETHERNET) && \ |
@@ -60,7 +59,11 @@ | |||
60 | */ | 59 | */ |
61 | 60 | ||
62 | static char version[] __initdata = "LCS driver"; | 61 | static char version[] __initdata = "LCS driver"; |
63 | static char debug_buffer[255]; | 62 | |
63 | /** | ||
64 | * the root device for lcs group devices | ||
65 | */ | ||
66 | static struct device *lcs_root_dev; | ||
64 | 67 | ||
65 | /** | 68 | /** |
66 | * Some prototypes. | 69 | * Some prototypes. |
@@ -76,6 +79,7 @@ static int lcs_recovery(void *ptr); | |||
76 | /** | 79 | /** |
77 | * Debug Facility Stuff | 80 | * Debug Facility Stuff |
78 | */ | 81 | */ |
82 | static char debug_buffer[255]; | ||
79 | static debug_info_t *lcs_dbf_setup; | 83 | static debug_info_t *lcs_dbf_setup; |
80 | static debug_info_t *lcs_dbf_trace; | 84 | static debug_info_t *lcs_dbf_trace; |
81 | 85 | ||
@@ -889,7 +893,7 @@ lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer, | |||
889 | rc = lcs_ready_buffer(&card->write, buffer); | 893 | rc = lcs_ready_buffer(&card->write, buffer); |
890 | if (rc) | 894 | if (rc) |
891 | return rc; | 895 | return rc; |
892 | init_timer(&timer); | 896 | init_timer_on_stack(&timer); |
893 | timer.function = lcs_lancmd_timeout; | 897 | timer.function = lcs_lancmd_timeout; |
894 | timer.data = (unsigned long) reply; | 898 | timer.data = (unsigned long) reply; |
895 | timer.expires = jiffies + HZ*card->lancmd_timeout; | 899 | timer.expires = jiffies + HZ*card->lancmd_timeout; |
@@ -1968,6 +1972,15 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char | |||
1968 | 1972 | ||
1969 | static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store); | 1973 | static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store); |
1970 | 1974 | ||
1975 | const char *lcs_type[] = { | ||
1976 | "not a channel", | ||
1977 | "2216 parallel", | ||
1978 | "2216 channel", | ||
1979 | "OSA LCS card", | ||
1980 | "unknown channel type", | ||
1981 | "unsupported channel type", | ||
1982 | }; | ||
1983 | |||
1971 | static ssize_t | 1984 | static ssize_t |
1972 | lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf) | 1985 | lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf) |
1973 | { | 1986 | { |
@@ -1977,7 +1990,7 @@ lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
1977 | if (!cgdev) | 1990 | if (!cgdev) |
1978 | return -ENODEV; | 1991 | return -ENODEV; |
1979 | 1992 | ||
1980 | return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]); | 1993 | return sprintf(buf, "%s\n", lcs_type[cgdev->cdev[0]->id.driver_info]); |
1981 | } | 1994 | } |
1982 | 1995 | ||
1983 | static DEVICE_ATTR(type, 0444, lcs_type_show, NULL); | 1996 | static DEVICE_ATTR(type, 0444, lcs_type_show, NULL); |
@@ -2130,8 +2143,12 @@ lcs_new_device(struct ccwgroup_device *ccwgdev) | |||
2130 | card->write.ccwdev = ccwgdev->cdev[1]; | 2143 | card->write.ccwdev = ccwgdev->cdev[1]; |
2131 | 2144 | ||
2132 | recover_state = card->state; | 2145 | recover_state = card->state; |
2133 | ccw_device_set_online(card->read.ccwdev); | 2146 | rc = ccw_device_set_online(card->read.ccwdev); |
2134 | ccw_device_set_online(card->write.ccwdev); | 2147 | if (rc) |
2148 | goto out_err; | ||
2149 | rc = ccw_device_set_online(card->write.ccwdev); | ||
2150 | if (rc) | ||
2151 | goto out_werr; | ||
2135 | 2152 | ||
2136 | LCS_DBF_TEXT(3, setup, "lcsnewdv"); | 2153 | LCS_DBF_TEXT(3, setup, "lcsnewdv"); |
2137 | 2154 | ||
@@ -2210,8 +2227,10 @@ netdev_out: | |||
2210 | return 0; | 2227 | return 0; |
2211 | out: | 2228 | out: |
2212 | 2229 | ||
2213 | ccw_device_set_offline(card->read.ccwdev); | ||
2214 | ccw_device_set_offline(card->write.ccwdev); | 2230 | ccw_device_set_offline(card->write.ccwdev); |
2231 | out_werr: | ||
2232 | ccw_device_set_offline(card->read.ccwdev); | ||
2233 | out_err: | ||
2215 | return -ENODEV; | 2234 | return -ENODEV; |
2216 | } | 2235 | } |
2217 | 2236 | ||
@@ -2364,6 +2383,22 @@ static int lcs_restore(struct ccwgroup_device *gdev) | |||
2364 | return lcs_pm_resume(card); | 2383 | return lcs_pm_resume(card); |
2365 | } | 2384 | } |
2366 | 2385 | ||
2386 | static struct ccw_device_id lcs_ids[] = { | ||
2387 | {CCW_DEVICE(0x3088, 0x08), .driver_info = lcs_channel_type_parallel}, | ||
2388 | {CCW_DEVICE(0x3088, 0x1f), .driver_info = lcs_channel_type_2216}, | ||
2389 | {CCW_DEVICE(0x3088, 0x60), .driver_info = lcs_channel_type_osa2}, | ||
2390 | {}, | ||
2391 | }; | ||
2392 | MODULE_DEVICE_TABLE(ccw, lcs_ids); | ||
2393 | |||
2394 | static struct ccw_driver lcs_ccw_driver = { | ||
2395 | .owner = THIS_MODULE, | ||
2396 | .name = "lcs", | ||
2397 | .ids = lcs_ids, | ||
2398 | .probe = ccwgroup_probe_ccwdev, | ||
2399 | .remove = ccwgroup_remove_ccwdev, | ||
2400 | }; | ||
2401 | |||
2367 | /** | 2402 | /** |
2368 | * LCS ccwgroup driver registration | 2403 | * LCS ccwgroup driver registration |
2369 | */ | 2404 | */ |
@@ -2383,6 +2418,33 @@ static struct ccwgroup_driver lcs_group_driver = { | |||
2383 | .restore = lcs_restore, | 2418 | .restore = lcs_restore, |
2384 | }; | 2419 | }; |
2385 | 2420 | ||
2421 | static ssize_t | ||
2422 | lcs_driver_group_store(struct device_driver *ddrv, const char *buf, | ||
2423 | size_t count) | ||
2424 | { | ||
2425 | int err; | ||
2426 | err = ccwgroup_create_from_string(lcs_root_dev, | ||
2427 | lcs_group_driver.driver_id, | ||
2428 | &lcs_ccw_driver, 2, buf); | ||
2429 | return err ? err : count; | ||
2430 | } | ||
2431 | |||
2432 | static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store); | ||
2433 | |||
2434 | static struct attribute *lcs_group_attrs[] = { | ||
2435 | &driver_attr_group.attr, | ||
2436 | NULL, | ||
2437 | }; | ||
2438 | |||
2439 | static struct attribute_group lcs_group_attr_group = { | ||
2440 | .attrs = lcs_group_attrs, | ||
2441 | }; | ||
2442 | |||
2443 | static const struct attribute_group *lcs_group_attr_groups[] = { | ||
2444 | &lcs_group_attr_group, | ||
2445 | NULL, | ||
2446 | }; | ||
2447 | |||
2386 | /** | 2448 | /** |
2387 | * LCS Module/Kernel initialization function | 2449 | * LCS Module/Kernel initialization function |
2388 | */ | 2450 | */ |
@@ -2394,17 +2456,30 @@ __init lcs_init_module(void) | |||
2394 | pr_info("Loading %s\n", version); | 2456 | pr_info("Loading %s\n", version); |
2395 | rc = lcs_register_debug_facility(); | 2457 | rc = lcs_register_debug_facility(); |
2396 | LCS_DBF_TEXT(0, setup, "lcsinit"); | 2458 | LCS_DBF_TEXT(0, setup, "lcsinit"); |
2397 | if (rc) { | 2459 | if (rc) |
2398 | pr_err("Initialization failed\n"); | 2460 | goto out_err; |
2399 | return rc; | 2461 | lcs_root_dev = root_device_register("lcs"); |
2400 | } | 2462 | rc = IS_ERR(lcs_root_dev) ? PTR_ERR(lcs_root_dev) : 0; |
2401 | 2463 | if (rc) | |
2402 | rc = register_cu3088_discipline(&lcs_group_driver); | 2464 | goto register_err; |
2403 | if (rc) { | 2465 | rc = ccw_driver_register(&lcs_ccw_driver); |
2404 | pr_err("Initialization failed\n"); | 2466 | if (rc) |
2405 | return rc; | 2467 | goto ccw_err; |
2406 | } | 2468 | lcs_group_driver.driver.groups = lcs_group_attr_groups; |
2469 | rc = ccwgroup_driver_register(&lcs_group_driver); | ||
2470 | if (rc) | ||
2471 | goto ccwgroup_err; | ||
2407 | return 0; | 2472 | return 0; |
2473 | |||
2474 | ccwgroup_err: | ||
2475 | ccw_driver_unregister(&lcs_ccw_driver); | ||
2476 | ccw_err: | ||
2477 | root_device_unregister(lcs_root_dev); | ||
2478 | register_err: | ||
2479 | lcs_unregister_debug_facility(); | ||
2480 | out_err: | ||
2481 | pr_err("Initializing the lcs device driver failed\n"); | ||
2482 | return rc; | ||
2408 | } | 2483 | } |
2409 | 2484 | ||
2410 | 2485 | ||
@@ -2416,7 +2491,11 @@ __exit lcs_cleanup_module(void) | |||
2416 | { | 2491 | { |
2417 | pr_info("Terminating lcs module.\n"); | 2492 | pr_info("Terminating lcs module.\n"); |
2418 | LCS_DBF_TEXT(0, trace, "cleanup"); | 2493 | LCS_DBF_TEXT(0, trace, "cleanup"); |
2419 | unregister_cu3088_discipline(&lcs_group_driver); | 2494 | driver_remove_file(&lcs_group_driver.driver, |
2495 | &driver_attr_group); | ||
2496 | ccwgroup_driver_unregister(&lcs_group_driver); | ||
2497 | ccw_driver_unregister(&lcs_ccw_driver); | ||
2498 | root_device_unregister(lcs_root_dev); | ||
2420 | lcs_unregister_debug_facility(); | 2499 | lcs_unregister_debug_facility(); |
2421 | } | 2500 | } |
2422 | 2501 | ||
diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h index 6d668642af27..8c03392ac833 100644 --- a/drivers/s390/net/lcs.h +++ b/drivers/s390/net/lcs.h | |||
@@ -36,6 +36,24 @@ static inline int lcs_dbf_passes(debug_info_t *dbf_grp, int level) | |||
36 | #define CARD_FROM_DEV(cdev) \ | 36 | #define CARD_FROM_DEV(cdev) \ |
37 | (struct lcs_card *) dev_get_drvdata( \ | 37 | (struct lcs_card *) dev_get_drvdata( \ |
38 | &((struct ccwgroup_device *)dev_get_drvdata(&cdev->dev))->dev); | 38 | &((struct ccwgroup_device *)dev_get_drvdata(&cdev->dev))->dev); |
39 | |||
40 | /** | ||
41 | * Enum for classifying detected devices. | ||
42 | */ | ||
43 | enum lcs_channel_types { | ||
44 | /* Device is not a channel */ | ||
45 | lcs_channel_type_none, | ||
46 | |||
47 | /* Device is a 2216 channel */ | ||
48 | lcs_channel_type_parallel, | ||
49 | |||
50 | /* Device is a 2216 channel */ | ||
51 | lcs_channel_type_2216, | ||
52 | |||
53 | /* Device is a OSA2 card */ | ||
54 | lcs_channel_type_osa2 | ||
55 | }; | ||
56 | |||
39 | /** | 57 | /** |
40 | * CCW commands used in this driver | 58 | * CCW commands used in this driver |
41 | */ | 59 | */ |
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index c84eadd3602a..395c04c2b00f 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c | |||
@@ -741,13 +741,13 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg) | |||
741 | if (single_flag) { | 741 | if (single_flag) { |
742 | if ((skb = skb_dequeue(&conn->commit_queue))) { | 742 | if ((skb = skb_dequeue(&conn->commit_queue))) { |
743 | atomic_dec(&skb->users); | 743 | atomic_dec(&skb->users); |
744 | dev_kfree_skb_any(skb); | ||
745 | if (privptr) { | 744 | if (privptr) { |
746 | privptr->stats.tx_packets++; | 745 | privptr->stats.tx_packets++; |
747 | privptr->stats.tx_bytes += | 746 | privptr->stats.tx_bytes += |
748 | (skb->len - NETIUCV_HDRLEN | 747 | (skb->len - NETIUCV_HDRLEN |
749 | - NETIUCV_HDRLEN); | 748 | - NETIUCV_HDRLEN); |
750 | } | 749 | } |
750 | dev_kfree_skb_any(skb); | ||
751 | } | 751 | } |
752 | } | 752 | } |
753 | conn->tx_buff->data = conn->tx_buff->head; | 753 | conn->tx_buff->data = conn->tx_buff->head; |
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 31a2b4e502ce..b232693378cd 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -122,7 +122,6 @@ struct qeth_perf_stats { | |||
122 | __u64 outbound_do_qdio_start_time; | 122 | __u64 outbound_do_qdio_start_time; |
123 | unsigned int outbound_do_qdio_cnt; | 123 | unsigned int outbound_do_qdio_cnt; |
124 | unsigned int outbound_do_qdio_time; | 124 | unsigned int outbound_do_qdio_time; |
125 | /* eddp data */ | ||
126 | unsigned int large_send_bytes; | 125 | unsigned int large_send_bytes; |
127 | unsigned int large_send_cnt; | 126 | unsigned int large_send_cnt; |
128 | unsigned int sg_skbs_sent; | 127 | unsigned int sg_skbs_sent; |
@@ -135,6 +134,7 @@ struct qeth_perf_stats { | |||
135 | unsigned int sg_frags_rx; | 134 | unsigned int sg_frags_rx; |
136 | unsigned int sg_alloc_page_rx; | 135 | unsigned int sg_alloc_page_rx; |
137 | unsigned int tx_csum; | 136 | unsigned int tx_csum; |
137 | unsigned int tx_lin; | ||
138 | }; | 138 | }; |
139 | 139 | ||
140 | /* Routing stuff */ | 140 | /* Routing stuff */ |
@@ -648,6 +648,7 @@ struct qeth_card_options { | |||
648 | enum qeth_large_send_types large_send; | 648 | enum qeth_large_send_types large_send; |
649 | int performance_stats; | 649 | int performance_stats; |
650 | int rx_sg_cb; | 650 | int rx_sg_cb; |
651 | enum qeth_ipa_isolation_modes isolation; | ||
651 | }; | 652 | }; |
652 | 653 | ||
653 | /* | 654 | /* |
@@ -776,7 +777,6 @@ static inline void qeth_put_buffer_pool_entry(struct qeth_card *card, | |||
776 | list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list); | 777 | list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list); |
777 | } | 778 | } |
778 | 779 | ||
779 | struct qeth_eddp_context; | ||
780 | extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; | 780 | extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; |
781 | extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; | 781 | extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; |
782 | const char *qeth_get_cardname_short(struct qeth_card *); | 782 | const char *qeth_get_cardname_short(struct qeth_card *); |
@@ -836,7 +836,6 @@ void qeth_prepare_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, char); | |||
836 | struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); | 836 | struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); |
837 | int qeth_mdio_read(struct net_device *, int, int); | 837 | int qeth_mdio_read(struct net_device *, int, int); |
838 | int qeth_snmp_command(struct qeth_card *, char __user *); | 838 | int qeth_snmp_command(struct qeth_card *, char __user *); |
839 | int qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types); | ||
840 | struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32); | 839 | struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32); |
841 | int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *, | 840 | int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *, |
842 | unsigned long); | 841 | unsigned long); |
@@ -849,13 +848,14 @@ int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *, | |||
849 | struct sk_buff *, struct qeth_hdr *, int, int, int); | 848 | struct sk_buff *, struct qeth_hdr *, int, int, int); |
850 | int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *, | 849 | int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *, |
851 | struct sk_buff *, struct qeth_hdr *, int); | 850 | struct sk_buff *, struct qeth_hdr *, int); |
852 | int qeth_core_get_stats_count(struct net_device *); | 851 | int qeth_core_get_sset_count(struct net_device *, int); |
853 | void qeth_core_get_ethtool_stats(struct net_device *, | 852 | void qeth_core_get_ethtool_stats(struct net_device *, |
854 | struct ethtool_stats *, u64 *); | 853 | struct ethtool_stats *, u64 *); |
855 | void qeth_core_get_strings(struct net_device *, u32, u8 *); | 854 | void qeth_core_get_strings(struct net_device *, u32, u8 *); |
856 | void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *); | 855 | void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *); |
857 | void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...); | 856 | void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...); |
858 | int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); | 857 | int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); |
858 | int qeth_set_access_ctrl_online(struct qeth_card *card); | ||
859 | 859 | ||
860 | /* exports for OSN */ | 860 | /* exports for OSN */ |
861 | int qeth_osn_assist(struct net_device *, void *, int); | 861 | int qeth_osn_assist(struct net_device *, void *, int); |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index c4a42d970158..d34804d5ece1 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -270,41 +270,6 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt) | |||
270 | return qeth_alloc_buffer_pool(card); | 270 | return qeth_alloc_buffer_pool(card); |
271 | } | 271 | } |
272 | 272 | ||
273 | int qeth_set_large_send(struct qeth_card *card, | ||
274 | enum qeth_large_send_types type) | ||
275 | { | ||
276 | int rc = 0; | ||
277 | |||
278 | if (card->dev == NULL) { | ||
279 | card->options.large_send = type; | ||
280 | return 0; | ||
281 | } | ||
282 | if (card->state == CARD_STATE_UP) | ||
283 | netif_tx_disable(card->dev); | ||
284 | card->options.large_send = type; | ||
285 | switch (card->options.large_send) { | ||
286 | case QETH_LARGE_SEND_TSO: | ||
287 | if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) { | ||
288 | card->dev->features |= NETIF_F_TSO | NETIF_F_SG | | ||
289 | NETIF_F_HW_CSUM; | ||
290 | } else { | ||
291 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | | ||
292 | NETIF_F_HW_CSUM); | ||
293 | card->options.large_send = QETH_LARGE_SEND_NO; | ||
294 | rc = -EOPNOTSUPP; | ||
295 | } | ||
296 | break; | ||
297 | default: /* includes QETH_LARGE_SEND_NO */ | ||
298 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | | ||
299 | NETIF_F_HW_CSUM); | ||
300 | break; | ||
301 | } | ||
302 | if (card->state == CARD_STATE_UP) | ||
303 | netif_wake_queue(card->dev); | ||
304 | return rc; | ||
305 | } | ||
306 | EXPORT_SYMBOL_GPL(qeth_set_large_send); | ||
307 | |||
308 | static int qeth_issue_next_read(struct qeth_card *card) | 273 | static int qeth_issue_next_read(struct qeth_card *card) |
309 | { | 274 | { |
310 | int rc; | 275 | int rc; |
@@ -1079,6 +1044,7 @@ static void qeth_set_intial_options(struct qeth_card *card) | |||
1079 | card->options.add_hhlen = DEFAULT_ADD_HHLEN; | 1044 | card->options.add_hhlen = DEFAULT_ADD_HHLEN; |
1080 | card->options.performance_stats = 0; | 1045 | card->options.performance_stats = 0; |
1081 | card->options.rx_sg_cb = QETH_RX_SG_CB; | 1046 | card->options.rx_sg_cb = QETH_RX_SG_CB; |
1047 | card->options.isolation = ISOLATION_MODE_NONE; | ||
1082 | } | 1048 | } |
1083 | 1049 | ||
1084 | static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread) | 1050 | static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread) |
@@ -3389,6 +3355,156 @@ int qeth_setadpparms_change_macaddr(struct qeth_card *card) | |||
3389 | } | 3355 | } |
3390 | EXPORT_SYMBOL_GPL(qeth_setadpparms_change_macaddr); | 3356 | EXPORT_SYMBOL_GPL(qeth_setadpparms_change_macaddr); |
3391 | 3357 | ||
3358 | static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card, | ||
3359 | struct qeth_reply *reply, unsigned long data) | ||
3360 | { | ||
3361 | struct qeth_ipa_cmd *cmd; | ||
3362 | struct qeth_set_access_ctrl *access_ctrl_req; | ||
3363 | int rc; | ||
3364 | |||
3365 | QETH_DBF_TEXT(TRACE, 4, "setaccb"); | ||
3366 | |||
3367 | cmd = (struct qeth_ipa_cmd *) data; | ||
3368 | access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl; | ||
3369 | QETH_DBF_TEXT_(SETUP, 2, "setaccb"); | ||
3370 | QETH_DBF_TEXT_(SETUP, 2, "%s", card->gdev->dev.kobj.name); | ||
3371 | QETH_DBF_TEXT_(SETUP, 2, "rc=%d", | ||
3372 | cmd->data.setadapterparms.hdr.return_code); | ||
3373 | switch (cmd->data.setadapterparms.hdr.return_code) { | ||
3374 | case SET_ACCESS_CTRL_RC_SUCCESS: | ||
3375 | case SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED: | ||
3376 | case SET_ACCESS_CTRL_RC_ALREADY_ISOLATED: | ||
3377 | { | ||
3378 | card->options.isolation = access_ctrl_req->subcmd_code; | ||
3379 | if (card->options.isolation == ISOLATION_MODE_NONE) { | ||
3380 | dev_info(&card->gdev->dev, | ||
3381 | "QDIO data connection isolation is deactivated\n"); | ||
3382 | } else { | ||
3383 | dev_info(&card->gdev->dev, | ||
3384 | "QDIO data connection isolation is activated\n"); | ||
3385 | } | ||
3386 | QETH_DBF_MESSAGE(3, "OK:SET_ACCESS_CTRL(%s, %d)==%d\n", | ||
3387 | card->gdev->dev.kobj.name, | ||
3388 | access_ctrl_req->subcmd_code, | ||
3389 | cmd->data.setadapterparms.hdr.return_code); | ||
3390 | rc = 0; | ||
3391 | break; | ||
3392 | } | ||
3393 | case SET_ACCESS_CTRL_RC_NOT_SUPPORTED: | ||
3394 | { | ||
3395 | QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%s,%d)==%d\n", | ||
3396 | card->gdev->dev.kobj.name, | ||
3397 | access_ctrl_req->subcmd_code, | ||
3398 | cmd->data.setadapterparms.hdr.return_code); | ||
3399 | dev_err(&card->gdev->dev, "Adapter does not " | ||
3400 | "support QDIO data connection isolation\n"); | ||
3401 | |||
3402 | /* ensure isolation mode is "none" */ | ||
3403 | card->options.isolation = ISOLATION_MODE_NONE; | ||
3404 | rc = -EOPNOTSUPP; | ||
3405 | break; | ||
3406 | } | ||
3407 | case SET_ACCESS_CTRL_RC_NONE_SHARED_ADAPTER: | ||
3408 | { | ||
3409 | QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d\n", | ||
3410 | card->gdev->dev.kobj.name, | ||
3411 | access_ctrl_req->subcmd_code, | ||
3412 | cmd->data.setadapterparms.hdr.return_code); | ||
3413 | dev_err(&card->gdev->dev, | ||
3414 | "Adapter is dedicated. " | ||
3415 | "QDIO data connection isolation not supported\n"); | ||
3416 | |||
3417 | /* ensure isolation mode is "none" */ | ||
3418 | card->options.isolation = ISOLATION_MODE_NONE; | ||
3419 | rc = -EOPNOTSUPP; | ||
3420 | break; | ||
3421 | } | ||
3422 | case SET_ACCESS_CTRL_RC_ACTIVE_CHECKSUM_OFF: | ||
3423 | { | ||
3424 | QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d\n", | ||
3425 | card->gdev->dev.kobj.name, | ||
3426 | access_ctrl_req->subcmd_code, | ||
3427 | cmd->data.setadapterparms.hdr.return_code); | ||
3428 | dev_err(&card->gdev->dev, | ||
3429 | "TSO does not permit QDIO data connection isolation\n"); | ||
3430 | |||
3431 | /* ensure isolation mode is "none" */ | ||
3432 | card->options.isolation = ISOLATION_MODE_NONE; | ||
3433 | rc = -EPERM; | ||
3434 | break; | ||
3435 | } | ||
3436 | default: | ||
3437 | { | ||
3438 | /* this should never happen */ | ||
3439 | QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d" | ||
3440 | "==UNKNOWN\n", | ||
3441 | card->gdev->dev.kobj.name, | ||
3442 | access_ctrl_req->subcmd_code, | ||
3443 | cmd->data.setadapterparms.hdr.return_code); | ||
3444 | |||
3445 | /* ensure isolation mode is "none" */ | ||
3446 | card->options.isolation = ISOLATION_MODE_NONE; | ||
3447 | rc = 0; | ||
3448 | break; | ||
3449 | } | ||
3450 | } | ||
3451 | qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd); | ||
3452 | return rc; | ||
3453 | } | ||
3454 | |||
3455 | static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card, | ||
3456 | enum qeth_ipa_isolation_modes isolation) | ||
3457 | { | ||
3458 | int rc; | ||
3459 | struct qeth_cmd_buffer *iob; | ||
3460 | struct qeth_ipa_cmd *cmd; | ||
3461 | struct qeth_set_access_ctrl *access_ctrl_req; | ||
3462 | |||
3463 | QETH_DBF_TEXT(TRACE, 4, "setacctl"); | ||
3464 | |||
3465 | QETH_DBF_TEXT_(SETUP, 2, "setacctl"); | ||
3466 | QETH_DBF_TEXT_(SETUP, 2, "%s", card->gdev->dev.kobj.name); | ||
3467 | |||
3468 | iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_ACCESS_CONTROL, | ||
3469 | sizeof(struct qeth_ipacmd_setadpparms_hdr) + | ||
3470 | sizeof(struct qeth_set_access_ctrl)); | ||
3471 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
3472 | access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl; | ||
3473 | access_ctrl_req->subcmd_code = isolation; | ||
3474 | |||
3475 | rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_set_access_ctrl_cb, | ||
3476 | NULL); | ||
3477 | QETH_DBF_TEXT_(SETUP, 2, "rc=%d", rc); | ||
3478 | return rc; | ||
3479 | } | ||
3480 | |||
3481 | int qeth_set_access_ctrl_online(struct qeth_card *card) | ||
3482 | { | ||
3483 | int rc = 0; | ||
3484 | |||
3485 | QETH_DBF_TEXT(TRACE, 4, "setactlo"); | ||
3486 | |||
3487 | if (card->info.type == QETH_CARD_TYPE_OSAE && | ||
3488 | qeth_adp_supported(card, IPA_SETADP_SET_ACCESS_CONTROL)) { | ||
3489 | rc = qeth_setadpparms_set_access_ctrl(card, | ||
3490 | card->options.isolation); | ||
3491 | if (rc) { | ||
3492 | QETH_DBF_MESSAGE(3, | ||
3493 | "IPA(SET_ACCESS_CTRL,%s,%d) sent failed", | ||
3494 | card->gdev->dev.kobj.name, | ||
3495 | rc); | ||
3496 | } | ||
3497 | } else if (card->options.isolation != ISOLATION_MODE_NONE) { | ||
3498 | card->options.isolation = ISOLATION_MODE_NONE; | ||
3499 | |||
3500 | dev_err(&card->gdev->dev, "Adapter does not " | ||
3501 | "support QDIO data connection isolation\n"); | ||
3502 | rc = -EOPNOTSUPP; | ||
3503 | } | ||
3504 | return rc; | ||
3505 | } | ||
3506 | EXPORT_SYMBOL_GPL(qeth_set_access_ctrl_online); | ||
3507 | |||
3392 | void qeth_tx_timeout(struct net_device *dev) | 3508 | void qeth_tx_timeout(struct net_device *dev) |
3393 | { | 3509 | { |
3394 | struct qeth_card *card; | 3510 | struct qeth_card *card; |
@@ -3732,30 +3848,36 @@ static int qeth_core_driver_group(const char *buf, struct device *root_dev, | |||
3732 | int qeth_core_hardsetup_card(struct qeth_card *card) | 3848 | int qeth_core_hardsetup_card(struct qeth_card *card) |
3733 | { | 3849 | { |
3734 | struct qdio_ssqd_desc *ssqd; | 3850 | struct qdio_ssqd_desc *ssqd; |
3735 | int retries = 3; | 3851 | int retries = 0; |
3736 | int mpno = 0; | 3852 | int mpno = 0; |
3737 | int rc; | 3853 | int rc; |
3738 | 3854 | ||
3739 | QETH_DBF_TEXT(SETUP, 2, "hrdsetup"); | 3855 | QETH_DBF_TEXT(SETUP, 2, "hrdsetup"); |
3740 | atomic_set(&card->force_alloc_skb, 0); | 3856 | atomic_set(&card->force_alloc_skb, 0); |
3741 | retry: | 3857 | retry: |
3742 | if (retries < 3) { | 3858 | if (retries) |
3743 | QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", | 3859 | QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", |
3744 | dev_name(&card->gdev->dev)); | 3860 | dev_name(&card->gdev->dev)); |
3745 | ccw_device_set_offline(CARD_DDEV(card)); | 3861 | ccw_device_set_offline(CARD_DDEV(card)); |
3746 | ccw_device_set_offline(CARD_WDEV(card)); | 3862 | ccw_device_set_offline(CARD_WDEV(card)); |
3747 | ccw_device_set_offline(CARD_RDEV(card)); | 3863 | ccw_device_set_offline(CARD_RDEV(card)); |
3748 | ccw_device_set_online(CARD_RDEV(card)); | 3864 | rc = ccw_device_set_online(CARD_RDEV(card)); |
3749 | ccw_device_set_online(CARD_WDEV(card)); | 3865 | if (rc) |
3750 | ccw_device_set_online(CARD_DDEV(card)); | 3866 | goto retriable; |
3751 | } | 3867 | rc = ccw_device_set_online(CARD_WDEV(card)); |
3868 | if (rc) | ||
3869 | goto retriable; | ||
3870 | rc = ccw_device_set_online(CARD_DDEV(card)); | ||
3871 | if (rc) | ||
3872 | goto retriable; | ||
3752 | rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD); | 3873 | rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD); |
3874 | retriable: | ||
3753 | if (rc == -ERESTARTSYS) { | 3875 | if (rc == -ERESTARTSYS) { |
3754 | QETH_DBF_TEXT(SETUP, 2, "break1"); | 3876 | QETH_DBF_TEXT(SETUP, 2, "break1"); |
3755 | return rc; | 3877 | return rc; |
3756 | } else if (rc) { | 3878 | } else if (rc) { |
3757 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | 3879 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); |
3758 | if (--retries < 0) | 3880 | if (++retries > 3) |
3759 | goto out; | 3881 | goto out; |
3760 | else | 3882 | else |
3761 | goto retry; | 3883 | goto retry; |
@@ -4303,13 +4425,19 @@ static struct { | |||
4303 | {"tx do_QDIO time"}, | 4425 | {"tx do_QDIO time"}, |
4304 | {"tx do_QDIO count"}, | 4426 | {"tx do_QDIO count"}, |
4305 | {"tx csum"}, | 4427 | {"tx csum"}, |
4428 | {"tx lin"}, | ||
4306 | }; | 4429 | }; |
4307 | 4430 | ||
4308 | int qeth_core_get_stats_count(struct net_device *dev) | 4431 | int qeth_core_get_sset_count(struct net_device *dev, int stringset) |
4309 | { | 4432 | { |
4310 | return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN); | 4433 | switch (stringset) { |
4434 | case ETH_SS_STATS: | ||
4435 | return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN); | ||
4436 | default: | ||
4437 | return -EINVAL; | ||
4438 | } | ||
4311 | } | 4439 | } |
4312 | EXPORT_SYMBOL_GPL(qeth_core_get_stats_count); | 4440 | EXPORT_SYMBOL_GPL(qeth_core_get_sset_count); |
4313 | 4441 | ||
4314 | void qeth_core_get_ethtool_stats(struct net_device *dev, | 4442 | void qeth_core_get_ethtool_stats(struct net_device *dev, |
4315 | struct ethtool_stats *stats, u64 *data) | 4443 | struct ethtool_stats *stats, u64 *data) |
@@ -4355,6 +4483,7 @@ void qeth_core_get_ethtool_stats(struct net_device *dev, | |||
4355 | data[31] = card->perf_stats.outbound_do_qdio_time; | 4483 | data[31] = card->perf_stats.outbound_do_qdio_time; |
4356 | data[32] = card->perf_stats.outbound_do_qdio_cnt; | 4484 | data[32] = card->perf_stats.outbound_do_qdio_cnt; |
4357 | data[33] = card->perf_stats.tx_csum; | 4485 | data[33] = card->perf_stats.tx_csum; |
4486 | data[34] = card->perf_stats.tx_lin; | ||
4358 | } | 4487 | } |
4359 | EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats); | 4488 | EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats); |
4360 | 4489 | ||
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index eecb2ee62e85..52c03438dbec 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h | |||
@@ -234,18 +234,19 @@ enum qeth_ipa_setdelip_flags { | |||
234 | 234 | ||
235 | /* SETADAPTER IPA Command: ****************************************************/ | 235 | /* SETADAPTER IPA Command: ****************************************************/ |
236 | enum qeth_ipa_setadp_cmd { | 236 | enum qeth_ipa_setadp_cmd { |
237 | IPA_SETADP_QUERY_COMMANDS_SUPPORTED = 0x0001, | 237 | IPA_SETADP_QUERY_COMMANDS_SUPPORTED = 0x00000001L, |
238 | IPA_SETADP_ALTER_MAC_ADDRESS = 0x0002, | 238 | IPA_SETADP_ALTER_MAC_ADDRESS = 0x00000002L, |
239 | IPA_SETADP_ADD_DELETE_GROUP_ADDRESS = 0x0004, | 239 | IPA_SETADP_ADD_DELETE_GROUP_ADDRESS = 0x00000004L, |
240 | IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR = 0x0008, | 240 | IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR = 0x00000008L, |
241 | IPA_SETADP_SET_ADDRESSING_MODE = 0x0010, | 241 | IPA_SETADP_SET_ADDRESSING_MODE = 0x00000010L, |
242 | IPA_SETADP_SET_CONFIG_PARMS = 0x0020, | 242 | IPA_SETADP_SET_CONFIG_PARMS = 0x00000020L, |
243 | IPA_SETADP_SET_CONFIG_PARMS_EXTENDED = 0x0040, | 243 | IPA_SETADP_SET_CONFIG_PARMS_EXTENDED = 0x00000040L, |
244 | IPA_SETADP_SET_BROADCAST_MODE = 0x0080, | 244 | IPA_SETADP_SET_BROADCAST_MODE = 0x00000080L, |
245 | IPA_SETADP_SEND_OSA_MESSAGE = 0x0100, | 245 | IPA_SETADP_SEND_OSA_MESSAGE = 0x00000100L, |
246 | IPA_SETADP_SET_SNMP_CONTROL = 0x0200, | 246 | IPA_SETADP_SET_SNMP_CONTROL = 0x00000200L, |
247 | IPA_SETADP_QUERY_CARD_INFO = 0x0400, | 247 | IPA_SETADP_QUERY_CARD_INFO = 0x00000400L, |
248 | IPA_SETADP_SET_PROMISC_MODE = 0x0800, | 248 | IPA_SETADP_SET_PROMISC_MODE = 0x00000800L, |
249 | IPA_SETADP_SET_ACCESS_CONTROL = 0x00010000L, | ||
249 | }; | 250 | }; |
250 | enum qeth_ipa_mac_ops { | 251 | enum qeth_ipa_mac_ops { |
251 | CHANGE_ADDR_READ_MAC = 0, | 252 | CHANGE_ADDR_READ_MAC = 0, |
@@ -264,6 +265,20 @@ enum qeth_ipa_promisc_modes { | |||
264 | SET_PROMISC_MODE_OFF = 0, | 265 | SET_PROMISC_MODE_OFF = 0, |
265 | SET_PROMISC_MODE_ON = 1, | 266 | SET_PROMISC_MODE_ON = 1, |
266 | }; | 267 | }; |
268 | enum qeth_ipa_isolation_modes { | ||
269 | ISOLATION_MODE_NONE = 0x00000000L, | ||
270 | ISOLATION_MODE_FWD = 0x00000001L, | ||
271 | ISOLATION_MODE_DROP = 0x00000002L, | ||
272 | }; | ||
273 | enum qeth_ipa_set_access_mode_rc { | ||
274 | SET_ACCESS_CTRL_RC_SUCCESS = 0x0000, | ||
275 | SET_ACCESS_CTRL_RC_NOT_SUPPORTED = 0x0004, | ||
276 | SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED = 0x0008, | ||
277 | SET_ACCESS_CTRL_RC_ALREADY_ISOLATED = 0x0010, | ||
278 | SET_ACCESS_CTRL_RC_NONE_SHARED_ADAPTER = 0x0014, | ||
279 | SET_ACCESS_CTRL_RC_ACTIVE_CHECKSUM_OFF = 0x0018, | ||
280 | }; | ||
281 | |||
267 | 282 | ||
268 | /* (SET)DELIP(M) IPA stuff ***************************************************/ | 283 | /* (SET)DELIP(M) IPA stuff ***************************************************/ |
269 | struct qeth_ipacmd_setdelip4 { | 284 | struct qeth_ipacmd_setdelip4 { |
@@ -376,6 +391,11 @@ struct qeth_snmp_ureq { | |||
376 | struct qeth_snmp_cmd cmd; | 391 | struct qeth_snmp_cmd cmd; |
377 | } __attribute__((packed)); | 392 | } __attribute__((packed)); |
378 | 393 | ||
394 | /* SET_ACCESS_CONTROL: same format for request and reply */ | ||
395 | struct qeth_set_access_ctrl { | ||
396 | __u32 subcmd_code; | ||
397 | } __attribute__((packed)); | ||
398 | |||
379 | struct qeth_ipacmd_setadpparms_hdr { | 399 | struct qeth_ipacmd_setadpparms_hdr { |
380 | __u32 supp_hw_cmds; | 400 | __u32 supp_hw_cmds; |
381 | __u32 reserved1; | 401 | __u32 reserved1; |
@@ -394,6 +414,7 @@ struct qeth_ipacmd_setadpparms { | |||
394 | struct qeth_query_cmds_supp query_cmds_supp; | 414 | struct qeth_query_cmds_supp query_cmds_supp; |
395 | struct qeth_change_addr change_addr; | 415 | struct qeth_change_addr change_addr; |
396 | struct qeth_snmp_cmd snmp; | 416 | struct qeth_snmp_cmd snmp; |
417 | struct qeth_set_access_ctrl set_access_ctrl; | ||
397 | __u32 mode; | 418 | __u32 mode; |
398 | } data; | 419 | } data; |
399 | } __attribute__ ((packed)); | 420 | } __attribute__ ((packed)); |
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 33505c2a0e3a..9ff2b36fdc43 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c | |||
@@ -416,7 +416,11 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, | |||
416 | static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show, | 416 | static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show, |
417 | qeth_dev_layer2_store); | 417 | qeth_dev_layer2_store); |
418 | 418 | ||
419 | static ssize_t qeth_dev_large_send_show(struct device *dev, | 419 | #define ATTR_QETH_ISOLATION_NONE ("none") |
420 | #define ATTR_QETH_ISOLATION_FWD ("forward") | ||
421 | #define ATTR_QETH_ISOLATION_DROP ("drop") | ||
422 | |||
423 | static ssize_t qeth_dev_isolation_show(struct device *dev, | ||
420 | struct device_attribute *attr, char *buf) | 424 | struct device_attribute *attr, char *buf) |
421 | { | 425 | { |
422 | struct qeth_card *card = dev_get_drvdata(dev); | 426 | struct qeth_card *card = dev_get_drvdata(dev); |
@@ -424,44 +428,69 @@ static ssize_t qeth_dev_large_send_show(struct device *dev, | |||
424 | if (!card) | 428 | if (!card) |
425 | return -EINVAL; | 429 | return -EINVAL; |
426 | 430 | ||
427 | switch (card->options.large_send) { | 431 | switch (card->options.isolation) { |
428 | case QETH_LARGE_SEND_NO: | 432 | case ISOLATION_MODE_NONE: |
429 | return sprintf(buf, "%s\n", "no"); | 433 | return snprintf(buf, 6, "%s\n", ATTR_QETH_ISOLATION_NONE); |
430 | case QETH_LARGE_SEND_TSO: | 434 | case ISOLATION_MODE_FWD: |
431 | return sprintf(buf, "%s\n", "TSO"); | 435 | return snprintf(buf, 9, "%s\n", ATTR_QETH_ISOLATION_FWD); |
436 | case ISOLATION_MODE_DROP: | ||
437 | return snprintf(buf, 6, "%s\n", ATTR_QETH_ISOLATION_DROP); | ||
432 | default: | 438 | default: |
433 | return sprintf(buf, "%s\n", "N/A"); | 439 | return snprintf(buf, 5, "%s\n", "N/A"); |
434 | } | 440 | } |
435 | } | 441 | } |
436 | 442 | ||
437 | static ssize_t qeth_dev_large_send_store(struct device *dev, | 443 | static ssize_t qeth_dev_isolation_store(struct device *dev, |
438 | struct device_attribute *attr, const char *buf, size_t count) | 444 | struct device_attribute *attr, const char *buf, size_t count) |
439 | { | 445 | { |
440 | struct qeth_card *card = dev_get_drvdata(dev); | 446 | struct qeth_card *card = dev_get_drvdata(dev); |
441 | enum qeth_large_send_types type; | 447 | enum qeth_ipa_isolation_modes isolation; |
442 | int rc = 0; | 448 | int rc = 0; |
443 | char *tmp; | 449 | char *tmp, *curtoken; |
450 | curtoken = (char *) buf; | ||
444 | 451 | ||
445 | if (!card) | 452 | if (!card) { |
446 | return -EINVAL; | 453 | rc = -EINVAL; |
447 | tmp = strsep((char **) &buf, "\n"); | 454 | goto out; |
448 | if (!strcmp(tmp, "no")) { | 455 | } |
449 | type = QETH_LARGE_SEND_NO; | 456 | |
450 | } else if (!strcmp(tmp, "TSO")) { | 457 | /* check for unknown, too, in case we do not yet know who we are */ |
451 | type = QETH_LARGE_SEND_TSO; | 458 | if (card->info.type != QETH_CARD_TYPE_OSAE && |
459 | card->info.type != QETH_CARD_TYPE_UNKNOWN) { | ||
460 | rc = -EOPNOTSUPP; | ||
461 | dev_err(&card->gdev->dev, "Adapter does not " | ||
462 | "support QDIO data connection isolation\n"); | ||
463 | goto out; | ||
464 | } | ||
465 | |||
466 | /* parse input into isolation mode */ | ||
467 | tmp = strsep(&curtoken, "\n"); | ||
468 | if (!strcmp(tmp, ATTR_QETH_ISOLATION_NONE)) { | ||
469 | isolation = ISOLATION_MODE_NONE; | ||
470 | } else if (!strcmp(tmp, ATTR_QETH_ISOLATION_FWD)) { | ||
471 | isolation = ISOLATION_MODE_FWD; | ||
472 | } else if (!strcmp(tmp, ATTR_QETH_ISOLATION_DROP)) { | ||
473 | isolation = ISOLATION_MODE_DROP; | ||
452 | } else { | 474 | } else { |
453 | return -EINVAL; | 475 | rc = -EINVAL; |
476 | goto out; | ||
454 | } | 477 | } |
455 | if (card->options.large_send == type) | 478 | rc = count; |
456 | return count; | 479 | |
457 | rc = qeth_set_large_send(card, type); | 480 | /* defer IP assist if device is offline (until discipline->set_online)*/ |
458 | if (rc) | 481 | card->options.isolation = isolation; |
459 | return rc; | 482 | if (card->state == CARD_STATE_SOFTSETUP || |
460 | return count; | 483 | card->state == CARD_STATE_UP) { |
484 | int ipa_rc = qeth_set_access_ctrl_online(card); | ||
485 | if (ipa_rc != 0) | ||
486 | rc = ipa_rc; | ||
487 | } | ||
488 | out: | ||
489 | return rc; | ||
461 | } | 490 | } |
462 | 491 | ||
463 | static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show, | 492 | static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show, |
464 | qeth_dev_large_send_store); | 493 | qeth_dev_isolation_store); |
465 | 494 | ||
466 | static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value) | 495 | static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value) |
467 | { | 496 | { |
@@ -582,7 +611,7 @@ static struct attribute *qeth_device_attrs[] = { | |||
582 | &dev_attr_recover.attr, | 611 | &dev_attr_recover.attr, |
583 | &dev_attr_performance_stats.attr, | 612 | &dev_attr_performance_stats.attr, |
584 | &dev_attr_layer2.attr, | 613 | &dev_attr_layer2.attr, |
585 | &dev_attr_large_send.attr, | 614 | &dev_attr_isolation.attr, |
586 | NULL, | 615 | NULL, |
587 | }; | 616 | }; |
588 | 617 | ||
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index f4f3ca1393b2..0b763396d5d1 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
@@ -866,7 +866,7 @@ static const struct ethtool_ops qeth_l2_ethtool_ops = { | |||
866 | .get_link = ethtool_op_get_link, | 866 | .get_link = ethtool_op_get_link, |
867 | .get_strings = qeth_core_get_strings, | 867 | .get_strings = qeth_core_get_strings, |
868 | .get_ethtool_stats = qeth_core_get_ethtool_stats, | 868 | .get_ethtool_stats = qeth_core_get_ethtool_stats, |
869 | .get_stats_count = qeth_core_get_stats_count, | 869 | .get_sset_count = qeth_core_get_sset_count, |
870 | .get_drvinfo = qeth_core_get_drvinfo, | 870 | .get_drvinfo = qeth_core_get_drvinfo, |
871 | .get_settings = qeth_core_ethtool_get_settings, | 871 | .get_settings = qeth_core_ethtool_get_settings, |
872 | }; | 872 | }; |
@@ -874,7 +874,7 @@ static const struct ethtool_ops qeth_l2_ethtool_ops = { | |||
874 | static const struct ethtool_ops qeth_l2_osn_ops = { | 874 | static const struct ethtool_ops qeth_l2_osn_ops = { |
875 | .get_strings = qeth_core_get_strings, | 875 | .get_strings = qeth_core_get_strings, |
876 | .get_ethtool_stats = qeth_core_get_ethtool_stats, | 876 | .get_ethtool_stats = qeth_core_get_ethtool_stats, |
877 | .get_stats_count = qeth_core_get_stats_count, | 877 | .get_sset_count = qeth_core_get_sset_count, |
878 | .get_drvinfo = qeth_core_get_drvinfo, | 878 | .get_drvinfo = qeth_core_get_drvinfo, |
879 | }; | 879 | }; |
880 | 880 | ||
@@ -940,30 +940,17 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
940 | 940 | ||
941 | qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1); | 941 | qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1); |
942 | recover_flag = card->state; | 942 | recover_flag = card->state; |
943 | rc = ccw_device_set_online(CARD_RDEV(card)); | ||
944 | if (rc) { | ||
945 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | ||
946 | return -EIO; | ||
947 | } | ||
948 | rc = ccw_device_set_online(CARD_WDEV(card)); | ||
949 | if (rc) { | ||
950 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | ||
951 | return -EIO; | ||
952 | } | ||
953 | rc = ccw_device_set_online(CARD_DDEV(card)); | ||
954 | if (rc) { | ||
955 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | ||
956 | return -EIO; | ||
957 | } | ||
958 | |||
959 | rc = qeth_core_hardsetup_card(card); | 943 | rc = qeth_core_hardsetup_card(card); |
960 | if (rc) { | 944 | if (rc) { |
961 | QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); | 945 | QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); |
946 | rc = -ENODEV; | ||
962 | goto out_remove; | 947 | goto out_remove; |
963 | } | 948 | } |
964 | 949 | ||
965 | if (!card->dev && qeth_l2_setup_netdev(card)) | 950 | if (!card->dev && qeth_l2_setup_netdev(card)) { |
951 | rc = -ENODEV; | ||
966 | goto out_remove; | 952 | goto out_remove; |
953 | } | ||
967 | 954 | ||
968 | if (card->info.type != QETH_CARD_TYPE_OSN) | 955 | if (card->info.type != QETH_CARD_TYPE_OSN) |
969 | qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); | 956 | qeth_l2_send_setmac(card, &card->dev->dev_addr[0]); |
@@ -983,12 +970,14 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
983 | card->lan_online = 0; | 970 | card->lan_online = 0; |
984 | return 0; | 971 | return 0; |
985 | } | 972 | } |
973 | rc = -ENODEV; | ||
986 | goto out_remove; | 974 | goto out_remove; |
987 | } else | 975 | } else |
988 | card->lan_online = 1; | 976 | card->lan_online = 1; |
989 | 977 | ||
990 | if (card->info.type != QETH_CARD_TYPE_OSN) { | 978 | if (card->info.type != QETH_CARD_TYPE_OSN) { |
991 | qeth_set_large_send(card, card->options.large_send); | 979 | /* configure isolation level */ |
980 | qeth_set_access_ctrl_online(card); | ||
992 | qeth_l2_process_vlans(card, 0); | 981 | qeth_l2_process_vlans(card, 0); |
993 | } | 982 | } |
994 | 983 | ||
@@ -997,6 +986,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
997 | rc = qeth_init_qdio_queues(card); | 986 | rc = qeth_init_qdio_queues(card); |
998 | if (rc) { | 987 | if (rc) { |
999 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); | 988 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); |
989 | rc = -ENODEV; | ||
1000 | goto out_remove; | 990 | goto out_remove; |
1001 | } | 991 | } |
1002 | card->state = CARD_STATE_SOFTSETUP; | 992 | card->state = CARD_STATE_SOFTSETUP; |
@@ -1018,6 +1008,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
1018 | /* let user_space know that device is online */ | 1008 | /* let user_space know that device is online */ |
1019 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); | 1009 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); |
1020 | return 0; | 1010 | return 0; |
1011 | |||
1021 | out_remove: | 1012 | out_remove: |
1022 | card->use_hard_stop = 1; | 1013 | card->use_hard_stop = 1; |
1023 | qeth_l2_stop_card(card, 0); | 1014 | qeth_l2_stop_card(card, 0); |
@@ -1028,7 +1019,7 @@ out_remove: | |||
1028 | card->state = CARD_STATE_RECOVER; | 1019 | card->state = CARD_STATE_RECOVER; |
1029 | else | 1020 | else |
1030 | card->state = CARD_STATE_DOWN; | 1021 | card->state = CARD_STATE_DOWN; |
1031 | return -ENODEV; | 1022 | return rc; |
1032 | } | 1023 | } |
1033 | 1024 | ||
1034 | static int qeth_l2_set_online(struct ccwgroup_device *gdev) | 1025 | static int qeth_l2_set_online(struct ccwgroup_device *gdev) |
diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h index 9f143c83bba3..321988fa9f7d 100644 --- a/drivers/s390/net/qeth_l3.h +++ b/drivers/s390/net/qeth_l3.h | |||
@@ -60,5 +60,7 @@ void qeth_l3_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *); | |||
60 | int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *); | 60 | int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *); |
61 | void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions, | 61 | void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions, |
62 | const u8 *); | 62 | const u8 *); |
63 | int qeth_l3_set_large_send(struct qeth_card *, enum qeth_large_send_types); | ||
64 | int qeth_l3_set_rx_csum(struct qeth_card *, enum qeth_checksum_types); | ||
63 | 65 | ||
64 | #endif /* __QETH_L3_H__ */ | 66 | #endif /* __QETH_L3_H__ */ |
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 073b6d354915..fd1b6ed3721f 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -41,6 +41,32 @@ static int qeth_l3_deregister_addr_entry(struct qeth_card *, | |||
41 | static int __qeth_l3_set_online(struct ccwgroup_device *, int); | 41 | static int __qeth_l3_set_online(struct ccwgroup_device *, int); |
42 | static int __qeth_l3_set_offline(struct ccwgroup_device *, int); | 42 | static int __qeth_l3_set_offline(struct ccwgroup_device *, int); |
43 | 43 | ||
44 | int qeth_l3_set_large_send(struct qeth_card *card, | ||
45 | enum qeth_large_send_types type) | ||
46 | { | ||
47 | int rc = 0; | ||
48 | |||
49 | card->options.large_send = type; | ||
50 | if (card->dev == NULL) | ||
51 | return 0; | ||
52 | |||
53 | if (card->options.large_send == QETH_LARGE_SEND_TSO) { | ||
54 | if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) { | ||
55 | card->dev->features |= NETIF_F_TSO | NETIF_F_SG | | ||
56 | NETIF_F_HW_CSUM; | ||
57 | } else { | ||
58 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | | ||
59 | NETIF_F_HW_CSUM); | ||
60 | card->options.large_send = QETH_LARGE_SEND_NO; | ||
61 | rc = -EOPNOTSUPP; | ||
62 | } | ||
63 | } else { | ||
64 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | | ||
65 | NETIF_F_HW_CSUM); | ||
66 | card->options.large_send = QETH_LARGE_SEND_NO; | ||
67 | } | ||
68 | return rc; | ||
69 | } | ||
44 | 70 | ||
45 | static int qeth_l3_isxdigit(char *buf) | 71 | static int qeth_l3_isxdigit(char *buf) |
46 | { | 72 | { |
@@ -1439,6 +1465,35 @@ static int qeth_l3_send_checksum_command(struct qeth_card *card) | |||
1439 | return 0; | 1465 | return 0; |
1440 | } | 1466 | } |
1441 | 1467 | ||
1468 | int qeth_l3_set_rx_csum(struct qeth_card *card, | ||
1469 | enum qeth_checksum_types csum_type) | ||
1470 | { | ||
1471 | int rc = 0; | ||
1472 | |||
1473 | if (card->options.checksum_type == HW_CHECKSUMMING) { | ||
1474 | if ((csum_type != HW_CHECKSUMMING) && | ||
1475 | (card->state != CARD_STATE_DOWN)) { | ||
1476 | rc = qeth_l3_send_simple_setassparms(card, | ||
1477 | IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0); | ||
1478 | if (rc) | ||
1479 | return -EIO; | ||
1480 | } | ||
1481 | } else { | ||
1482 | if (csum_type == HW_CHECKSUMMING) { | ||
1483 | if (card->state != CARD_STATE_DOWN) { | ||
1484 | if (!qeth_is_supported(card, | ||
1485 | IPA_INBOUND_CHECKSUM)) | ||
1486 | return -EPERM; | ||
1487 | rc = qeth_l3_send_checksum_command(card); | ||
1488 | if (rc) | ||
1489 | return -EIO; | ||
1490 | } | ||
1491 | } | ||
1492 | } | ||
1493 | card->options.checksum_type = csum_type; | ||
1494 | return rc; | ||
1495 | } | ||
1496 | |||
1442 | static int qeth_l3_start_ipa_checksum(struct qeth_card *card) | 1497 | static int qeth_l3_start_ipa_checksum(struct qeth_card *card) |
1443 | { | 1498 | { |
1444 | int rc = 0; | 1499 | int rc = 0; |
@@ -1506,6 +1561,8 @@ static int qeth_l3_start_ipa_tso(struct qeth_card *card) | |||
1506 | static int qeth_l3_start_ipassists(struct qeth_card *card) | 1561 | static int qeth_l3_start_ipassists(struct qeth_card *card) |
1507 | { | 1562 | { |
1508 | QETH_DBF_TEXT(TRACE, 3, "strtipas"); | 1563 | QETH_DBF_TEXT(TRACE, 3, "strtipas"); |
1564 | |||
1565 | qeth_set_access_ctrl_online(card); /* go on*/ | ||
1509 | qeth_l3_start_ipa_arp_processing(card); /* go on*/ | 1566 | qeth_l3_start_ipa_arp_processing(card); /* go on*/ |
1510 | qeth_l3_start_ipa_ip_fragmentation(card); /* go on*/ | 1567 | qeth_l3_start_ipa_ip_fragmentation(card); /* go on*/ |
1511 | qeth_l3_start_ipa_source_mac(card); /* go on*/ | 1568 | qeth_l3_start_ipa_source_mac(card); /* go on*/ |
@@ -2684,6 +2741,24 @@ static void qeth_tx_csum(struct sk_buff *skb) | |||
2684 | *(__sum16 *)(skb->data + offset) = csum_fold(csum); | 2741 | *(__sum16 *)(skb->data + offset) = csum_fold(csum); |
2685 | } | 2742 | } |
2686 | 2743 | ||
2744 | static inline int qeth_l3_tso_elements(struct sk_buff *skb) | ||
2745 | { | ||
2746 | unsigned long tcpd = (unsigned long)tcp_hdr(skb) + | ||
2747 | tcp_hdr(skb)->doff * 4; | ||
2748 | int tcpd_len = skb->len - (tcpd - (unsigned long)skb->data); | ||
2749 | int elements = PFN_UP(tcpd + tcpd_len) - PFN_DOWN(tcpd); | ||
2750 | elements += skb_shinfo(skb)->nr_frags; | ||
2751 | return elements; | ||
2752 | } | ||
2753 | |||
2754 | static inline int qeth_l3_tso_check(struct sk_buff *skb) | ||
2755 | { | ||
2756 | int len = ((unsigned long)tcp_hdr(skb) + tcp_hdr(skb)->doff * 4) - | ||
2757 | (unsigned long)skb->data; | ||
2758 | return (((unsigned long)skb->data & PAGE_MASK) != | ||
2759 | (((unsigned long)skb->data + len) & PAGE_MASK)); | ||
2760 | } | ||
2761 | |||
2687 | static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | 2762 | static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) |
2688 | { | 2763 | { |
2689 | int rc; | 2764 | int rc; |
@@ -2777,16 +2852,21 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2777 | /* fix hardware limitation: as long as we do not have sbal | 2852 | /* fix hardware limitation: as long as we do not have sbal |
2778 | * chaining we can not send long frag lists | 2853 | * chaining we can not send long frag lists |
2779 | */ | 2854 | */ |
2780 | if ((large_send == QETH_LARGE_SEND_TSO) && | 2855 | if (large_send == QETH_LARGE_SEND_TSO) { |
2781 | ((skb_shinfo(new_skb)->nr_frags + 2) > 16)) { | 2856 | if (qeth_l3_tso_elements(new_skb) + 1 > 16) { |
2782 | if (skb_linearize(new_skb)) | 2857 | if (skb_linearize(new_skb)) |
2783 | goto tx_drop; | 2858 | goto tx_drop; |
2859 | if (card->options.performance_stats) | ||
2860 | card->perf_stats.tx_lin++; | ||
2861 | } | ||
2784 | } | 2862 | } |
2785 | 2863 | ||
2786 | if ((large_send == QETH_LARGE_SEND_TSO) && | 2864 | if ((large_send == QETH_LARGE_SEND_TSO) && |
2787 | (cast_type == RTN_UNSPEC)) { | 2865 | (cast_type == RTN_UNSPEC)) { |
2788 | hdr = (struct qeth_hdr *)skb_push(new_skb, | 2866 | hdr = (struct qeth_hdr *)skb_push(new_skb, |
2789 | sizeof(struct qeth_hdr_tso)); | 2867 | sizeof(struct qeth_hdr_tso)); |
2868 | if (qeth_l3_tso_check(new_skb)) | ||
2869 | QETH_DBF_MESSAGE(2, "tso skb misaligned\n"); | ||
2790 | memset(hdr, 0, sizeof(struct qeth_hdr_tso)); | 2870 | memset(hdr, 0, sizeof(struct qeth_hdr_tso)); |
2791 | qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type); | 2871 | qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type); |
2792 | qeth_tso_fill_header(card, hdr, new_skb); | 2872 | qeth_tso_fill_header(card, hdr, new_skb); |
@@ -2903,46 +2983,28 @@ static u32 qeth_l3_ethtool_get_rx_csum(struct net_device *dev) | |||
2903 | static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data) | 2983 | static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data) |
2904 | { | 2984 | { |
2905 | struct qeth_card *card = dev->ml_priv; | 2985 | struct qeth_card *card = dev->ml_priv; |
2906 | enum qeth_card_states old_state; | ||
2907 | enum qeth_checksum_types csum_type; | 2986 | enum qeth_checksum_types csum_type; |
2908 | 2987 | ||
2909 | if ((card->state != CARD_STATE_UP) && | ||
2910 | (card->state != CARD_STATE_DOWN)) | ||
2911 | return -EPERM; | ||
2912 | |||
2913 | if (data) | 2988 | if (data) |
2914 | csum_type = HW_CHECKSUMMING; | 2989 | csum_type = HW_CHECKSUMMING; |
2915 | else | 2990 | else |
2916 | csum_type = SW_CHECKSUMMING; | 2991 | csum_type = SW_CHECKSUMMING; |
2917 | 2992 | ||
2918 | if (card->options.checksum_type != csum_type) { | 2993 | return qeth_l3_set_rx_csum(card, csum_type); |
2919 | old_state = card->state; | ||
2920 | if (card->state == CARD_STATE_UP) | ||
2921 | __qeth_l3_set_offline(card->gdev, 1); | ||
2922 | card->options.checksum_type = csum_type; | ||
2923 | if (old_state == CARD_STATE_UP) | ||
2924 | __qeth_l3_set_online(card->gdev, 1); | ||
2925 | } | ||
2926 | return 0; | ||
2927 | } | 2994 | } |
2928 | 2995 | ||
2929 | static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data) | 2996 | static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data) |
2930 | { | 2997 | { |
2931 | struct qeth_card *card = dev->ml_priv; | 2998 | struct qeth_card *card = dev->ml_priv; |
2999 | int rc = 0; | ||
2932 | 3000 | ||
2933 | if (data) { | 3001 | if (data) { |
2934 | if (card->options.large_send == QETH_LARGE_SEND_NO) { | 3002 | rc = qeth_l3_set_large_send(card, QETH_LARGE_SEND_TSO); |
2935 | if (card->info.type == QETH_CARD_TYPE_IQD) | ||
2936 | return -EPERM; | ||
2937 | else | ||
2938 | card->options.large_send = QETH_LARGE_SEND_TSO; | ||
2939 | dev->features |= NETIF_F_TSO; | ||
2940 | } | ||
2941 | } else { | 3003 | } else { |
2942 | dev->features &= ~NETIF_F_TSO; | 3004 | dev->features &= ~NETIF_F_TSO; |
2943 | card->options.large_send = QETH_LARGE_SEND_NO; | 3005 | card->options.large_send = QETH_LARGE_SEND_NO; |
2944 | } | 3006 | } |
2945 | return 0; | 3007 | return rc; |
2946 | } | 3008 | } |
2947 | 3009 | ||
2948 | static const struct ethtool_ops qeth_l3_ethtool_ops = { | 3010 | static const struct ethtool_ops qeth_l3_ethtool_ops = { |
@@ -2957,7 +3019,7 @@ static const struct ethtool_ops qeth_l3_ethtool_ops = { | |||
2957 | .set_tso = qeth_l3_ethtool_set_tso, | 3019 | .set_tso = qeth_l3_ethtool_set_tso, |
2958 | .get_strings = qeth_core_get_strings, | 3020 | .get_strings = qeth_core_get_strings, |
2959 | .get_ethtool_stats = qeth_core_get_ethtool_stats, | 3021 | .get_ethtool_stats = qeth_core_get_ethtool_stats, |
2960 | .get_stats_count = qeth_core_get_stats_count, | 3022 | .get_sset_count = qeth_core_get_sset_count, |
2961 | .get_drvinfo = qeth_core_get_drvinfo, | 3023 | .get_drvinfo = qeth_core_get_drvinfo, |
2962 | .get_settings = qeth_core_ethtool_get_settings, | 3024 | .get_settings = qeth_core_ethtool_get_settings, |
2963 | }; | 3025 | }; |
@@ -3058,6 +3120,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) | |||
3058 | NETIF_F_HW_VLAN_RX | | 3120 | NETIF_F_HW_VLAN_RX | |
3059 | NETIF_F_HW_VLAN_FILTER; | 3121 | NETIF_F_HW_VLAN_FILTER; |
3060 | card->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | 3122 | card->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; |
3123 | card->dev->gso_max_size = 15 * PAGE_SIZE; | ||
3061 | 3124 | ||
3062 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); | 3125 | SET_NETDEV_DEV(card->dev, &card->gdev->dev); |
3063 | return register_netdev(card->dev); | 3126 | return register_netdev(card->dev); |
@@ -3154,32 +3217,19 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3154 | qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1); | 3217 | qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1); |
3155 | 3218 | ||
3156 | recover_flag = card->state; | 3219 | recover_flag = card->state; |
3157 | rc = ccw_device_set_online(CARD_RDEV(card)); | ||
3158 | if (rc) { | ||
3159 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | ||
3160 | return -EIO; | ||
3161 | } | ||
3162 | rc = ccw_device_set_online(CARD_WDEV(card)); | ||
3163 | if (rc) { | ||
3164 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | ||
3165 | return -EIO; | ||
3166 | } | ||
3167 | rc = ccw_device_set_online(CARD_DDEV(card)); | ||
3168 | if (rc) { | ||
3169 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | ||
3170 | return -EIO; | ||
3171 | } | ||
3172 | |||
3173 | rc = qeth_core_hardsetup_card(card); | 3220 | rc = qeth_core_hardsetup_card(card); |
3174 | if (rc) { | 3221 | if (rc) { |
3175 | QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); | 3222 | QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc); |
3223 | rc = -ENODEV; | ||
3176 | goto out_remove; | 3224 | goto out_remove; |
3177 | } | 3225 | } |
3178 | 3226 | ||
3179 | qeth_l3_query_ipassists(card, QETH_PROT_IPV4); | 3227 | qeth_l3_query_ipassists(card, QETH_PROT_IPV4); |
3180 | 3228 | ||
3181 | if (!card->dev && qeth_l3_setup_netdev(card)) | 3229 | if (!card->dev && qeth_l3_setup_netdev(card)) { |
3230 | rc = -ENODEV; | ||
3182 | goto out_remove; | 3231 | goto out_remove; |
3232 | } | ||
3183 | 3233 | ||
3184 | card->state = CARD_STATE_HARDSETUP; | 3234 | card->state = CARD_STATE_HARDSETUP; |
3185 | qeth_print_status_message(card); | 3235 | qeth_print_status_message(card); |
@@ -3196,10 +3246,11 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3196 | card->lan_online = 0; | 3246 | card->lan_online = 0; |
3197 | return 0; | 3247 | return 0; |
3198 | } | 3248 | } |
3249 | rc = -ENODEV; | ||
3199 | goto out_remove; | 3250 | goto out_remove; |
3200 | } else | 3251 | } else |
3201 | card->lan_online = 1; | 3252 | card->lan_online = 1; |
3202 | qeth_set_large_send(card, card->options.large_send); | 3253 | qeth_l3_set_large_send(card, card->options.large_send); |
3203 | 3254 | ||
3204 | rc = qeth_l3_setadapter_parms(card); | 3255 | rc = qeth_l3_setadapter_parms(card); |
3205 | if (rc) | 3256 | if (rc) |
@@ -3218,6 +3269,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3218 | rc = qeth_init_qdio_queues(card); | 3269 | rc = qeth_init_qdio_queues(card); |
3219 | if (rc) { | 3270 | if (rc) { |
3220 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); | 3271 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); |
3272 | rc = -ENODEV; | ||
3221 | goto out_remove; | 3273 | goto out_remove; |
3222 | } | 3274 | } |
3223 | card->state = CARD_STATE_SOFTSETUP; | 3275 | card->state = CARD_STATE_SOFTSETUP; |
@@ -3248,7 +3300,7 @@ out_remove: | |||
3248 | card->state = CARD_STATE_RECOVER; | 3300 | card->state = CARD_STATE_RECOVER; |
3249 | else | 3301 | else |
3250 | card->state = CARD_STATE_DOWN; | 3302 | card->state = CARD_STATE_DOWN; |
3251 | return -ENODEV; | 3303 | return rc; |
3252 | } | 3304 | } |
3253 | 3305 | ||
3254 | static int qeth_l3_set_online(struct ccwgroup_device *gdev) | 3306 | static int qeth_l3_set_online(struct ccwgroup_device *gdev) |
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index c144b9924d52..3360b0941aa1 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c | |||
@@ -293,31 +293,79 @@ static ssize_t qeth_l3_dev_checksum_store(struct device *dev, | |||
293 | struct device_attribute *attr, const char *buf, size_t count) | 293 | struct device_attribute *attr, const char *buf, size_t count) |
294 | { | 294 | { |
295 | struct qeth_card *card = dev_get_drvdata(dev); | 295 | struct qeth_card *card = dev_get_drvdata(dev); |
296 | enum qeth_checksum_types csum_type; | ||
296 | char *tmp; | 297 | char *tmp; |
298 | int rc; | ||
297 | 299 | ||
298 | if (!card) | 300 | if (!card) |
299 | return -EINVAL; | 301 | return -EINVAL; |
300 | 302 | ||
301 | if ((card->state != CARD_STATE_DOWN) && | ||
302 | (card->state != CARD_STATE_RECOVER)) | ||
303 | return -EPERM; | ||
304 | |||
305 | tmp = strsep((char **) &buf, "\n"); | 303 | tmp = strsep((char **) &buf, "\n"); |
306 | if (!strcmp(tmp, "sw_checksumming")) | 304 | if (!strcmp(tmp, "sw_checksumming")) |
307 | card->options.checksum_type = SW_CHECKSUMMING; | 305 | csum_type = SW_CHECKSUMMING; |
308 | else if (!strcmp(tmp, "hw_checksumming")) | 306 | else if (!strcmp(tmp, "hw_checksumming")) |
309 | card->options.checksum_type = HW_CHECKSUMMING; | 307 | csum_type = HW_CHECKSUMMING; |
310 | else if (!strcmp(tmp, "no_checksumming")) | 308 | else if (!strcmp(tmp, "no_checksumming")) |
311 | card->options.checksum_type = NO_CHECKSUMMING; | 309 | csum_type = NO_CHECKSUMMING; |
312 | else { | 310 | else |
313 | return -EINVAL; | 311 | return -EINVAL; |
314 | } | 312 | |
313 | rc = qeth_l3_set_rx_csum(card, csum_type); | ||
314 | if (rc) | ||
315 | return rc; | ||
315 | return count; | 316 | return count; |
316 | } | 317 | } |
317 | 318 | ||
318 | static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show, | 319 | static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show, |
319 | qeth_l3_dev_checksum_store); | 320 | qeth_l3_dev_checksum_store); |
320 | 321 | ||
322 | static ssize_t qeth_l3_dev_large_send_show(struct device *dev, | ||
323 | struct device_attribute *attr, char *buf) | ||
324 | { | ||
325 | struct qeth_card *card = dev_get_drvdata(dev); | ||
326 | |||
327 | if (!card) | ||
328 | return -EINVAL; | ||
329 | |||
330 | switch (card->options.large_send) { | ||
331 | case QETH_LARGE_SEND_NO: | ||
332 | return sprintf(buf, "%s\n", "no"); | ||
333 | case QETH_LARGE_SEND_TSO: | ||
334 | return sprintf(buf, "%s\n", "TSO"); | ||
335 | default: | ||
336 | return sprintf(buf, "%s\n", "N/A"); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | static ssize_t qeth_l3_dev_large_send_store(struct device *dev, | ||
341 | struct device_attribute *attr, const char *buf, size_t count) | ||
342 | { | ||
343 | struct qeth_card *card = dev_get_drvdata(dev); | ||
344 | enum qeth_large_send_types type; | ||
345 | int rc = 0; | ||
346 | char *tmp; | ||
347 | |||
348 | if (!card) | ||
349 | return -EINVAL; | ||
350 | tmp = strsep((char **) &buf, "\n"); | ||
351 | if (!strcmp(tmp, "no")) | ||
352 | type = QETH_LARGE_SEND_NO; | ||
353 | else if (!strcmp(tmp, "TSO")) | ||
354 | type = QETH_LARGE_SEND_TSO; | ||
355 | else | ||
356 | return -EINVAL; | ||
357 | |||
358 | if (card->options.large_send == type) | ||
359 | return count; | ||
360 | rc = qeth_l3_set_large_send(card, type); | ||
361 | if (rc) | ||
362 | return rc; | ||
363 | return count; | ||
364 | } | ||
365 | |||
366 | static DEVICE_ATTR(large_send, 0644, qeth_l3_dev_large_send_show, | ||
367 | qeth_l3_dev_large_send_store); | ||
368 | |||
321 | static struct attribute *qeth_l3_device_attrs[] = { | 369 | static struct attribute *qeth_l3_device_attrs[] = { |
322 | &dev_attr_route4.attr, | 370 | &dev_attr_route4.attr, |
323 | &dev_attr_route6.attr, | 371 | &dev_attr_route6.attr, |
@@ -325,6 +373,7 @@ static struct attribute *qeth_l3_device_attrs[] = { | |||
325 | &dev_attr_broadcast_mode.attr, | 373 | &dev_attr_broadcast_mode.attr, |
326 | &dev_attr_canonical_macaddr.attr, | 374 | &dev_attr_canonical_macaddr.attr, |
327 | &dev_attr_checksumming.attr, | 375 | &dev_attr_checksumming.attr, |
376 | &dev_attr_large_send.attr, | ||
328 | NULL, | 377 | NULL, |
329 | }; | 378 | }; |
330 | 379 | ||