mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
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
This commit is contained in:
commit
d7fc02c7ba
1394 changed files with 113445 additions and 70680 deletions
|
|
@ -3,11 +3,11 @@
|
|||
#
|
||||
|
||||
ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o
|
||||
obj-$(CONFIG_CTCM) += ctcm.o fsm.o cu3088.o
|
||||
obj-$(CONFIG_CTCM) += ctcm.o fsm.o
|
||||
obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
|
||||
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
|
||||
obj-$(CONFIG_LCS) += lcs.o cu3088.o
|
||||
obj-$(CONFIG_CLAW) += claw.o cu3088.o
|
||||
obj-$(CONFIG_LCS) += lcs.o
|
||||
obj-$(CONFIG_CLAW) += claw.o
|
||||
qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o
|
||||
obj-$(CONFIG_QETH) += qeth.o
|
||||
qeth_l2-y += qeth_l2_main.o
|
||||
|
|
|
|||
|
|
@ -90,7 +90,6 @@
|
|||
#include <linux/timer.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "cu3088.h"
|
||||
#include "claw.h"
|
||||
|
||||
/*
|
||||
|
|
@ -258,6 +257,9 @@ static int claw_pm_prepare(struct ccwgroup_device *gdev)
|
|||
return -EPERM;
|
||||
}
|
||||
|
||||
/* the root device for claw group devices */
|
||||
static struct device *claw_root_dev;
|
||||
|
||||
/* ccwgroup table */
|
||||
|
||||
static struct ccwgroup_driver claw_group_driver = {
|
||||
|
|
@ -272,6 +274,47 @@ static struct ccwgroup_driver claw_group_driver = {
|
|||
.prepare = claw_pm_prepare,
|
||||
};
|
||||
|
||||
static struct ccw_device_id claw_ids[] = {
|
||||
{CCW_DEVICE(0x3088, 0x61), .driver_info = claw_channel_type_claw},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(ccw, claw_ids);
|
||||
|
||||
static struct ccw_driver claw_ccw_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "claw",
|
||||
.ids = claw_ids,
|
||||
.probe = ccwgroup_probe_ccwdev,
|
||||
.remove = ccwgroup_remove_ccwdev,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
claw_driver_group_store(struct device_driver *ddrv, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
int err;
|
||||
err = ccwgroup_create_from_string(claw_root_dev,
|
||||
claw_group_driver.driver_id,
|
||||
&claw_ccw_driver, 3, buf);
|
||||
return err ? err : count;
|
||||
}
|
||||
|
||||
static DRIVER_ATTR(group, 0200, NULL, claw_driver_group_store);
|
||||
|
||||
static struct attribute *claw_group_attrs[] = {
|
||||
&driver_attr_group.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group claw_group_attr_group = {
|
||||
.attrs = claw_group_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *claw_group_attr_groups[] = {
|
||||
&claw_group_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* Key functions
|
||||
*/
|
||||
|
|
@ -3326,7 +3369,11 @@ claw_remove_files(struct device *dev)
|
|||
static void __exit
|
||||
claw_cleanup(void)
|
||||
{
|
||||
unregister_cu3088_discipline(&claw_group_driver);
|
||||
driver_remove_file(&claw_group_driver.driver,
|
||||
&driver_attr_group);
|
||||
ccwgroup_driver_unregister(&claw_group_driver);
|
||||
ccw_driver_unregister(&claw_ccw_driver);
|
||||
root_device_unregister(claw_root_dev);
|
||||
claw_unregister_debug_facility();
|
||||
pr_info("Driver unloaded\n");
|
||||
|
||||
|
|
@ -3348,16 +3395,31 @@ claw_init(void)
|
|||
if (ret) {
|
||||
pr_err("Registering with the S/390 debug feature"
|
||||
" failed with error code %d\n", ret);
|
||||
return ret;
|
||||
goto out_err;
|
||||
}
|
||||
CLAW_DBF_TEXT(2, setup, "init_mod");
|
||||
ret = register_cu3088_discipline(&claw_group_driver);
|
||||
if (ret) {
|
||||
CLAW_DBF_TEXT(2, setup, "init_bad");
|
||||
claw_unregister_debug_facility();
|
||||
pr_err("Registering with the cu3088 device driver failed "
|
||||
"with error code %d\n", ret);
|
||||
}
|
||||
claw_root_dev = root_device_register("qeth");
|
||||
ret = IS_ERR(claw_root_dev) ? PTR_ERR(claw_root_dev) : 0;
|
||||
if (ret)
|
||||
goto register_err;
|
||||
ret = ccw_driver_register(&claw_ccw_driver);
|
||||
if (ret)
|
||||
goto ccw_err;
|
||||
claw_group_driver.driver.groups = claw_group_attr_groups;
|
||||
ret = ccwgroup_driver_register(&claw_group_driver);
|
||||
if (ret)
|
||||
goto ccwgroup_err;
|
||||
return 0;
|
||||
|
||||
ccwgroup_err:
|
||||
ccw_driver_unregister(&claw_ccw_driver);
|
||||
ccw_err:
|
||||
root_device_unregister(claw_root_dev);
|
||||
register_err:
|
||||
CLAW_DBF_TEXT(2, setup, "init_bad");
|
||||
claw_unregister_debug_facility();
|
||||
out_err:
|
||||
pr_err("Initializing the claw device driver failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,6 +129,18 @@ static inline int claw_dbf_passes(debug_info_t *dbf_grp, int level)
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Enum for classifying detected devices.
|
||||
*/
|
||||
enum claw_channel_types {
|
||||
/* Device is not a channel */
|
||||
claw_channel_type_none,
|
||||
|
||||
/* Device is a CLAW channel device */
|
||||
claw_channel_type_claw
|
||||
};
|
||||
|
||||
|
||||
/*******************************************************
|
||||
* Define Control Blocks *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
#include <asm/idals.h>
|
||||
|
||||
#include "fsm.h"
|
||||
#include "cu3088.h"
|
||||
|
||||
#include "ctcm_dbug.h"
|
||||
#include "ctcm_main.h"
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
#include <asm/idals.h>
|
||||
|
||||
#include "fsm.h"
|
||||
#include "cu3088.h"
|
||||
#include "ctcm_main.h"
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -51,12 +51,16 @@
|
|||
|
||||
#include <asm/idals.h>
|
||||
|
||||
#include "cu3088.h"
|
||||
#include "ctcm_fsms.h"
|
||||
#include "ctcm_main.h"
|
||||
|
||||
/* Some common global variables */
|
||||
|
||||
/**
|
||||
* The root device for ctcm group devices
|
||||
*/
|
||||
static struct device *ctcm_root_dev;
|
||||
|
||||
/*
|
||||
* Linked list of all detected channels.
|
||||
*/
|
||||
|
|
@ -246,7 +250,7 @@ static void channel_remove(struct channel *ch)
|
|||
*
|
||||
* returns Pointer to a channel or NULL if no matching channel available.
|
||||
*/
|
||||
static struct channel *channel_get(enum channel_types type,
|
||||
static struct channel *channel_get(enum ctcm_channel_types type,
|
||||
char *id, int direction)
|
||||
{
|
||||
struct channel *ch = channels;
|
||||
|
|
@ -1342,7 +1346,7 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev)
|
|||
*
|
||||
* returns 0 on success, !0 on error.
|
||||
*/
|
||||
static int add_channel(struct ccw_device *cdev, enum channel_types type,
|
||||
static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type,
|
||||
struct ctcm_priv *priv)
|
||||
{
|
||||
struct channel **c = &channels;
|
||||
|
|
@ -1501,13 +1505,13 @@ free_return: /* note that all channel pointers are 0 or valid */
|
|||
/*
|
||||
* Return type of a detected device.
|
||||
*/
|
||||
static enum channel_types get_channel_type(struct ccw_device_id *id)
|
||||
static enum ctcm_channel_types get_channel_type(struct ccw_device_id *id)
|
||||
{
|
||||
enum channel_types type;
|
||||
type = (enum channel_types)id->driver_info;
|
||||
enum ctcm_channel_types type;
|
||||
type = (enum ctcm_channel_types)id->driver_info;
|
||||
|
||||
if (type == channel_type_ficon)
|
||||
type = channel_type_escon;
|
||||
if (type == ctcm_channel_type_ficon)
|
||||
type = ctcm_channel_type_escon;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
|
@ -1525,16 +1529,21 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
|
|||
char read_id[CTCM_ID_SIZE];
|
||||
char write_id[CTCM_ID_SIZE];
|
||||
int direction;
|
||||
enum channel_types type;
|
||||
enum ctcm_channel_types type;
|
||||
struct ctcm_priv *priv;
|
||||
struct net_device *dev;
|
||||
struct ccw_device *cdev0;
|
||||
struct ccw_device *cdev1;
|
||||
struct channel *readc;
|
||||
struct channel *writec;
|
||||
int ret;
|
||||
int result;
|
||||
|
||||
priv = dev_get_drvdata(&cgdev->dev);
|
||||
if (!priv)
|
||||
return -ENODEV;
|
||||
if (!priv) {
|
||||
result = -ENODEV;
|
||||
goto out_err_result;
|
||||
}
|
||||
|
||||
cdev0 = cgdev->cdev[0];
|
||||
cdev1 = cgdev->cdev[1];
|
||||
|
|
@ -1545,31 +1554,40 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
|
|||
snprintf(write_id, CTCM_ID_SIZE, "ch-%s", dev_name(&cdev1->dev));
|
||||
|
||||
ret = add_channel(cdev0, type, priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) {
|
||||
result = ret;
|
||||
goto out_err_result;
|
||||
}
|
||||
ret = add_channel(cdev1, type, priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ret) {
|
||||
result = ret;
|
||||
goto out_remove_channel1;
|
||||
}
|
||||
|
||||
ret = ccw_device_set_online(cdev0);
|
||||
if (ret != 0) {
|
||||
/* may be ok to fail now - can be done later */
|
||||
CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
|
||||
"%s(%s) set_online rc=%d",
|
||||
CTCM_FUNTAIL, read_id, ret);
|
||||
result = -EIO;
|
||||
goto out_remove_channel2;
|
||||
}
|
||||
|
||||
ret = ccw_device_set_online(cdev1);
|
||||
if (ret != 0) {
|
||||
/* may be ok to fail now - can be done later */
|
||||
CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE,
|
||||
"%s(%s) set_online rc=%d",
|
||||
CTCM_FUNTAIL, write_id, ret);
|
||||
|
||||
result = -EIO;
|
||||
goto out_ccw1;
|
||||
}
|
||||
|
||||
dev = ctcm_init_netdevice(priv);
|
||||
if (dev == NULL)
|
||||
goto out;
|
||||
if (dev == NULL) {
|
||||
result = -ENODEV;
|
||||
goto out_ccw2;
|
||||
}
|
||||
|
||||
for (direction = READ; direction <= WRITE; direction++) {
|
||||
priv->channel[direction] =
|
||||
|
|
@ -1587,12 +1605,14 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
|
|||
/* sysfs magic */
|
||||
SET_NETDEV_DEV(dev, &cgdev->dev);
|
||||
|
||||
if (register_netdev(dev))
|
||||
goto out_dev;
|
||||
if (register_netdev(dev)) {
|
||||
result = -ENODEV;
|
||||
goto out_dev;
|
||||
}
|
||||
|
||||
if (ctcm_add_attributes(&cgdev->dev)) {
|
||||
unregister_netdev(dev);
|
||||
goto out_dev;
|
||||
result = -ENODEV;
|
||||
goto out_unregister;
|
||||
}
|
||||
|
||||
strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name));
|
||||
|
|
@ -1608,13 +1628,22 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev)
|
|||
priv->channel[WRITE]->id, priv->protocol);
|
||||
|
||||
return 0;
|
||||
out_unregister:
|
||||
unregister_netdev(dev);
|
||||
out_dev:
|
||||
ctcm_free_netdevice(dev);
|
||||
out:
|
||||
out_ccw2:
|
||||
ccw_device_set_offline(cgdev->cdev[1]);
|
||||
out_ccw1:
|
||||
ccw_device_set_offline(cgdev->cdev[0]);
|
||||
|
||||
return -ENODEV;
|
||||
out_remove_channel2:
|
||||
readc = channel_get(type, read_id, READ);
|
||||
channel_remove(readc);
|
||||
out_remove_channel1:
|
||||
writec = channel_get(type, write_id, WRITE);
|
||||
channel_remove(writec);
|
||||
out_err_result:
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1695,6 +1724,11 @@ static int ctcm_pm_suspend(struct ccwgroup_device *gdev)
|
|||
return 0;
|
||||
netif_device_detach(priv->channel[READ]->netdev);
|
||||
ctcm_close(priv->channel[READ]->netdev);
|
||||
if (!wait_event_timeout(priv->fsm->wait_q,
|
||||
fsm_getstate(priv->fsm) == DEV_STATE_STOPPED, CTCM_TIME_5_SEC)) {
|
||||
netif_device_attach(priv->channel[READ]->netdev);
|
||||
return -EBUSY;
|
||||
}
|
||||
ccw_device_set_offline(gdev->cdev[1]);
|
||||
ccw_device_set_offline(gdev->cdev[0]);
|
||||
return 0;
|
||||
|
|
@ -1719,6 +1753,22 @@ err_out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static struct ccw_device_id ctcm_ids[] = {
|
||||
{CCW_DEVICE(0x3088, 0x08), .driver_info = ctcm_channel_type_parallel},
|
||||
{CCW_DEVICE(0x3088, 0x1e), .driver_info = ctcm_channel_type_ficon},
|
||||
{CCW_DEVICE(0x3088, 0x1f), .driver_info = ctcm_channel_type_escon},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(ccw, ctcm_ids);
|
||||
|
||||
static struct ccw_driver ctcm_ccw_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "ctcm",
|
||||
.ids = ctcm_ids,
|
||||
.probe = ccwgroup_probe_ccwdev,
|
||||
.remove = ccwgroup_remove_ccwdev,
|
||||
};
|
||||
|
||||
static struct ccwgroup_driver ctcm_group_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = CTC_DRIVER_NAME,
|
||||
|
|
@ -1733,6 +1783,33 @@ static struct ccwgroup_driver ctcm_group_driver = {
|
|||
.restore = ctcm_pm_resume,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
ctcm_driver_group_store(struct device_driver *ddrv, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ccwgroup_create_from_string(ctcm_root_dev,
|
||||
ctcm_group_driver.driver_id,
|
||||
&ctcm_ccw_driver, 2, buf);
|
||||
return err ? err : count;
|
||||
}
|
||||
|
||||
static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store);
|
||||
|
||||
static struct attribute *ctcm_group_attrs[] = {
|
||||
&driver_attr_group.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group ctcm_group_attr_group = {
|
||||
.attrs = ctcm_group_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *ctcm_group_attr_groups[] = {
|
||||
&ctcm_group_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* Module related routines
|
||||
|
|
@ -1746,7 +1823,10 @@ static struct ccwgroup_driver ctcm_group_driver = {
|
|||
*/
|
||||
static void __exit ctcm_exit(void)
|
||||
{
|
||||
unregister_cu3088_discipline(&ctcm_group_driver);
|
||||
driver_remove_file(&ctcm_group_driver.driver, &driver_attr_group);
|
||||
ccwgroup_driver_unregister(&ctcm_group_driver);
|
||||
ccw_driver_unregister(&ctcm_ccw_driver);
|
||||
root_device_unregister(ctcm_root_dev);
|
||||
ctcm_unregister_dbf_views();
|
||||
pr_info("CTCM driver unloaded\n");
|
||||
}
|
||||
|
|
@ -1772,17 +1852,31 @@ static int __init ctcm_init(void)
|
|||
channels = NULL;
|
||||
|
||||
ret = ctcm_register_dbf_views();
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
ret = register_cu3088_discipline(&ctcm_group_driver);
|
||||
if (ret) {
|
||||
ctcm_unregister_dbf_views();
|
||||
pr_err("%s / register_cu3088_discipline failed, ret = %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto out_err;
|
||||
ctcm_root_dev = root_device_register("ctcm");
|
||||
ret = IS_ERR(ctcm_root_dev) ? PTR_ERR(ctcm_root_dev) : 0;
|
||||
if (ret)
|
||||
goto register_err;
|
||||
ret = ccw_driver_register(&ctcm_ccw_driver);
|
||||
if (ret)
|
||||
goto ccw_err;
|
||||
ctcm_group_driver.driver.groups = ctcm_group_attr_groups;
|
||||
ret = ccwgroup_driver_register(&ctcm_group_driver);
|
||||
if (ret)
|
||||
goto ccwgroup_err;
|
||||
print_banner();
|
||||
return 0;
|
||||
|
||||
ccwgroup_err:
|
||||
ccw_driver_unregister(&ctcm_ccw_driver);
|
||||
ccw_err:
|
||||
root_device_unregister(ctcm_root_dev);
|
||||
register_err:
|
||||
ctcm_unregister_dbf_views();
|
||||
out_err:
|
||||
pr_err("%s / Initializing the ctcm device driver failed, ret = %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#include <linux/netdevice.h>
|
||||
|
||||
#include "fsm.h"
|
||||
#include "cu3088.h"
|
||||
#include "ctcm_dbug.h"
|
||||
#include "ctcm_mpc.h"
|
||||
|
||||
|
|
@ -66,6 +65,23 @@
|
|||
ctcmpc_dumpit(buf, len); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* Enum for classifying detected devices
|
||||
*/
|
||||
enum ctcm_channel_types {
|
||||
/* Device is not a channel */
|
||||
ctcm_channel_type_none,
|
||||
|
||||
/* Device is a CTC/A */
|
||||
ctcm_channel_type_parallel,
|
||||
|
||||
/* Device is a FICON channel */
|
||||
ctcm_channel_type_ficon,
|
||||
|
||||
/* Device is a ESCON channel */
|
||||
ctcm_channel_type_escon
|
||||
};
|
||||
|
||||
/*
|
||||
* CCW commands, used in this driver.
|
||||
*/
|
||||
|
|
@ -121,7 +137,7 @@ struct channel {
|
|||
* Type of this channel.
|
||||
* CTC/A or Escon for valid channels.
|
||||
*/
|
||||
enum channel_types type;
|
||||
enum ctcm_channel_types type;
|
||||
/*
|
||||
* Misc. flags. See CHANNEL_FLAGS_... below
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@
|
|||
#include <linux/moduleparam.h>
|
||||
#include <asm/idals.h>
|
||||
|
||||
#include "cu3088.h"
|
||||
#include "ctcm_mpc.h"
|
||||
#include "ctcm_main.h"
|
||||
#include "ctcm_fsms.h"
|
||||
|
|
|
|||
|
|
@ -158,6 +158,15 @@ static ssize_t ctcm_proto_store(struct device *dev,
|
|||
return count;
|
||||
}
|
||||
|
||||
const char *ctcm_type[] = {
|
||||
"not a channel",
|
||||
"CTC/A",
|
||||
"FICON channel",
|
||||
"ESCON channel",
|
||||
"unknown channel type",
|
||||
"unsupported channel type",
|
||||
};
|
||||
|
||||
static ssize_t ctcm_type_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
|
@ -168,7 +177,7 @@ static ssize_t ctcm_type_show(struct device *dev,
|
|||
return -ENODEV;
|
||||
|
||||
return sprintf(buf, "%s\n",
|
||||
cu3088_type[cgdev->cdev[0]->id.driver_info]);
|
||||
ctcm_type[cgdev->cdev[0]->id.driver_info]);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(buffer, 0644, ctcm_buffer_show, ctcm_buffer_write);
|
||||
|
|
|
|||
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* CTC / LCS ccw_device driver
|
||||
*
|
||||
* Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
|
||||
* Author(s): Arnd Bergmann <arndb@de.ibm.com>
|
||||
* Cornelia Huck <cornelia.huck@de.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <asm/ccwdev.h>
|
||||
#include <asm/ccwgroup.h>
|
||||
|
||||
#include "cu3088.h"
|
||||
|
||||
const char *cu3088_type[] = {
|
||||
"not a channel",
|
||||
"CTC/A",
|
||||
"ESCON channel",
|
||||
"FICON channel",
|
||||
"OSA LCS card",
|
||||
"CLAW channel device",
|
||||
"unknown channel type",
|
||||
"unsupported channel type",
|
||||
};
|
||||
|
||||
/* static definitions */
|
||||
|
||||
static struct ccw_device_id cu3088_ids[] = {
|
||||
{ CCW_DEVICE(0x3088, 0x08), .driver_info = channel_type_parallel },
|
||||
{ CCW_DEVICE(0x3088, 0x1f), .driver_info = channel_type_escon },
|
||||
{ CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon },
|
||||
{ CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 },
|
||||
{ CCW_DEVICE(0x3088, 0x61), .driver_info = channel_type_claw },
|
||||
{ /* end of list */ }
|
||||
};
|
||||
|
||||
static struct ccw_driver cu3088_driver;
|
||||
|
||||
static struct device *cu3088_root_dev;
|
||||
|
||||
static ssize_t
|
||||
group_write(struct device_driver *drv, const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
struct ccwgroup_driver *cdrv;
|
||||
|
||||
cdrv = to_ccwgroupdrv(drv);
|
||||
if (!cdrv)
|
||||
return -EINVAL;
|
||||
ret = ccwgroup_create_from_string(cu3088_root_dev, cdrv->driver_id,
|
||||
&cu3088_driver, 2, buf);
|
||||
|
||||
return (ret == 0) ? count : ret;
|
||||
}
|
||||
|
||||
static DRIVER_ATTR(group, 0200, NULL, group_write);
|
||||
|
||||
/* Register-unregister for ctc&lcs */
|
||||
int
|
||||
register_cu3088_discipline(struct ccwgroup_driver *dcp)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (!dcp)
|
||||
return -EINVAL;
|
||||
|
||||
/* Register discipline.*/
|
||||
rc = ccwgroup_driver_register(dcp);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = driver_create_file(&dcp->driver, &driver_attr_group);
|
||||
if (rc)
|
||||
ccwgroup_driver_unregister(dcp);
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
unregister_cu3088_discipline(struct ccwgroup_driver *dcp)
|
||||
{
|
||||
if (!dcp)
|
||||
return;
|
||||
|
||||
driver_remove_file(&dcp->driver, &driver_attr_group);
|
||||
ccwgroup_driver_unregister(dcp);
|
||||
}
|
||||
|
||||
static struct ccw_driver cu3088_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.ids = cu3088_ids,
|
||||
.name = "cu3088",
|
||||
.probe = ccwgroup_probe_ccwdev,
|
||||
.remove = ccwgroup_remove_ccwdev,
|
||||
};
|
||||
|
||||
/* module setup */
|
||||
static int __init
|
||||
cu3088_init (void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
cu3088_root_dev = root_device_register("cu3088");
|
||||
if (IS_ERR(cu3088_root_dev))
|
||||
return PTR_ERR(cu3088_root_dev);
|
||||
rc = ccw_driver_register(&cu3088_driver);
|
||||
if (rc)
|
||||
root_device_unregister(cu3088_root_dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit
|
||||
cu3088_exit (void)
|
||||
{
|
||||
ccw_driver_unregister(&cu3088_driver);
|
||||
root_device_unregister(cu3088_root_dev);
|
||||
}
|
||||
|
||||
MODULE_DEVICE_TABLE(ccw,cu3088_ids);
|
||||
MODULE_AUTHOR("Arnd Bergmann <[email protected]>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(cu3088_init);
|
||||
module_exit(cu3088_exit);
|
||||
|
||||
EXPORT_SYMBOL_GPL(cu3088_type);
|
||||
EXPORT_SYMBOL_GPL(register_cu3088_discipline);
|
||||
EXPORT_SYMBOL_GPL(unregister_cu3088_discipline);
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef _CU3088_H
|
||||
#define _CU3088_H
|
||||
|
||||
/**
|
||||
* Enum for classifying detected devices.
|
||||
*/
|
||||
enum channel_types {
|
||||
/* Device is not a channel */
|
||||
channel_type_none,
|
||||
|
||||
/* Device is a CTC/A */
|
||||
channel_type_parallel,
|
||||
|
||||
/* Device is a ESCON channel */
|
||||
channel_type_escon,
|
||||
|
||||
/* Device is a FICON channel */
|
||||
channel_type_ficon,
|
||||
|
||||
/* Device is a OSA2 card */
|
||||
channel_type_osa2,
|
||||
|
||||
/* Device is a CLAW channel device */
|
||||
channel_type_claw,
|
||||
|
||||
/* Device is a channel, but we don't know
|
||||
* anything about it */
|
||||
channel_type_unknown,
|
||||
|
||||
/* Device is an unsupported model */
|
||||
channel_type_unsupported,
|
||||
|
||||
/* number of type entries */
|
||||
num_channel_types
|
||||
};
|
||||
|
||||
extern const char *cu3088_type[num_channel_types];
|
||||
extern int register_cu3088_discipline(struct ccwgroup_driver *);
|
||||
extern void unregister_cu3088_discipline(struct ccwgroup_driver *);
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,7 @@ init_fsm(char *name, const char **state_names, const char **event_names, int nr_
|
|||
return NULL;
|
||||
}
|
||||
strlcpy(this->name, name, sizeof(this->name));
|
||||
init_waitqueue_head(&this->wait_q);
|
||||
|
||||
f = kzalloc(sizeof(fsm), order);
|
||||
if (f == NULL) {
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ typedef struct fsm_instance_t {
|
|||
char name[16];
|
||||
void *userdata;
|
||||
int userint;
|
||||
wait_queue_head_t wait_q;
|
||||
#if FSM_DEBUG_HISTORY
|
||||
int history_index;
|
||||
int history_size;
|
||||
|
|
@ -197,6 +198,7 @@ fsm_newstate(fsm_instance *fi, int newstate)
|
|||
printk(KERN_DEBUG "fsm(%s): New state %s\n", fi->name,
|
||||
fi->f->state_names[newstate]);
|
||||
#endif
|
||||
wake_up(&fi->wait_q);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@
|
|||
#include <asm/ccwgroup.h>
|
||||
|
||||
#include "lcs.h"
|
||||
#include "cu3088.h"
|
||||
|
||||
|
||||
#if !defined(CONFIG_NET_ETHERNET) && \
|
||||
|
|
@ -60,7 +59,11 @@
|
|||
*/
|
||||
|
||||
static char version[] __initdata = "LCS driver";
|
||||
static char debug_buffer[255];
|
||||
|
||||
/**
|
||||
* the root device for lcs group devices
|
||||
*/
|
||||
static struct device *lcs_root_dev;
|
||||
|
||||
/**
|
||||
* Some prototypes.
|
||||
|
|
@ -76,6 +79,7 @@ static int lcs_recovery(void *ptr);
|
|||
/**
|
||||
* Debug Facility Stuff
|
||||
*/
|
||||
static char debug_buffer[255];
|
||||
static debug_info_t *lcs_dbf_setup;
|
||||
static debug_info_t *lcs_dbf_trace;
|
||||
|
||||
|
|
@ -889,7 +893,7 @@ lcs_send_lancmd(struct lcs_card *card, struct lcs_buffer *buffer,
|
|||
rc = lcs_ready_buffer(&card->write, buffer);
|
||||
if (rc)
|
||||
return rc;
|
||||
init_timer(&timer);
|
||||
init_timer_on_stack(&timer);
|
||||
timer.function = lcs_lancmd_timeout;
|
||||
timer.data = (unsigned long) reply;
|
||||
timer.expires = jiffies + HZ*card->lancmd_timeout;
|
||||
|
|
@ -1968,6 +1972,15 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char
|
|||
|
||||
static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store);
|
||||
|
||||
const char *lcs_type[] = {
|
||||
"not a channel",
|
||||
"2216 parallel",
|
||||
"2216 channel",
|
||||
"OSA LCS card",
|
||||
"unknown channel type",
|
||||
"unsupported channel type",
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
|
|
@ -1977,7 +1990,7 @@ lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|||
if (!cgdev)
|
||||
return -ENODEV;
|
||||
|
||||
return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]);
|
||||
return sprintf(buf, "%s\n", lcs_type[cgdev->cdev[0]->id.driver_info]);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(type, 0444, lcs_type_show, NULL);
|
||||
|
|
@ -2130,8 +2143,12 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
|
|||
card->write.ccwdev = ccwgdev->cdev[1];
|
||||
|
||||
recover_state = card->state;
|
||||
ccw_device_set_online(card->read.ccwdev);
|
||||
ccw_device_set_online(card->write.ccwdev);
|
||||
rc = ccw_device_set_online(card->read.ccwdev);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
rc = ccw_device_set_online(card->write.ccwdev);
|
||||
if (rc)
|
||||
goto out_werr;
|
||||
|
||||
LCS_DBF_TEXT(3, setup, "lcsnewdv");
|
||||
|
||||
|
|
@ -2210,8 +2227,10 @@ netdev_out:
|
|||
return 0;
|
||||
out:
|
||||
|
||||
ccw_device_set_offline(card->read.ccwdev);
|
||||
ccw_device_set_offline(card->write.ccwdev);
|
||||
out_werr:
|
||||
ccw_device_set_offline(card->read.ccwdev);
|
||||
out_err:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
@ -2364,6 +2383,22 @@ static int lcs_restore(struct ccwgroup_device *gdev)
|
|||
return lcs_pm_resume(card);
|
||||
}
|
||||
|
||||
static struct ccw_device_id lcs_ids[] = {
|
||||
{CCW_DEVICE(0x3088, 0x08), .driver_info = lcs_channel_type_parallel},
|
||||
{CCW_DEVICE(0x3088, 0x1f), .driver_info = lcs_channel_type_2216},
|
||||
{CCW_DEVICE(0x3088, 0x60), .driver_info = lcs_channel_type_osa2},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(ccw, lcs_ids);
|
||||
|
||||
static struct ccw_driver lcs_ccw_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "lcs",
|
||||
.ids = lcs_ids,
|
||||
.probe = ccwgroup_probe_ccwdev,
|
||||
.remove = ccwgroup_remove_ccwdev,
|
||||
};
|
||||
|
||||
/**
|
||||
* LCS ccwgroup driver registration
|
||||
*/
|
||||
|
|
@ -2383,6 +2418,33 @@ static struct ccwgroup_driver lcs_group_driver = {
|
|||
.restore = lcs_restore,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
lcs_driver_group_store(struct device_driver *ddrv, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
int err;
|
||||
err = ccwgroup_create_from_string(lcs_root_dev,
|
||||
lcs_group_driver.driver_id,
|
||||
&lcs_ccw_driver, 2, buf);
|
||||
return err ? err : count;
|
||||
}
|
||||
|
||||
static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store);
|
||||
|
||||
static struct attribute *lcs_group_attrs[] = {
|
||||
&driver_attr_group.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group lcs_group_attr_group = {
|
||||
.attrs = lcs_group_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *lcs_group_attr_groups[] = {
|
||||
&lcs_group_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/**
|
||||
* LCS Module/Kernel initialization function
|
||||
*/
|
||||
|
|
@ -2394,17 +2456,30 @@ __init lcs_init_module(void)
|
|||
pr_info("Loading %s\n", version);
|
||||
rc = lcs_register_debug_facility();
|
||||
LCS_DBF_TEXT(0, setup, "lcsinit");
|
||||
if (rc) {
|
||||
pr_err("Initialization failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = register_cu3088_discipline(&lcs_group_driver);
|
||||
if (rc) {
|
||||
pr_err("Initialization failed\n");
|
||||
return rc;
|
||||
}
|
||||
if (rc)
|
||||
goto out_err;
|
||||
lcs_root_dev = root_device_register("lcs");
|
||||
rc = IS_ERR(lcs_root_dev) ? PTR_ERR(lcs_root_dev) : 0;
|
||||
if (rc)
|
||||
goto register_err;
|
||||
rc = ccw_driver_register(&lcs_ccw_driver);
|
||||
if (rc)
|
||||
goto ccw_err;
|
||||
lcs_group_driver.driver.groups = lcs_group_attr_groups;
|
||||
rc = ccwgroup_driver_register(&lcs_group_driver);
|
||||
if (rc)
|
||||
goto ccwgroup_err;
|
||||
return 0;
|
||||
|
||||
ccwgroup_err:
|
||||
ccw_driver_unregister(&lcs_ccw_driver);
|
||||
ccw_err:
|
||||
root_device_unregister(lcs_root_dev);
|
||||
register_err:
|
||||
lcs_unregister_debug_facility();
|
||||
out_err:
|
||||
pr_err("Initializing the lcs device driver failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2416,7 +2491,11 @@ __exit lcs_cleanup_module(void)
|
|||
{
|
||||
pr_info("Terminating lcs module.\n");
|
||||
LCS_DBF_TEXT(0, trace, "cleanup");
|
||||
unregister_cu3088_discipline(&lcs_group_driver);
|
||||
driver_remove_file(&lcs_group_driver.driver,
|
||||
&driver_attr_group);
|
||||
ccwgroup_driver_unregister(&lcs_group_driver);
|
||||
ccw_driver_unregister(&lcs_ccw_driver);
|
||||
root_device_unregister(lcs_root_dev);
|
||||
lcs_unregister_debug_facility();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,24 @@ static inline int lcs_dbf_passes(debug_info_t *dbf_grp, int level)
|
|||
#define CARD_FROM_DEV(cdev) \
|
||||
(struct lcs_card *) dev_get_drvdata( \
|
||||
&((struct ccwgroup_device *)dev_get_drvdata(&cdev->dev))->dev);
|
||||
|
||||
/**
|
||||
* Enum for classifying detected devices.
|
||||
*/
|
||||
enum lcs_channel_types {
|
||||
/* Device is not a channel */
|
||||
lcs_channel_type_none,
|
||||
|
||||
/* Device is a 2216 channel */
|
||||
lcs_channel_type_parallel,
|
||||
|
||||
/* Device is a 2216 channel */
|
||||
lcs_channel_type_2216,
|
||||
|
||||
/* Device is a OSA2 card */
|
||||
lcs_channel_type_osa2
|
||||
};
|
||||
|
||||
/**
|
||||
* CCW commands used in this driver
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -741,13 +741,13 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
|
|||
if (single_flag) {
|
||||
if ((skb = skb_dequeue(&conn->commit_queue))) {
|
||||
atomic_dec(&skb->users);
|
||||
dev_kfree_skb_any(skb);
|
||||
if (privptr) {
|
||||
privptr->stats.tx_packets++;
|
||||
privptr->stats.tx_bytes +=
|
||||
(skb->len - NETIUCV_HDRLEN
|
||||
- NETIUCV_HDRLEN);
|
||||
- NETIUCV_HDRLEN);
|
||||
}
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
}
|
||||
conn->tx_buff->data = conn->tx_buff->head;
|
||||
|
|
|
|||
|
|
@ -122,7 +122,6 @@ struct qeth_perf_stats {
|
|||
__u64 outbound_do_qdio_start_time;
|
||||
unsigned int outbound_do_qdio_cnt;
|
||||
unsigned int outbound_do_qdio_time;
|
||||
/* eddp data */
|
||||
unsigned int large_send_bytes;
|
||||
unsigned int large_send_cnt;
|
||||
unsigned int sg_skbs_sent;
|
||||
|
|
@ -135,6 +134,7 @@ struct qeth_perf_stats {
|
|||
unsigned int sg_frags_rx;
|
||||
unsigned int sg_alloc_page_rx;
|
||||
unsigned int tx_csum;
|
||||
unsigned int tx_lin;
|
||||
};
|
||||
|
||||
/* Routing stuff */
|
||||
|
|
@ -648,6 +648,7 @@ struct qeth_card_options {
|
|||
enum qeth_large_send_types large_send;
|
||||
int performance_stats;
|
||||
int rx_sg_cb;
|
||||
enum qeth_ipa_isolation_modes isolation;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -776,7 +777,6 @@ static inline void qeth_put_buffer_pool_entry(struct qeth_card *card,
|
|||
list_add_tail(&entry->list, &card->qdio.in_buf_pool.entry_list);
|
||||
}
|
||||
|
||||
struct qeth_eddp_context;
|
||||
extern struct ccwgroup_driver qeth_l2_ccwgroup_driver;
|
||||
extern struct ccwgroup_driver qeth_l3_ccwgroup_driver;
|
||||
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);
|
|||
struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
|
||||
int qeth_mdio_read(struct net_device *, int, int);
|
||||
int qeth_snmp_command(struct qeth_card *, char __user *);
|
||||
int qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
|
||||
struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32);
|
||||
int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *,
|
||||
unsigned long);
|
||||
|
|
@ -849,13 +848,14 @@ int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *,
|
|||
struct sk_buff *, struct qeth_hdr *, int, int, int);
|
||||
int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *,
|
||||
struct sk_buff *, struct qeth_hdr *, int);
|
||||
int qeth_core_get_stats_count(struct net_device *);
|
||||
int qeth_core_get_sset_count(struct net_device *, int);
|
||||
void qeth_core_get_ethtool_stats(struct net_device *,
|
||||
struct ethtool_stats *, u64 *);
|
||||
void qeth_core_get_strings(struct net_device *, u32, u8 *);
|
||||
void qeth_core_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
|
||||
void qeth_dbf_longtext(enum qeth_dbf_names dbf_nix, int level, char *text, ...);
|
||||
int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *);
|
||||
int qeth_set_access_ctrl_online(struct qeth_card *card);
|
||||
|
||||
/* exports for OSN */
|
||||
int qeth_osn_assist(struct net_device *, void *, int);
|
||||
|
|
|
|||
|
|
@ -270,41 +270,6 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt)
|
|||
return qeth_alloc_buffer_pool(card);
|
||||
}
|
||||
|
||||
int qeth_set_large_send(struct qeth_card *card,
|
||||
enum qeth_large_send_types type)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (card->dev == NULL) {
|
||||
card->options.large_send = type;
|
||||
return 0;
|
||||
}
|
||||
if (card->state == CARD_STATE_UP)
|
||||
netif_tx_disable(card->dev);
|
||||
card->options.large_send = type;
|
||||
switch (card->options.large_send) {
|
||||
case QETH_LARGE_SEND_TSO:
|
||||
if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
|
||||
card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
|
||||
NETIF_F_HW_CSUM;
|
||||
} else {
|
||||
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
|
||||
NETIF_F_HW_CSUM);
|
||||
card->options.large_send = QETH_LARGE_SEND_NO;
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
break;
|
||||
default: /* includes QETH_LARGE_SEND_NO */
|
||||
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
|
||||
NETIF_F_HW_CSUM);
|
||||
break;
|
||||
}
|
||||
if (card->state == CARD_STATE_UP)
|
||||
netif_wake_queue(card->dev);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_set_large_send);
|
||||
|
||||
static int qeth_issue_next_read(struct qeth_card *card)
|
||||
{
|
||||
int rc;
|
||||
|
|
@ -1079,6 +1044,7 @@ static void qeth_set_intial_options(struct qeth_card *card)
|
|||
card->options.add_hhlen = DEFAULT_ADD_HHLEN;
|
||||
card->options.performance_stats = 0;
|
||||
card->options.rx_sg_cb = QETH_RX_SG_CB;
|
||||
card->options.isolation = ISOLATION_MODE_NONE;
|
||||
}
|
||||
|
||||
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)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_setadpparms_change_macaddr);
|
||||
|
||||
static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,
|
||||
struct qeth_reply *reply, unsigned long data)
|
||||
{
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
struct qeth_set_access_ctrl *access_ctrl_req;
|
||||
int rc;
|
||||
|
||||
QETH_DBF_TEXT(TRACE, 4, "setaccb");
|
||||
|
||||
cmd = (struct qeth_ipa_cmd *) data;
|
||||
access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl;
|
||||
QETH_DBF_TEXT_(SETUP, 2, "setaccb");
|
||||
QETH_DBF_TEXT_(SETUP, 2, "%s", card->gdev->dev.kobj.name);
|
||||
QETH_DBF_TEXT_(SETUP, 2, "rc=%d",
|
||||
cmd->data.setadapterparms.hdr.return_code);
|
||||
switch (cmd->data.setadapterparms.hdr.return_code) {
|
||||
case SET_ACCESS_CTRL_RC_SUCCESS:
|
||||
case SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED:
|
||||
case SET_ACCESS_CTRL_RC_ALREADY_ISOLATED:
|
||||
{
|
||||
card->options.isolation = access_ctrl_req->subcmd_code;
|
||||
if (card->options.isolation == ISOLATION_MODE_NONE) {
|
||||
dev_info(&card->gdev->dev,
|
||||
"QDIO data connection isolation is deactivated\n");
|
||||
} else {
|
||||
dev_info(&card->gdev->dev,
|
||||
"QDIO data connection isolation is activated\n");
|
||||
}
|
||||
QETH_DBF_MESSAGE(3, "OK:SET_ACCESS_CTRL(%s, %d)==%d\n",
|
||||
card->gdev->dev.kobj.name,
|
||||
access_ctrl_req->subcmd_code,
|
||||
cmd->data.setadapterparms.hdr.return_code);
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
case SET_ACCESS_CTRL_RC_NOT_SUPPORTED:
|
||||
{
|
||||
QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%s,%d)==%d\n",
|
||||
card->gdev->dev.kobj.name,
|
||||
access_ctrl_req->subcmd_code,
|
||||
cmd->data.setadapterparms.hdr.return_code);
|
||||
dev_err(&card->gdev->dev, "Adapter does not "
|
||||
"support QDIO data connection isolation\n");
|
||||
|
||||
/* ensure isolation mode is "none" */
|
||||
card->options.isolation = ISOLATION_MODE_NONE;
|
||||
rc = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
case SET_ACCESS_CTRL_RC_NONE_SHARED_ADAPTER:
|
||||
{
|
||||
QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d\n",
|
||||
card->gdev->dev.kobj.name,
|
||||
access_ctrl_req->subcmd_code,
|
||||
cmd->data.setadapterparms.hdr.return_code);
|
||||
dev_err(&card->gdev->dev,
|
||||
"Adapter is dedicated. "
|
||||
"QDIO data connection isolation not supported\n");
|
||||
|
||||
/* ensure isolation mode is "none" */
|
||||
card->options.isolation = ISOLATION_MODE_NONE;
|
||||
rc = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
case SET_ACCESS_CTRL_RC_ACTIVE_CHECKSUM_OFF:
|
||||
{
|
||||
QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d\n",
|
||||
card->gdev->dev.kobj.name,
|
||||
access_ctrl_req->subcmd_code,
|
||||
cmd->data.setadapterparms.hdr.return_code);
|
||||
dev_err(&card->gdev->dev,
|
||||
"TSO does not permit QDIO data connection isolation\n");
|
||||
|
||||
/* ensure isolation mode is "none" */
|
||||
card->options.isolation = ISOLATION_MODE_NONE;
|
||||
rc = -EPERM;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* this should never happen */
|
||||
QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_MODE(%s,%d)==%d"
|
||||
"==UNKNOWN\n",
|
||||
card->gdev->dev.kobj.name,
|
||||
access_ctrl_req->subcmd_code,
|
||||
cmd->data.setadapterparms.hdr.return_code);
|
||||
|
||||
/* ensure isolation mode is "none" */
|
||||
card->options.isolation = ISOLATION_MODE_NONE;
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_setadpparms_set_access_ctrl(struct qeth_card *card,
|
||||
enum qeth_ipa_isolation_modes isolation)
|
||||
{
|
||||
int rc;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
struct qeth_set_access_ctrl *access_ctrl_req;
|
||||
|
||||
QETH_DBF_TEXT(TRACE, 4, "setacctl");
|
||||
|
||||
QETH_DBF_TEXT_(SETUP, 2, "setacctl");
|
||||
QETH_DBF_TEXT_(SETUP, 2, "%s", card->gdev->dev.kobj.name);
|
||||
|
||||
iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_ACCESS_CONTROL,
|
||||
sizeof(struct qeth_ipacmd_setadpparms_hdr) +
|
||||
sizeof(struct qeth_set_access_ctrl));
|
||||
cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
|
||||
access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl;
|
||||
access_ctrl_req->subcmd_code = isolation;
|
||||
|
||||
rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_set_access_ctrl_cb,
|
||||
NULL);
|
||||
QETH_DBF_TEXT_(SETUP, 2, "rc=%d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int qeth_set_access_ctrl_online(struct qeth_card *card)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
QETH_DBF_TEXT(TRACE, 4, "setactlo");
|
||||
|
||||
if (card->info.type == QETH_CARD_TYPE_OSAE &&
|
||||
qeth_adp_supported(card, IPA_SETADP_SET_ACCESS_CONTROL)) {
|
||||
rc = qeth_setadpparms_set_access_ctrl(card,
|
||||
card->options.isolation);
|
||||
if (rc) {
|
||||
QETH_DBF_MESSAGE(3,
|
||||
"IPA(SET_ACCESS_CTRL,%s,%d) sent failed",
|
||||
card->gdev->dev.kobj.name,
|
||||
rc);
|
||||
}
|
||||
} else if (card->options.isolation != ISOLATION_MODE_NONE) {
|
||||
card->options.isolation = ISOLATION_MODE_NONE;
|
||||
|
||||
dev_err(&card->gdev->dev, "Adapter does not "
|
||||
"support QDIO data connection isolation\n");
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_set_access_ctrl_online);
|
||||
|
||||
void qeth_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
struct qeth_card *card;
|
||||
|
|
@ -3732,30 +3848,36 @@ static int qeth_core_driver_group(const char *buf, struct device *root_dev,
|
|||
int qeth_core_hardsetup_card(struct qeth_card *card)
|
||||
{
|
||||
struct qdio_ssqd_desc *ssqd;
|
||||
int retries = 3;
|
||||
int retries = 0;
|
||||
int mpno = 0;
|
||||
int rc;
|
||||
|
||||
QETH_DBF_TEXT(SETUP, 2, "hrdsetup");
|
||||
atomic_set(&card->force_alloc_skb, 0);
|
||||
retry:
|
||||
if (retries < 3) {
|
||||
if (retries)
|
||||
QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n",
|
||||
dev_name(&card->gdev->dev));
|
||||
ccw_device_set_offline(CARD_DDEV(card));
|
||||
ccw_device_set_offline(CARD_WDEV(card));
|
||||
ccw_device_set_offline(CARD_RDEV(card));
|
||||
ccw_device_set_online(CARD_RDEV(card));
|
||||
ccw_device_set_online(CARD_WDEV(card));
|
||||
ccw_device_set_online(CARD_DDEV(card));
|
||||
}
|
||||
ccw_device_set_offline(CARD_DDEV(card));
|
||||
ccw_device_set_offline(CARD_WDEV(card));
|
||||
ccw_device_set_offline(CARD_RDEV(card));
|
||||
rc = ccw_device_set_online(CARD_RDEV(card));
|
||||
if (rc)
|
||||
goto retriable;
|
||||
rc = ccw_device_set_online(CARD_WDEV(card));
|
||||
if (rc)
|
||||
goto retriable;
|
||||
rc = ccw_device_set_online(CARD_DDEV(card));
|
||||
if (rc)
|
||||
goto retriable;
|
||||
rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);
|
||||
retriable:
|
||||
if (rc == -ERESTARTSYS) {
|
||||
QETH_DBF_TEXT(SETUP, 2, "break1");
|
||||
return rc;
|
||||
} else if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
|
||||
if (--retries < 0)
|
||||
if (++retries > 3)
|
||||
goto out;
|
||||
else
|
||||
goto retry;
|
||||
|
|
@ -4303,13 +4425,19 @@ static struct {
|
|||
{"tx do_QDIO time"},
|
||||
{"tx do_QDIO count"},
|
||||
{"tx csum"},
|
||||
{"tx lin"},
|
||||
};
|
||||
|
||||
int qeth_core_get_stats_count(struct net_device *dev)
|
||||
int qeth_core_get_sset_count(struct net_device *dev, int stringset)
|
||||
{
|
||||
return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN);
|
||||
switch (stringset) {
|
||||
case ETH_SS_STATS:
|
||||
return (sizeof(qeth_ethtool_stats_keys) / ETH_GSTRING_LEN);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_core_get_stats_count);
|
||||
EXPORT_SYMBOL_GPL(qeth_core_get_sset_count);
|
||||
|
||||
void qeth_core_get_ethtool_stats(struct net_device *dev,
|
||||
struct ethtool_stats *stats, u64 *data)
|
||||
|
|
@ -4355,6 +4483,7 @@ void qeth_core_get_ethtool_stats(struct net_device *dev,
|
|||
data[31] = card->perf_stats.outbound_do_qdio_time;
|
||||
data[32] = card->perf_stats.outbound_do_qdio_cnt;
|
||||
data[33] = card->perf_stats.tx_csum;
|
||||
data[34] = card->perf_stats.tx_lin;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
|
||||
|
||||
|
|
|
|||
|
|
@ -234,18 +234,19 @@ enum qeth_ipa_setdelip_flags {
|
|||
|
||||
/* SETADAPTER IPA Command: ****************************************************/
|
||||
enum qeth_ipa_setadp_cmd {
|
||||
IPA_SETADP_QUERY_COMMANDS_SUPPORTED = 0x0001,
|
||||
IPA_SETADP_ALTER_MAC_ADDRESS = 0x0002,
|
||||
IPA_SETADP_ADD_DELETE_GROUP_ADDRESS = 0x0004,
|
||||
IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR = 0x0008,
|
||||
IPA_SETADP_SET_ADDRESSING_MODE = 0x0010,
|
||||
IPA_SETADP_SET_CONFIG_PARMS = 0x0020,
|
||||
IPA_SETADP_SET_CONFIG_PARMS_EXTENDED = 0x0040,
|
||||
IPA_SETADP_SET_BROADCAST_MODE = 0x0080,
|
||||
IPA_SETADP_SEND_OSA_MESSAGE = 0x0100,
|
||||
IPA_SETADP_SET_SNMP_CONTROL = 0x0200,
|
||||
IPA_SETADP_QUERY_CARD_INFO = 0x0400,
|
||||
IPA_SETADP_SET_PROMISC_MODE = 0x0800,
|
||||
IPA_SETADP_QUERY_COMMANDS_SUPPORTED = 0x00000001L,
|
||||
IPA_SETADP_ALTER_MAC_ADDRESS = 0x00000002L,
|
||||
IPA_SETADP_ADD_DELETE_GROUP_ADDRESS = 0x00000004L,
|
||||
IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR = 0x00000008L,
|
||||
IPA_SETADP_SET_ADDRESSING_MODE = 0x00000010L,
|
||||
IPA_SETADP_SET_CONFIG_PARMS = 0x00000020L,
|
||||
IPA_SETADP_SET_CONFIG_PARMS_EXTENDED = 0x00000040L,
|
||||
IPA_SETADP_SET_BROADCAST_MODE = 0x00000080L,
|
||||
IPA_SETADP_SEND_OSA_MESSAGE = 0x00000100L,
|
||||
IPA_SETADP_SET_SNMP_CONTROL = 0x00000200L,
|
||||
IPA_SETADP_QUERY_CARD_INFO = 0x00000400L,
|
||||
IPA_SETADP_SET_PROMISC_MODE = 0x00000800L,
|
||||
IPA_SETADP_SET_ACCESS_CONTROL = 0x00010000L,
|
||||
};
|
||||
enum qeth_ipa_mac_ops {
|
||||
CHANGE_ADDR_READ_MAC = 0,
|
||||
|
|
@ -264,6 +265,20 @@ enum qeth_ipa_promisc_modes {
|
|||
SET_PROMISC_MODE_OFF = 0,
|
||||
SET_PROMISC_MODE_ON = 1,
|
||||
};
|
||||
enum qeth_ipa_isolation_modes {
|
||||
ISOLATION_MODE_NONE = 0x00000000L,
|
||||
ISOLATION_MODE_FWD = 0x00000001L,
|
||||
ISOLATION_MODE_DROP = 0x00000002L,
|
||||
};
|
||||
enum qeth_ipa_set_access_mode_rc {
|
||||
SET_ACCESS_CTRL_RC_SUCCESS = 0x0000,
|
||||
SET_ACCESS_CTRL_RC_NOT_SUPPORTED = 0x0004,
|
||||
SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED = 0x0008,
|
||||
SET_ACCESS_CTRL_RC_ALREADY_ISOLATED = 0x0010,
|
||||
SET_ACCESS_CTRL_RC_NONE_SHARED_ADAPTER = 0x0014,
|
||||
SET_ACCESS_CTRL_RC_ACTIVE_CHECKSUM_OFF = 0x0018,
|
||||
};
|
||||
|
||||
|
||||
/* (SET)DELIP(M) IPA stuff ***************************************************/
|
||||
struct qeth_ipacmd_setdelip4 {
|
||||
|
|
@ -376,6 +391,11 @@ struct qeth_snmp_ureq {
|
|||
struct qeth_snmp_cmd cmd;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* SET_ACCESS_CONTROL: same format for request and reply */
|
||||
struct qeth_set_access_ctrl {
|
||||
__u32 subcmd_code;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct qeth_ipacmd_setadpparms_hdr {
|
||||
__u32 supp_hw_cmds;
|
||||
__u32 reserved1;
|
||||
|
|
@ -394,6 +414,7 @@ struct qeth_ipacmd_setadpparms {
|
|||
struct qeth_query_cmds_supp query_cmds_supp;
|
||||
struct qeth_change_addr change_addr;
|
||||
struct qeth_snmp_cmd snmp;
|
||||
struct qeth_set_access_ctrl set_access_ctrl;
|
||||
__u32 mode;
|
||||
} data;
|
||||
} __attribute__ ((packed));
|
||||
|
|
|
|||
|
|
@ -416,7 +416,11 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
|
|||
static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
|
||||
qeth_dev_layer2_store);
|
||||
|
||||
static ssize_t qeth_dev_large_send_show(struct device *dev,
|
||||
#define ATTR_QETH_ISOLATION_NONE ("none")
|
||||
#define ATTR_QETH_ISOLATION_FWD ("forward")
|
||||
#define ATTR_QETH_ISOLATION_DROP ("drop")
|
||||
|
||||
static ssize_t qeth_dev_isolation_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(dev);
|
||||
|
|
@ -424,44 +428,69 @@ static ssize_t qeth_dev_large_send_show(struct device *dev,
|
|||
if (!card)
|
||||
return -EINVAL;
|
||||
|
||||
switch (card->options.large_send) {
|
||||
case QETH_LARGE_SEND_NO:
|
||||
return sprintf(buf, "%s\n", "no");
|
||||
case QETH_LARGE_SEND_TSO:
|
||||
return sprintf(buf, "%s\n", "TSO");
|
||||
switch (card->options.isolation) {
|
||||
case ISOLATION_MODE_NONE:
|
||||
return snprintf(buf, 6, "%s\n", ATTR_QETH_ISOLATION_NONE);
|
||||
case ISOLATION_MODE_FWD:
|
||||
return snprintf(buf, 9, "%s\n", ATTR_QETH_ISOLATION_FWD);
|
||||
case ISOLATION_MODE_DROP:
|
||||
return snprintf(buf, 6, "%s\n", ATTR_QETH_ISOLATION_DROP);
|
||||
default:
|
||||
return sprintf(buf, "%s\n", "N/A");
|
||||
return snprintf(buf, 5, "%s\n", "N/A");
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t qeth_dev_large_send_store(struct device *dev,
|
||||
static ssize_t qeth_dev_isolation_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(dev);
|
||||
enum qeth_large_send_types type;
|
||||
enum qeth_ipa_isolation_modes isolation;
|
||||
int rc = 0;
|
||||
char *tmp;
|
||||
char *tmp, *curtoken;
|
||||
curtoken = (char *) buf;
|
||||
|
||||
if (!card)
|
||||
return -EINVAL;
|
||||
tmp = strsep((char **) &buf, "\n");
|
||||
if (!strcmp(tmp, "no")) {
|
||||
type = QETH_LARGE_SEND_NO;
|
||||
} else if (!strcmp(tmp, "TSO")) {
|
||||
type = QETH_LARGE_SEND_TSO;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
if (!card) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (card->options.large_send == type)
|
||||
return count;
|
||||
rc = qeth_set_large_send(card, type);
|
||||
if (rc)
|
||||
return rc;
|
||||
return count;
|
||||
|
||||
/* check for unknown, too, in case we do not yet know who we are */
|
||||
if (card->info.type != QETH_CARD_TYPE_OSAE &&
|
||||
card->info.type != QETH_CARD_TYPE_UNKNOWN) {
|
||||
rc = -EOPNOTSUPP;
|
||||
dev_err(&card->gdev->dev, "Adapter does not "
|
||||
"support QDIO data connection isolation\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* parse input into isolation mode */
|
||||
tmp = strsep(&curtoken, "\n");
|
||||
if (!strcmp(tmp, ATTR_QETH_ISOLATION_NONE)) {
|
||||
isolation = ISOLATION_MODE_NONE;
|
||||
} else if (!strcmp(tmp, ATTR_QETH_ISOLATION_FWD)) {
|
||||
isolation = ISOLATION_MODE_FWD;
|
||||
} else if (!strcmp(tmp, ATTR_QETH_ISOLATION_DROP)) {
|
||||
isolation = ISOLATION_MODE_DROP;
|
||||
} else {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
rc = count;
|
||||
|
||||
/* defer IP assist if device is offline (until discipline->set_online)*/
|
||||
card->options.isolation = isolation;
|
||||
if (card->state == CARD_STATE_SOFTSETUP ||
|
||||
card->state == CARD_STATE_UP) {
|
||||
int ipa_rc = qeth_set_access_ctrl_online(card);
|
||||
if (ipa_rc != 0)
|
||||
rc = ipa_rc;
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(large_send, 0644, qeth_dev_large_send_show,
|
||||
qeth_dev_large_send_store);
|
||||
static DEVICE_ATTR(isolation, 0644, qeth_dev_isolation_show,
|
||||
qeth_dev_isolation_store);
|
||||
|
||||
static ssize_t qeth_dev_blkt_show(char *buf, struct qeth_card *card, int value)
|
||||
{
|
||||
|
|
@ -582,7 +611,7 @@ static struct attribute *qeth_device_attrs[] = {
|
|||
&dev_attr_recover.attr,
|
||||
&dev_attr_performance_stats.attr,
|
||||
&dev_attr_layer2.attr,
|
||||
&dev_attr_large_send.attr,
|
||||
&dev_attr_isolation.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -866,7 +866,7 @@ static const struct ethtool_ops qeth_l2_ethtool_ops = {
|
|||
.get_link = ethtool_op_get_link,
|
||||
.get_strings = qeth_core_get_strings,
|
||||
.get_ethtool_stats = qeth_core_get_ethtool_stats,
|
||||
.get_stats_count = qeth_core_get_stats_count,
|
||||
.get_sset_count = qeth_core_get_sset_count,
|
||||
.get_drvinfo = qeth_core_get_drvinfo,
|
||||
.get_settings = qeth_core_ethtool_get_settings,
|
||||
};
|
||||
|
|
@ -874,7 +874,7 @@ static const struct ethtool_ops qeth_l2_ethtool_ops = {
|
|||
static const struct ethtool_ops qeth_l2_osn_ops = {
|
||||
.get_strings = qeth_core_get_strings,
|
||||
.get_ethtool_stats = qeth_core_get_ethtool_stats,
|
||||
.get_stats_count = qeth_core_get_stats_count,
|
||||
.get_sset_count = qeth_core_get_sset_count,
|
||||
.get_drvinfo = qeth_core_get_drvinfo,
|
||||
};
|
||||
|
||||
|
|
@ -940,30 +940,17 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
|
||||
qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
|
||||
recover_flag = card->state;
|
||||
rc = ccw_device_set_online(CARD_RDEV(card));
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
|
||||
return -EIO;
|
||||
}
|
||||
rc = ccw_device_set_online(CARD_WDEV(card));
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
|
||||
return -EIO;
|
||||
}
|
||||
rc = ccw_device_set_online(CARD_DDEV(card));
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = qeth_core_hardsetup_card(card);
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
|
||||
rc = -ENODEV;
|
||||
goto out_remove;
|
||||
}
|
||||
|
||||
if (!card->dev && qeth_l2_setup_netdev(card))
|
||||
if (!card->dev && qeth_l2_setup_netdev(card)) {
|
||||
rc = -ENODEV;
|
||||
goto out_remove;
|
||||
}
|
||||
|
||||
if (card->info.type != QETH_CARD_TYPE_OSN)
|
||||
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)
|
|||
card->lan_online = 0;
|
||||
return 0;
|
||||
}
|
||||
rc = -ENODEV;
|
||||
goto out_remove;
|
||||
} else
|
||||
card->lan_online = 1;
|
||||
|
||||
if (card->info.type != QETH_CARD_TYPE_OSN) {
|
||||
qeth_set_large_send(card, card->options.large_send);
|
||||
/* configure isolation level */
|
||||
qeth_set_access_ctrl_online(card);
|
||||
qeth_l2_process_vlans(card, 0);
|
||||
}
|
||||
|
||||
|
|
@ -997,6 +986,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
rc = qeth_init_qdio_queues(card);
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
|
||||
rc = -ENODEV;
|
||||
goto out_remove;
|
||||
}
|
||||
card->state = CARD_STATE_SOFTSETUP;
|
||||
|
|
@ -1018,6 +1008,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
/* let user_space know that device is online */
|
||||
kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
|
||||
return 0;
|
||||
|
||||
out_remove:
|
||||
card->use_hard_stop = 1;
|
||||
qeth_l2_stop_card(card, 0);
|
||||
|
|
@ -1028,7 +1019,7 @@ out_remove:
|
|||
card->state = CARD_STATE_RECOVER;
|
||||
else
|
||||
card->state = CARD_STATE_DOWN;
|
||||
return -ENODEV;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l2_set_online(struct ccwgroup_device *gdev)
|
||||
|
|
|
|||
|
|
@ -60,5 +60,7 @@ void qeth_l3_del_vipa(struct qeth_card *, enum qeth_prot_versions, const u8 *);
|
|||
int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
|
||||
void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions,
|
||||
const u8 *);
|
||||
int qeth_l3_set_large_send(struct qeth_card *, enum qeth_large_send_types);
|
||||
int qeth_l3_set_rx_csum(struct qeth_card *, enum qeth_checksum_types);
|
||||
|
||||
#endif /* __QETH_L3_H__ */
|
||||
|
|
|
|||
|
|
@ -41,6 +41,32 @@ static int qeth_l3_deregister_addr_entry(struct qeth_card *,
|
|||
static int __qeth_l3_set_online(struct ccwgroup_device *, int);
|
||||
static int __qeth_l3_set_offline(struct ccwgroup_device *, int);
|
||||
|
||||
int qeth_l3_set_large_send(struct qeth_card *card,
|
||||
enum qeth_large_send_types type)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
card->options.large_send = type;
|
||||
if (card->dev == NULL)
|
||||
return 0;
|
||||
|
||||
if (card->options.large_send == QETH_LARGE_SEND_TSO) {
|
||||
if (qeth_is_supported(card, IPA_OUTBOUND_TSO)) {
|
||||
card->dev->features |= NETIF_F_TSO | NETIF_F_SG |
|
||||
NETIF_F_HW_CSUM;
|
||||
} else {
|
||||
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
|
||||
NETIF_F_HW_CSUM);
|
||||
card->options.large_send = QETH_LARGE_SEND_NO;
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
} else {
|
||||
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG |
|
||||
NETIF_F_HW_CSUM);
|
||||
card->options.large_send = QETH_LARGE_SEND_NO;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l3_isxdigit(char *buf)
|
||||
{
|
||||
|
|
@ -1439,6 +1465,35 @@ static int qeth_l3_send_checksum_command(struct qeth_card *card)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int qeth_l3_set_rx_csum(struct qeth_card *card,
|
||||
enum qeth_checksum_types csum_type)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (card->options.checksum_type == HW_CHECKSUMMING) {
|
||||
if ((csum_type != HW_CHECKSUMMING) &&
|
||||
(card->state != CARD_STATE_DOWN)) {
|
||||
rc = qeth_l3_send_simple_setassparms(card,
|
||||
IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0);
|
||||
if (rc)
|
||||
return -EIO;
|
||||
}
|
||||
} else {
|
||||
if (csum_type == HW_CHECKSUMMING) {
|
||||
if (card->state != CARD_STATE_DOWN) {
|
||||
if (!qeth_is_supported(card,
|
||||
IPA_INBOUND_CHECKSUM))
|
||||
return -EPERM;
|
||||
rc = qeth_l3_send_checksum_command(card);
|
||||
if (rc)
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
card->options.checksum_type = csum_type;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l3_start_ipa_checksum(struct qeth_card *card)
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
@ -1506,6 +1561,8 @@ static int qeth_l3_start_ipa_tso(struct qeth_card *card)
|
|||
static int qeth_l3_start_ipassists(struct qeth_card *card)
|
||||
{
|
||||
QETH_DBF_TEXT(TRACE, 3, "strtipas");
|
||||
|
||||
qeth_set_access_ctrl_online(card); /* go on*/
|
||||
qeth_l3_start_ipa_arp_processing(card); /* go on*/
|
||||
qeth_l3_start_ipa_ip_fragmentation(card); /* go on*/
|
||||
qeth_l3_start_ipa_source_mac(card); /* go on*/
|
||||
|
|
@ -2684,6 +2741,24 @@ static void qeth_tx_csum(struct sk_buff *skb)
|
|||
*(__sum16 *)(skb->data + offset) = csum_fold(csum);
|
||||
}
|
||||
|
||||
static inline int qeth_l3_tso_elements(struct sk_buff *skb)
|
||||
{
|
||||
unsigned long tcpd = (unsigned long)tcp_hdr(skb) +
|
||||
tcp_hdr(skb)->doff * 4;
|
||||
int tcpd_len = skb->len - (tcpd - (unsigned long)skb->data);
|
||||
int elements = PFN_UP(tcpd + tcpd_len) - PFN_DOWN(tcpd);
|
||||
elements += skb_shinfo(skb)->nr_frags;
|
||||
return elements;
|
||||
}
|
||||
|
||||
static inline int qeth_l3_tso_check(struct sk_buff *skb)
|
||||
{
|
||||
int len = ((unsigned long)tcp_hdr(skb) + tcp_hdr(skb)->doff * 4) -
|
||||
(unsigned long)skb->data;
|
||||
return (((unsigned long)skb->data & PAGE_MASK) !=
|
||||
(((unsigned long)skb->data + len) & PAGE_MASK));
|
||||
}
|
||||
|
||||
static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
int rc;
|
||||
|
|
@ -2777,16 +2852,21 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
/* fix hardware limitation: as long as we do not have sbal
|
||||
* chaining we can not send long frag lists
|
||||
*/
|
||||
if ((large_send == QETH_LARGE_SEND_TSO) &&
|
||||
((skb_shinfo(new_skb)->nr_frags + 2) > 16)) {
|
||||
if (skb_linearize(new_skb))
|
||||
goto tx_drop;
|
||||
if (large_send == QETH_LARGE_SEND_TSO) {
|
||||
if (qeth_l3_tso_elements(new_skb) + 1 > 16) {
|
||||
if (skb_linearize(new_skb))
|
||||
goto tx_drop;
|
||||
if (card->options.performance_stats)
|
||||
card->perf_stats.tx_lin++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((large_send == QETH_LARGE_SEND_TSO) &&
|
||||
(cast_type == RTN_UNSPEC)) {
|
||||
hdr = (struct qeth_hdr *)skb_push(new_skb,
|
||||
sizeof(struct qeth_hdr_tso));
|
||||
if (qeth_l3_tso_check(new_skb))
|
||||
QETH_DBF_MESSAGE(2, "tso skb misaligned\n");
|
||||
memset(hdr, 0, sizeof(struct qeth_hdr_tso));
|
||||
qeth_l3_fill_header(card, hdr, new_skb, ipv, cast_type);
|
||||
qeth_tso_fill_header(card, hdr, new_skb);
|
||||
|
|
@ -2903,46 +2983,28 @@ static u32 qeth_l3_ethtool_get_rx_csum(struct net_device *dev)
|
|||
static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data)
|
||||
{
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
enum qeth_card_states old_state;
|
||||
enum qeth_checksum_types csum_type;
|
||||
|
||||
if ((card->state != CARD_STATE_UP) &&
|
||||
(card->state != CARD_STATE_DOWN))
|
||||
return -EPERM;
|
||||
|
||||
if (data)
|
||||
csum_type = HW_CHECKSUMMING;
|
||||
else
|
||||
csum_type = SW_CHECKSUMMING;
|
||||
|
||||
if (card->options.checksum_type != csum_type) {
|
||||
old_state = card->state;
|
||||
if (card->state == CARD_STATE_UP)
|
||||
__qeth_l3_set_offline(card->gdev, 1);
|
||||
card->options.checksum_type = csum_type;
|
||||
if (old_state == CARD_STATE_UP)
|
||||
__qeth_l3_set_online(card->gdev, 1);
|
||||
}
|
||||
return 0;
|
||||
return qeth_l3_set_rx_csum(card, csum_type);
|
||||
}
|
||||
|
||||
static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data)
|
||||
{
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
int rc = 0;
|
||||
|
||||
if (data) {
|
||||
if (card->options.large_send == QETH_LARGE_SEND_NO) {
|
||||
if (card->info.type == QETH_CARD_TYPE_IQD)
|
||||
return -EPERM;
|
||||
else
|
||||
card->options.large_send = QETH_LARGE_SEND_TSO;
|
||||
dev->features |= NETIF_F_TSO;
|
||||
}
|
||||
rc = qeth_l3_set_large_send(card, QETH_LARGE_SEND_TSO);
|
||||
} else {
|
||||
dev->features &= ~NETIF_F_TSO;
|
||||
card->options.large_send = QETH_LARGE_SEND_NO;
|
||||
}
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops qeth_l3_ethtool_ops = {
|
||||
|
|
@ -2957,7 +3019,7 @@ static const struct ethtool_ops qeth_l3_ethtool_ops = {
|
|||
.set_tso = qeth_l3_ethtool_set_tso,
|
||||
.get_strings = qeth_core_get_strings,
|
||||
.get_ethtool_stats = qeth_core_get_ethtool_stats,
|
||||
.get_stats_count = qeth_core_get_stats_count,
|
||||
.get_sset_count = qeth_core_get_sset_count,
|
||||
.get_drvinfo = qeth_core_get_drvinfo,
|
||||
.get_settings = qeth_core_ethtool_get_settings,
|
||||
};
|
||||
|
|
@ -3058,6 +3120,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
|
|||
NETIF_F_HW_VLAN_RX |
|
||||
NETIF_F_HW_VLAN_FILTER;
|
||||
card->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
|
||||
card->dev->gso_max_size = 15 * PAGE_SIZE;
|
||||
|
||||
SET_NETDEV_DEV(card->dev, &card->gdev->dev);
|
||||
return register_netdev(card->dev);
|
||||
|
|
@ -3154,32 +3217,19 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 1);
|
||||
|
||||
recover_flag = card->state;
|
||||
rc = ccw_device_set_online(CARD_RDEV(card));
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
|
||||
return -EIO;
|
||||
}
|
||||
rc = ccw_device_set_online(CARD_WDEV(card));
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
|
||||
return -EIO;
|
||||
}
|
||||
rc = ccw_device_set_online(CARD_DDEV(card));
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = qeth_core_hardsetup_card(card);
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
|
||||
rc = -ENODEV;
|
||||
goto out_remove;
|
||||
}
|
||||
|
||||
qeth_l3_query_ipassists(card, QETH_PROT_IPV4);
|
||||
|
||||
if (!card->dev && qeth_l3_setup_netdev(card))
|
||||
if (!card->dev && qeth_l3_setup_netdev(card)) {
|
||||
rc = -ENODEV;
|
||||
goto out_remove;
|
||||
}
|
||||
|
||||
card->state = CARD_STATE_HARDSETUP;
|
||||
qeth_print_status_message(card);
|
||||
|
|
@ -3196,10 +3246,11 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
card->lan_online = 0;
|
||||
return 0;
|
||||
}
|
||||
rc = -ENODEV;
|
||||
goto out_remove;
|
||||
} else
|
||||
card->lan_online = 1;
|
||||
qeth_set_large_send(card, card->options.large_send);
|
||||
qeth_l3_set_large_send(card, card->options.large_send);
|
||||
|
||||
rc = qeth_l3_setadapter_parms(card);
|
||||
if (rc)
|
||||
|
|
@ -3218,6 +3269,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
|||
rc = qeth_init_qdio_queues(card);
|
||||
if (rc) {
|
||||
QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
|
||||
rc = -ENODEV;
|
||||
goto out_remove;
|
||||
}
|
||||
card->state = CARD_STATE_SOFTSETUP;
|
||||
|
|
@ -3248,7 +3300,7 @@ out_remove:
|
|||
card->state = CARD_STATE_RECOVER;
|
||||
else
|
||||
card->state = CARD_STATE_DOWN;
|
||||
return -ENODEV;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l3_set_online(struct ccwgroup_device *gdev)
|
||||
|
|
|
|||
|
|
@ -293,31 +293,79 @@ static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
|
|||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(dev);
|
||||
enum qeth_checksum_types csum_type;
|
||||
char *tmp;
|
||||
int rc;
|
||||
|
||||
if (!card)
|
||||
return -EINVAL;
|
||||
|
||||
if ((card->state != CARD_STATE_DOWN) &&
|
||||
(card->state != CARD_STATE_RECOVER))
|
||||
return -EPERM;
|
||||
|
||||
tmp = strsep((char **) &buf, "\n");
|
||||
if (!strcmp(tmp, "sw_checksumming"))
|
||||
card->options.checksum_type = SW_CHECKSUMMING;
|
||||
csum_type = SW_CHECKSUMMING;
|
||||
else if (!strcmp(tmp, "hw_checksumming"))
|
||||
card->options.checksum_type = HW_CHECKSUMMING;
|
||||
csum_type = HW_CHECKSUMMING;
|
||||
else if (!strcmp(tmp, "no_checksumming"))
|
||||
card->options.checksum_type = NO_CHECKSUMMING;
|
||||
else {
|
||||
csum_type = NO_CHECKSUMMING;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = qeth_l3_set_rx_csum(card, csum_type);
|
||||
if (rc)
|
||||
return rc;
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(checksumming, 0644, qeth_l3_dev_checksum_show,
|
||||
qeth_l3_dev_checksum_store);
|
||||
|
||||
static ssize_t qeth_l3_dev_large_send_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(dev);
|
||||
|
||||
if (!card)
|
||||
return -EINVAL;
|
||||
|
||||
switch (card->options.large_send) {
|
||||
case QETH_LARGE_SEND_NO:
|
||||
return sprintf(buf, "%s\n", "no");
|
||||
case QETH_LARGE_SEND_TSO:
|
||||
return sprintf(buf, "%s\n", "TSO");
|
||||
default:
|
||||
return sprintf(buf, "%s\n", "N/A");
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t qeth_l3_dev_large_send_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(dev);
|
||||
enum qeth_large_send_types type;
|
||||
int rc = 0;
|
||||
char *tmp;
|
||||
|
||||
if (!card)
|
||||
return -EINVAL;
|
||||
tmp = strsep((char **) &buf, "\n");
|
||||
if (!strcmp(tmp, "no"))
|
||||
type = QETH_LARGE_SEND_NO;
|
||||
else if (!strcmp(tmp, "TSO"))
|
||||
type = QETH_LARGE_SEND_TSO;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (card->options.large_send == type)
|
||||
return count;
|
||||
rc = qeth_l3_set_large_send(card, type);
|
||||
if (rc)
|
||||
return rc;
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(large_send, 0644, qeth_l3_dev_large_send_show,
|
||||
qeth_l3_dev_large_send_store);
|
||||
|
||||
static struct attribute *qeth_l3_device_attrs[] = {
|
||||
&dev_attr_route4.attr,
|
||||
&dev_attr_route6.attr,
|
||||
|
|
@ -325,6 +373,7 @@ static struct attribute *qeth_l3_device_attrs[] = {
|
|||
&dev_attr_broadcast_mode.attr,
|
||||
&dev_attr_canonical_macaddr.attr,
|
||||
&dev_attr_checksumming.attr,
|
||||
&dev_attr_large_send.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue