diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/s390/net | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/s390/net')
25 files changed, 1027 insertions, 1663 deletions
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig index dfda748c400..fa80ba1f034 100644 --- a/drivers/s390/net/Kconfig +++ b/drivers/s390/net/Kconfig | |||
@@ -4,10 +4,11 @@ menu "S/390 network device drivers" | |||
4 | config LCS | 4 | config LCS |
5 | def_tristate m | 5 | def_tristate m |
6 | prompt "Lan Channel Station Interface" | 6 | prompt "Lan Channel Station Interface" |
7 | depends on CCW && NETDEVICES && (ETHERNET || FDDI) | 7 | depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI) |
8 | help | 8 | help |
9 | Select this option if you want to use LCS networking on IBM System z. | 9 | Select this option if you want to use LCS networking on IBM System z. |
10 | This device driver supports FDDI (IEEE 802.7) and Ethernet. | 10 | This device driver supports Token Ring (IEEE 802.5), |
11 | FDDI (IEEE 802.7) and Ethernet. | ||
11 | To compile as a module, choose M. The module name is lcs. | 12 | To compile as a module, choose M. The module name is lcs. |
12 | If you do not know what it is, it's safe to choose Y. | 13 | If you do not know what it is, it's safe to choose Y. |
13 | 14 | ||
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 83bc9c5fa0c..f1fa2483ae6 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/claw.c | ||
2 | * ESCON CLAW network driver | 3 | * ESCON CLAW network driver |
3 | * | 4 | * |
4 | * Linux for zSeries version | 5 | * Linux for zSeries version |
@@ -62,6 +63,7 @@ | |||
62 | 63 | ||
63 | #define KMSG_COMPONENT "claw" | 64 | #define KMSG_COMPONENT "claw" |
64 | 65 | ||
66 | #include <linux/kernel_stat.h> | ||
65 | #include <asm/ccwdev.h> | 67 | #include <asm/ccwdev.h> |
66 | #include <asm/ccwgroup.h> | 68 | #include <asm/ccwgroup.h> |
67 | #include <asm/debug.h> | 69 | #include <asm/debug.h> |
@@ -135,6 +137,7 @@ static inline void | |||
135 | claw_set_busy(struct net_device *dev) | 137 | claw_set_busy(struct net_device *dev) |
136 | { | 138 | { |
137 | ((struct claw_privbk *)dev->ml_priv)->tbusy = 1; | 139 | ((struct claw_privbk *)dev->ml_priv)->tbusy = 1; |
140 | eieio(); | ||
138 | } | 141 | } |
139 | 142 | ||
140 | static inline void | 143 | static inline void |
@@ -142,11 +145,13 @@ claw_clear_busy(struct net_device *dev) | |||
142 | { | 145 | { |
143 | clear_bit(0, &(((struct claw_privbk *) dev->ml_priv)->tbusy)); | 146 | clear_bit(0, &(((struct claw_privbk *) dev->ml_priv)->tbusy)); |
144 | netif_wake_queue(dev); | 147 | netif_wake_queue(dev); |
148 | eieio(); | ||
145 | } | 149 | } |
146 | 150 | ||
147 | static inline int | 151 | static inline int |
148 | claw_check_busy(struct net_device *dev) | 152 | claw_check_busy(struct net_device *dev) |
149 | { | 153 | { |
154 | eieio(); | ||
150 | return ((struct claw_privbk *) dev->ml_priv)->tbusy; | 155 | return ((struct claw_privbk *) dev->ml_priv)->tbusy; |
151 | } | 156 | } |
152 | 157 | ||
@@ -229,6 +234,8 @@ static ssize_t claw_rbuff_show(struct device *dev, | |||
229 | static ssize_t claw_rbuff_write(struct device *dev, | 234 | static ssize_t claw_rbuff_write(struct device *dev, |
230 | struct device_attribute *attr, | 235 | struct device_attribute *attr, |
231 | const char *buf, size_t count); | 236 | const char *buf, size_t count); |
237 | static int claw_add_files(struct device *dev); | ||
238 | static void claw_remove_files(struct device *dev); | ||
232 | 239 | ||
233 | /* Functions for System Validate */ | 240 | /* Functions for System Validate */ |
234 | static int claw_process_control( struct net_device *dev, struct ccwbk * p_ccw); | 241 | static int claw_process_control( struct net_device *dev, struct ccwbk * p_ccw); |
@@ -261,10 +268,12 @@ static struct ccwgroup_driver claw_group_driver = { | |||
261 | .owner = THIS_MODULE, | 268 | .owner = THIS_MODULE, |
262 | .name = "claw", | 269 | .name = "claw", |
263 | }, | 270 | }, |
264 | .setup = claw_probe, | 271 | .max_slaves = 2, |
265 | .remove = claw_remove_device, | 272 | .driver_id = 0xC3D3C1E6, |
266 | .set_online = claw_new_device, | 273 | .probe = claw_probe, |
267 | .set_offline = claw_shutdown_device, | 274 | .remove = claw_remove_device, |
275 | .set_online = claw_new_device, | ||
276 | .set_offline = claw_shutdown_device, | ||
268 | .prepare = claw_pm_prepare, | 277 | .prepare = claw_pm_prepare, |
269 | }; | 278 | }; |
270 | 279 | ||
@@ -282,27 +291,32 @@ static struct ccw_driver claw_ccw_driver = { | |||
282 | .ids = claw_ids, | 291 | .ids = claw_ids, |
283 | .probe = ccwgroup_probe_ccwdev, | 292 | .probe = ccwgroup_probe_ccwdev, |
284 | .remove = ccwgroup_remove_ccwdev, | 293 | .remove = ccwgroup_remove_ccwdev, |
285 | .int_class = IRQIO_CLW, | ||
286 | }; | 294 | }; |
287 | 295 | ||
288 | static ssize_t claw_driver_group_store(struct device_driver *ddrv, | 296 | static ssize_t |
289 | const char *buf, size_t count) | 297 | claw_driver_group_store(struct device_driver *ddrv, const char *buf, |
298 | size_t count) | ||
290 | { | 299 | { |
291 | int err; | 300 | int err; |
292 | err = ccwgroup_create_dev(claw_root_dev, &claw_group_driver, 2, buf); | 301 | err = ccwgroup_create_from_string(claw_root_dev, |
302 | claw_group_driver.driver_id, | ||
303 | &claw_ccw_driver, 2, buf); | ||
293 | return err ? err : count; | 304 | return err ? err : count; |
294 | } | 305 | } |
306 | |||
295 | static DRIVER_ATTR(group, 0200, NULL, claw_driver_group_store); | 307 | static DRIVER_ATTR(group, 0200, NULL, claw_driver_group_store); |
296 | 308 | ||
297 | static struct attribute *claw_drv_attrs[] = { | 309 | static struct attribute *claw_group_attrs[] = { |
298 | &driver_attr_group.attr, | 310 | &driver_attr_group.attr, |
299 | NULL, | 311 | NULL, |
300 | }; | 312 | }; |
301 | static struct attribute_group claw_drv_attr_group = { | 313 | |
302 | .attrs = claw_drv_attrs, | 314 | static struct attribute_group claw_group_attr_group = { |
315 | .attrs = claw_group_attrs, | ||
303 | }; | 316 | }; |
304 | static const struct attribute_group *claw_drv_attr_groups[] = { | 317 | |
305 | &claw_drv_attr_group, | 318 | static const struct attribute_group *claw_group_attr_groups[] = { |
319 | &claw_group_attr_group, | ||
306 | NULL, | 320 | NULL, |
307 | }; | 321 | }; |
308 | 322 | ||
@@ -310,6 +324,60 @@ static const struct attribute_group *claw_drv_attr_groups[] = { | |||
310 | * Key functions | 324 | * Key functions |
311 | */ | 325 | */ |
312 | 326 | ||
327 | /*----------------------------------------------------------------* | ||
328 | * claw_probe * | ||
329 | * this function is called for each CLAW device. * | ||
330 | *----------------------------------------------------------------*/ | ||
331 | static int | ||
332 | claw_probe(struct ccwgroup_device *cgdev) | ||
333 | { | ||
334 | int rc; | ||
335 | struct claw_privbk *privptr=NULL; | ||
336 | |||
337 | CLAW_DBF_TEXT(2, setup, "probe"); | ||
338 | if (!get_device(&cgdev->dev)) | ||
339 | return -ENODEV; | ||
340 | privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL); | ||
341 | dev_set_drvdata(&cgdev->dev, privptr); | ||
342 | if (privptr == NULL) { | ||
343 | probe_error(cgdev); | ||
344 | put_device(&cgdev->dev); | ||
345 | CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM); | ||
346 | return -ENOMEM; | ||
347 | } | ||
348 | privptr->p_mtc_envelope= kzalloc( MAX_ENVELOPE_SIZE, GFP_KERNEL); | ||
349 | privptr->p_env = kzalloc(sizeof(struct claw_env), GFP_KERNEL); | ||
350 | if ((privptr->p_mtc_envelope==NULL) || (privptr->p_env==NULL)) { | ||
351 | probe_error(cgdev); | ||
352 | put_device(&cgdev->dev); | ||
353 | CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM); | ||
354 | return -ENOMEM; | ||
355 | } | ||
356 | memcpy(privptr->p_env->adapter_name,WS_NAME_NOT_DEF,8); | ||
357 | memcpy(privptr->p_env->host_name,WS_NAME_NOT_DEF,8); | ||
358 | memcpy(privptr->p_env->api_type,WS_NAME_NOT_DEF,8); | ||
359 | privptr->p_env->packing = 0; | ||
360 | privptr->p_env->write_buffers = 5; | ||
361 | privptr->p_env->read_buffers = 5; | ||
362 | privptr->p_env->read_size = CLAW_FRAME_SIZE; | ||
363 | privptr->p_env->write_size = CLAW_FRAME_SIZE; | ||
364 | rc = claw_add_files(&cgdev->dev); | ||
365 | if (rc) { | ||
366 | probe_error(cgdev); | ||
367 | put_device(&cgdev->dev); | ||
368 | dev_err(&cgdev->dev, "Creating the /proc files for a new" | ||
369 | " CLAW device failed\n"); | ||
370 | CLAW_DBF_TEXT_(2, setup, "probex%d", rc); | ||
371 | return rc; | ||
372 | } | ||
373 | privptr->p_env->p_priv = privptr; | ||
374 | cgdev->cdev[0]->handler = claw_irq_handler; | ||
375 | cgdev->cdev[1]->handler = claw_irq_handler; | ||
376 | CLAW_DBF_TEXT(2, setup, "prbext 0"); | ||
377 | |||
378 | return 0; | ||
379 | } /* end of claw_probe */ | ||
380 | |||
313 | /*-------------------------------------------------------------------* | 381 | /*-------------------------------------------------------------------* |
314 | * claw_tx * | 382 | * claw_tx * |
315 | *-------------------------------------------------------------------*/ | 383 | *-------------------------------------------------------------------*/ |
@@ -577,6 +645,7 @@ claw_irq_handler(struct ccw_device *cdev, | |||
577 | struct claw_env *p_env; | 645 | struct claw_env *p_env; |
578 | struct chbk *p_ch_r=NULL; | 646 | struct chbk *p_ch_r=NULL; |
579 | 647 | ||
648 | kstat_cpu(smp_processor_id()).irqs[IOINT_CLW]++; | ||
580 | CLAW_DBF_TEXT(4, trace, "clawirq"); | 649 | CLAW_DBF_TEXT(4, trace, "clawirq"); |
581 | /* Bypass all 'unsolicited interrupts' */ | 650 | /* Bypass all 'unsolicited interrupts' */ |
582 | privptr = dev_get_drvdata(&cdev->dev); | 651 | privptr = dev_get_drvdata(&cdev->dev); |
@@ -3018,11 +3087,14 @@ claw_remove_device(struct ccwgroup_device *cgdev) | |||
3018 | { | 3087 | { |
3019 | struct claw_privbk *priv; | 3088 | struct claw_privbk *priv; |
3020 | 3089 | ||
3090 | BUG_ON(!cgdev); | ||
3021 | CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev)); | 3091 | CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev)); |
3022 | priv = dev_get_drvdata(&cgdev->dev); | 3092 | priv = dev_get_drvdata(&cgdev->dev); |
3093 | BUG_ON(!priv); | ||
3023 | dev_info(&cgdev->dev, " will be removed.\n"); | 3094 | dev_info(&cgdev->dev, " will be removed.\n"); |
3024 | if (cgdev->state == CCWGROUP_ONLINE) | 3095 | if (cgdev->state == CCWGROUP_ONLINE) |
3025 | claw_shutdown_device(cgdev); | 3096 | claw_shutdown_device(cgdev); |
3097 | claw_remove_files(&cgdev->dev); | ||
3026 | kfree(priv->p_mtc_envelope); | 3098 | kfree(priv->p_mtc_envelope); |
3027 | priv->p_mtc_envelope=NULL; | 3099 | priv->p_mtc_envelope=NULL; |
3028 | kfree(priv->p_env); | 3100 | kfree(priv->p_env); |
@@ -3250,6 +3322,7 @@ claw_rbuff_write(struct device *dev, struct device_attribute *attr, | |||
3250 | CLAW_DBF_TEXT_(2, setup, "RB=%d", p_env->read_buffers); | 3322 | CLAW_DBF_TEXT_(2, setup, "RB=%d", p_env->read_buffers); |
3251 | return count; | 3323 | return count; |
3252 | } | 3324 | } |
3325 | |||
3253 | static DEVICE_ATTR(read_buffer, 0644, claw_rbuff_show, claw_rbuff_write); | 3326 | static DEVICE_ATTR(read_buffer, 0644, claw_rbuff_show, claw_rbuff_write); |
3254 | 3327 | ||
3255 | static struct attribute *claw_attr[] = { | 3328 | static struct attribute *claw_attr[] = { |
@@ -3260,73 +3333,40 @@ static struct attribute *claw_attr[] = { | |||
3260 | &dev_attr_host_name.attr, | 3333 | &dev_attr_host_name.attr, |
3261 | NULL, | 3334 | NULL, |
3262 | }; | 3335 | }; |
3336 | |||
3263 | static struct attribute_group claw_attr_group = { | 3337 | static struct attribute_group claw_attr_group = { |
3264 | .attrs = claw_attr, | 3338 | .attrs = claw_attr, |
3265 | }; | 3339 | }; |
3266 | static const struct attribute_group *claw_attr_groups[] = { | ||
3267 | &claw_attr_group, | ||
3268 | NULL, | ||
3269 | }; | ||
3270 | static const struct device_type claw_devtype = { | ||
3271 | .name = "claw", | ||
3272 | .groups = claw_attr_groups, | ||
3273 | }; | ||
3274 | 3340 | ||
3275 | /*----------------------------------------------------------------* | 3341 | static int |
3276 | * claw_probe * | 3342 | claw_add_files(struct device *dev) |
3277 | * this function is called for each CLAW device. * | ||
3278 | *----------------------------------------------------------------*/ | ||
3279 | static int claw_probe(struct ccwgroup_device *cgdev) | ||
3280 | { | 3343 | { |
3281 | struct claw_privbk *privptr = NULL; | 3344 | CLAW_DBF_TEXT(2, setup, "add_file"); |
3282 | 3345 | return sysfs_create_group(&dev->kobj, &claw_attr_group); | |
3283 | CLAW_DBF_TEXT(2, setup, "probe"); | 3346 | } |
3284 | if (!get_device(&cgdev->dev)) | ||
3285 | return -ENODEV; | ||
3286 | privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL); | ||
3287 | dev_set_drvdata(&cgdev->dev, privptr); | ||
3288 | if (privptr == NULL) { | ||
3289 | probe_error(cgdev); | ||
3290 | put_device(&cgdev->dev); | ||
3291 | CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM); | ||
3292 | return -ENOMEM; | ||
3293 | } | ||
3294 | privptr->p_mtc_envelope = kzalloc(MAX_ENVELOPE_SIZE, GFP_KERNEL); | ||
3295 | privptr->p_env = kzalloc(sizeof(struct claw_env), GFP_KERNEL); | ||
3296 | if ((privptr->p_mtc_envelope == NULL) || (privptr->p_env == NULL)) { | ||
3297 | probe_error(cgdev); | ||
3298 | put_device(&cgdev->dev); | ||
3299 | CLAW_DBF_TEXT_(2, setup, "probex%d", -ENOMEM); | ||
3300 | return -ENOMEM; | ||
3301 | } | ||
3302 | memcpy(privptr->p_env->adapter_name, WS_NAME_NOT_DEF, 8); | ||
3303 | memcpy(privptr->p_env->host_name, WS_NAME_NOT_DEF, 8); | ||
3304 | memcpy(privptr->p_env->api_type, WS_NAME_NOT_DEF, 8); | ||
3305 | privptr->p_env->packing = 0; | ||
3306 | privptr->p_env->write_buffers = 5; | ||
3307 | privptr->p_env->read_buffers = 5; | ||
3308 | privptr->p_env->read_size = CLAW_FRAME_SIZE; | ||
3309 | privptr->p_env->write_size = CLAW_FRAME_SIZE; | ||
3310 | privptr->p_env->p_priv = privptr; | ||
3311 | cgdev->cdev[0]->handler = claw_irq_handler; | ||
3312 | cgdev->cdev[1]->handler = claw_irq_handler; | ||
3313 | cgdev->dev.type = &claw_devtype; | ||
3314 | CLAW_DBF_TEXT(2, setup, "prbext 0"); | ||
3315 | 3347 | ||
3316 | return 0; | 3348 | static void |
3317 | } /* end of claw_probe */ | 3349 | claw_remove_files(struct device *dev) |
3350 | { | ||
3351 | CLAW_DBF_TEXT(2, setup, "rem_file"); | ||
3352 | sysfs_remove_group(&dev->kobj, &claw_attr_group); | ||
3353 | } | ||
3318 | 3354 | ||
3319 | /*--------------------------------------------------------------------* | 3355 | /*--------------------------------------------------------------------* |
3320 | * claw_init and cleanup * | 3356 | * claw_init and cleanup * |
3321 | *---------------------------------------------------------------------*/ | 3357 | *---------------------------------------------------------------------*/ |
3322 | 3358 | ||
3323 | static void __exit claw_cleanup(void) | 3359 | static void __exit |
3360 | claw_cleanup(void) | ||
3324 | { | 3361 | { |
3362 | driver_remove_file(&claw_group_driver.driver, | ||
3363 | &driver_attr_group); | ||
3325 | ccwgroup_driver_unregister(&claw_group_driver); | 3364 | ccwgroup_driver_unregister(&claw_group_driver); |
3326 | ccw_driver_unregister(&claw_ccw_driver); | 3365 | ccw_driver_unregister(&claw_ccw_driver); |
3327 | root_device_unregister(claw_root_dev); | 3366 | root_device_unregister(claw_root_dev); |
3328 | claw_unregister_debug_facility(); | 3367 | claw_unregister_debug_facility(); |
3329 | pr_info("Driver unloaded\n"); | 3368 | pr_info("Driver unloaded\n"); |
3369 | |||
3330 | } | 3370 | } |
3331 | 3371 | ||
3332 | /** | 3372 | /** |
@@ -3335,7 +3375,8 @@ static void __exit claw_cleanup(void) | |||
3335 | * | 3375 | * |
3336 | * @return 0 on success, !0 on error. | 3376 | * @return 0 on success, !0 on error. |
3337 | */ | 3377 | */ |
3338 | static int __init claw_init(void) | 3378 | static int __init |
3379 | claw_init(void) | ||
3339 | { | 3380 | { |
3340 | int ret = 0; | 3381 | int ret = 0; |
3341 | 3382 | ||
@@ -3354,7 +3395,7 @@ static int __init claw_init(void) | |||
3354 | ret = ccw_driver_register(&claw_ccw_driver); | 3395 | ret = ccw_driver_register(&claw_ccw_driver); |
3355 | if (ret) | 3396 | if (ret) |
3356 | goto ccw_err; | 3397 | goto ccw_err; |
3357 | claw_group_driver.driver.groups = claw_drv_attr_groups; | 3398 | claw_group_driver.driver.groups = claw_group_attr_groups; |
3358 | ret = ccwgroup_driver_register(&claw_group_driver); | 3399 | ret = ccwgroup_driver_register(&claw_group_driver); |
3359 | if (ret) | 3400 | if (ret) |
3360 | goto ccwgroup_err; | 3401 | goto ccwgroup_err; |
@@ -3377,5 +3418,5 @@ module_exit(claw_cleanup); | |||
3377 | 3418 | ||
3378 | MODULE_AUTHOR("Andy Richter <richtera@us.ibm.com>"); | 3419 | MODULE_AUTHOR("Andy Richter <richtera@us.ibm.com>"); |
3379 | MODULE_DESCRIPTION("Linux for System z CLAW Driver\n" \ | 3420 | MODULE_DESCRIPTION("Linux for System z CLAW Driver\n" \ |
3380 | "Copyright IBM Corp. 2000, 2008\n"); | 3421 | "Copyright 2000,2008 IBM Corporation\n"); |
3381 | MODULE_LICENSE("GPL"); | 3422 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/s390/net/ctcm_dbug.c b/drivers/s390/net/ctcm_dbug.c index 6514e1cb3f1..d962fd741a2 100644 --- a/drivers/s390/net/ctcm_dbug.c +++ b/drivers/s390/net/ctcm_dbug.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/ctcm_dbug.c | ||
3 | * | ||
2 | * Copyright IBM Corp. 2001, 2007 | 4 | * Copyright IBM Corp. 2001, 2007 |
3 | * Authors: Peter Tiedemann (ptiedem@de.ibm.com) | 5 | * Authors: Peter Tiedemann (ptiedem@de.ibm.com) |
4 | * | 6 | * |
diff --git a/drivers/s390/net/ctcm_dbug.h b/drivers/s390/net/ctcm_dbug.h index 47bf0501995..26966d0b9ab 100644 --- a/drivers/s390/net/ctcm_dbug.h +++ b/drivers/s390/net/ctcm_dbug.h | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/ctcm_dbug.h | ||
3 | * | ||
2 | * Copyright IBM Corp. 2001, 2007 | 4 | * Copyright IBM Corp. 2001, 2007 |
3 | * Authors: Peter Tiedemann (ptiedem@de.ibm.com) | 5 | * Authors: Peter Tiedemann (ptiedem@de.ibm.com) |
4 | * | 6 | * |
diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c index fb92524d24e..2d602207541 100644 --- a/drivers/s390/net/ctcm_fsms.c +++ b/drivers/s390/net/ctcm_fsms.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/ctcm_fsms.c | ||
3 | * | ||
2 | * Copyright IBM Corp. 2001, 2007 | 4 | * Copyright IBM Corp. 2001, 2007 |
3 | * Authors: Fritz Elfert (felfert@millenux.com) | 5 | * Authors: Fritz Elfert (felfert@millenux.com) |
4 | * Peter Tiedemann (ptiedem@de.ibm.com) | 6 | * Peter Tiedemann (ptiedem@de.ibm.com) |
@@ -1339,12 +1341,6 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg) | |||
1339 | 1341 | ||
1340 | spin_unlock(&ch->collect_lock); | 1342 | spin_unlock(&ch->collect_lock); |
1341 | clear_normalized_cda(&ch->ccw[1]); | 1343 | clear_normalized_cda(&ch->ccw[1]); |
1342 | |||
1343 | CTCM_PR_DBGDATA("ccwcda=0x%p data=0x%p\n", | ||
1344 | (void *)(unsigned long)ch->ccw[1].cda, | ||
1345 | ch->trans_skb->data); | ||
1346 | ch->ccw[1].count = ch->max_bufsize; | ||
1347 | |||
1348 | if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) { | 1344 | if (set_normalized_cda(&ch->ccw[1], ch->trans_skb->data)) { |
1349 | dev_kfree_skb_any(ch->trans_skb); | 1345 | dev_kfree_skb_any(ch->trans_skb); |
1350 | ch->trans_skb = NULL; | 1346 | ch->trans_skb = NULL; |
@@ -1354,11 +1350,6 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg) | |||
1354 | fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev); | 1350 | fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev); |
1355 | return; | 1351 | return; |
1356 | } | 1352 | } |
1357 | |||
1358 | CTCM_PR_DBGDATA("ccwcda=0x%p data=0x%p\n", | ||
1359 | (void *)(unsigned long)ch->ccw[1].cda, | ||
1360 | ch->trans_skb->data); | ||
1361 | |||
1362 | ch->ccw[1].count = ch->trans_skb->len; | 1353 | ch->ccw[1].count = ch->trans_skb->len; |
1363 | fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch); | 1354 | fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch); |
1364 | ch->prof.send_stamp = current_kernel_time(); /* xtime */ | 1355 | ch->prof.send_stamp = current_kernel_time(); /* xtime */ |
@@ -1523,7 +1514,7 @@ static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg) | |||
1523 | goto done; | 1514 | goto done; |
1524 | default: | 1515 | default: |
1525 | break; | 1516 | break; |
1526 | } | 1517 | }; |
1527 | 1518 | ||
1528 | fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) | 1519 | fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == CTCM_READ) |
1529 | ? CTC_STATE_RXINIT : CTC_STATE_TXINIT); | 1520 | ? CTC_STATE_RXINIT : CTC_STATE_TXINIT); |
diff --git a/drivers/s390/net/ctcm_fsms.h b/drivers/s390/net/ctcm_fsms.h index c963d04799c..046d077fabb 100644 --- a/drivers/s390/net/ctcm_fsms.h +++ b/drivers/s390/net/ctcm_fsms.h | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/ctcm_fsms.h | ||
3 | * | ||
2 | * Copyright IBM Corp. 2001, 2007 | 4 | * Copyright IBM Corp. 2001, 2007 |
3 | * Authors: Fritz Elfert (felfert@millenux.com) | 5 | * Authors: Fritz Elfert (felfert@millenux.com) |
4 | * Peter Tiedemann (ptiedem@de.ibm.com) | 6 | * Peter Tiedemann (ptiedem@de.ibm.com) |
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 676f12049a3..426787efc49 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/ctcm_main.c | ||
3 | * | ||
2 | * Copyright IBM Corp. 2001, 2009 | 4 | * Copyright IBM Corp. 2001, 2009 |
3 | * Author(s): | 5 | * Author(s): |
4 | * Original CTC driver(s): | 6 | * Original CTC driver(s): |
@@ -22,6 +24,7 @@ | |||
22 | #define KMSG_COMPONENT "ctcm" | 24 | #define KMSG_COMPONENT "ctcm" |
23 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 25 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
24 | 26 | ||
27 | #include <linux/kernel_stat.h> | ||
25 | #include <linux/module.h> | 28 | #include <linux/module.h> |
26 | #include <linux/init.h> | 29 | #include <linux/init.h> |
27 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
@@ -560,9 +563,6 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
560 | skb_queue_tail(&ch->io_queue, skb); | 563 | skb_queue_tail(&ch->io_queue, skb); |
561 | ccw_idx = 3; | 564 | ccw_idx = 3; |
562 | } | 565 | } |
563 | if (do_debug_ccw) | ||
564 | ctcmpc_dumpit((char *)&ch->ccw[ccw_idx], | ||
565 | sizeof(struct ccw1) * 3); | ||
566 | ch->retry = 0; | 566 | ch->retry = 0; |
567 | fsm_newstate(ch->fsm, CTC_STATE_TX); | 567 | fsm_newstate(ch->fsm, CTC_STATE_TX); |
568 | fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch); | 568 | fsm_addtimer(&ch->timer, CTCM_TIME_5_SEC, CTC_EVENT_TIMER, ch); |
@@ -1203,6 +1203,7 @@ static void ctcm_irq_handler(struct ccw_device *cdev, | |||
1203 | int cstat; | 1203 | int cstat; |
1204 | int dstat; | 1204 | int dstat; |
1205 | 1205 | ||
1206 | kstat_cpu(smp_processor_id()).irqs[IOINT_CTC]++; | ||
1206 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, | 1207 | CTCM_DBF_TEXT_(TRACE, CTC_DBF_DEBUG, |
1207 | "Enter %s(%s)", CTCM_FUNTAIL, dev_name(&cdev->dev)); | 1208 | "Enter %s(%s)", CTCM_FUNTAIL, dev_name(&cdev->dev)); |
1208 | 1209 | ||
@@ -1294,11 +1295,6 @@ static void ctcm_irq_handler(struct ccw_device *cdev, | |||
1294 | 1295 | ||
1295 | } | 1296 | } |
1296 | 1297 | ||
1297 | static const struct device_type ctcm_devtype = { | ||
1298 | .name = "ctcm", | ||
1299 | .groups = ctcm_attr_groups, | ||
1300 | }; | ||
1301 | |||
1302 | /** | 1298 | /** |
1303 | * Add ctcm specific attributes. | 1299 | * Add ctcm specific attributes. |
1304 | * Add ctcm private data. | 1300 | * Add ctcm private data. |
@@ -1310,6 +1306,7 @@ static const struct device_type ctcm_devtype = { | |||
1310 | static int ctcm_probe_device(struct ccwgroup_device *cgdev) | 1306 | static int ctcm_probe_device(struct ccwgroup_device *cgdev) |
1311 | { | 1307 | { |
1312 | struct ctcm_priv *priv; | 1308 | struct ctcm_priv *priv; |
1309 | int rc; | ||
1313 | 1310 | ||
1314 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, | 1311 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, |
1315 | "%s %p", | 1312 | "%s %p", |
@@ -1326,11 +1323,17 @@ static int ctcm_probe_device(struct ccwgroup_device *cgdev) | |||
1326 | put_device(&cgdev->dev); | 1323 | put_device(&cgdev->dev); |
1327 | return -ENOMEM; | 1324 | return -ENOMEM; |
1328 | } | 1325 | } |
1326 | |||
1327 | rc = ctcm_add_files(&cgdev->dev); | ||
1328 | if (rc) { | ||
1329 | kfree(priv); | ||
1330 | put_device(&cgdev->dev); | ||
1331 | return rc; | ||
1332 | } | ||
1329 | priv->buffer_size = CTCM_BUFSIZE_DEFAULT; | 1333 | priv->buffer_size = CTCM_BUFSIZE_DEFAULT; |
1330 | cgdev->cdev[0]->handler = ctcm_irq_handler; | 1334 | cgdev->cdev[0]->handler = ctcm_irq_handler; |
1331 | cgdev->cdev[1]->handler = ctcm_irq_handler; | 1335 | cgdev->cdev[1]->handler = ctcm_irq_handler; |
1332 | dev_set_drvdata(&cgdev->dev, priv); | 1336 | dev_set_drvdata(&cgdev->dev, priv); |
1333 | cgdev->dev.type = &ctcm_devtype; | ||
1334 | 1337 | ||
1335 | return 0; | 1338 | return 0; |
1336 | } | 1339 | } |
@@ -1454,7 +1457,7 @@ static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type, | |||
1454 | ch_fsm_len, GFP_KERNEL); | 1457 | ch_fsm_len, GFP_KERNEL); |
1455 | } | 1458 | } |
1456 | if (ch->fsm == NULL) | 1459 | if (ch->fsm == NULL) |
1457 | goto nomem_return; | 1460 | goto free_return; |
1458 | 1461 | ||
1459 | fsm_newstate(ch->fsm, CTC_STATE_IDLE); | 1462 | fsm_newstate(ch->fsm, CTC_STATE_IDLE); |
1460 | 1463 | ||
@@ -1607,6 +1610,11 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1607 | goto out_dev; | 1610 | goto out_dev; |
1608 | } | 1611 | } |
1609 | 1612 | ||
1613 | if (ctcm_add_attributes(&cgdev->dev)) { | ||
1614 | result = -ENODEV; | ||
1615 | goto out_unregister; | ||
1616 | } | ||
1617 | |||
1610 | strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name)); | 1618 | strlcpy(priv->fsm->name, dev->name, sizeof(priv->fsm->name)); |
1611 | 1619 | ||
1612 | dev_info(&dev->dev, | 1620 | dev_info(&dev->dev, |
@@ -1620,6 +1628,8 @@ static int ctcm_new_device(struct ccwgroup_device *cgdev) | |||
1620 | priv->channel[CTCM_WRITE]->id, priv->protocol); | 1628 | priv->channel[CTCM_WRITE]->id, priv->protocol); |
1621 | 1629 | ||
1622 | return 0; | 1630 | return 0; |
1631 | out_unregister: | ||
1632 | unregister_netdev(dev); | ||
1623 | out_dev: | 1633 | out_dev: |
1624 | ctcm_free_netdevice(dev); | 1634 | ctcm_free_netdevice(dev); |
1625 | out_ccw2: | 1635 | out_ccw2: |
@@ -1658,6 +1668,7 @@ static int ctcm_shutdown_device(struct ccwgroup_device *cgdev) | |||
1658 | /* Close the device */ | 1668 | /* Close the device */ |
1659 | ctcm_close(dev); | 1669 | ctcm_close(dev); |
1660 | dev->flags &= ~IFF_RUNNING; | 1670 | dev->flags &= ~IFF_RUNNING; |
1671 | ctcm_remove_attributes(&cgdev->dev); | ||
1661 | channel_free(priv->channel[CTCM_READ]); | 1672 | channel_free(priv->channel[CTCM_READ]); |
1662 | } else | 1673 | } else |
1663 | dev = NULL; | 1674 | dev = NULL; |
@@ -1691,12 +1702,15 @@ static void ctcm_remove_device(struct ccwgroup_device *cgdev) | |||
1691 | { | 1702 | { |
1692 | struct ctcm_priv *priv = dev_get_drvdata(&cgdev->dev); | 1703 | struct ctcm_priv *priv = dev_get_drvdata(&cgdev->dev); |
1693 | 1704 | ||
1705 | BUG_ON(priv == NULL); | ||
1706 | |||
1694 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, | 1707 | CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, |
1695 | "removing device %p, proto : %d", | 1708 | "removing device %p, proto : %d", |
1696 | cgdev, priv->protocol); | 1709 | cgdev, priv->protocol); |
1697 | 1710 | ||
1698 | if (cgdev->state == CCWGROUP_ONLINE) | 1711 | if (cgdev->state == CCWGROUP_ONLINE) |
1699 | ctcm_shutdown_device(cgdev); | 1712 | ctcm_shutdown_device(cgdev); |
1713 | ctcm_remove_files(&cgdev->dev); | ||
1700 | dev_set_drvdata(&cgdev->dev, NULL); | 1714 | dev_set_drvdata(&cgdev->dev, NULL); |
1701 | kfree(priv); | 1715 | kfree(priv); |
1702 | put_device(&cgdev->dev); | 1716 | put_device(&cgdev->dev); |
@@ -1755,7 +1769,6 @@ static struct ccw_driver ctcm_ccw_driver = { | |||
1755 | .ids = ctcm_ids, | 1769 | .ids = ctcm_ids, |
1756 | .probe = ccwgroup_probe_ccwdev, | 1770 | .probe = ccwgroup_probe_ccwdev, |
1757 | .remove = ccwgroup_remove_ccwdev, | 1771 | .remove = ccwgroup_remove_ccwdev, |
1758 | .int_class = IRQIO_CTC, | ||
1759 | }; | 1772 | }; |
1760 | 1773 | ||
1761 | static struct ccwgroup_driver ctcm_group_driver = { | 1774 | static struct ccwgroup_driver ctcm_group_driver = { |
@@ -1763,7 +1776,9 @@ static struct ccwgroup_driver ctcm_group_driver = { | |||
1763 | .owner = THIS_MODULE, | 1776 | .owner = THIS_MODULE, |
1764 | .name = CTC_DRIVER_NAME, | 1777 | .name = CTC_DRIVER_NAME, |
1765 | }, | 1778 | }, |
1766 | .setup = ctcm_probe_device, | 1779 | .max_slaves = 2, |
1780 | .driver_id = 0xC3E3C3D4, /* CTCM */ | ||
1781 | .probe = ctcm_probe_device, | ||
1767 | .remove = ctcm_remove_device, | 1782 | .remove = ctcm_remove_device, |
1768 | .set_online = ctcm_new_device, | 1783 | .set_online = ctcm_new_device, |
1769 | .set_offline = ctcm_shutdown_device, | 1784 | .set_offline = ctcm_shutdown_device, |
@@ -1772,25 +1787,31 @@ static struct ccwgroup_driver ctcm_group_driver = { | |||
1772 | .restore = ctcm_pm_resume, | 1787 | .restore = ctcm_pm_resume, |
1773 | }; | 1788 | }; |
1774 | 1789 | ||
1775 | static ssize_t ctcm_driver_group_store(struct device_driver *ddrv, | 1790 | static ssize_t |
1776 | const char *buf, size_t count) | 1791 | ctcm_driver_group_store(struct device_driver *ddrv, const char *buf, |
1792 | size_t count) | ||
1777 | { | 1793 | { |
1778 | int err; | 1794 | int err; |
1779 | 1795 | ||
1780 | err = ccwgroup_create_dev(ctcm_root_dev, &ctcm_group_driver, 2, buf); | 1796 | err = ccwgroup_create_from_string(ctcm_root_dev, |
1797 | ctcm_group_driver.driver_id, | ||
1798 | &ctcm_ccw_driver, 2, buf); | ||
1781 | return err ? err : count; | 1799 | return err ? err : count; |
1782 | } | 1800 | } |
1801 | |||
1783 | static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store); | 1802 | static DRIVER_ATTR(group, 0200, NULL, ctcm_driver_group_store); |
1784 | 1803 | ||
1785 | static struct attribute *ctcm_drv_attrs[] = { | 1804 | static struct attribute *ctcm_group_attrs[] = { |
1786 | &driver_attr_group.attr, | 1805 | &driver_attr_group.attr, |
1787 | NULL, | 1806 | NULL, |
1788 | }; | 1807 | }; |
1789 | static struct attribute_group ctcm_drv_attr_group = { | 1808 | |
1790 | .attrs = ctcm_drv_attrs, | 1809 | static struct attribute_group ctcm_group_attr_group = { |
1810 | .attrs = ctcm_group_attrs, | ||
1791 | }; | 1811 | }; |
1792 | static const struct attribute_group *ctcm_drv_attr_groups[] = { | 1812 | |
1793 | &ctcm_drv_attr_group, | 1813 | static const struct attribute_group *ctcm_group_attr_groups[] = { |
1814 | &ctcm_group_attr_group, | ||
1794 | NULL, | 1815 | NULL, |
1795 | }; | 1816 | }; |
1796 | 1817 | ||
@@ -1806,6 +1827,7 @@ static const struct attribute_group *ctcm_drv_attr_groups[] = { | |||
1806 | */ | 1827 | */ |
1807 | static void __exit ctcm_exit(void) | 1828 | static void __exit ctcm_exit(void) |
1808 | { | 1829 | { |
1830 | driver_remove_file(&ctcm_group_driver.driver, &driver_attr_group); | ||
1809 | ccwgroup_driver_unregister(&ctcm_group_driver); | 1831 | ccwgroup_driver_unregister(&ctcm_group_driver); |
1810 | ccw_driver_unregister(&ctcm_ccw_driver); | 1832 | ccw_driver_unregister(&ctcm_ccw_driver); |
1811 | root_device_unregister(ctcm_root_dev); | 1833 | root_device_unregister(ctcm_root_dev); |
@@ -1843,7 +1865,7 @@ static int __init ctcm_init(void) | |||
1843 | ret = ccw_driver_register(&ctcm_ccw_driver); | 1865 | ret = ccw_driver_register(&ctcm_ccw_driver); |
1844 | if (ret) | 1866 | if (ret) |
1845 | goto ccw_err; | 1867 | goto ccw_err; |
1846 | ctcm_group_driver.driver.groups = ctcm_drv_attr_groups; | 1868 | ctcm_group_driver.driver.groups = ctcm_group_attr_groups; |
1847 | ret = ccwgroup_driver_register(&ctcm_group_driver); | 1869 | ret = ccwgroup_driver_register(&ctcm_group_driver); |
1848 | if (ret) | 1870 | if (ret) |
1849 | goto ccwgroup_err; | 1871 | goto ccwgroup_err; |
diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h index 477c933685f..24d5215eb0c 100644 --- a/drivers/s390/net/ctcm_main.h +++ b/drivers/s390/net/ctcm_main.h | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/ctcm_main.h | ||
3 | * | ||
2 | * Copyright IBM Corp. 2001, 2007 | 4 | * Copyright IBM Corp. 2001, 2007 |
3 | * Authors: Fritz Elfert (felfert@millenux.com) | 5 | * Authors: Fritz Elfert (felfert@millenux.com) |
4 | * Peter Tiedemann (ptiedem@de.ibm.com) | 6 | * Peter Tiedemann (ptiedem@de.ibm.com) |
@@ -223,7 +225,13 @@ struct ctcm_priv { | |||
223 | int ctcm_open(struct net_device *dev); | 225 | int ctcm_open(struct net_device *dev); |
224 | int ctcm_close(struct net_device *dev); | 226 | int ctcm_close(struct net_device *dev); |
225 | 227 | ||
226 | extern const struct attribute_group *ctcm_attr_groups[]; | 228 | /* |
229 | * prototypes for non-static sysfs functions | ||
230 | */ | ||
231 | int ctcm_add_attributes(struct device *dev); | ||
232 | void ctcm_remove_attributes(struct device *dev); | ||
233 | int ctcm_add_files(struct device *dev); | ||
234 | void ctcm_remove_files(struct device *dev); | ||
227 | 235 | ||
228 | /* | 236 | /* |
229 | * Compatibility macros for busy handling | 237 | * Compatibility macros for busy handling |
diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index 2dbc77b5137..da4c747335e 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/ctcm_mpc.c | ||
3 | * | ||
2 | * Copyright IBM Corp. 2004, 2007 | 4 | * Copyright IBM Corp. 2004, 2007 |
3 | * Authors: Belinda Thompson (belindat@us.ibm.com) | 5 | * Authors: Belinda Thompson (belindat@us.ibm.com) |
4 | * Andy Richter (richtera@us.ibm.com) | 6 | * Andy Richter (richtera@us.ibm.com) |
@@ -51,8 +53,8 @@ | |||
51 | #include <linux/moduleparam.h> | 53 | #include <linux/moduleparam.h> |
52 | #include <asm/idals.h> | 54 | #include <asm/idals.h> |
53 | 55 | ||
54 | #include "ctcm_main.h" | ||
55 | #include "ctcm_mpc.h" | 56 | #include "ctcm_mpc.h" |
57 | #include "ctcm_main.h" | ||
56 | #include "ctcm_fsms.h" | 58 | #include "ctcm_fsms.h" |
57 | 59 | ||
58 | static const struct xid2 init_xid = { | 60 | static const struct xid2 init_xid = { |
@@ -130,7 +132,7 @@ void ctcmpc_dumpit(char *buf, int len) | |||
130 | __u32 ct, sw, rm, dup; | 132 | __u32 ct, sw, rm, dup; |
131 | char *ptr, *rptr; | 133 | char *ptr, *rptr; |
132 | char tbuf[82], tdup[82]; | 134 | char tbuf[82], tdup[82]; |
133 | #ifdef CONFIG_64BIT | 135 | #if (UTS_MACHINE == s390x) |
134 | char addr[22]; | 136 | char addr[22]; |
135 | #else | 137 | #else |
136 | char addr[12]; | 138 | char addr[12]; |
@@ -147,8 +149,8 @@ void ctcmpc_dumpit(char *buf, int len) | |||
147 | 149 | ||
148 | for (ct = 0; ct < len; ct++, ptr++, rptr++) { | 150 | for (ct = 0; ct < len; ct++, ptr++, rptr++) { |
149 | if (sw == 0) { | 151 | if (sw == 0) { |
150 | #ifdef CONFIG_64BIT | 152 | #if (UTS_MACHINE == s390x) |
151 | sprintf(addr, "%16.16llx", (__u64)rptr); | 153 | sprintf(addr, "%16.16lx", (__u64)rptr); |
152 | #else | 154 | #else |
153 | sprintf(addr, "%8.8X", (__u32)rptr); | 155 | sprintf(addr, "%8.8X", (__u32)rptr); |
154 | #endif | 156 | #endif |
@@ -162,8 +164,8 @@ void ctcmpc_dumpit(char *buf, int len) | |||
162 | if (sw == 8) | 164 | if (sw == 8) |
163 | strcat(bhex, " "); | 165 | strcat(bhex, " "); |
164 | 166 | ||
165 | #if CONFIG_64BIT | 167 | #if (UTS_MACHINE == s390x) |
166 | sprintf(tbuf, "%2.2llX", (__u64)*ptr); | 168 | sprintf(tbuf, "%2.2lX", (__u64)*ptr); |
167 | #else | 169 | #else |
168 | sprintf(tbuf, "%2.2X", (__u32)*ptr); | 170 | sprintf(tbuf, "%2.2X", (__u32)*ptr); |
169 | #endif | 171 | #endif |
@@ -1367,6 +1369,7 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg) | |||
1367 | struct mpc_group *grp; | 1369 | struct mpc_group *grp; |
1368 | struct channel *wch; | 1370 | struct channel *wch; |
1369 | 1371 | ||
1372 | BUG_ON(dev == NULL); | ||
1370 | CTCM_PR_DEBUG("Enter %s: %s\n", __func__, dev->name); | 1373 | CTCM_PR_DEBUG("Enter %s: %s\n", __func__, dev->name); |
1371 | 1374 | ||
1372 | priv = dev->ml_priv; | 1375 | priv = dev->ml_priv; |
@@ -1471,6 +1474,8 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg) | |||
1471 | struct channel *wch; | 1474 | struct channel *wch; |
1472 | struct channel *rch; | 1475 | struct channel *rch; |
1473 | 1476 | ||
1477 | BUG_ON(dev == NULL); | ||
1478 | |||
1474 | priv = dev->ml_priv; | 1479 | priv = dev->ml_priv; |
1475 | grp = priv->mpcg; | 1480 | grp = priv->mpcg; |
1476 | wch = priv->channel[CTCM_WRITE]; | 1481 | wch = priv->channel[CTCM_WRITE]; |
diff --git a/drivers/s390/net/ctcm_mpc.h b/drivers/s390/net/ctcm_mpc.h index bd1b1cc54ff..1fa07b0c11c 100644 --- a/drivers/s390/net/ctcm_mpc.h +++ b/drivers/s390/net/ctcm_mpc.h | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/ctcm_mpc.h | ||
3 | * | ||
2 | * Copyright IBM Corp. 2007 | 4 | * Copyright IBM Corp. 2007 |
3 | * Authors: Peter Tiedemann (ptiedem@de.ibm.com) | 5 | * Authors: Peter Tiedemann (ptiedem@de.ibm.com) |
4 | * | 6 | * |
diff --git a/drivers/s390/net/ctcm_sysfs.c b/drivers/s390/net/ctcm_sysfs.c index 985b5dcbdac..8305319b2a8 100644 --- a/drivers/s390/net/ctcm_sysfs.c +++ b/drivers/s390/net/ctcm_sysfs.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/ctcm_sysfs.c | ||
3 | * | ||
2 | * Copyright IBM Corp. 2007, 2007 | 4 | * Copyright IBM Corp. 2007, 2007 |
3 | * Authors: Peter Tiedemann (ptiedem@de.ibm.com) | 5 | * Authors: Peter Tiedemann (ptiedem@de.ibm.com) |
4 | * | 6 | * |
@@ -11,7 +13,6 @@ | |||
11 | #define KMSG_COMPONENT "ctcm" | 13 | #define KMSG_COMPONENT "ctcm" |
12 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 14 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
13 | 15 | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/sysfs.h> | 16 | #include <linux/sysfs.h> |
16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
17 | #include "ctcm_main.h" | 18 | #include "ctcm_main.h" |
@@ -107,12 +108,10 @@ static void ctcm_print_statistics(struct ctcm_priv *priv) | |||
107 | } | 108 | } |
108 | 109 | ||
109 | static ssize_t stats_show(struct device *dev, | 110 | static ssize_t stats_show(struct device *dev, |
110 | struct device_attribute *attr, char *buf) | 111 | struct device_attribute *attr, char *buf) |
111 | { | 112 | { |
112 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | ||
113 | struct ctcm_priv *priv = dev_get_drvdata(dev); | 113 | struct ctcm_priv *priv = dev_get_drvdata(dev); |
114 | 114 | if (!priv) | |
115 | if (!priv || gdev->state != CCWGROUP_ONLINE) | ||
116 | return -ENODEV; | 115 | return -ENODEV; |
117 | ctcm_print_statistics(priv); | 116 | ctcm_print_statistics(priv); |
118 | return sprintf(buf, "0\n"); | 117 | return sprintf(buf, "0\n"); |
@@ -160,7 +159,7 @@ static ssize_t ctcm_proto_store(struct device *dev, | |||
160 | return count; | 159 | return count; |
161 | } | 160 | } |
162 | 161 | ||
163 | static const char *ctcm_type[] = { | 162 | const char *ctcm_type[] = { |
164 | "not a channel", | 163 | "not a channel", |
165 | "CTC/A", | 164 | "CTC/A", |
166 | "FICON channel", | 165 | "FICON channel", |
@@ -191,14 +190,34 @@ static struct attribute *ctcm_attr[] = { | |||
191 | &dev_attr_protocol.attr, | 190 | &dev_attr_protocol.attr, |
192 | &dev_attr_type.attr, | 191 | &dev_attr_type.attr, |
193 | &dev_attr_buffer.attr, | 192 | &dev_attr_buffer.attr, |
194 | &dev_attr_stats.attr, | ||
195 | NULL, | 193 | NULL, |
196 | }; | 194 | }; |
197 | 195 | ||
198 | static struct attribute_group ctcm_attr_group = { | 196 | static struct attribute_group ctcm_attr_group = { |
199 | .attrs = ctcm_attr, | 197 | .attrs = ctcm_attr, |
200 | }; | 198 | }; |
201 | const struct attribute_group *ctcm_attr_groups[] = { | 199 | |
202 | &ctcm_attr_group, | 200 | int ctcm_add_attributes(struct device *dev) |
203 | NULL, | 201 | { |
204 | }; | 202 | int rc; |
203 | |||
204 | rc = device_create_file(dev, &dev_attr_stats); | ||
205 | |||
206 | return rc; | ||
207 | } | ||
208 | |||
209 | void ctcm_remove_attributes(struct device *dev) | ||
210 | { | ||
211 | device_remove_file(dev, &dev_attr_stats); | ||
212 | } | ||
213 | |||
214 | int ctcm_add_files(struct device *dev) | ||
215 | { | ||
216 | return sysfs_create_group(&dev->kobj, &ctcm_attr_group); | ||
217 | } | ||
218 | |||
219 | void ctcm_remove_files(struct device *dev) | ||
220 | { | ||
221 | sysfs_remove_group(&dev->kobj, &ctcm_attr_group); | ||
222 | } | ||
223 | |||
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index c645dc9e98a..c3b8064a102 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
@@ -26,10 +26,12 @@ | |||
26 | #define KMSG_COMPONENT "lcs" | 26 | #define KMSG_COMPONENT "lcs" |
27 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 27 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
28 | 28 | ||
29 | #include <linux/kernel_stat.h> | ||
29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
30 | #include <linux/if.h> | 31 | #include <linux/if.h> |
31 | #include <linux/netdevice.h> | 32 | #include <linux/netdevice.h> |
32 | #include <linux/etherdevice.h> | 33 | #include <linux/etherdevice.h> |
34 | #include <linux/trdevice.h> | ||
33 | #include <linux/fddidevice.h> | 35 | #include <linux/fddidevice.h> |
34 | #include <linux/inetdevice.h> | 36 | #include <linux/inetdevice.h> |
35 | #include <linux/in.h> | 37 | #include <linux/in.h> |
@@ -49,7 +51,8 @@ | |||
49 | #include "lcs.h" | 51 | #include "lcs.h" |
50 | 52 | ||
51 | 53 | ||
52 | #if !defined(CONFIG_ETHERNET) && !defined(CONFIG_FDDI) | 54 | #if !defined(CONFIG_NET_ETHERNET) && \ |
55 | !defined(CONFIG_TR) && !defined(CONFIG_FDDI) | ||
53 | #error Cannot compile lcs.c without some net devices switched on. | 56 | #error Cannot compile lcs.c without some net devices switched on. |
54 | #endif | 57 | #endif |
55 | 58 | ||
@@ -282,7 +285,7 @@ lcs_setup_write_ccws(struct lcs_card *card) | |||
282 | 285 | ||
283 | LCS_DBF_TEXT(3, setup, "iwritccw"); | 286 | LCS_DBF_TEXT(3, setup, "iwritccw"); |
284 | /* Setup write ccws. */ | 287 | /* Setup write ccws. */ |
285 | memset(card->write.ccws, 0, sizeof(struct ccw1) * (LCS_NUM_BUFFS + 1)); | 288 | memset(card->write.ccws, 0, sizeof(struct ccw1) * LCS_NUM_BUFFS + 1); |
286 | for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) { | 289 | for (cnt = 0; cnt < LCS_NUM_BUFFS; cnt++) { |
287 | card->write.ccws[cnt].cmd_code = LCS_CCW_WRITE; | 290 | card->write.ccws[cnt].cmd_code = LCS_CCW_WRITE; |
288 | card->write.ccws[cnt].count = 0; | 291 | card->write.ccws[cnt].count = 0; |
@@ -1164,7 +1167,10 @@ static void | |||
1164 | lcs_get_mac_for_ipm(__be32 ipm, char *mac, struct net_device *dev) | 1167 | lcs_get_mac_for_ipm(__be32 ipm, char *mac, struct net_device *dev) |
1165 | { | 1168 | { |
1166 | LCS_DBF_TEXT(4,trace, "getmac"); | 1169 | LCS_DBF_TEXT(4,trace, "getmac"); |
1167 | ip_eth_mc_map(ipm, mac); | 1170 | if (dev->type == ARPHRD_IEEE802_TR) |
1171 | ip_tr_mc_map(ipm, mac); | ||
1172 | else | ||
1173 | ip_eth_mc_map(ipm, mac); | ||
1168 | } | 1174 | } |
1169 | 1175 | ||
1170 | /** | 1176 | /** |
@@ -1393,6 +1399,7 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1393 | int rc, index; | 1399 | int rc, index; |
1394 | int cstat, dstat; | 1400 | int cstat, dstat; |
1395 | 1401 | ||
1402 | kstat_cpu(smp_processor_id()).irqs[IOINT_LCS]++; | ||
1396 | if (lcs_check_irb_error(cdev, irb)) | 1403 | if (lcs_check_irb_error(cdev, irb)) |
1397 | return; | 1404 | return; |
1398 | 1405 | ||
@@ -1629,13 +1636,19 @@ lcs_startlan_auto(struct lcs_card *card) | |||
1629 | int rc; | 1636 | int rc; |
1630 | 1637 | ||
1631 | LCS_DBF_TEXT(2, trace, "strtauto"); | 1638 | LCS_DBF_TEXT(2, trace, "strtauto"); |
1632 | #ifdef CONFIG_ETHERNET | 1639 | #ifdef CONFIG_NET_ETHERNET |
1633 | card->lan_type = LCS_FRAME_TYPE_ENET; | 1640 | card->lan_type = LCS_FRAME_TYPE_ENET; |
1634 | rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP); | 1641 | rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP); |
1635 | if (rc == 0) | 1642 | if (rc == 0) |
1636 | return 0; | 1643 | return 0; |
1637 | 1644 | ||
1638 | #endif | 1645 | #endif |
1646 | #ifdef CONFIG_TR | ||
1647 | card->lan_type = LCS_FRAME_TYPE_TR; | ||
1648 | rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP); | ||
1649 | if (rc == 0) | ||
1650 | return 0; | ||
1651 | #endif | ||
1639 | #ifdef CONFIG_FDDI | 1652 | #ifdef CONFIG_FDDI |
1640 | card->lan_type = LCS_FRAME_TYPE_FDDI; | 1653 | card->lan_type = LCS_FRAME_TYPE_FDDI; |
1641 | rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP); | 1654 | rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP); |
@@ -1959,7 +1972,7 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char | |||
1959 | 1972 | ||
1960 | static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store); | 1973 | static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store); |
1961 | 1974 | ||
1962 | static const char *lcs_type[] = { | 1975 | const char *lcs_type[] = { |
1963 | "not a channel", | 1976 | "not a channel", |
1964 | "2216 parallel", | 1977 | "2216 parallel", |
1965 | "2216 channel", | 1978 | "2216 channel", |
@@ -2040,17 +2053,10 @@ static struct attribute * lcs_attrs[] = { | |||
2040 | &dev_attr_recover.attr, | 2053 | &dev_attr_recover.attr, |
2041 | NULL, | 2054 | NULL, |
2042 | }; | 2055 | }; |
2056 | |||
2043 | static struct attribute_group lcs_attr_group = { | 2057 | static struct attribute_group lcs_attr_group = { |
2044 | .attrs = lcs_attrs, | 2058 | .attrs = lcs_attrs, |
2045 | }; | 2059 | }; |
2046 | static const struct attribute_group *lcs_attr_groups[] = { | ||
2047 | &lcs_attr_group, | ||
2048 | NULL, | ||
2049 | }; | ||
2050 | static const struct device_type lcs_devtype = { | ||
2051 | .name = "lcs", | ||
2052 | .groups = lcs_attr_groups, | ||
2053 | }; | ||
2054 | 2060 | ||
2055 | /** | 2061 | /** |
2056 | * lcs_probe_device is called on establishing a new ccwgroup_device. | 2062 | * lcs_probe_device is called on establishing a new ccwgroup_device. |
@@ -2059,6 +2065,7 @@ static int | |||
2059 | lcs_probe_device(struct ccwgroup_device *ccwgdev) | 2065 | lcs_probe_device(struct ccwgroup_device *ccwgdev) |
2060 | { | 2066 | { |
2061 | struct lcs_card *card; | 2067 | struct lcs_card *card; |
2068 | int ret; | ||
2062 | 2069 | ||
2063 | if (!get_device(&ccwgdev->dev)) | 2070 | if (!get_device(&ccwgdev->dev)) |
2064 | return -ENODEV; | 2071 | return -ENODEV; |
@@ -2070,6 +2077,12 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev) | |||
2070 | put_device(&ccwgdev->dev); | 2077 | put_device(&ccwgdev->dev); |
2071 | return -ENOMEM; | 2078 | return -ENOMEM; |
2072 | } | 2079 | } |
2080 | ret = sysfs_create_group(&ccwgdev->dev.kobj, &lcs_attr_group); | ||
2081 | if (ret) { | ||
2082 | lcs_free_card(card); | ||
2083 | put_device(&ccwgdev->dev); | ||
2084 | return ret; | ||
2085 | } | ||
2073 | dev_set_drvdata(&ccwgdev->dev, card); | 2086 | dev_set_drvdata(&ccwgdev->dev, card); |
2074 | ccwgdev->cdev[0]->handler = lcs_irq; | 2087 | ccwgdev->cdev[0]->handler = lcs_irq; |
2075 | ccwgdev->cdev[1]->handler = lcs_irq; | 2088 | ccwgdev->cdev[1]->handler = lcs_irq; |
@@ -2078,9 +2091,7 @@ lcs_probe_device(struct ccwgroup_device *ccwgdev) | |||
2078 | card->thread_start_mask = 0; | 2091 | card->thread_start_mask = 0; |
2079 | card->thread_allowed_mask = 0; | 2092 | card->thread_allowed_mask = 0; |
2080 | card->thread_running_mask = 0; | 2093 | card->thread_running_mask = 0; |
2081 | ccwgdev->dev.type = &lcs_devtype; | 2094 | return 0; |
2082 | |||
2083 | return 0; | ||
2084 | } | 2095 | } |
2085 | 2096 | ||
2086 | static int | 2097 | static int |
@@ -2111,7 +2122,7 @@ static const struct net_device_ops lcs_mc_netdev_ops = { | |||
2111 | .ndo_stop = lcs_stop_device, | 2122 | .ndo_stop = lcs_stop_device, |
2112 | .ndo_get_stats = lcs_getstats, | 2123 | .ndo_get_stats = lcs_getstats, |
2113 | .ndo_start_xmit = lcs_start_xmit, | 2124 | .ndo_start_xmit = lcs_start_xmit, |
2114 | .ndo_set_rx_mode = lcs_set_multicast_list, | 2125 | .ndo_set_multicast_list = lcs_set_multicast_list, |
2115 | }; | 2126 | }; |
2116 | 2127 | ||
2117 | static int | 2128 | static int |
@@ -2157,12 +2168,18 @@ lcs_new_device(struct ccwgroup_device *ccwgdev) | |||
2157 | goto netdev_out; | 2168 | goto netdev_out; |
2158 | } | 2169 | } |
2159 | switch (card->lan_type) { | 2170 | switch (card->lan_type) { |
2160 | #ifdef CONFIG_ETHERNET | 2171 | #ifdef CONFIG_NET_ETHERNET |
2161 | case LCS_FRAME_TYPE_ENET: | 2172 | case LCS_FRAME_TYPE_ENET: |
2162 | card->lan_type_trans = eth_type_trans; | 2173 | card->lan_type_trans = eth_type_trans; |
2163 | dev = alloc_etherdev(0); | 2174 | dev = alloc_etherdev(0); |
2164 | break; | 2175 | break; |
2165 | #endif | 2176 | #endif |
2177 | #ifdef CONFIG_TR | ||
2178 | case LCS_FRAME_TYPE_TR: | ||
2179 | card->lan_type_trans = tr_type_trans; | ||
2180 | dev = alloc_trdev(0); | ||
2181 | break; | ||
2182 | #endif | ||
2166 | #ifdef CONFIG_FDDI | 2183 | #ifdef CONFIG_FDDI |
2167 | case LCS_FRAME_TYPE_FDDI: | 2184 | case LCS_FRAME_TYPE_FDDI: |
2168 | card->lan_type_trans = fddi_type_trans; | 2185 | card->lan_type_trans = fddi_type_trans; |
@@ -2225,7 +2242,7 @@ __lcs_shutdown_device(struct ccwgroup_device *ccwgdev, int recovery_mode) | |||
2225 | { | 2242 | { |
2226 | struct lcs_card *card; | 2243 | struct lcs_card *card; |
2227 | enum lcs_dev_states recover_state; | 2244 | enum lcs_dev_states recover_state; |
2228 | int ret = 0, ret2 = 0, ret3 = 0; | 2245 | int ret; |
2229 | 2246 | ||
2230 | LCS_DBF_TEXT(3, setup, "shtdndev"); | 2247 | LCS_DBF_TEXT(3, setup, "shtdndev"); |
2231 | card = dev_get_drvdata(&ccwgdev->dev); | 2248 | card = dev_get_drvdata(&ccwgdev->dev); |
@@ -2240,15 +2257,13 @@ __lcs_shutdown_device(struct ccwgroup_device *ccwgdev, int recovery_mode) | |||
2240 | recover_state = card->state; | 2257 | recover_state = card->state; |
2241 | 2258 | ||
2242 | ret = lcs_stop_device(card->dev); | 2259 | ret = lcs_stop_device(card->dev); |
2243 | ret2 = ccw_device_set_offline(card->read.ccwdev); | 2260 | ret = ccw_device_set_offline(card->read.ccwdev); |
2244 | ret3 = ccw_device_set_offline(card->write.ccwdev); | 2261 | ret = ccw_device_set_offline(card->write.ccwdev); |
2245 | if (!ret) | ||
2246 | ret = (ret2) ? ret2 : ret3; | ||
2247 | if (ret) | ||
2248 | LCS_DBF_TEXT_(3, setup, "1err:%d", ret); | ||
2249 | if (recover_state == DEV_STATE_UP) { | 2262 | if (recover_state == DEV_STATE_UP) { |
2250 | card->state = DEV_STATE_RECOVER; | 2263 | card->state = DEV_STATE_RECOVER; |
2251 | } | 2264 | } |
2265 | if (ret) | ||
2266 | return ret; | ||
2252 | return 0; | 2267 | return 0; |
2253 | } | 2268 | } |
2254 | 2269 | ||
@@ -2308,9 +2323,9 @@ lcs_remove_device(struct ccwgroup_device *ccwgdev) | |||
2308 | } | 2323 | } |
2309 | if (card->dev) | 2324 | if (card->dev) |
2310 | unregister_netdev(card->dev); | 2325 | unregister_netdev(card->dev); |
2326 | sysfs_remove_group(&ccwgdev->dev.kobj, &lcs_attr_group); | ||
2311 | lcs_cleanup_card(card); | 2327 | lcs_cleanup_card(card); |
2312 | lcs_free_card(card); | 2328 | lcs_free_card(card); |
2313 | dev_set_drvdata(&ccwgdev->dev, NULL); | ||
2314 | put_device(&ccwgdev->dev); | 2329 | put_device(&ccwgdev->dev); |
2315 | } | 2330 | } |
2316 | 2331 | ||
@@ -2384,7 +2399,6 @@ static struct ccw_driver lcs_ccw_driver = { | |||
2384 | .ids = lcs_ids, | 2399 | .ids = lcs_ids, |
2385 | .probe = ccwgroup_probe_ccwdev, | 2400 | .probe = ccwgroup_probe_ccwdev, |
2386 | .remove = ccwgroup_remove_ccwdev, | 2401 | .remove = ccwgroup_remove_ccwdev, |
2387 | .int_class = IRQIO_LCS, | ||
2388 | }; | 2402 | }; |
2389 | 2403 | ||
2390 | /** | 2404 | /** |
@@ -2395,7 +2409,9 @@ static struct ccwgroup_driver lcs_group_driver = { | |||
2395 | .owner = THIS_MODULE, | 2409 | .owner = THIS_MODULE, |
2396 | .name = "lcs", | 2410 | .name = "lcs", |
2397 | }, | 2411 | }, |
2398 | .setup = lcs_probe_device, | 2412 | .max_slaves = 2, |
2413 | .driver_id = 0xD3C3E2, | ||
2414 | .probe = lcs_probe_device, | ||
2399 | .remove = lcs_remove_device, | 2415 | .remove = lcs_remove_device, |
2400 | .set_online = lcs_new_device, | 2416 | .set_online = lcs_new_device, |
2401 | .set_offline = lcs_shutdown_device, | 2417 | .set_offline = lcs_shutdown_device, |
@@ -2406,24 +2422,30 @@ static struct ccwgroup_driver lcs_group_driver = { | |||
2406 | .restore = lcs_restore, | 2422 | .restore = lcs_restore, |
2407 | }; | 2423 | }; |
2408 | 2424 | ||
2409 | static ssize_t lcs_driver_group_store(struct device_driver *ddrv, | 2425 | static ssize_t |
2410 | const char *buf, size_t count) | 2426 | lcs_driver_group_store(struct device_driver *ddrv, const char *buf, |
2427 | size_t count) | ||
2411 | { | 2428 | { |
2412 | int err; | 2429 | int err; |
2413 | err = ccwgroup_create_dev(lcs_root_dev, &lcs_group_driver, 2, buf); | 2430 | err = ccwgroup_create_from_string(lcs_root_dev, |
2431 | lcs_group_driver.driver_id, | ||
2432 | &lcs_ccw_driver, 2, buf); | ||
2414 | return err ? err : count; | 2433 | return err ? err : count; |
2415 | } | 2434 | } |
2435 | |||
2416 | static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store); | 2436 | static DRIVER_ATTR(group, 0200, NULL, lcs_driver_group_store); |
2417 | 2437 | ||
2418 | static struct attribute *lcs_drv_attrs[] = { | 2438 | static struct attribute *lcs_group_attrs[] = { |
2419 | &driver_attr_group.attr, | 2439 | &driver_attr_group.attr, |
2420 | NULL, | 2440 | NULL, |
2421 | }; | 2441 | }; |
2422 | static struct attribute_group lcs_drv_attr_group = { | 2442 | |
2423 | .attrs = lcs_drv_attrs, | 2443 | static struct attribute_group lcs_group_attr_group = { |
2444 | .attrs = lcs_group_attrs, | ||
2424 | }; | 2445 | }; |
2425 | static const struct attribute_group *lcs_drv_attr_groups[] = { | 2446 | |
2426 | &lcs_drv_attr_group, | 2447 | static const struct attribute_group *lcs_group_attr_groups[] = { |
2448 | &lcs_group_attr_group, | ||
2427 | NULL, | 2449 | NULL, |
2428 | }; | 2450 | }; |
2429 | 2451 | ||
@@ -2447,7 +2469,7 @@ __init lcs_init_module(void) | |||
2447 | rc = ccw_driver_register(&lcs_ccw_driver); | 2469 | rc = ccw_driver_register(&lcs_ccw_driver); |
2448 | if (rc) | 2470 | if (rc) |
2449 | goto ccw_err; | 2471 | goto ccw_err; |
2450 | lcs_group_driver.driver.groups = lcs_drv_attr_groups; | 2472 | lcs_group_driver.driver.groups = lcs_group_attr_groups; |
2451 | rc = ccwgroup_driver_register(&lcs_group_driver); | 2473 | rc = ccwgroup_driver_register(&lcs_group_driver); |
2452 | if (rc) | 2474 | if (rc) |
2453 | goto ccwgroup_err; | 2475 | goto ccwgroup_err; |
@@ -2473,6 +2495,8 @@ __exit lcs_cleanup_module(void) | |||
2473 | { | 2495 | { |
2474 | pr_info("Terminating lcs module.\n"); | 2496 | pr_info("Terminating lcs module.\n"); |
2475 | LCS_DBF_TEXT(0, trace, "cleanup"); | 2497 | LCS_DBF_TEXT(0, trace, "cleanup"); |
2498 | driver_remove_file(&lcs_group_driver.driver, | ||
2499 | &driver_attr_group); | ||
2476 | ccwgroup_driver_unregister(&lcs_group_driver); | 2500 | ccwgroup_driver_unregister(&lcs_group_driver); |
2477 | ccw_driver_unregister(&lcs_ccw_driver); | 2501 | ccw_driver_unregister(&lcs_ccw_driver); |
2478 | root_device_unregister(lcs_root_dev); | 2502 | root_device_unregister(lcs_root_dev); |
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 4ffa66c87ea..3251333a23d 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c | |||
@@ -63,7 +63,6 @@ | |||
63 | 63 | ||
64 | #include <asm/io.h> | 64 | #include <asm/io.h> |
65 | #include <asm/uaccess.h> | 65 | #include <asm/uaccess.h> |
66 | #include <asm/ebcdic.h> | ||
67 | 66 | ||
68 | #include <net/iucv/iucv.h> | 67 | #include <net/iucv/iucv.h> |
69 | #include "fsm.h" | 68 | #include "fsm.h" |
@@ -76,7 +75,7 @@ MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver"); | |||
76 | * Debug Facility stuff | 75 | * Debug Facility stuff |
77 | */ | 76 | */ |
78 | #define IUCV_DBF_SETUP_NAME "iucv_setup" | 77 | #define IUCV_DBF_SETUP_NAME "iucv_setup" |
79 | #define IUCV_DBF_SETUP_LEN 64 | 78 | #define IUCV_DBF_SETUP_LEN 32 |
80 | #define IUCV_DBF_SETUP_PAGES 2 | 79 | #define IUCV_DBF_SETUP_PAGES 2 |
81 | #define IUCV_DBF_SETUP_NR_AREAS 1 | 80 | #define IUCV_DBF_SETUP_NR_AREAS 1 |
82 | #define IUCV_DBF_SETUP_LEVEL 3 | 81 | #define IUCV_DBF_SETUP_LEVEL 3 |
@@ -227,7 +226,6 @@ struct iucv_connection { | |||
227 | struct net_device *netdev; | 226 | struct net_device *netdev; |
228 | struct connection_profile prof; | 227 | struct connection_profile prof; |
229 | char userid[9]; | 228 | char userid[9]; |
230 | char userdata[17]; | ||
231 | }; | 229 | }; |
232 | 230 | ||
233 | /** | 231 | /** |
@@ -265,7 +263,7 @@ struct ll_header { | |||
265 | }; | 263 | }; |
266 | 264 | ||
267 | #define NETIUCV_HDRLEN (sizeof(struct ll_header)) | 265 | #define NETIUCV_HDRLEN (sizeof(struct ll_header)) |
268 | #define NETIUCV_BUFSIZE_MAX 65537 | 266 | #define NETIUCV_BUFSIZE_MAX 32768 |
269 | #define NETIUCV_BUFSIZE_DEFAULT NETIUCV_BUFSIZE_MAX | 267 | #define NETIUCV_BUFSIZE_DEFAULT NETIUCV_BUFSIZE_MAX |
270 | #define NETIUCV_MTU_MAX (NETIUCV_BUFSIZE_MAX - NETIUCV_HDRLEN) | 268 | #define NETIUCV_MTU_MAX (NETIUCV_BUFSIZE_MAX - NETIUCV_HDRLEN) |
271 | #define NETIUCV_MTU_DEFAULT 9216 | 269 | #define NETIUCV_MTU_DEFAULT 9216 |
@@ -290,12 +288,7 @@ static inline int netiucv_test_and_set_busy(struct net_device *dev) | |||
290 | return test_and_set_bit(0, &priv->tbusy); | 288 | return test_and_set_bit(0, &priv->tbusy); |
291 | } | 289 | } |
292 | 290 | ||
293 | static u8 iucvMagic_ascii[16] = { | 291 | static u8 iucvMagic[16] = { |
294 | 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
295 | 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 | ||
296 | }; | ||
297 | |||
298 | static u8 iucvMagic_ebcdic[16] = { | ||
299 | 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, | 292 | 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, |
300 | 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 | 293 | 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 |
301 | }; | 294 | }; |
@@ -308,38 +301,18 @@ static u8 iucvMagic_ebcdic[16] = { | |||
308 | * | 301 | * |
309 | * @returns The printable string (static data!!) | 302 | * @returns The printable string (static data!!) |
310 | */ | 303 | */ |
311 | static char *netiucv_printname(char *name, int len) | 304 | static char *netiucv_printname(char *name) |
312 | { | 305 | { |
313 | static char tmp[17]; | 306 | static char tmp[9]; |
314 | char *p = tmp; | 307 | char *p = tmp; |
315 | memcpy(tmp, name, len); | 308 | memcpy(tmp, name, 8); |
316 | tmp[len] = '\0'; | 309 | tmp[8] = '\0'; |
317 | while (*p && ((p - tmp) < len) && (!isspace(*p))) | 310 | while (*p && (!isspace(*p))) |
318 | p++; | 311 | p++; |
319 | *p = '\0'; | 312 | *p = '\0'; |
320 | return tmp; | 313 | return tmp; |
321 | } | 314 | } |
322 | 315 | ||
323 | static char *netiucv_printuser(struct iucv_connection *conn) | ||
324 | { | ||
325 | static char tmp_uid[9]; | ||
326 | static char tmp_udat[17]; | ||
327 | static char buf[100]; | ||
328 | |||
329 | if (memcmp(conn->userdata, iucvMagic_ebcdic, 16)) { | ||
330 | tmp_uid[8] = '\0'; | ||
331 | tmp_udat[16] = '\0'; | ||
332 | memcpy(tmp_uid, conn->userid, 8); | ||
333 | memcpy(tmp_uid, netiucv_printname(tmp_uid, 8), 8); | ||
334 | memcpy(tmp_udat, conn->userdata, 16); | ||
335 | EBCASC(tmp_udat, 16); | ||
336 | memcpy(tmp_udat, netiucv_printname(tmp_udat, 16), 16); | ||
337 | sprintf(buf, "%s.%s", tmp_uid, tmp_udat); | ||
338 | return buf; | ||
339 | } else | ||
340 | return netiucv_printname(conn->userid, 8); | ||
341 | } | ||
342 | |||
343 | /** | 316 | /** |
344 | * States of the interface statemachine. | 317 | * States of the interface statemachine. |
345 | */ | 318 | */ |
@@ -590,18 +563,15 @@ static int netiucv_callback_connreq(struct iucv_path *path, | |||
590 | { | 563 | { |
591 | struct iucv_connection *conn = path->private; | 564 | struct iucv_connection *conn = path->private; |
592 | struct iucv_event ev; | 565 | struct iucv_event ev; |
593 | static char tmp_user[9]; | ||
594 | static char tmp_udat[17]; | ||
595 | int rc; | 566 | int rc; |
596 | 567 | ||
568 | if (memcmp(iucvMagic, ipuser, 16)) | ||
569 | /* ipuser must match iucvMagic. */ | ||
570 | return -EINVAL; | ||
597 | rc = -EINVAL; | 571 | rc = -EINVAL; |
598 | memcpy(tmp_user, netiucv_printname(ipvmid, 8), 8); | ||
599 | memcpy(tmp_udat, ipuser, 16); | ||
600 | EBCASC(tmp_udat, 16); | ||
601 | read_lock_bh(&iucv_connection_rwlock); | 572 | read_lock_bh(&iucv_connection_rwlock); |
602 | list_for_each_entry(conn, &iucv_connection_list, list) { | 573 | list_for_each_entry(conn, &iucv_connection_list, list) { |
603 | if (strncmp(ipvmid, conn->userid, 8) || | 574 | if (strncmp(ipvmid, conn->userid, 8)) |
604 | strncmp(ipuser, conn->userdata, 16)) | ||
605 | continue; | 575 | continue; |
606 | /* Found a matching connection for this path. */ | 576 | /* Found a matching connection for this path. */ |
607 | conn->path = path; | 577 | conn->path = path; |
@@ -610,8 +580,6 @@ static int netiucv_callback_connreq(struct iucv_path *path, | |||
610 | fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev); | 580 | fsm_event(conn->fsm, CONN_EVENT_CONN_REQ, &ev); |
611 | rc = 0; | 581 | rc = 0; |
612 | } | 582 | } |
613 | IUCV_DBF_TEXT_(setup, 2, "Connection requested for %s.%s\n", | ||
614 | tmp_user, netiucv_printname(tmp_udat, 16)); | ||
615 | read_unlock_bh(&iucv_connection_rwlock); | 583 | read_unlock_bh(&iucv_connection_rwlock); |
616 | return rc; | 584 | return rc; |
617 | } | 585 | } |
@@ -848,7 +816,7 @@ static void conn_action_connaccept(fsm_instance *fi, int event, void *arg) | |||
848 | conn->path = path; | 816 | conn->path = path; |
849 | path->msglim = NETIUCV_QUEUELEN_DEFAULT; | 817 | path->msglim = NETIUCV_QUEUELEN_DEFAULT; |
850 | path->flags = 0; | 818 | path->flags = 0; |
851 | rc = iucv_path_accept(path, &netiucv_handler, conn->userdata , conn); | 819 | rc = iucv_path_accept(path, &netiucv_handler, NULL, conn); |
852 | if (rc) { | 820 | if (rc) { |
853 | IUCV_DBF_TEXT_(setup, 2, "rc %d from iucv_accept", rc); | 821 | IUCV_DBF_TEXT_(setup, 2, "rc %d from iucv_accept", rc); |
854 | return; | 822 | return; |
@@ -886,7 +854,7 @@ static void conn_action_conntimsev(fsm_instance *fi, int event, void *arg) | |||
886 | 854 | ||
887 | IUCV_DBF_TEXT(trace, 3, __func__); | 855 | IUCV_DBF_TEXT(trace, 3, __func__); |
888 | fsm_deltimer(&conn->timer); | 856 | fsm_deltimer(&conn->timer); |
889 | iucv_path_sever(conn->path, conn->userdata); | 857 | iucv_path_sever(conn->path, NULL); |
890 | fsm_newstate(fi, CONN_STATE_STARTWAIT); | 858 | fsm_newstate(fi, CONN_STATE_STARTWAIT); |
891 | } | 859 | } |
892 | 860 | ||
@@ -899,9 +867,9 @@ static void conn_action_connsever(fsm_instance *fi, int event, void *arg) | |||
899 | IUCV_DBF_TEXT(trace, 3, __func__); | 867 | IUCV_DBF_TEXT(trace, 3, __func__); |
900 | 868 | ||
901 | fsm_deltimer(&conn->timer); | 869 | fsm_deltimer(&conn->timer); |
902 | iucv_path_sever(conn->path, conn->userdata); | 870 | iucv_path_sever(conn->path, NULL); |
903 | dev_info(privptr->dev, "The peer z/VM guest %s has closed the " | 871 | dev_info(privptr->dev, "The peer interface of the IUCV device" |
904 | "connection\n", netiucv_printuser(conn)); | 872 | " has closed the connection\n"); |
905 | IUCV_DBF_TEXT(data, 2, | 873 | IUCV_DBF_TEXT(data, 2, |
906 | "conn_action_connsever: Remote dropped connection\n"); | 874 | "conn_action_connsever: Remote dropped connection\n"); |
907 | fsm_newstate(fi, CONN_STATE_STARTWAIT); | 875 | fsm_newstate(fi, CONN_STATE_STARTWAIT); |
@@ -918,6 +886,8 @@ static void conn_action_start(fsm_instance *fi, int event, void *arg) | |||
918 | IUCV_DBF_TEXT(trace, 3, __func__); | 886 | IUCV_DBF_TEXT(trace, 3, __func__); |
919 | 887 | ||
920 | fsm_newstate(fi, CONN_STATE_STARTWAIT); | 888 | fsm_newstate(fi, CONN_STATE_STARTWAIT); |
889 | IUCV_DBF_TEXT_(setup, 2, "%s('%s'): connecting ...\n", | ||
890 | netdev->name, conn->userid); | ||
921 | 891 | ||
922 | /* | 892 | /* |
923 | * We must set the state before calling iucv_connect because the | 893 | * We must set the state before calling iucv_connect because the |
@@ -927,11 +897,8 @@ static void conn_action_start(fsm_instance *fi, int event, void *arg) | |||
927 | 897 | ||
928 | fsm_newstate(fi, CONN_STATE_SETUPWAIT); | 898 | fsm_newstate(fi, CONN_STATE_SETUPWAIT); |
929 | conn->path = iucv_path_alloc(NETIUCV_QUEUELEN_DEFAULT, 0, GFP_KERNEL); | 899 | conn->path = iucv_path_alloc(NETIUCV_QUEUELEN_DEFAULT, 0, GFP_KERNEL); |
930 | IUCV_DBF_TEXT_(setup, 2, "%s: connecting to %s ...\n", | ||
931 | netdev->name, netiucv_printuser(conn)); | ||
932 | |||
933 | rc = iucv_path_connect(conn->path, &netiucv_handler, conn->userid, | 900 | rc = iucv_path_connect(conn->path, &netiucv_handler, conn->userid, |
934 | NULL, conn->userdata, conn); | 901 | NULL, iucvMagic, conn); |
935 | switch (rc) { | 902 | switch (rc) { |
936 | case 0: | 903 | case 0: |
937 | netdev->tx_queue_len = conn->path->msglim; | 904 | netdev->tx_queue_len = conn->path->msglim; |
@@ -941,13 +908,13 @@ static void conn_action_start(fsm_instance *fi, int event, void *arg) | |||
941 | case 11: | 908 | case 11: |
942 | dev_warn(privptr->dev, | 909 | dev_warn(privptr->dev, |
943 | "The IUCV device failed to connect to z/VM guest %s\n", | 910 | "The IUCV device failed to connect to z/VM guest %s\n", |
944 | netiucv_printname(conn->userid, 8)); | 911 | netiucv_printname(conn->userid)); |
945 | fsm_newstate(fi, CONN_STATE_STARTWAIT); | 912 | fsm_newstate(fi, CONN_STATE_STARTWAIT); |
946 | break; | 913 | break; |
947 | case 12: | 914 | case 12: |
948 | dev_warn(privptr->dev, | 915 | dev_warn(privptr->dev, |
949 | "The IUCV device failed to connect to the peer on z/VM" | 916 | "The IUCV device failed to connect to the peer on z/VM" |
950 | " guest %s\n", netiucv_printname(conn->userid, 8)); | 917 | " guest %s\n", netiucv_printname(conn->userid)); |
951 | fsm_newstate(fi, CONN_STATE_STARTWAIT); | 918 | fsm_newstate(fi, CONN_STATE_STARTWAIT); |
952 | break; | 919 | break; |
953 | case 13: | 920 | case 13: |
@@ -960,7 +927,7 @@ static void conn_action_start(fsm_instance *fi, int event, void *arg) | |||
960 | dev_err(privptr->dev, | 927 | dev_err(privptr->dev, |
961 | "z/VM guest %s has too many IUCV connections" | 928 | "z/VM guest %s has too many IUCV connections" |
962 | " to connect with the IUCV device\n", | 929 | " to connect with the IUCV device\n", |
963 | netiucv_printname(conn->userid, 8)); | 930 | netiucv_printname(conn->userid)); |
964 | fsm_newstate(fi, CONN_STATE_CONNERR); | 931 | fsm_newstate(fi, CONN_STATE_CONNERR); |
965 | break; | 932 | break; |
966 | case 15: | 933 | case 15: |
@@ -1005,7 +972,7 @@ static void conn_action_stop(fsm_instance *fi, int event, void *arg) | |||
1005 | netiucv_purge_skb_queue(&conn->collect_queue); | 972 | netiucv_purge_skb_queue(&conn->collect_queue); |
1006 | if (conn->path) { | 973 | if (conn->path) { |
1007 | IUCV_DBF_TEXT(trace, 5, "calling iucv_path_sever\n"); | 974 | IUCV_DBF_TEXT(trace, 5, "calling iucv_path_sever\n"); |
1008 | iucv_path_sever(conn->path, conn->userdata); | 975 | iucv_path_sever(conn->path, iucvMagic); |
1009 | kfree(conn->path); | 976 | kfree(conn->path); |
1010 | conn->path = NULL; | 977 | conn->path = NULL; |
1011 | } | 978 | } |
@@ -1123,8 +1090,7 @@ dev_action_connup(fsm_instance *fi, int event, void *arg) | |||
1123 | fsm_newstate(fi, DEV_STATE_RUNNING); | 1090 | fsm_newstate(fi, DEV_STATE_RUNNING); |
1124 | dev_info(privptr->dev, | 1091 | dev_info(privptr->dev, |
1125 | "The IUCV device has been connected" | 1092 | "The IUCV device has been connected" |
1126 | " successfully to %s\n", | 1093 | " successfully to %s\n", privptr->conn->userid); |
1127 | netiucv_printuser(privptr->conn)); | ||
1128 | IUCV_DBF_TEXT(setup, 3, | 1094 | IUCV_DBF_TEXT(setup, 3, |
1129 | "connection is up and running\n"); | 1095 | "connection is up and running\n"); |
1130 | break; | 1096 | break; |
@@ -1486,72 +1452,45 @@ static ssize_t user_show(struct device *dev, struct device_attribute *attr, | |||
1486 | struct netiucv_priv *priv = dev_get_drvdata(dev); | 1452 | struct netiucv_priv *priv = dev_get_drvdata(dev); |
1487 | 1453 | ||
1488 | IUCV_DBF_TEXT(trace, 5, __func__); | 1454 | IUCV_DBF_TEXT(trace, 5, __func__); |
1489 | return sprintf(buf, "%s\n", netiucv_printuser(priv->conn)); | 1455 | return sprintf(buf, "%s\n", netiucv_printname(priv->conn->userid)); |
1490 | } | 1456 | } |
1491 | 1457 | ||
1492 | static int netiucv_check_user(const char *buf, size_t count, char *username, | 1458 | static ssize_t user_write(struct device *dev, struct device_attribute *attr, |
1493 | char *userdata) | 1459 | const char *buf, size_t count) |
1494 | { | 1460 | { |
1495 | const char *p; | 1461 | struct netiucv_priv *priv = dev_get_drvdata(dev); |
1496 | int i; | 1462 | struct net_device *ndev = priv->conn->netdev; |
1463 | char *p; | ||
1464 | char *tmp; | ||
1465 | char username[9]; | ||
1466 | int i; | ||
1467 | struct iucv_connection *cp; | ||
1497 | 1468 | ||
1498 | p = strchr(buf, '.'); | 1469 | IUCV_DBF_TEXT(trace, 3, __func__); |
1499 | if ((p && ((count > 26) || | 1470 | if (count > 9) { |
1500 | ((p - buf) > 8) || | 1471 | IUCV_DBF_TEXT_(setup, 2, |
1501 | (buf + count - p > 18))) || | 1472 | "%d is length of username\n", (int) count); |
1502 | (!p && (count > 9))) { | ||
1503 | IUCV_DBF_TEXT(setup, 2, "conn_write: too long\n"); | ||
1504 | return -EINVAL; | 1473 | return -EINVAL; |
1505 | } | 1474 | } |
1506 | 1475 | ||
1507 | for (i = 0, p = buf; i < 8 && *p && *p != '.'; i++, p++) { | 1476 | tmp = strsep((char **) &buf, "\n"); |
1508 | if (isalnum(*p) || *p == '$') { | 1477 | for (i = 0, p = tmp; i < 8 && *p; i++, p++) { |
1509 | username[i] = toupper(*p); | 1478 | if (isalnum(*p) || (*p == '$')) { |
1479 | username[i]= toupper(*p); | ||
1510 | continue; | 1480 | continue; |
1511 | } | 1481 | } |
1512 | if (*p == '\n') | 1482 | if (*p == '\n') { |
1513 | /* trailing lf, grr */ | 1483 | /* trailing lf, grr */ |
1514 | break; | 1484 | break; |
1485 | } | ||
1515 | IUCV_DBF_TEXT_(setup, 2, | 1486 | IUCV_DBF_TEXT_(setup, 2, |
1516 | "conn_write: invalid character %02x\n", *p); | 1487 | "username: invalid character %c\n", *p); |
1517 | return -EINVAL; | 1488 | return -EINVAL; |
1518 | } | 1489 | } |
1519 | while (i < 8) | 1490 | while (i < 8) |
1520 | username[i++] = ' '; | 1491 | username[i++] = ' '; |
1521 | username[8] = '\0'; | 1492 | username[8] = '\0'; |
1522 | 1493 | ||
1523 | if (*p == '.') { | ||
1524 | p++; | ||
1525 | for (i = 0; i < 16 && *p; i++, p++) { | ||
1526 | if (*p == '\n') | ||
1527 | break; | ||
1528 | userdata[i] = toupper(*p); | ||
1529 | } | ||
1530 | while (i > 0 && i < 16) | ||
1531 | userdata[i++] = ' '; | ||
1532 | } else | ||
1533 | memcpy(userdata, iucvMagic_ascii, 16); | ||
1534 | userdata[16] = '\0'; | ||
1535 | ASCEBC(userdata, 16); | ||
1536 | |||
1537 | return 0; | ||
1538 | } | ||
1539 | |||
1540 | static ssize_t user_write(struct device *dev, struct device_attribute *attr, | ||
1541 | const char *buf, size_t count) | ||
1542 | { | ||
1543 | struct netiucv_priv *priv = dev_get_drvdata(dev); | ||
1544 | struct net_device *ndev = priv->conn->netdev; | ||
1545 | char username[9]; | ||
1546 | char userdata[17]; | ||
1547 | int rc; | ||
1548 | struct iucv_connection *cp; | ||
1549 | |||
1550 | IUCV_DBF_TEXT(trace, 3, __func__); | ||
1551 | rc = netiucv_check_user(buf, count, username, userdata); | ||
1552 | if (rc) | ||
1553 | return rc; | ||
1554 | |||
1555 | if (memcmp(username, priv->conn->userid, 9) && | 1494 | if (memcmp(username, priv->conn->userid, 9) && |
1556 | (ndev->flags & (IFF_UP | IFF_RUNNING))) { | 1495 | (ndev->flags & (IFF_UP | IFF_RUNNING))) { |
1557 | /* username changed while the interface is active. */ | 1496 | /* username changed while the interface is active. */ |
@@ -1560,17 +1499,15 @@ static ssize_t user_write(struct device *dev, struct device_attribute *attr, | |||
1560 | } | 1499 | } |
1561 | read_lock_bh(&iucv_connection_rwlock); | 1500 | read_lock_bh(&iucv_connection_rwlock); |
1562 | list_for_each_entry(cp, &iucv_connection_list, list) { | 1501 | list_for_each_entry(cp, &iucv_connection_list, list) { |
1563 | if (!strncmp(username, cp->userid, 9) && | 1502 | if (!strncmp(username, cp->userid, 9) && cp->netdev != ndev) { |
1564 | !strncmp(userdata, cp->userdata, 17) && cp->netdev != ndev) { | ||
1565 | read_unlock_bh(&iucv_connection_rwlock); | 1503 | read_unlock_bh(&iucv_connection_rwlock); |
1566 | IUCV_DBF_TEXT_(setup, 2, "user_write: Connection to %s " | 1504 | IUCV_DBF_TEXT_(setup, 2, "user_write: Connection " |
1567 | "already exists\n", netiucv_printuser(cp)); | 1505 | "to %s already exists\n", username); |
1568 | return -EEXIST; | 1506 | return -EEXIST; |
1569 | } | 1507 | } |
1570 | } | 1508 | } |
1571 | read_unlock_bh(&iucv_connection_rwlock); | 1509 | read_unlock_bh(&iucv_connection_rwlock); |
1572 | memcpy(priv->conn->userid, username, 9); | 1510 | memcpy(priv->conn->userid, username, 9); |
1573 | memcpy(priv->conn->userdata, userdata, 17); | ||
1574 | return count; | 1511 | return count; |
1575 | } | 1512 | } |
1576 | 1513 | ||
@@ -1600,8 +1537,7 @@ static ssize_t buffer_write (struct device *dev, struct device_attribute *attr, | |||
1600 | bs1 = simple_strtoul(buf, &e, 0); | 1537 | bs1 = simple_strtoul(buf, &e, 0); |
1601 | 1538 | ||
1602 | if (e && (!isspace(*e))) { | 1539 | if (e && (!isspace(*e))) { |
1603 | IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %02x\n", | 1540 | IUCV_DBF_TEXT_(setup, 2, "buffer_write: invalid char %c\n", *e); |
1604 | *e); | ||
1605 | return -EINVAL; | 1541 | return -EINVAL; |
1606 | } | 1542 | } |
1607 | if (bs1 > NETIUCV_BUFSIZE_MAX) { | 1543 | if (bs1 > NETIUCV_BUFSIZE_MAX) { |
@@ -1854,11 +1790,26 @@ static struct attribute_group netiucv_stat_attr_group = { | |||
1854 | .attrs = netiucv_stat_attrs, | 1790 | .attrs = netiucv_stat_attrs, |
1855 | }; | 1791 | }; |
1856 | 1792 | ||
1857 | static const struct attribute_group *netiucv_attr_groups[] = { | 1793 | static int netiucv_add_files(struct device *dev) |
1858 | &netiucv_stat_attr_group, | 1794 | { |
1859 | &netiucv_attr_group, | 1795 | int ret; |
1860 | NULL, | 1796 | |
1861 | }; | 1797 | IUCV_DBF_TEXT(trace, 3, __func__); |
1798 | ret = sysfs_create_group(&dev->kobj, &netiucv_attr_group); | ||
1799 | if (ret) | ||
1800 | return ret; | ||
1801 | ret = sysfs_create_group(&dev->kobj, &netiucv_stat_attr_group); | ||
1802 | if (ret) | ||
1803 | sysfs_remove_group(&dev->kobj, &netiucv_attr_group); | ||
1804 | return ret; | ||
1805 | } | ||
1806 | |||
1807 | static void netiucv_remove_files(struct device *dev) | ||
1808 | { | ||
1809 | IUCV_DBF_TEXT(trace, 3, __func__); | ||
1810 | sysfs_remove_group(&dev->kobj, &netiucv_stat_attr_group); | ||
1811 | sysfs_remove_group(&dev->kobj, &netiucv_attr_group); | ||
1812 | } | ||
1862 | 1813 | ||
1863 | static int netiucv_register_device(struct net_device *ndev) | 1814 | static int netiucv_register_device(struct net_device *ndev) |
1864 | { | 1815 | { |
@@ -1872,7 +1823,6 @@ static int netiucv_register_device(struct net_device *ndev) | |||
1872 | dev_set_name(dev, "net%s", ndev->name); | 1823 | dev_set_name(dev, "net%s", ndev->name); |
1873 | dev->bus = &iucv_bus; | 1824 | dev->bus = &iucv_bus; |
1874 | dev->parent = iucv_root; | 1825 | dev->parent = iucv_root; |
1875 | dev->groups = netiucv_attr_groups; | ||
1876 | /* | 1826 | /* |
1877 | * The release function could be called after the | 1827 | * The release function could be called after the |
1878 | * module has been unloaded. It's _only_ task is to | 1828 | * module has been unloaded. It's _only_ task is to |
@@ -1890,14 +1840,22 @@ static int netiucv_register_device(struct net_device *ndev) | |||
1890 | put_device(dev); | 1840 | put_device(dev); |
1891 | return ret; | 1841 | return ret; |
1892 | } | 1842 | } |
1843 | ret = netiucv_add_files(dev); | ||
1844 | if (ret) | ||
1845 | goto out_unreg; | ||
1893 | priv->dev = dev; | 1846 | priv->dev = dev; |
1894 | dev_set_drvdata(dev, priv); | 1847 | dev_set_drvdata(dev, priv); |
1895 | return 0; | 1848 | return 0; |
1849 | |||
1850 | out_unreg: | ||
1851 | device_unregister(dev); | ||
1852 | return ret; | ||
1896 | } | 1853 | } |
1897 | 1854 | ||
1898 | static void netiucv_unregister_device(struct device *dev) | 1855 | static void netiucv_unregister_device(struct device *dev) |
1899 | { | 1856 | { |
1900 | IUCV_DBF_TEXT(trace, 3, __func__); | 1857 | IUCV_DBF_TEXT(trace, 3, __func__); |
1858 | netiucv_remove_files(dev); | ||
1901 | device_unregister(dev); | 1859 | device_unregister(dev); |
1902 | } | 1860 | } |
1903 | 1861 | ||
@@ -1906,8 +1864,7 @@ static void netiucv_unregister_device(struct device *dev) | |||
1906 | * Add it to the list of netiucv connections; | 1864 | * Add it to the list of netiucv connections; |
1907 | */ | 1865 | */ |
1908 | static struct iucv_connection *netiucv_new_connection(struct net_device *dev, | 1866 | static struct iucv_connection *netiucv_new_connection(struct net_device *dev, |
1909 | char *username, | 1867 | char *username) |
1910 | char *userdata) | ||
1911 | { | 1868 | { |
1912 | struct iucv_connection *conn; | 1869 | struct iucv_connection *conn; |
1913 | 1870 | ||
@@ -1936,8 +1893,6 @@ static struct iucv_connection *netiucv_new_connection(struct net_device *dev, | |||
1936 | fsm_settimer(conn->fsm, &conn->timer); | 1893 | fsm_settimer(conn->fsm, &conn->timer); |
1937 | fsm_newstate(conn->fsm, CONN_STATE_INVALID); | 1894 | fsm_newstate(conn->fsm, CONN_STATE_INVALID); |
1938 | 1895 | ||
1939 | if (userdata) | ||
1940 | memcpy(conn->userdata, userdata, 17); | ||
1941 | if (username) { | 1896 | if (username) { |
1942 | memcpy(conn->userid, username, 9); | 1897 | memcpy(conn->userid, username, 9); |
1943 | fsm_newstate(conn->fsm, CONN_STATE_STOPPED); | 1898 | fsm_newstate(conn->fsm, CONN_STATE_STOPPED); |
@@ -1964,7 +1919,6 @@ out: | |||
1964 | */ | 1919 | */ |
1965 | static void netiucv_remove_connection(struct iucv_connection *conn) | 1920 | static void netiucv_remove_connection(struct iucv_connection *conn) |
1966 | { | 1921 | { |
1967 | |||
1968 | IUCV_DBF_TEXT(trace, 3, __func__); | 1922 | IUCV_DBF_TEXT(trace, 3, __func__); |
1969 | write_lock_bh(&iucv_connection_rwlock); | 1923 | write_lock_bh(&iucv_connection_rwlock); |
1970 | list_del_init(&conn->list); | 1924 | list_del_init(&conn->list); |
@@ -1972,7 +1926,7 @@ static void netiucv_remove_connection(struct iucv_connection *conn) | |||
1972 | fsm_deltimer(&conn->timer); | 1926 | fsm_deltimer(&conn->timer); |
1973 | netiucv_purge_skb_queue(&conn->collect_queue); | 1927 | netiucv_purge_skb_queue(&conn->collect_queue); |
1974 | if (conn->path) { | 1928 | if (conn->path) { |
1975 | iucv_path_sever(conn->path, conn->userdata); | 1929 | iucv_path_sever(conn->path, iucvMagic); |
1976 | kfree(conn->path); | 1930 | kfree(conn->path); |
1977 | conn->path = NULL; | 1931 | conn->path = NULL; |
1978 | } | 1932 | } |
@@ -2031,7 +1985,7 @@ static void netiucv_setup_netdevice(struct net_device *dev) | |||
2031 | /** | 1985 | /** |
2032 | * Allocate and initialize everything of a net device. | 1986 | * Allocate and initialize everything of a net device. |
2033 | */ | 1987 | */ |
2034 | static struct net_device *netiucv_init_netdevice(char *username, char *userdata) | 1988 | static struct net_device *netiucv_init_netdevice(char *username) |
2035 | { | 1989 | { |
2036 | struct netiucv_priv *privptr; | 1990 | struct netiucv_priv *privptr; |
2037 | struct net_device *dev; | 1991 | struct net_device *dev; |
@@ -2040,8 +1994,6 @@ static struct net_device *netiucv_init_netdevice(char *username, char *userdata) | |||
2040 | netiucv_setup_netdevice); | 1994 | netiucv_setup_netdevice); |
2041 | if (!dev) | 1995 | if (!dev) |
2042 | return NULL; | 1996 | return NULL; |
2043 | if (dev_alloc_name(dev, dev->name) < 0) | ||
2044 | goto out_netdev; | ||
2045 | 1997 | ||
2046 | privptr = netdev_priv(dev); | 1998 | privptr = netdev_priv(dev); |
2047 | privptr->fsm = init_fsm("netiucvdev", dev_state_names, | 1999 | privptr->fsm = init_fsm("netiucvdev", dev_state_names, |
@@ -2050,7 +2002,7 @@ static struct net_device *netiucv_init_netdevice(char *username, char *userdata) | |||
2050 | if (!privptr->fsm) | 2002 | if (!privptr->fsm) |
2051 | goto out_netdev; | 2003 | goto out_netdev; |
2052 | 2004 | ||
2053 | privptr->conn = netiucv_new_connection(dev, username, userdata); | 2005 | privptr->conn = netiucv_new_connection(dev, username); |
2054 | if (!privptr->conn) { | 2006 | if (!privptr->conn) { |
2055 | IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_new_connection\n"); | 2007 | IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_new_connection\n"); |
2056 | goto out_fsm; | 2008 | goto out_fsm; |
@@ -2068,31 +2020,47 @@ out_netdev: | |||
2068 | static ssize_t conn_write(struct device_driver *drv, | 2020 | static ssize_t conn_write(struct device_driver *drv, |
2069 | const char *buf, size_t count) | 2021 | const char *buf, size_t count) |
2070 | { | 2022 | { |
2023 | const char *p; | ||
2071 | char username[9]; | 2024 | char username[9]; |
2072 | char userdata[17]; | 2025 | int i, rc; |
2073 | int rc; | ||
2074 | struct net_device *dev; | 2026 | struct net_device *dev; |
2075 | struct netiucv_priv *priv; | 2027 | struct netiucv_priv *priv; |
2076 | struct iucv_connection *cp; | 2028 | struct iucv_connection *cp; |
2077 | 2029 | ||
2078 | IUCV_DBF_TEXT(trace, 3, __func__); | 2030 | IUCV_DBF_TEXT(trace, 3, __func__); |
2079 | rc = netiucv_check_user(buf, count, username, userdata); | 2031 | if (count>9) { |
2080 | if (rc) | 2032 | IUCV_DBF_TEXT(setup, 2, "conn_write: too long\n"); |
2081 | return rc; | 2033 | return -EINVAL; |
2034 | } | ||
2035 | |||
2036 | for (i = 0, p = buf; i < 8 && *p; i++, p++) { | ||
2037 | if (isalnum(*p) || *p == '$') { | ||
2038 | username[i] = toupper(*p); | ||
2039 | continue; | ||
2040 | } | ||
2041 | if (*p == '\n') | ||
2042 | /* trailing lf, grr */ | ||
2043 | break; | ||
2044 | IUCV_DBF_TEXT_(setup, 2, | ||
2045 | "conn_write: invalid character %c\n", *p); | ||
2046 | return -EINVAL; | ||
2047 | } | ||
2048 | while (i < 8) | ||
2049 | username[i++] = ' '; | ||
2050 | username[8] = '\0'; | ||
2082 | 2051 | ||
2083 | read_lock_bh(&iucv_connection_rwlock); | 2052 | read_lock_bh(&iucv_connection_rwlock); |
2084 | list_for_each_entry(cp, &iucv_connection_list, list) { | 2053 | list_for_each_entry(cp, &iucv_connection_list, list) { |
2085 | if (!strncmp(username, cp->userid, 9) && | 2054 | if (!strncmp(username, cp->userid, 9)) { |
2086 | !strncmp(userdata, cp->userdata, 17)) { | ||
2087 | read_unlock_bh(&iucv_connection_rwlock); | 2055 | read_unlock_bh(&iucv_connection_rwlock); |
2088 | IUCV_DBF_TEXT_(setup, 2, "conn_write: Connection to %s " | 2056 | IUCV_DBF_TEXT_(setup, 2, "conn_write: Connection " |
2089 | "already exists\n", netiucv_printuser(cp)); | 2057 | "to %s already exists\n", username); |
2090 | return -EEXIST; | 2058 | return -EEXIST; |
2091 | } | 2059 | } |
2092 | } | 2060 | } |
2093 | read_unlock_bh(&iucv_connection_rwlock); | 2061 | read_unlock_bh(&iucv_connection_rwlock); |
2094 | 2062 | ||
2095 | dev = netiucv_init_netdevice(username, userdata); | 2063 | dev = netiucv_init_netdevice(username); |
2096 | if (!dev) { | 2064 | if (!dev) { |
2097 | IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_init_netdevice\n"); | 2065 | IUCV_DBF_TEXT(setup, 2, "NULL from netiucv_init_netdevice\n"); |
2098 | return -ENODEV; | 2066 | return -ENODEV; |
@@ -2113,9 +2081,8 @@ static ssize_t conn_write(struct device_driver *drv, | |||
2113 | if (rc) | 2081 | if (rc) |
2114 | goto out_unreg; | 2082 | goto out_unreg; |
2115 | 2083 | ||
2116 | dev_info(priv->dev, "The IUCV interface to %s has been established " | 2084 | dev_info(priv->dev, "The IUCV interface to %s has been" |
2117 | "successfully\n", | 2085 | " established successfully\n", netiucv_printname(username)); |
2118 | netiucv_printuser(priv->conn)); | ||
2119 | 2086 | ||
2120 | return count; | 2087 | return count; |
2121 | 2088 | ||
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 480fbeab025..26a4110eeb2 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/qeth_core.h | ||
3 | * | ||
2 | * Copyright IBM Corp. 2007 | 4 | * Copyright IBM Corp. 2007 |
3 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, | 5 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, |
4 | * Frank Pavlic <fpavlic@de.ibm.com>, | 6 | * Frank Pavlic <fpavlic@de.ibm.com>, |
@@ -11,6 +13,8 @@ | |||
11 | 13 | ||
12 | #include <linux/if.h> | 14 | #include <linux/if.h> |
13 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
16 | #include <linux/if_tr.h> | ||
17 | #include <linux/trdevice.h> | ||
14 | #include <linux/etherdevice.h> | 18 | #include <linux/etherdevice.h> |
15 | #include <linux/if_vlan.h> | 19 | #include <linux/if_vlan.h> |
16 | #include <linux/ctype.h> | 20 | #include <linux/ctype.h> |
@@ -106,10 +110,6 @@ struct qeth_perf_stats { | |||
106 | 110 | ||
107 | unsigned int sc_dp_p; | 111 | unsigned int sc_dp_p; |
108 | unsigned int sc_p_dp; | 112 | unsigned int sc_p_dp; |
109 | /* qdio_cq_handler: number of times called, time spent in */ | ||
110 | __u64 cq_start_time; | ||
111 | unsigned int cq_cnt; | ||
112 | unsigned int cq_time; | ||
113 | /* qdio_input_handler: number of times called, time spent in */ | 113 | /* qdio_input_handler: number of times called, time spent in */ |
114 | __u64 inbound_start_time; | 114 | __u64 inbound_start_time; |
115 | unsigned int inbound_cnt; | 115 | unsigned int inbound_cnt; |
@@ -213,7 +213,6 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, | |||
213 | */ | 213 | */ |
214 | #define QETH_TX_TIMEOUT 100 * HZ | 214 | #define QETH_TX_TIMEOUT 100 * HZ |
215 | #define QETH_RCD_TIMEOUT 60 * HZ | 215 | #define QETH_RCD_TIMEOUT 60 * HZ |
216 | #define QETH_RECLAIM_WORK_TIME HZ | ||
217 | #define QETH_HEADER_SIZE 32 | 216 | #define QETH_HEADER_SIZE 32 |
218 | #define QETH_MAX_PORTNO 15 | 217 | #define QETH_MAX_PORTNO 15 |
219 | 218 | ||
@@ -232,7 +231,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, | |||
232 | #define QETH_IN_BUF_COUNT_MAX 128 | 231 | #define QETH_IN_BUF_COUNT_MAX 128 |
233 | #define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12) | 232 | #define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12) |
234 | #define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \ | 233 | #define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \ |
235 | ((card)->qdio.in_buf_pool.buf_count / 2) | 234 | ((card)->qdio.in_buf_pool.buf_count / 2) |
236 | 235 | ||
237 | /* buffers we have to be behind before we get a PCI */ | 236 | /* buffers we have to be behind before we get a PCI */ |
238 | #define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1) | 237 | #define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1) |
@@ -261,7 +260,6 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, | |||
261 | 260 | ||
262 | /* large receive scatter gather copy break */ | 261 | /* large receive scatter gather copy break */ |
263 | #define QETH_RX_SG_CB (PAGE_SIZE >> 1) | 262 | #define QETH_RX_SG_CB (PAGE_SIZE >> 1) |
264 | #define QETH_RX_PULL_LEN 256 | ||
265 | 263 | ||
266 | struct qeth_hdr_layer3 { | 264 | struct qeth_hdr_layer3 { |
267 | __u8 id; | 265 | __u8 id; |
@@ -377,21 +375,6 @@ enum qeth_qdio_buffer_states { | |||
377 | * outbound: filled by driver; owned by hardware in order to be sent | 375 | * outbound: filled by driver; owned by hardware in order to be sent |
378 | */ | 376 | */ |
379 | QETH_QDIO_BUF_PRIMED, | 377 | QETH_QDIO_BUF_PRIMED, |
380 | /* | ||
381 | * inbound: not applicable | ||
382 | * outbound: identified to be pending in TPQ | ||
383 | */ | ||
384 | QETH_QDIO_BUF_PENDING, | ||
385 | /* | ||
386 | * inbound: not applicable | ||
387 | * outbound: found in completion queue | ||
388 | */ | ||
389 | QETH_QDIO_BUF_IN_CQ, | ||
390 | /* | ||
391 | * inbound: not applicable | ||
392 | * outbound: handled via transfer pending / completion queue | ||
393 | */ | ||
394 | QETH_QDIO_BUF_HANDLED_DELAYED, | ||
395 | }; | 378 | }; |
396 | 379 | ||
397 | enum qeth_qdio_info_states { | 380 | enum qeth_qdio_info_states { |
@@ -416,7 +399,6 @@ struct qeth_qdio_buffer { | |||
416 | struct qdio_buffer *buffer; | 399 | struct qdio_buffer *buffer; |
417 | /* the buffer pool entry currently associated to this buffer */ | 400 | /* the buffer pool entry currently associated to this buffer */ |
418 | struct qeth_buffer_pool_entry *pool_entry; | 401 | struct qeth_buffer_pool_entry *pool_entry; |
419 | struct sk_buff *rx_skb; | ||
420 | }; | 402 | }; |
421 | 403 | ||
422 | struct qeth_qdio_q { | 404 | struct qeth_qdio_q { |
@@ -430,11 +412,8 @@ struct qeth_qdio_out_buffer { | |||
430 | atomic_t state; | 412 | atomic_t state; |
431 | int next_element_to_fill; | 413 | int next_element_to_fill; |
432 | struct sk_buff_head skb_list; | 414 | struct sk_buff_head skb_list; |
415 | struct list_head ctx_list; | ||
433 | int is_header[16]; | 416 | int is_header[16]; |
434 | |||
435 | struct qaob *aob; | ||
436 | struct qeth_qdio_out_q *q; | ||
437 | struct qeth_qdio_out_buffer *next_pending; | ||
438 | }; | 417 | }; |
439 | 418 | ||
440 | struct qeth_card; | 419 | struct qeth_card; |
@@ -447,8 +426,7 @@ enum qeth_out_q_states { | |||
447 | 426 | ||
448 | struct qeth_qdio_out_q { | 427 | struct qeth_qdio_out_q { |
449 | struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q]; | 428 | struct qdio_buffer qdio_bufs[QDIO_MAX_BUFFERS_PER_Q]; |
450 | struct qeth_qdio_out_buffer *bufs[QDIO_MAX_BUFFERS_PER_Q]; | 429 | struct qeth_qdio_out_buffer bufs[QDIO_MAX_BUFFERS_PER_Q]; |
451 | struct qdio_outbuf_state *bufstates; /* convenience pointer */ | ||
452 | int queue_no; | 430 | int queue_no; |
453 | struct qeth_card *card; | 431 | struct qeth_card *card; |
454 | atomic_t state; | 432 | atomic_t state; |
@@ -469,9 +447,7 @@ struct qeth_qdio_out_q { | |||
469 | struct qeth_qdio_info { | 447 | struct qeth_qdio_info { |
470 | atomic_t state; | 448 | atomic_t state; |
471 | /* input */ | 449 | /* input */ |
472 | int no_in_queues; | ||
473 | struct qeth_qdio_q *in_q; | 450 | struct qeth_qdio_q *in_q; |
474 | struct qeth_qdio_q *c_q; | ||
475 | struct qeth_qdio_buffer_pool in_buf_pool; | 451 | struct qeth_qdio_buffer_pool in_buf_pool; |
476 | struct qeth_qdio_buffer_pool init_pool; | 452 | struct qeth_qdio_buffer_pool init_pool; |
477 | int in_buf_size; | 453 | int in_buf_size; |
@@ -479,7 +455,6 @@ struct qeth_qdio_info { | |||
479 | /* output */ | 455 | /* output */ |
480 | int no_out_queues; | 456 | int no_out_queues; |
481 | struct qeth_qdio_out_q **out_qs; | 457 | struct qeth_qdio_out_q **out_qs; |
482 | struct qdio_outbuf_state *out_bufstates; | ||
483 | 458 | ||
484 | /* priority queueing */ | 459 | /* priority queueing */ |
485 | int do_prio_queueing; | 460 | int do_prio_queueing; |
@@ -551,12 +526,6 @@ enum qeth_cmd_buffer_state { | |||
551 | BUF_STATE_PROCESSED, | 526 | BUF_STATE_PROCESSED, |
552 | }; | 527 | }; |
553 | 528 | ||
554 | enum qeth_cq { | ||
555 | QETH_CQ_DISABLED = 0, | ||
556 | QETH_CQ_ENABLED = 1, | ||
557 | QETH_CQ_NOTAVAILABLE = 2, | ||
558 | }; | ||
559 | |||
560 | struct qeth_ipato { | 529 | struct qeth_ipato { |
561 | int enabled; | 530 | int enabled; |
562 | int invert4; | 531 | int invert4; |
@@ -672,6 +641,8 @@ struct qeth_card_options { | |||
672 | struct qeth_ipa_info adp; /*Adapter parameters*/ | 641 | struct qeth_ipa_info adp; /*Adapter parameters*/ |
673 | struct qeth_routing_info route6; | 642 | struct qeth_routing_info route6; |
674 | struct qeth_ipa_info ipa6; | 643 | struct qeth_ipa_info ipa6; |
644 | int broadcast_mode; | ||
645 | int macaddr_mode; | ||
675 | int fake_broadcast; | 646 | int fake_broadcast; |
676 | int add_hhlen; | 647 | int add_hhlen; |
677 | int layer2; | 648 | int layer2; |
@@ -679,8 +650,6 @@ struct qeth_card_options { | |||
679 | int rx_sg_cb; | 650 | int rx_sg_cb; |
680 | enum qeth_ipa_isolation_modes isolation; | 651 | enum qeth_ipa_isolation_modes isolation; |
681 | int sniffer; | 652 | int sniffer; |
682 | enum qeth_cq cq; | ||
683 | char hsuid[9]; | ||
684 | }; | 653 | }; |
685 | 654 | ||
686 | /* | 655 | /* |
@@ -705,16 +674,7 @@ struct qeth_discipline { | |||
705 | qdio_handler_t *input_handler; | 674 | qdio_handler_t *input_handler; |
706 | qdio_handler_t *output_handler; | 675 | qdio_handler_t *output_handler; |
707 | int (*recover)(void *ptr); | 676 | int (*recover)(void *ptr); |
708 | int (*setup) (struct ccwgroup_device *); | 677 | struct ccwgroup_driver *ccwgdriver; |
709 | void (*remove) (struct ccwgroup_device *); | ||
710 | int (*set_online) (struct ccwgroup_device *); | ||
711 | int (*set_offline) (struct ccwgroup_device *); | ||
712 | void (*shutdown)(struct ccwgroup_device *); | ||
713 | int (*prepare) (struct ccwgroup_device *); | ||
714 | void (*complete) (struct ccwgroup_device *); | ||
715 | int (*freeze)(struct ccwgroup_device *); | ||
716 | int (*thaw) (struct ccwgroup_device *); | ||
717 | int (*restore)(struct ccwgroup_device *); | ||
718 | }; | 678 | }; |
719 | 679 | ||
720 | struct qeth_vlan_vid { | 680 | struct qeth_vlan_vid { |
@@ -778,7 +738,7 @@ struct qeth_card { | |||
778 | struct qeth_perf_stats perf_stats; | 738 | struct qeth_perf_stats perf_stats; |
779 | int read_or_write_problem; | 739 | int read_or_write_problem; |
780 | struct qeth_osn_info osn_info; | 740 | struct qeth_osn_info osn_info; |
781 | struct qeth_discipline *discipline; | 741 | struct qeth_discipline discipline; |
782 | atomic_t force_alloc_skb; | 742 | atomic_t force_alloc_skb; |
783 | struct service_level qeth_service_level; | 743 | struct service_level qeth_service_level; |
784 | struct qdio_ssqd_desc ssqd; | 744 | struct qdio_ssqd_desc ssqd; |
@@ -787,8 +747,6 @@ struct qeth_card { | |||
787 | struct mutex discipline_mutex; | 747 | struct mutex discipline_mutex; |
788 | struct napi_struct napi; | 748 | struct napi_struct napi; |
789 | struct qeth_rx rx; | 749 | struct qeth_rx rx; |
790 | struct delayed_work buffer_reclaim_work; | ||
791 | int reclaim_index; | ||
792 | }; | 750 | }; |
793 | 751 | ||
794 | struct qeth_card_list_struct { | 752 | struct qeth_card_list_struct { |
@@ -844,16 +802,16 @@ static inline int qeth_is_diagass_supported(struct qeth_card *card, | |||
844 | return card->info.diagass_support & (__u32)cmd; | 802 | return card->info.diagass_support & (__u32)cmd; |
845 | } | 803 | } |
846 | 804 | ||
847 | extern struct qeth_discipline qeth_l2_discipline; | 805 | extern struct ccwgroup_driver qeth_l2_ccwgroup_driver; |
848 | extern struct qeth_discipline qeth_l3_discipline; | 806 | extern struct ccwgroup_driver qeth_l3_ccwgroup_driver; |
849 | extern const struct attribute_group *qeth_generic_attr_groups[]; | ||
850 | extern const struct attribute_group *qeth_osn_attr_groups[]; | ||
851 | |||
852 | const char *qeth_get_cardname_short(struct qeth_card *); | 807 | const char *qeth_get_cardname_short(struct qeth_card *); |
853 | int qeth_realloc_buffer_pool(struct qeth_card *, int); | 808 | int qeth_realloc_buffer_pool(struct qeth_card *, int); |
854 | int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id); | 809 | int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id); |
855 | void qeth_core_free_discipline(struct qeth_card *); | 810 | void qeth_core_free_discipline(struct qeth_card *); |
856 | void qeth_buffer_reclaim_work(struct work_struct *); | 811 | int qeth_core_create_device_attributes(struct device *); |
812 | void qeth_core_remove_device_attributes(struct device *); | ||
813 | int qeth_core_create_osn_attributes(struct device *); | ||
814 | void qeth_core_remove_osn_attributes(struct device *); | ||
857 | 815 | ||
858 | /* exports for qeth discipline device drivers */ | 816 | /* exports for qeth discipline device drivers */ |
859 | extern struct qeth_card_list_struct qeth_core_card_list; | 817 | extern struct qeth_card_list_struct qeth_core_card_list; |
@@ -882,7 +840,7 @@ int qeth_check_qdio_errors(struct qeth_card *, struct qdio_buffer *, | |||
882 | unsigned int, const char *); | 840 | unsigned int, const char *); |
883 | void qeth_queue_input_buffer(struct qeth_card *, int); | 841 | void qeth_queue_input_buffer(struct qeth_card *, int); |
884 | struct sk_buff *qeth_core_get_next_skb(struct qeth_card *, | 842 | struct sk_buff *qeth_core_get_next_skb(struct qeth_card *, |
885 | struct qeth_qdio_buffer *, struct qdio_buffer_element **, int *, | 843 | struct qdio_buffer *, struct qdio_buffer_element **, int *, |
886 | struct qeth_hdr **); | 844 | struct qeth_hdr **); |
887 | void qeth_schedule_recovery(struct qeth_card *); | 845 | void qeth_schedule_recovery(struct qeth_card *); |
888 | void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long); | 846 | void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long); |
@@ -908,7 +866,6 @@ void qeth_prepare_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, char); | |||
908 | struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); | 866 | struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *); |
909 | int qeth_mdio_read(struct net_device *, int, int); | 867 | int qeth_mdio_read(struct net_device *, int, int); |
910 | int qeth_snmp_command(struct qeth_card *, char __user *); | 868 | int qeth_snmp_command(struct qeth_card *, char __user *); |
911 | int qeth_query_oat_command(struct qeth_card *, char __user *); | ||
912 | struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32); | 869 | struct qeth_cmd_buffer *qeth_get_adapter_cmd(struct qeth_card *, __u32, __u32); |
913 | int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *, | 870 | int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *, |
914 | unsigned long); | 871 | unsigned long); |
@@ -930,10 +887,8 @@ void qeth_dbf_longtext(debug_info_t *id, int level, char *text, ...); | |||
930 | int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); | 887 | int qeth_core_ethtool_get_settings(struct net_device *, struct ethtool_cmd *); |
931 | int qeth_set_access_ctrl_online(struct qeth_card *card); | 888 | int qeth_set_access_ctrl_online(struct qeth_card *card); |
932 | int qeth_hdr_chk_and_bounce(struct sk_buff *, int); | 889 | int qeth_hdr_chk_and_bounce(struct sk_buff *, int); |
933 | int qeth_configure_cq(struct qeth_card *, enum qeth_cq); | ||
934 | int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); | 890 | int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); |
935 | int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot); | 891 | int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot); |
936 | void qeth_trace_features(struct qeth_card *); | ||
937 | 892 | ||
938 | /* exports for OSN */ | 893 | /* exports for OSN */ |
939 | int qeth_osn_assist(struct net_device *, void *, int); | 894 | 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 638a57f4d8a..4550573c25e 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/qeth_core_main.c | ||
3 | * | ||
2 | * Copyright IBM Corp. 2007, 2009 | 4 | * Copyright IBM Corp. 2007, 2009 |
3 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, | 5 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, |
4 | * Frank Pavlic <fpavlic@de.ibm.com>, | 6 | * Frank Pavlic <fpavlic@de.ibm.com>, |
@@ -19,12 +21,10 @@ | |||
19 | #include <linux/mii.h> | 21 | #include <linux/mii.h> |
20 | #include <linux/kthread.h> | 22 | #include <linux/kthread.h> |
21 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
22 | #include <net/iucv/af_iucv.h> | ||
23 | 24 | ||
24 | #include <asm/ebcdic.h> | 25 | #include <asm/ebcdic.h> |
25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
26 | #include <asm/sysinfo.h> | 27 | #include <asm/sysinfo.h> |
27 | #include <asm/compat.h> | ||
28 | 28 | ||
29 | #include "qeth_core.h" | 29 | #include "qeth_core.h" |
30 | 30 | ||
@@ -44,12 +44,10 @@ struct qeth_card_list_struct qeth_core_card_list; | |||
44 | EXPORT_SYMBOL_GPL(qeth_core_card_list); | 44 | EXPORT_SYMBOL_GPL(qeth_core_card_list); |
45 | struct kmem_cache *qeth_core_header_cache; | 45 | struct kmem_cache *qeth_core_header_cache; |
46 | EXPORT_SYMBOL_GPL(qeth_core_header_cache); | 46 | EXPORT_SYMBOL_GPL(qeth_core_header_cache); |
47 | static struct kmem_cache *qeth_qdio_outbuf_cache; | ||
48 | 47 | ||
49 | static struct device *qeth_core_root_dev; | 48 | static struct device *qeth_core_root_dev; |
50 | static unsigned int known_devices[][6] = QETH_MODELLIST_ARRAY; | 49 | static unsigned int known_devices[][6] = QETH_MODELLIST_ARRAY; |
51 | static struct lock_class_key qdio_out_skb_queue_key; | 50 | static struct lock_class_key qdio_out_skb_queue_key; |
52 | static struct mutex qeth_mod_mutex; | ||
53 | 51 | ||
54 | static void qeth_send_control_data_cb(struct qeth_channel *, | 52 | static void qeth_send_control_data_cb(struct qeth_channel *, |
55 | struct qeth_cmd_buffer *); | 53 | struct qeth_cmd_buffer *); |
@@ -58,28 +56,20 @@ static struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *); | |||
58 | static void qeth_setup_ccw(struct qeth_channel *, unsigned char *, __u32); | 56 | static void qeth_setup_ccw(struct qeth_channel *, unsigned char *, __u32); |
59 | static void qeth_free_buffer_pool(struct qeth_card *); | 57 | static void qeth_free_buffer_pool(struct qeth_card *); |
60 | static int qeth_qdio_establish(struct qeth_card *); | 58 | static int qeth_qdio_establish(struct qeth_card *); |
61 | static void qeth_free_qdio_buffers(struct qeth_card *); | 59 | |
62 | static void qeth_notify_skbs(struct qeth_qdio_out_q *queue, | ||
63 | struct qeth_qdio_out_buffer *buf, | ||
64 | enum iucv_tx_notify notification); | ||
65 | static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf); | ||
66 | static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | ||
67 | struct qeth_qdio_out_buffer *buf, | ||
68 | enum qeth_qdio_buffer_states newbufstate); | ||
69 | static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); | ||
70 | 60 | ||
71 | static inline const char *qeth_get_cardname(struct qeth_card *card) | 61 | static inline const char *qeth_get_cardname(struct qeth_card *card) |
72 | { | 62 | { |
73 | if (card->info.guestlan) { | 63 | if (card->info.guestlan) { |
74 | switch (card->info.type) { | 64 | switch (card->info.type) { |
75 | case QETH_CARD_TYPE_OSD: | 65 | case QETH_CARD_TYPE_OSD: |
76 | return " Virtual NIC QDIO"; | 66 | return " Guest LAN QDIO"; |
77 | case QETH_CARD_TYPE_IQD: | 67 | case QETH_CARD_TYPE_IQD: |
78 | return " Virtual NIC Hiper"; | 68 | return " Guest LAN Hiper"; |
79 | case QETH_CARD_TYPE_OSM: | 69 | case QETH_CARD_TYPE_OSM: |
80 | return " Virtual NIC QDIO - OSM"; | 70 | return " Guest LAN QDIO - OSM"; |
81 | case QETH_CARD_TYPE_OSX: | 71 | case QETH_CARD_TYPE_OSX: |
82 | return " Virtual NIC QDIO - OSX"; | 72 | return " Guest LAN QDIO - OSX"; |
83 | default: | 73 | default: |
84 | return " unknown"; | 74 | return " unknown"; |
85 | } | 75 | } |
@@ -108,13 +98,13 @@ const char *qeth_get_cardname_short(struct qeth_card *card) | |||
108 | if (card->info.guestlan) { | 98 | if (card->info.guestlan) { |
109 | switch (card->info.type) { | 99 | switch (card->info.type) { |
110 | case QETH_CARD_TYPE_OSD: | 100 | case QETH_CARD_TYPE_OSD: |
111 | return "Virt.NIC QDIO"; | 101 | return "GuestLAN QDIO"; |
112 | case QETH_CARD_TYPE_IQD: | 102 | case QETH_CARD_TYPE_IQD: |
113 | return "Virt.NIC Hiper"; | 103 | return "GuestLAN Hiper"; |
114 | case QETH_CARD_TYPE_OSM: | 104 | case QETH_CARD_TYPE_OSM: |
115 | return "Virt.NIC OSM"; | 105 | return "GuestLAN OSM"; |
116 | case QETH_CARD_TYPE_OSX: | 106 | case QETH_CARD_TYPE_OSX: |
117 | return "Virt.NIC OSX"; | 107 | return "GuestLAN OSX"; |
118 | default: | 108 | default: |
119 | return "unknown"; | 109 | return "unknown"; |
120 | } | 110 | } |
@@ -209,7 +199,7 @@ static int qeth_alloc_buffer_pool(struct qeth_card *card) | |||
209 | 199 | ||
210 | QETH_CARD_TEXT(card, 5, "alocpool"); | 200 | QETH_CARD_TEXT(card, 5, "alocpool"); |
211 | for (i = 0; i < card->qdio.init_pool.buf_count; ++i) { | 201 | for (i = 0; i < card->qdio.init_pool.buf_count; ++i) { |
212 | pool_entry = kzalloc(sizeof(*pool_entry), GFP_KERNEL); | 202 | pool_entry = kmalloc(sizeof(*pool_entry), GFP_KERNEL); |
213 | if (!pool_entry) { | 203 | if (!pool_entry) { |
214 | qeth_free_buffer_pool(card); | 204 | qeth_free_buffer_pool(card); |
215 | return -ENOMEM; | 205 | return -ENOMEM; |
@@ -249,205 +239,6 @@ int qeth_realloc_buffer_pool(struct qeth_card *card, int bufcnt) | |||
249 | } | 239 | } |
250 | EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool); | 240 | EXPORT_SYMBOL_GPL(qeth_realloc_buffer_pool); |
251 | 241 | ||
252 | static inline int qeth_cq_init(struct qeth_card *card) | ||
253 | { | ||
254 | int rc; | ||
255 | |||
256 | if (card->options.cq == QETH_CQ_ENABLED) { | ||
257 | QETH_DBF_TEXT(SETUP, 2, "cqinit"); | ||
258 | memset(card->qdio.c_q->qdio_bufs, 0, | ||
259 | QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer)); | ||
260 | card->qdio.c_q->next_buf_to_init = 127; | ||
261 | rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, | ||
262 | card->qdio.no_in_queues - 1, 0, | ||
263 | 127); | ||
264 | if (rc) { | ||
265 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | ||
266 | goto out; | ||
267 | } | ||
268 | } | ||
269 | rc = 0; | ||
270 | out: | ||
271 | return rc; | ||
272 | } | ||
273 | |||
274 | static inline int qeth_alloc_cq(struct qeth_card *card) | ||
275 | { | ||
276 | int rc; | ||
277 | |||
278 | if (card->options.cq == QETH_CQ_ENABLED) { | ||
279 | int i; | ||
280 | struct qdio_outbuf_state *outbuf_states; | ||
281 | |||
282 | QETH_DBF_TEXT(SETUP, 2, "cqon"); | ||
283 | card->qdio.c_q = kzalloc(sizeof(struct qeth_qdio_q), | ||
284 | GFP_KERNEL); | ||
285 | if (!card->qdio.c_q) { | ||
286 | rc = -1; | ||
287 | goto kmsg_out; | ||
288 | } | ||
289 | QETH_DBF_HEX(SETUP, 2, &card->qdio.c_q, sizeof(void *)); | ||
290 | |||
291 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) { | ||
292 | card->qdio.c_q->bufs[i].buffer = | ||
293 | &card->qdio.c_q->qdio_bufs[i]; | ||
294 | } | ||
295 | |||
296 | card->qdio.no_in_queues = 2; | ||
297 | |||
298 | card->qdio.out_bufstates = (struct qdio_outbuf_state *) | ||
299 | kzalloc(card->qdio.no_out_queues * | ||
300 | QDIO_MAX_BUFFERS_PER_Q * | ||
301 | sizeof(struct qdio_outbuf_state), GFP_KERNEL); | ||
302 | outbuf_states = card->qdio.out_bufstates; | ||
303 | if (outbuf_states == NULL) { | ||
304 | rc = -1; | ||
305 | goto free_cq_out; | ||
306 | } | ||
307 | for (i = 0; i < card->qdio.no_out_queues; ++i) { | ||
308 | card->qdio.out_qs[i]->bufstates = outbuf_states; | ||
309 | outbuf_states += QDIO_MAX_BUFFERS_PER_Q; | ||
310 | } | ||
311 | } else { | ||
312 | QETH_DBF_TEXT(SETUP, 2, "nocq"); | ||
313 | card->qdio.c_q = NULL; | ||
314 | card->qdio.no_in_queues = 1; | ||
315 | } | ||
316 | QETH_DBF_TEXT_(SETUP, 2, "iqc%d", card->qdio.no_in_queues); | ||
317 | rc = 0; | ||
318 | out: | ||
319 | return rc; | ||
320 | free_cq_out: | ||
321 | kfree(card->qdio.c_q); | ||
322 | card->qdio.c_q = NULL; | ||
323 | kmsg_out: | ||
324 | dev_err(&card->gdev->dev, "Failed to create completion queue\n"); | ||
325 | goto out; | ||
326 | } | ||
327 | |||
328 | static inline void qeth_free_cq(struct qeth_card *card) | ||
329 | { | ||
330 | if (card->qdio.c_q) { | ||
331 | --card->qdio.no_in_queues; | ||
332 | kfree(card->qdio.c_q); | ||
333 | card->qdio.c_q = NULL; | ||
334 | } | ||
335 | kfree(card->qdio.out_bufstates); | ||
336 | card->qdio.out_bufstates = NULL; | ||
337 | } | ||
338 | |||
339 | static inline enum iucv_tx_notify qeth_compute_cq_notification(int sbalf15, | ||
340 | int delayed) { | ||
341 | enum iucv_tx_notify n; | ||
342 | |||
343 | switch (sbalf15) { | ||
344 | case 0: | ||
345 | n = delayed ? TX_NOTIFY_DELAYED_OK : TX_NOTIFY_OK; | ||
346 | break; | ||
347 | case 4: | ||
348 | case 16: | ||
349 | case 17: | ||
350 | case 18: | ||
351 | n = delayed ? TX_NOTIFY_DELAYED_UNREACHABLE : | ||
352 | TX_NOTIFY_UNREACHABLE; | ||
353 | break; | ||
354 | default: | ||
355 | n = delayed ? TX_NOTIFY_DELAYED_GENERALERROR : | ||
356 | TX_NOTIFY_GENERALERROR; | ||
357 | break; | ||
358 | } | ||
359 | |||
360 | return n; | ||
361 | } | ||
362 | |||
363 | static inline void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, | ||
364 | int bidx, int forced_cleanup) | ||
365 | { | ||
366 | if (q->card->options.cq != QETH_CQ_ENABLED) | ||
367 | return; | ||
368 | |||
369 | if (q->bufs[bidx]->next_pending != NULL) { | ||
370 | struct qeth_qdio_out_buffer *head = q->bufs[bidx]; | ||
371 | struct qeth_qdio_out_buffer *c = q->bufs[bidx]->next_pending; | ||
372 | |||
373 | while (c) { | ||
374 | if (forced_cleanup || | ||
375 | atomic_read(&c->state) == | ||
376 | QETH_QDIO_BUF_HANDLED_DELAYED) { | ||
377 | struct qeth_qdio_out_buffer *f = c; | ||
378 | QETH_CARD_TEXT(f->q->card, 5, "fp"); | ||
379 | QETH_CARD_TEXT_(f->q->card, 5, "%lx", (long) f); | ||
380 | /* release here to avoid interleaving between | ||
381 | outbound tasklet and inbound tasklet | ||
382 | regarding notifications and lifecycle */ | ||
383 | qeth_release_skbs(c); | ||
384 | |||
385 | c = f->next_pending; | ||
386 | WARN_ON_ONCE(head->next_pending != f); | ||
387 | head->next_pending = c; | ||
388 | kmem_cache_free(qeth_qdio_outbuf_cache, f); | ||
389 | } else { | ||
390 | head = c; | ||
391 | c = c->next_pending; | ||
392 | } | ||
393 | |||
394 | } | ||
395 | } | ||
396 | if (forced_cleanup && (atomic_read(&(q->bufs[bidx]->state)) == | ||
397 | QETH_QDIO_BUF_HANDLED_DELAYED)) { | ||
398 | /* for recovery situations */ | ||
399 | q->bufs[bidx]->aob = q->bufstates[bidx].aob; | ||
400 | qeth_init_qdio_out_buf(q, bidx); | ||
401 | QETH_CARD_TEXT(q->card, 2, "clprecov"); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | |||
406 | static inline void qeth_qdio_handle_aob(struct qeth_card *card, | ||
407 | unsigned long phys_aob_addr) { | ||
408 | struct qaob *aob; | ||
409 | struct qeth_qdio_out_buffer *buffer; | ||
410 | enum iucv_tx_notify notification; | ||
411 | |||
412 | aob = (struct qaob *) phys_to_virt(phys_aob_addr); | ||
413 | QETH_CARD_TEXT(card, 5, "haob"); | ||
414 | QETH_CARD_TEXT_(card, 5, "%lx", phys_aob_addr); | ||
415 | buffer = (struct qeth_qdio_out_buffer *) aob->user1; | ||
416 | QETH_CARD_TEXT_(card, 5, "%lx", aob->user1); | ||
417 | |||
418 | if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED, | ||
419 | QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) { | ||
420 | notification = TX_NOTIFY_OK; | ||
421 | } else { | ||
422 | WARN_ON_ONCE(atomic_read(&buffer->state) != | ||
423 | QETH_QDIO_BUF_PENDING); | ||
424 | atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ); | ||
425 | notification = TX_NOTIFY_DELAYED_OK; | ||
426 | } | ||
427 | |||
428 | if (aob->aorc != 0) { | ||
429 | QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc); | ||
430 | notification = qeth_compute_cq_notification(aob->aorc, 1); | ||
431 | } | ||
432 | qeth_notify_skbs(buffer->q, buffer, notification); | ||
433 | |||
434 | buffer->aob = NULL; | ||
435 | qeth_clear_output_buffer(buffer->q, buffer, | ||
436 | QETH_QDIO_BUF_HANDLED_DELAYED); | ||
437 | |||
438 | /* from here on: do not touch buffer anymore */ | ||
439 | qdio_release_aob(aob); | ||
440 | } | ||
441 | |||
442 | static inline int qeth_is_cq(struct qeth_card *card, unsigned int queue) | ||
443 | { | ||
444 | return card->options.cq == QETH_CQ_ENABLED && | ||
445 | card->qdio.c_q != NULL && | ||
446 | queue != 0 && | ||
447 | queue == card->qdio.no_in_queues - 1; | ||
448 | } | ||
449 | |||
450 | |||
451 | static int qeth_issue_next_read(struct qeth_card *card) | 242 | static int qeth_issue_next_read(struct qeth_card *card) |
452 | { | 243 | { |
453 | int rc; | 244 | int rc; |
@@ -488,7 +279,7 @@ static struct qeth_reply *qeth_alloc_reply(struct qeth_card *card) | |||
488 | atomic_set(&reply->refcnt, 1); | 279 | atomic_set(&reply->refcnt, 1); |
489 | atomic_set(&reply->received, 0); | 280 | atomic_set(&reply->received, 0); |
490 | reply->card = card; | 281 | reply->card = card; |
491 | } | 282 | }; |
492 | return reply; | 283 | return reply; |
493 | } | 284 | } |
494 | 285 | ||
@@ -676,7 +467,6 @@ void qeth_release_buffer(struct qeth_channel *channel, | |||
676 | iob->callback = qeth_send_control_data_cb; | 467 | iob->callback = qeth_send_control_data_cb; |
677 | iob->rc = 0; | 468 | iob->rc = 0; |
678 | spin_unlock_irqrestore(&channel->iob_lock, flags); | 469 | spin_unlock_irqrestore(&channel->iob_lock, flags); |
679 | wake_up(&channel->wait_q); | ||
680 | } | 470 | } |
681 | EXPORT_SYMBOL_GPL(qeth_release_buffer); | 471 | EXPORT_SYMBOL_GPL(qeth_release_buffer); |
682 | 472 | ||
@@ -799,7 +589,7 @@ static int qeth_setup_channel(struct qeth_channel *channel) | |||
799 | QETH_DBF_TEXT(SETUP, 2, "setupch"); | 589 | QETH_DBF_TEXT(SETUP, 2, "setupch"); |
800 | for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) { | 590 | for (cnt = 0; cnt < QETH_CMD_BUFFER_NO; cnt++) { |
801 | channel->iob[cnt].data = | 591 | channel->iob[cnt].data = |
802 | kzalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL); | 592 | kmalloc(QETH_BUFSIZE, GFP_DMA|GFP_KERNEL); |
803 | if (channel->iob[cnt].data == NULL) | 593 | if (channel->iob[cnt].data == NULL) |
804 | break; | 594 | break; |
805 | channel->iob[cnt].state = BUF_STATE_FREE; | 595 | channel->iob[cnt].state = BUF_STATE_FREE; |
@@ -1093,74 +883,22 @@ out: | |||
1093 | return; | 883 | return; |
1094 | } | 884 | } |
1095 | 885 | ||
1096 | static void qeth_notify_skbs(struct qeth_qdio_out_q *q, | 886 | static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, |
1097 | struct qeth_qdio_out_buffer *buf, | 887 | struct qeth_qdio_out_buffer *buf) |
1098 | enum iucv_tx_notify notification) | ||
1099 | { | ||
1100 | struct sk_buff *skb; | ||
1101 | |||
1102 | if (skb_queue_empty(&buf->skb_list)) | ||
1103 | goto out; | ||
1104 | skb = skb_peek(&buf->skb_list); | ||
1105 | while (skb) { | ||
1106 | QETH_CARD_TEXT_(q->card, 5, "skbn%d", notification); | ||
1107 | QETH_CARD_TEXT_(q->card, 5, "%lx", (long) skb); | ||
1108 | if (skb->protocol == ETH_P_AF_IUCV) { | ||
1109 | if (skb->sk) { | ||
1110 | struct iucv_sock *iucv = iucv_sk(skb->sk); | ||
1111 | iucv->sk_txnotify(skb, notification); | ||
1112 | } | ||
1113 | } | ||
1114 | if (skb_queue_is_last(&buf->skb_list, skb)) | ||
1115 | skb = NULL; | ||
1116 | else | ||
1117 | skb = skb_queue_next(&buf->skb_list, skb); | ||
1118 | } | ||
1119 | out: | ||
1120 | return; | ||
1121 | } | ||
1122 | |||
1123 | static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf) | ||
1124 | { | 888 | { |
889 | int i; | ||
1125 | struct sk_buff *skb; | 890 | struct sk_buff *skb; |
1126 | struct iucv_sock *iucv; | ||
1127 | int notify_general_error = 0; | ||
1128 | |||
1129 | if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING) | ||
1130 | notify_general_error = 1; | ||
1131 | 891 | ||
1132 | /* release may never happen from within CQ tasklet scope */ | 892 | /* is PCI flag set on buffer? */ |
1133 | WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ); | 893 | if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ) |
894 | atomic_dec(&queue->set_pci_flags_count); | ||
1134 | 895 | ||
1135 | skb = skb_dequeue(&buf->skb_list); | 896 | skb = skb_dequeue(&buf->skb_list); |
1136 | while (skb) { | 897 | while (skb) { |
1137 | QETH_CARD_TEXT(buf->q->card, 5, "skbr"); | ||
1138 | QETH_CARD_TEXT_(buf->q->card, 5, "%lx", (long) skb); | ||
1139 | if (notify_general_error && skb->protocol == ETH_P_AF_IUCV) { | ||
1140 | if (skb->sk) { | ||
1141 | iucv = iucv_sk(skb->sk); | ||
1142 | iucv->sk_txnotify(skb, TX_NOTIFY_GENERALERROR); | ||
1143 | } | ||
1144 | } | ||
1145 | atomic_dec(&skb->users); | 898 | atomic_dec(&skb->users); |
1146 | dev_kfree_skb_any(skb); | 899 | dev_kfree_skb_any(skb); |
1147 | skb = skb_dequeue(&buf->skb_list); | 900 | skb = skb_dequeue(&buf->skb_list); |
1148 | } | 901 | } |
1149 | } | ||
1150 | |||
1151 | static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | ||
1152 | struct qeth_qdio_out_buffer *buf, | ||
1153 | enum qeth_qdio_buffer_states newbufstate) | ||
1154 | { | ||
1155 | int i; | ||
1156 | |||
1157 | /* is PCI flag set on buffer? */ | ||
1158 | if (buf->buffer->element[0].sflags & SBAL_SFLAGS0_PCI_REQ) | ||
1159 | atomic_dec(&queue->set_pci_flags_count); | ||
1160 | |||
1161 | if (newbufstate == QETH_QDIO_BUF_EMPTY) { | ||
1162 | qeth_release_skbs(buf); | ||
1163 | } | ||
1164 | for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) { | 902 | for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) { |
1165 | if (buf->buffer->element[i].addr && buf->is_header[i]) | 903 | if (buf->buffer->element[i].addr && buf->is_header[i]) |
1166 | kmem_cache_free(qeth_core_header_cache, | 904 | kmem_cache_free(qeth_core_header_cache, |
@@ -1174,36 +912,21 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | |||
1174 | buf->buffer->element[15].eflags = 0; | 912 | buf->buffer->element[15].eflags = 0; |
1175 | buf->buffer->element[15].sflags = 0; | 913 | buf->buffer->element[15].sflags = 0; |
1176 | buf->next_element_to_fill = 0; | 914 | buf->next_element_to_fill = 0; |
1177 | atomic_set(&buf->state, newbufstate); | 915 | atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); |
1178 | } | ||
1179 | |||
1180 | static void qeth_clear_outq_buffers(struct qeth_qdio_out_q *q, int free) | ||
1181 | { | ||
1182 | int j; | ||
1183 | |||
1184 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { | ||
1185 | if (!q->bufs[j]) | ||
1186 | continue; | ||
1187 | qeth_cleanup_handled_pending(q, j, 1); | ||
1188 | qeth_clear_output_buffer(q, q->bufs[j], QETH_QDIO_BUF_EMPTY); | ||
1189 | if (free) { | ||
1190 | kmem_cache_free(qeth_qdio_outbuf_cache, q->bufs[j]); | ||
1191 | q->bufs[j] = NULL; | ||
1192 | } | ||
1193 | } | ||
1194 | } | 916 | } |
1195 | 917 | ||
1196 | void qeth_clear_qdio_buffers(struct qeth_card *card) | 918 | void qeth_clear_qdio_buffers(struct qeth_card *card) |
1197 | { | 919 | { |
1198 | int i; | 920 | int i, j; |
1199 | 921 | ||
1200 | QETH_CARD_TEXT(card, 2, "clearqdbf"); | 922 | QETH_CARD_TEXT(card, 2, "clearqdbf"); |
1201 | /* clear outbound buffers to free skbs */ | 923 | /* clear outbound buffers to free skbs */ |
1202 | for (i = 0; i < card->qdio.no_out_queues; ++i) { | 924 | for (i = 0; i < card->qdio.no_out_queues; ++i) |
1203 | if (card->qdio.out_qs[i]) { | 925 | if (card->qdio.out_qs[i]) { |
1204 | qeth_clear_outq_buffers(card->qdio.out_qs[i], 0); | 926 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) |
927 | qeth_clear_output_buffer(card->qdio.out_qs[i], | ||
928 | &card->qdio.out_qs[i]->bufs[j]); | ||
1205 | } | 929 | } |
1206 | } | ||
1207 | } | 930 | } |
1208 | EXPORT_SYMBOL_GPL(qeth_clear_qdio_buffers); | 931 | EXPORT_SYMBOL_GPL(qeth_clear_qdio_buffers); |
1209 | 932 | ||
@@ -1227,11 +950,6 @@ static void qeth_free_qdio_buffers(struct qeth_card *card) | |||
1227 | if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) == | 950 | if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) == |
1228 | QETH_QDIO_UNINITIALIZED) | 951 | QETH_QDIO_UNINITIALIZED) |
1229 | return; | 952 | return; |
1230 | |||
1231 | qeth_free_cq(card); | ||
1232 | cancel_delayed_work_sync(&card->buffer_reclaim_work); | ||
1233 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) | ||
1234 | dev_kfree_skb_any(card->qdio.in_q->bufs[j].rx_skb); | ||
1235 | kfree(card->qdio.in_q); | 953 | kfree(card->qdio.in_q); |
1236 | card->qdio.in_q = NULL; | 954 | card->qdio.in_q = NULL; |
1237 | /* inbound buffer pool */ | 955 | /* inbound buffer pool */ |
@@ -1239,7 +957,9 @@ static void qeth_free_qdio_buffers(struct qeth_card *card) | |||
1239 | /* free outbound qdio_qs */ | 957 | /* free outbound qdio_qs */ |
1240 | if (card->qdio.out_qs) { | 958 | if (card->qdio.out_qs) { |
1241 | for (i = 0; i < card->qdio.no_out_queues; ++i) { | 959 | for (i = 0; i < card->qdio.no_out_queues; ++i) { |
1242 | qeth_clear_outq_buffers(card->qdio.out_qs[i], 1); | 960 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) |
961 | qeth_clear_output_buffer(card->qdio.out_qs[i], | ||
962 | &card->qdio.out_qs[i]->bufs[j]); | ||
1243 | kfree(card->qdio.out_qs[i]); | 963 | kfree(card->qdio.out_qs[i]); |
1244 | } | 964 | } |
1245 | kfree(card->qdio.out_qs); | 965 | kfree(card->qdio.out_qs); |
@@ -1256,30 +976,7 @@ static void qeth_clean_channel(struct qeth_channel *channel) | |||
1256 | kfree(channel->iob[cnt].data); | 976 | kfree(channel->iob[cnt].data); |
1257 | } | 977 | } |
1258 | 978 | ||
1259 | static void qeth_set_single_write_queues(struct qeth_card *card) | 979 | static void qeth_get_channel_path_desc(struct qeth_card *card) |
1260 | { | ||
1261 | if ((atomic_read(&card->qdio.state) != QETH_QDIO_UNINITIALIZED) && | ||
1262 | (card->qdio.no_out_queues == 4)) | ||
1263 | qeth_free_qdio_buffers(card); | ||
1264 | |||
1265 | card->qdio.no_out_queues = 1; | ||
1266 | if (card->qdio.default_out_queue != 0) | ||
1267 | dev_info(&card->gdev->dev, "Priority Queueing not supported\n"); | ||
1268 | |||
1269 | card->qdio.default_out_queue = 0; | ||
1270 | } | ||
1271 | |||
1272 | static void qeth_set_multiple_write_queues(struct qeth_card *card) | ||
1273 | { | ||
1274 | if ((atomic_read(&card->qdio.state) != QETH_QDIO_UNINITIALIZED) && | ||
1275 | (card->qdio.no_out_queues == 1)) { | ||
1276 | qeth_free_qdio_buffers(card); | ||
1277 | card->qdio.default_out_queue = 2; | ||
1278 | } | ||
1279 | card->qdio.no_out_queues = 4; | ||
1280 | } | ||
1281 | |||
1282 | static void qeth_update_from_chp_desc(struct qeth_card *card) | ||
1283 | { | 980 | { |
1284 | struct ccw_device *ccwdev; | 981 | struct ccw_device *ccwdev; |
1285 | struct channelPath_dsc { | 982 | struct channelPath_dsc { |
@@ -1296,23 +993,36 @@ static void qeth_update_from_chp_desc(struct qeth_card *card) | |||
1296 | QETH_DBF_TEXT(SETUP, 2, "chp_desc"); | 993 | QETH_DBF_TEXT(SETUP, 2, "chp_desc"); |
1297 | 994 | ||
1298 | ccwdev = card->data.ccwdev; | 995 | ccwdev = card->data.ccwdev; |
1299 | chp_dsc = ccw_device_get_chp_desc(ccwdev, 0); | 996 | chp_dsc = (struct channelPath_dsc *)ccw_device_get_chp_desc(ccwdev, 0); |
1300 | if (!chp_dsc) | 997 | if (chp_dsc != NULL) { |
1301 | goto out; | 998 | /* CHPP field bit 6 == 1 -> single queue */ |
1302 | 999 | if ((chp_dsc->chpp & 0x02) == 0x02) { | |
1303 | card->info.func_level = 0x4100 + chp_dsc->desc; | 1000 | if ((atomic_read(&card->qdio.state) != |
1304 | if (card->info.type == QETH_CARD_TYPE_IQD) | 1001 | QETH_QDIO_UNINITIALIZED) && |
1305 | goto out; | 1002 | (card->qdio.no_out_queues == 4)) |
1306 | 1003 | /* change from 4 to 1 outbound queues */ | |
1307 | /* CHPP field bit 6 == 1 -> single queue */ | 1004 | qeth_free_qdio_buffers(card); |
1308 | if ((chp_dsc->chpp & 0x02) == 0x02) | 1005 | card->qdio.no_out_queues = 1; |
1309 | qeth_set_single_write_queues(card); | 1006 | if (card->qdio.default_out_queue != 0) |
1310 | else | 1007 | dev_info(&card->gdev->dev, |
1311 | qeth_set_multiple_write_queues(card); | 1008 | "Priority Queueing not supported\n"); |
1312 | out: | 1009 | card->qdio.default_out_queue = 0; |
1313 | kfree(chp_dsc); | 1010 | } else { |
1011 | if ((atomic_read(&card->qdio.state) != | ||
1012 | QETH_QDIO_UNINITIALIZED) && | ||
1013 | (card->qdio.no_out_queues == 1)) { | ||
1014 | /* change from 1 to 4 outbound queues */ | ||
1015 | qeth_free_qdio_buffers(card); | ||
1016 | card->qdio.default_out_queue = 2; | ||
1017 | } | ||
1018 | card->qdio.no_out_queues = 4; | ||
1019 | } | ||
1020 | card->info.func_level = 0x4100 + chp_dsc->desc; | ||
1021 | kfree(chp_dsc); | ||
1022 | } | ||
1314 | QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues); | 1023 | QETH_DBF_TEXT_(SETUP, 2, "nr:%x", card->qdio.no_out_queues); |
1315 | QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level); | 1024 | QETH_DBF_TEXT_(SETUP, 2, "lvl:%02x", card->info.func_level); |
1025 | return; | ||
1316 | } | 1026 | } |
1317 | 1027 | ||
1318 | static void qeth_init_qdio_info(struct qeth_card *card) | 1028 | static void qeth_init_qdio_info(struct qeth_card *card) |
@@ -1334,12 +1044,13 @@ static void qeth_set_intial_options(struct qeth_card *card) | |||
1334 | { | 1044 | { |
1335 | card->options.route4.type = NO_ROUTER; | 1045 | card->options.route4.type = NO_ROUTER; |
1336 | card->options.route6.type = NO_ROUTER; | 1046 | card->options.route6.type = NO_ROUTER; |
1047 | card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS; | ||
1048 | card->options.macaddr_mode = QETH_TR_MACADDR_NONCANONICAL; | ||
1337 | card->options.fake_broadcast = 0; | 1049 | card->options.fake_broadcast = 0; |
1338 | card->options.add_hhlen = DEFAULT_ADD_HHLEN; | 1050 | card->options.add_hhlen = DEFAULT_ADD_HHLEN; |
1339 | card->options.performance_stats = 0; | 1051 | card->options.performance_stats = 0; |
1340 | card->options.rx_sg_cb = QETH_RX_SG_CB; | 1052 | card->options.rx_sg_cb = QETH_RX_SG_CB; |
1341 | card->options.isolation = ISOLATION_MODE_NONE; | 1053 | card->options.isolation = ISOLATION_MODE_NONE; |
1342 | card->options.cq = QETH_CQ_DISABLED; | ||
1343 | } | 1054 | } |
1344 | 1055 | ||
1345 | static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread) | 1056 | static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread) |
@@ -1359,7 +1070,6 @@ static int qeth_do_start_thread(struct qeth_card *card, unsigned long thread) | |||
1359 | 1070 | ||
1360 | static void qeth_start_kernel_thread(struct work_struct *work) | 1071 | static void qeth_start_kernel_thread(struct work_struct *work) |
1361 | { | 1072 | { |
1362 | struct task_struct *ts; | ||
1363 | struct qeth_card *card = container_of(work, struct qeth_card, | 1073 | struct qeth_card *card = container_of(work, struct qeth_card, |
1364 | kernel_thread_starter); | 1074 | kernel_thread_starter); |
1365 | QETH_CARD_TEXT(card , 2, "strthrd"); | 1075 | QETH_CARD_TEXT(card , 2, "strthrd"); |
@@ -1367,15 +1077,9 @@ static void qeth_start_kernel_thread(struct work_struct *work) | |||
1367 | if (card->read.state != CH_STATE_UP && | 1077 | if (card->read.state != CH_STATE_UP && |
1368 | card->write.state != CH_STATE_UP) | 1078 | card->write.state != CH_STATE_UP) |
1369 | return; | 1079 | return; |
1370 | if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) { | 1080 | if (qeth_do_start_thread(card, QETH_RECOVER_THREAD)) |
1371 | ts = kthread_run(card->discipline->recover, (void *)card, | 1081 | kthread_run(card->discipline.recover, (void *) card, |
1372 | "qeth_recover"); | 1082 | "qeth_recover"); |
1373 | if (IS_ERR(ts)) { | ||
1374 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | ||
1375 | qeth_clear_thread_running_bit(card, | ||
1376 | QETH_RECOVER_THREAD); | ||
1377 | } | ||
1378 | } | ||
1379 | } | 1083 | } |
1380 | 1084 | ||
1381 | static int qeth_setup_card(struct qeth_card *card) | 1085 | static int qeth_setup_card(struct qeth_card *card) |
@@ -1415,7 +1119,6 @@ static int qeth_setup_card(struct qeth_card *card) | |||
1415 | card->ipato.invert6 = 0; | 1119 | card->ipato.invert6 = 0; |
1416 | /* init QDIO stuff */ | 1120 | /* init QDIO stuff */ |
1417 | qeth_init_qdio_info(card); | 1121 | qeth_init_qdio_info(card); |
1418 | INIT_DELAYED_WORK(&card->buffer_reclaim_work, qeth_buffer_reclaim_work); | ||
1419 | return 0; | 1122 | return 0; |
1420 | } | 1123 | } |
1421 | 1124 | ||
@@ -1437,7 +1140,7 @@ static struct qeth_card *qeth_alloc_card(void) | |||
1437 | if (!card) | 1140 | if (!card) |
1438 | goto out; | 1141 | goto out; |
1439 | QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); | 1142 | QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *)); |
1440 | card->ip_tbd_list = kzalloc(sizeof(struct list_head), GFP_KERNEL); | 1143 | card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_KERNEL); |
1441 | if (!card->ip_tbd_list) { | 1144 | if (!card->ip_tbd_list) { |
1442 | QETH_DBF_TEXT(SETUP, 0, "iptbdnom"); | 1145 | QETH_DBF_TEXT(SETUP, 0, "iptbdnom"); |
1443 | goto out_card; | 1146 | goto out_card; |
@@ -1477,10 +1180,9 @@ static int qeth_determine_card_type(struct qeth_card *card) | |||
1477 | card->info.type = known_devices[i][QETH_DEV_MODEL_IND]; | 1180 | card->info.type = known_devices[i][QETH_DEV_MODEL_IND]; |
1478 | card->qdio.no_out_queues = | 1181 | card->qdio.no_out_queues = |
1479 | known_devices[i][QETH_QUEUE_NO_IND]; | 1182 | known_devices[i][QETH_QUEUE_NO_IND]; |
1480 | card->qdio.no_in_queues = 1; | ||
1481 | card->info.is_multicast_different = | 1183 | card->info.is_multicast_different = |
1482 | known_devices[i][QETH_MULTICAST_IND]; | 1184 | known_devices[i][QETH_MULTICAST_IND]; |
1483 | qeth_update_from_chp_desc(card); | 1185 | qeth_get_channel_path_desc(card); |
1484 | return 0; | 1186 | return 0; |
1485 | } | 1187 | } |
1486 | i++; | 1188 | i++; |
@@ -1675,8 +1377,7 @@ static void qeth_configure_blkt_default(struct qeth_card *card, char *prcd) | |||
1675 | { | 1377 | { |
1676 | QETH_DBF_TEXT(SETUP, 2, "cfgblkt"); | 1378 | QETH_DBF_TEXT(SETUP, 2, "cfgblkt"); |
1677 | 1379 | ||
1678 | if (prcd[74] == 0xF0 && prcd[75] == 0xF0 && | 1380 | if (prcd[74] == 0xF0 && prcd[75] == 0xF0 && prcd[76] == 0xF5) { |
1679 | (prcd[76] == 0xF5 || prcd[76] == 0xF6)) { | ||
1680 | card->info.blkt.time_total = 250; | 1381 | card->info.blkt.time_total = 250; |
1681 | card->info.blkt.inter_packet = 5; | 1382 | card->info.blkt.inter_packet = 5; |
1682 | card->info.blkt.inter_packet_jumbo = 15; | 1383 | card->info.blkt.inter_packet_jumbo = 15; |
@@ -2036,7 +1737,7 @@ int qeth_send_control_data(struct qeth_card *card, int len, | |||
2036 | if (time_after(jiffies, timeout)) | 1737 | if (time_after(jiffies, timeout)) |
2037 | goto time_err; | 1738 | goto time_err; |
2038 | cpu_relax(); | 1739 | cpu_relax(); |
2039 | } | 1740 | }; |
2040 | } | 1741 | } |
2041 | 1742 | ||
2042 | if (reply->rc == -EIO) | 1743 | if (reply->rc == -EIO) |
@@ -2279,6 +1980,7 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply, | |||
2279 | unsigned long data) | 1980 | unsigned long data) |
2280 | { | 1981 | { |
2281 | struct qeth_cmd_buffer *iob; | 1982 | struct qeth_cmd_buffer *iob; |
1983 | int rc = 0; | ||
2282 | 1984 | ||
2283 | QETH_DBF_TEXT(SETUP, 2, "ulpstpcb"); | 1985 | QETH_DBF_TEXT(SETUP, 2, "ulpstpcb"); |
2284 | 1986 | ||
@@ -2294,7 +1996,7 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply, | |||
2294 | iob->rc = -EMLINK; | 1996 | iob->rc = -EMLINK; |
2295 | } | 1997 | } |
2296 | QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc); | 1998 | QETH_DBF_TEXT_(SETUP, 2, " rc%d", iob->rc); |
2297 | return 0; | 1999 | return rc; |
2298 | } | 2000 | } |
2299 | 2001 | ||
2300 | static int qeth_ulp_setup(struct qeth_card *card) | 2002 | static int qeth_ulp_setup(struct qeth_card *card) |
@@ -2325,37 +2027,6 @@ static int qeth_ulp_setup(struct qeth_card *card) | |||
2325 | return rc; | 2027 | return rc; |
2326 | } | 2028 | } |
2327 | 2029 | ||
2328 | static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx) | ||
2329 | { | ||
2330 | int rc; | ||
2331 | struct qeth_qdio_out_buffer *newbuf; | ||
2332 | |||
2333 | rc = 0; | ||
2334 | newbuf = kmem_cache_zalloc(qeth_qdio_outbuf_cache, GFP_ATOMIC); | ||
2335 | if (!newbuf) { | ||
2336 | rc = -ENOMEM; | ||
2337 | goto out; | ||
2338 | } | ||
2339 | newbuf->buffer = &q->qdio_bufs[bidx]; | ||
2340 | skb_queue_head_init(&newbuf->skb_list); | ||
2341 | lockdep_set_class(&newbuf->skb_list.lock, &qdio_out_skb_queue_key); | ||
2342 | newbuf->q = q; | ||
2343 | newbuf->aob = NULL; | ||
2344 | newbuf->next_pending = q->bufs[bidx]; | ||
2345 | atomic_set(&newbuf->state, QETH_QDIO_BUF_EMPTY); | ||
2346 | q->bufs[bidx] = newbuf; | ||
2347 | if (q->bufstates) { | ||
2348 | q->bufstates[bidx].user = newbuf; | ||
2349 | QETH_CARD_TEXT_(q->card, 2, "nbs%d", bidx); | ||
2350 | QETH_CARD_TEXT_(q->card, 2, "%lx", (long) newbuf); | ||
2351 | QETH_CARD_TEXT_(q->card, 2, "%lx", | ||
2352 | (long) newbuf->next_pending); | ||
2353 | } | ||
2354 | out: | ||
2355 | return rc; | ||
2356 | } | ||
2357 | |||
2358 | |||
2359 | static int qeth_alloc_qdio_buffers(struct qeth_card *card) | 2030 | static int qeth_alloc_qdio_buffers(struct qeth_card *card) |
2360 | { | 2031 | { |
2361 | int i, j; | 2032 | int i, j; |
@@ -2366,63 +2037,52 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card) | |||
2366 | QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED) | 2037 | QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED) |
2367 | return 0; | 2038 | return 0; |
2368 | 2039 | ||
2369 | card->qdio.in_q = kzalloc(sizeof(struct qeth_qdio_q), | 2040 | card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), |
2370 | GFP_KERNEL); | 2041 | GFP_KERNEL); |
2371 | if (!card->qdio.in_q) | 2042 | if (!card->qdio.in_q) |
2372 | goto out_nomem; | 2043 | goto out_nomem; |
2373 | QETH_DBF_TEXT(SETUP, 2, "inq"); | 2044 | QETH_DBF_TEXT(SETUP, 2, "inq"); |
2374 | QETH_DBF_HEX(SETUP, 2, &card->qdio.in_q, sizeof(void *)); | 2045 | QETH_DBF_HEX(SETUP, 2, &card->qdio.in_q, sizeof(void *)); |
2375 | memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q)); | 2046 | memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q)); |
2376 | /* give inbound qeth_qdio_buffers their qdio_buffers */ | 2047 | /* give inbound qeth_qdio_buffers their qdio_buffers */ |
2377 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) { | 2048 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) |
2378 | card->qdio.in_q->bufs[i].buffer = | 2049 | card->qdio.in_q->bufs[i].buffer = |
2379 | &card->qdio.in_q->qdio_bufs[i]; | 2050 | &card->qdio.in_q->qdio_bufs[i]; |
2380 | card->qdio.in_q->bufs[i].rx_skb = NULL; | ||
2381 | } | ||
2382 | /* inbound buffer pool */ | 2051 | /* inbound buffer pool */ |
2383 | if (qeth_alloc_buffer_pool(card)) | 2052 | if (qeth_alloc_buffer_pool(card)) |
2384 | goto out_freeinq; | 2053 | goto out_freeinq; |
2385 | |||
2386 | /* outbound */ | 2054 | /* outbound */ |
2387 | card->qdio.out_qs = | 2055 | card->qdio.out_qs = |
2388 | kzalloc(card->qdio.no_out_queues * | 2056 | kmalloc(card->qdio.no_out_queues * |
2389 | sizeof(struct qeth_qdio_out_q *), GFP_KERNEL); | 2057 | sizeof(struct qeth_qdio_out_q *), GFP_KERNEL); |
2390 | if (!card->qdio.out_qs) | 2058 | if (!card->qdio.out_qs) |
2391 | goto out_freepool; | 2059 | goto out_freepool; |
2392 | for (i = 0; i < card->qdio.no_out_queues; ++i) { | 2060 | for (i = 0; i < card->qdio.no_out_queues; ++i) { |
2393 | card->qdio.out_qs[i] = kzalloc(sizeof(struct qeth_qdio_out_q), | 2061 | card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q), |
2394 | GFP_KERNEL); | 2062 | GFP_KERNEL); |
2395 | if (!card->qdio.out_qs[i]) | 2063 | if (!card->qdio.out_qs[i]) |
2396 | goto out_freeoutq; | 2064 | goto out_freeoutq; |
2397 | QETH_DBF_TEXT_(SETUP, 2, "outq %i", i); | 2065 | QETH_DBF_TEXT_(SETUP, 2, "outq %i", i); |
2398 | QETH_DBF_HEX(SETUP, 2, &card->qdio.out_qs[i], sizeof(void *)); | 2066 | QETH_DBF_HEX(SETUP, 2, &card->qdio.out_qs[i], sizeof(void *)); |
2067 | memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q)); | ||
2399 | card->qdio.out_qs[i]->queue_no = i; | 2068 | card->qdio.out_qs[i]->queue_no = i; |
2400 | /* give outbound qeth_qdio_buffers their qdio_buffers */ | 2069 | /* give outbound qeth_qdio_buffers their qdio_buffers */ |
2401 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { | 2070 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { |
2402 | WARN_ON(card->qdio.out_qs[i]->bufs[j] != NULL); | 2071 | card->qdio.out_qs[i]->bufs[j].buffer = |
2403 | if (qeth_init_qdio_out_buf(card->qdio.out_qs[i], j)) | 2072 | &card->qdio.out_qs[i]->qdio_bufs[j]; |
2404 | goto out_freeoutqbufs; | 2073 | skb_queue_head_init(&card->qdio.out_qs[i]->bufs[j]. |
2074 | skb_list); | ||
2075 | lockdep_set_class( | ||
2076 | &card->qdio.out_qs[i]->bufs[j].skb_list.lock, | ||
2077 | &qdio_out_skb_queue_key); | ||
2078 | INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list); | ||
2405 | } | 2079 | } |
2406 | } | 2080 | } |
2407 | |||
2408 | /* completion */ | ||
2409 | if (qeth_alloc_cq(card)) | ||
2410 | goto out_freeoutq; | ||
2411 | |||
2412 | return 0; | 2081 | return 0; |
2413 | 2082 | ||
2414 | out_freeoutqbufs: | ||
2415 | while (j > 0) { | ||
2416 | --j; | ||
2417 | kmem_cache_free(qeth_qdio_outbuf_cache, | ||
2418 | card->qdio.out_qs[i]->bufs[j]); | ||
2419 | card->qdio.out_qs[i]->bufs[j] = NULL; | ||
2420 | } | ||
2421 | out_freeoutq: | 2083 | out_freeoutq: |
2422 | while (i > 0) { | 2084 | while (i > 0) |
2423 | kfree(card->qdio.out_qs[--i]); | 2085 | kfree(card->qdio.out_qs[--i]); |
2424 | qeth_clear_outq_buffers(card->qdio.out_qs[i], 1); | ||
2425 | } | ||
2426 | kfree(card->qdio.out_qs); | 2086 | kfree(card->qdio.out_qs); |
2427 | card->qdio.out_qs = NULL; | 2087 | card->qdio.out_qs = NULL; |
2428 | out_freepool: | 2088 | out_freepool: |
@@ -2693,12 +2353,6 @@ static int qeth_init_input_buffer(struct qeth_card *card, | |||
2693 | struct qeth_buffer_pool_entry *pool_entry; | 2353 | struct qeth_buffer_pool_entry *pool_entry; |
2694 | int i; | 2354 | int i; |
2695 | 2355 | ||
2696 | if ((card->options.cq == QETH_CQ_ENABLED) && (!buf->rx_skb)) { | ||
2697 | buf->rx_skb = dev_alloc_skb(QETH_RX_PULL_LEN + ETH_HLEN); | ||
2698 | if (!buf->rx_skb) | ||
2699 | return 1; | ||
2700 | } | ||
2701 | |||
2702 | pool_entry = qeth_find_free_buffer_pool_entry(card); | 2356 | pool_entry = qeth_find_free_buffer_pool_entry(card); |
2703 | if (!pool_entry) | 2357 | if (!pool_entry) |
2704 | return 1; | 2358 | return 1; |
@@ -2745,21 +2399,13 @@ int qeth_init_qdio_queues(struct qeth_card *card) | |||
2745 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); | 2399 | QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc); |
2746 | return rc; | 2400 | return rc; |
2747 | } | 2401 | } |
2748 | |||
2749 | /* completion */ | ||
2750 | rc = qeth_cq_init(card); | ||
2751 | if (rc) { | ||
2752 | return rc; | ||
2753 | } | ||
2754 | |||
2755 | /* outbound queue */ | 2402 | /* outbound queue */ |
2756 | for (i = 0; i < card->qdio.no_out_queues; ++i) { | 2403 | for (i = 0; i < card->qdio.no_out_queues; ++i) { |
2757 | memset(card->qdio.out_qs[i]->qdio_bufs, 0, | 2404 | memset(card->qdio.out_qs[i]->qdio_bufs, 0, |
2758 | QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer)); | 2405 | QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer)); |
2759 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { | 2406 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) { |
2760 | qeth_clear_output_buffer(card->qdio.out_qs[i], | 2407 | qeth_clear_output_buffer(card->qdio.out_qs[i], |
2761 | card->qdio.out_qs[i]->bufs[j], | 2408 | &card->qdio.out_qs[i]->bufs[j]); |
2762 | QETH_QDIO_BUF_EMPTY); | ||
2763 | } | 2409 | } |
2764 | card->qdio.out_qs[i]->card = card; | 2410 | card->qdio.out_qs[i]->card = card; |
2765 | card->qdio.out_qs[i]->next_buf_to_fill = 0; | 2411 | card->qdio.out_qs[i]->next_buf_to_fill = 0; |
@@ -2940,33 +2586,16 @@ static int qeth_query_ipassists_cb(struct qeth_card *card, | |||
2940 | QETH_DBF_TEXT(SETUP, 2, "qipasscb"); | 2586 | QETH_DBF_TEXT(SETUP, 2, "qipasscb"); |
2941 | 2587 | ||
2942 | cmd = (struct qeth_ipa_cmd *) data; | 2588 | cmd = (struct qeth_ipa_cmd *) data; |
2943 | |||
2944 | switch (cmd->hdr.return_code) { | ||
2945 | case IPA_RC_NOTSUPP: | ||
2946 | case IPA_RC_L2_UNSUPPORTED_CMD: | ||
2947 | QETH_DBF_TEXT(SETUP, 2, "ipaunsup"); | ||
2948 | card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS; | ||
2949 | card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS; | ||
2950 | return -0; | ||
2951 | default: | ||
2952 | if (cmd->hdr.return_code) { | ||
2953 | QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled " | ||
2954 | "rc=%d\n", | ||
2955 | dev_name(&card->gdev->dev), | ||
2956 | cmd->hdr.return_code); | ||
2957 | return 0; | ||
2958 | } | ||
2959 | } | ||
2960 | |||
2961 | if (cmd->hdr.prot_version == QETH_PROT_IPV4) { | 2589 | if (cmd->hdr.prot_version == QETH_PROT_IPV4) { |
2962 | card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; | 2590 | card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; |
2963 | card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; | 2591 | card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; |
2964 | } else if (cmd->hdr.prot_version == QETH_PROT_IPV6) { | 2592 | } else { |
2965 | card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; | 2593 | card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; |
2966 | card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; | 2594 | card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; |
2967 | } else | 2595 | } |
2968 | QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected" | 2596 | QETH_DBF_TEXT(SETUP, 2, "suppenbl"); |
2969 | "\n", dev_name(&card->gdev->dev)); | 2597 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_supported); |
2598 | QETH_DBF_TEXT_(SETUP, 2, "%x", cmd->hdr.ipa_enabled); | ||
2970 | return 0; | 2599 | return 0; |
2971 | } | 2600 | } |
2972 | 2601 | ||
@@ -3016,7 +2645,7 @@ static void qeth_get_trap_id(struct qeth_card *card, struct qeth_trap_id *tid) | |||
3016 | struct sysinfo_2_2_2 *info222 = (struct sysinfo_2_2_2 *)info; | 2645 | struct sysinfo_2_2_2 *info222 = (struct sysinfo_2_2_2 *)info; |
3017 | struct sysinfo_3_2_2 *info322 = (struct sysinfo_3_2_2 *)info; | 2646 | struct sysinfo_3_2_2 *info322 = (struct sysinfo_3_2_2 *)info; |
3018 | struct ccw_dev_id ccwid; | 2647 | struct ccw_dev_id ccwid; |
3019 | int level; | 2648 | int level, rc; |
3020 | 2649 | ||
3021 | tid->chpid = card->info.chpid; | 2650 | tid->chpid = card->info.chpid; |
3022 | ccw_device_get_id(CARD_RDEV(card), &ccwid); | 2651 | ccw_device_get_id(CARD_RDEV(card), &ccwid); |
@@ -3024,10 +2653,17 @@ static void qeth_get_trap_id(struct qeth_card *card, struct qeth_trap_id *tid) | |||
3024 | tid->devno = ccwid.devno; | 2653 | tid->devno = ccwid.devno; |
3025 | if (!info) | 2654 | if (!info) |
3026 | return; | 2655 | return; |
3027 | level = stsi(NULL, 0, 0, 0); | 2656 | |
3028 | if ((level >= 2) && (stsi(info222, 2, 2, 2) == 0)) | 2657 | rc = stsi(NULL, 0, 0, 0); |
2658 | if (rc == -ENOSYS) | ||
2659 | level = rc; | ||
2660 | else | ||
2661 | level = (((unsigned int) rc) >> 28); | ||
2662 | |||
2663 | if ((level >= 2) && (stsi(info222, 2, 2, 2) != -ENOSYS)) | ||
3029 | tid->lparnr = info222->lpar_number; | 2664 | tid->lparnr = info222->lpar_number; |
3030 | if ((level >= 3) && (stsi(info322, 3, 2, 2) == 0)) { | 2665 | |
2666 | if ((level >= 3) && (stsi(info322, 3, 2, 2) != -ENOSYS)) { | ||
3031 | EBCASC(info322->vm[0].name, sizeof(info322->vm[0].name)); | 2667 | EBCASC(info322->vm[0].name, sizeof(info322->vm[0].name)); |
3032 | memcpy(tid->vmname, info322->vm[0].name, sizeof(tid->vmname)); | 2668 | memcpy(tid->vmname, info322->vm[0].name, sizeof(tid->vmname)); |
3033 | } | 2669 | } |
@@ -3098,19 +2734,9 @@ int qeth_check_qdio_errors(struct qeth_card *card, struct qdio_buffer *buf, | |||
3098 | } | 2734 | } |
3099 | EXPORT_SYMBOL_GPL(qeth_check_qdio_errors); | 2735 | EXPORT_SYMBOL_GPL(qeth_check_qdio_errors); |
3100 | 2736 | ||
3101 | void qeth_buffer_reclaim_work(struct work_struct *work) | ||
3102 | { | ||
3103 | struct qeth_card *card = container_of(work, struct qeth_card, | ||
3104 | buffer_reclaim_work.work); | ||
3105 | |||
3106 | QETH_CARD_TEXT_(card, 2, "brw:%x", card->reclaim_index); | ||
3107 | qeth_queue_input_buffer(card, card->reclaim_index); | ||
3108 | } | ||
3109 | |||
3110 | void qeth_queue_input_buffer(struct qeth_card *card, int index) | 2737 | void qeth_queue_input_buffer(struct qeth_card *card, int index) |
3111 | { | 2738 | { |
3112 | struct qeth_qdio_q *queue = card->qdio.in_q; | 2739 | struct qeth_qdio_q *queue = card->qdio.in_q; |
3113 | struct list_head *lh; | ||
3114 | int count; | 2740 | int count; |
3115 | int i; | 2741 | int i; |
3116 | int rc; | 2742 | int rc; |
@@ -3142,20 +2768,6 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index) | |||
3142 | atomic_add_unless(&card->force_alloc_skb, -1, 0); | 2768 | atomic_add_unless(&card->force_alloc_skb, -1, 0); |
3143 | } | 2769 | } |
3144 | 2770 | ||
3145 | if (!count) { | ||
3146 | i = 0; | ||
3147 | list_for_each(lh, &card->qdio.in_buf_pool.entry_list) | ||
3148 | i++; | ||
3149 | if (i == card->qdio.in_buf_pool.buf_count) { | ||
3150 | QETH_CARD_TEXT(card, 2, "qsarbw"); | ||
3151 | card->reclaim_index = index; | ||
3152 | schedule_delayed_work( | ||
3153 | &card->buffer_reclaim_work, | ||
3154 | QETH_RECLAIM_WORK_TIME); | ||
3155 | } | ||
3156 | return; | ||
3157 | } | ||
3158 | |||
3159 | /* | 2771 | /* |
3160 | * according to old code it should be avoided to requeue all | 2772 | * according to old code it should be avoided to requeue all |
3161 | * 128 buffers in order to benefit from PCI avoidance. | 2773 | * 128 buffers in order to benefit from PCI avoidance. |
@@ -3175,6 +2787,8 @@ void qeth_queue_input_buffer(struct qeth_card *card, int index) | |||
3175 | qeth_get_micros() - | 2787 | qeth_get_micros() - |
3176 | card->perf_stats.inbound_do_qdio_start_time; | 2788 | card->perf_stats.inbound_do_qdio_start_time; |
3177 | if (rc) { | 2789 | if (rc) { |
2790 | dev_warn(&card->gdev->dev, | ||
2791 | "QDIO reported an error, rc=%i\n", rc); | ||
3178 | QETH_CARD_TEXT(card, 2, "qinberr"); | 2792 | QETH_CARD_TEXT(card, 2, "qinberr"); |
3179 | } | 2793 | } |
3180 | queue->next_buf_to_init = (queue->next_buf_to_init + count) % | 2794 | queue->next_buf_to_init = (queue->next_buf_to_init + count) % |
@@ -3248,12 +2862,12 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | |||
3248 | queue->card->perf_stats.sc_p_dp++; | 2862 | queue->card->perf_stats.sc_p_dp++; |
3249 | queue->do_pack = 0; | 2863 | queue->do_pack = 0; |
3250 | /* flush packing buffers */ | 2864 | /* flush packing buffers */ |
3251 | buffer = queue->bufs[queue->next_buf_to_fill]; | 2865 | buffer = &queue->bufs[queue->next_buf_to_fill]; |
3252 | if ((atomic_read(&buffer->state) == | 2866 | if ((atomic_read(&buffer->state) == |
3253 | QETH_QDIO_BUF_EMPTY) && | 2867 | QETH_QDIO_BUF_EMPTY) && |
3254 | (buffer->next_element_to_fill > 0)) { | 2868 | (buffer->next_element_to_fill > 0)) { |
3255 | atomic_set(&buffer->state, | 2869 | atomic_set(&buffer->state, |
3256 | QETH_QDIO_BUF_PRIMED); | 2870 | QETH_QDIO_BUF_PRIMED); |
3257 | flush_count++; | 2871 | flush_count++; |
3258 | queue->next_buf_to_fill = | 2872 | queue->next_buf_to_fill = |
3259 | (queue->next_buf_to_fill + 1) % | 2873 | (queue->next_buf_to_fill + 1) % |
@@ -3264,7 +2878,6 @@ static int qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | |||
3264 | return flush_count; | 2878 | return flush_count; |
3265 | } | 2879 | } |
3266 | 2880 | ||
3267 | |||
3268 | /* | 2881 | /* |
3269 | * Called to flush a packing buffer if no more pci flags are on the queue. | 2882 | * Called to flush a packing buffer if no more pci flags are on the queue. |
3270 | * Checks if there is a packing buffer and prepares it to be flushed. | 2883 | * Checks if there is a packing buffer and prepares it to be flushed. |
@@ -3274,7 +2887,7 @@ static int qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue) | |||
3274 | { | 2887 | { |
3275 | struct qeth_qdio_out_buffer *buffer; | 2888 | struct qeth_qdio_out_buffer *buffer; |
3276 | 2889 | ||
3277 | buffer = queue->bufs[queue->next_buf_to_fill]; | 2890 | buffer = &queue->bufs[queue->next_buf_to_fill]; |
3278 | if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) && | 2891 | if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) && |
3279 | (buffer->next_element_to_fill > 0)) { | 2892 | (buffer->next_element_to_fill > 0)) { |
3280 | /* it's a packing buffer */ | 2893 | /* it's a packing buffer */ |
@@ -3295,14 +2908,10 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, | |||
3295 | unsigned int qdio_flags; | 2908 | unsigned int qdio_flags; |
3296 | 2909 | ||
3297 | for (i = index; i < index + count; ++i) { | 2910 | for (i = index; i < index + count; ++i) { |
3298 | int bidx = i % QDIO_MAX_BUFFERS_PER_Q; | 2911 | buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; |
3299 | buf = queue->bufs[bidx]; | ||
3300 | buf->buffer->element[buf->next_element_to_fill - 1].eflags |= | 2912 | buf->buffer->element[buf->next_element_to_fill - 1].eflags |= |
3301 | SBAL_EFLAGS_LAST_ENTRY; | 2913 | SBAL_EFLAGS_LAST_ENTRY; |
3302 | 2914 | ||
3303 | if (queue->bufstates) | ||
3304 | queue->bufstates[bidx].user = buf; | ||
3305 | |||
3306 | if (queue->card->info.type == QETH_CARD_TYPE_IQD) | 2915 | if (queue->card->info.type == QETH_CARD_TYPE_IQD) |
3307 | continue; | 2916 | continue; |
3308 | 2917 | ||
@@ -3351,12 +2960,9 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, | |||
3351 | if (rc) { | 2960 | if (rc) { |
3352 | queue->card->stats.tx_errors += count; | 2961 | queue->card->stats.tx_errors += count; |
3353 | /* ignore temporary SIGA errors without busy condition */ | 2962 | /* ignore temporary SIGA errors without busy condition */ |
3354 | if (rc == -ENOBUFS) | 2963 | if (rc == QDIO_ERROR_SIGA_TARGET) |
3355 | return; | 2964 | return; |
3356 | QETH_CARD_TEXT(queue->card, 2, "flushbuf"); | 2965 | QETH_CARD_TEXT(queue->card, 2, "flushbuf"); |
3357 | QETH_CARD_TEXT_(queue->card, 2, " q%d", queue->queue_no); | ||
3358 | QETH_CARD_TEXT_(queue->card, 2, " idx%d", index); | ||
3359 | QETH_CARD_TEXT_(queue->card, 2, " c%d", count); | ||
3360 | QETH_CARD_TEXT_(queue->card, 2, " err%d", rc); | 2966 | QETH_CARD_TEXT_(queue->card, 2, " err%d", rc); |
3361 | 2967 | ||
3362 | /* this must not happen under normal circumstances. if it | 2968 | /* this must not happen under normal circumstances. if it |
@@ -3418,120 +3024,14 @@ void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue, | |||
3418 | } | 3024 | } |
3419 | EXPORT_SYMBOL_GPL(qeth_qdio_start_poll); | 3025 | EXPORT_SYMBOL_GPL(qeth_qdio_start_poll); |
3420 | 3026 | ||
3421 | int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq) | ||
3422 | { | ||
3423 | int rc; | ||
3424 | |||
3425 | if (card->options.cq == QETH_CQ_NOTAVAILABLE) { | ||
3426 | rc = -1; | ||
3427 | goto out; | ||
3428 | } else { | ||
3429 | if (card->options.cq == cq) { | ||
3430 | rc = 0; | ||
3431 | goto out; | ||
3432 | } | ||
3433 | |||
3434 | if (card->state != CARD_STATE_DOWN && | ||
3435 | card->state != CARD_STATE_RECOVER) { | ||
3436 | rc = -1; | ||
3437 | goto out; | ||
3438 | } | ||
3439 | |||
3440 | qeth_free_qdio_buffers(card); | ||
3441 | card->options.cq = cq; | ||
3442 | rc = 0; | ||
3443 | } | ||
3444 | out: | ||
3445 | return rc; | ||
3446 | |||
3447 | } | ||
3448 | EXPORT_SYMBOL_GPL(qeth_configure_cq); | ||
3449 | |||
3450 | |||
3451 | static void qeth_qdio_cq_handler(struct qeth_card *card, | ||
3452 | unsigned int qdio_err, | ||
3453 | unsigned int queue, int first_element, int count) { | ||
3454 | struct qeth_qdio_q *cq = card->qdio.c_q; | ||
3455 | int i; | ||
3456 | int rc; | ||
3457 | |||
3458 | if (!qeth_is_cq(card, queue)) | ||
3459 | goto out; | ||
3460 | |||
3461 | QETH_CARD_TEXT_(card, 5, "qcqhe%d", first_element); | ||
3462 | QETH_CARD_TEXT_(card, 5, "qcqhc%d", count); | ||
3463 | QETH_CARD_TEXT_(card, 5, "qcqherr%d", qdio_err); | ||
3464 | |||
3465 | if (qdio_err) { | ||
3466 | netif_stop_queue(card->dev); | ||
3467 | qeth_schedule_recovery(card); | ||
3468 | goto out; | ||
3469 | } | ||
3470 | |||
3471 | if (card->options.performance_stats) { | ||
3472 | card->perf_stats.cq_cnt++; | ||
3473 | card->perf_stats.cq_start_time = qeth_get_micros(); | ||
3474 | } | ||
3475 | |||
3476 | for (i = first_element; i < first_element + count; ++i) { | ||
3477 | int bidx = i % QDIO_MAX_BUFFERS_PER_Q; | ||
3478 | struct qdio_buffer *buffer = &cq->qdio_bufs[bidx]; | ||
3479 | int e; | ||
3480 | |||
3481 | e = 0; | ||
3482 | while (buffer->element[e].addr) { | ||
3483 | unsigned long phys_aob_addr; | ||
3484 | |||
3485 | phys_aob_addr = (unsigned long) buffer->element[e].addr; | ||
3486 | qeth_qdio_handle_aob(card, phys_aob_addr); | ||
3487 | buffer->element[e].addr = NULL; | ||
3488 | buffer->element[e].eflags = 0; | ||
3489 | buffer->element[e].sflags = 0; | ||
3490 | buffer->element[e].length = 0; | ||
3491 | |||
3492 | ++e; | ||
3493 | } | ||
3494 | |||
3495 | buffer->element[15].eflags = 0; | ||
3496 | buffer->element[15].sflags = 0; | ||
3497 | } | ||
3498 | rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, queue, | ||
3499 | card->qdio.c_q->next_buf_to_init, | ||
3500 | count); | ||
3501 | if (rc) { | ||
3502 | dev_warn(&card->gdev->dev, | ||
3503 | "QDIO reported an error, rc=%i\n", rc); | ||
3504 | QETH_CARD_TEXT(card, 2, "qcqherr"); | ||
3505 | } | ||
3506 | card->qdio.c_q->next_buf_to_init = (card->qdio.c_q->next_buf_to_init | ||
3507 | + count) % QDIO_MAX_BUFFERS_PER_Q; | ||
3508 | |||
3509 | netif_wake_queue(card->dev); | ||
3510 | |||
3511 | if (card->options.performance_stats) { | ||
3512 | int delta_t = qeth_get_micros(); | ||
3513 | delta_t -= card->perf_stats.cq_start_time; | ||
3514 | card->perf_stats.cq_time += delta_t; | ||
3515 | } | ||
3516 | out: | ||
3517 | return; | ||
3518 | } | ||
3519 | |||
3520 | void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err, | 3027 | void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err, |
3521 | unsigned int queue, int first_elem, int count, | 3028 | unsigned int queue, int first_element, int count, |
3522 | unsigned long card_ptr) | 3029 | unsigned long card_ptr) |
3523 | { | 3030 | { |
3524 | struct qeth_card *card = (struct qeth_card *)card_ptr; | 3031 | struct qeth_card *card = (struct qeth_card *)card_ptr; |
3525 | 3032 | ||
3526 | QETH_CARD_TEXT_(card, 2, "qihq%d", queue); | 3033 | if (qdio_err) |
3527 | QETH_CARD_TEXT_(card, 2, "qiec%d", qdio_err); | ||
3528 | |||
3529 | if (qeth_is_cq(card, queue)) | ||
3530 | qeth_qdio_cq_handler(card, qdio_err, queue, first_elem, count); | ||
3531 | else if (qdio_err) | ||
3532 | qeth_schedule_recovery(card); | 3034 | qeth_schedule_recovery(card); |
3533 | |||
3534 | |||
3535 | } | 3035 | } |
3536 | EXPORT_SYMBOL_GPL(qeth_qdio_input_handler); | 3036 | EXPORT_SYMBOL_GPL(qeth_qdio_input_handler); |
3537 | 3037 | ||
@@ -3545,7 +3045,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, | |||
3545 | int i; | 3045 | int i; |
3546 | 3046 | ||
3547 | QETH_CARD_TEXT(card, 6, "qdouhdl"); | 3047 | QETH_CARD_TEXT(card, 6, "qdouhdl"); |
3548 | if (qdio_error & QDIO_ERROR_FATAL) { | 3048 | if (qdio_error & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) { |
3549 | QETH_CARD_TEXT(card, 2, "achkcond"); | 3049 | QETH_CARD_TEXT(card, 2, "achkcond"); |
3550 | netif_stop_queue(card->dev); | 3050 | netif_stop_queue(card->dev); |
3551 | qeth_schedule_recovery(card); | 3051 | qeth_schedule_recovery(card); |
@@ -3557,44 +3057,9 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, | |||
3557 | qeth_get_micros(); | 3057 | qeth_get_micros(); |
3558 | } | 3058 | } |
3559 | for (i = first_element; i < (first_element + count); ++i) { | 3059 | for (i = first_element; i < (first_element + count); ++i) { |
3560 | int bidx = i % QDIO_MAX_BUFFERS_PER_Q; | 3060 | buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; |
3561 | buffer = queue->bufs[bidx]; | ||
3562 | qeth_handle_send_error(card, buffer, qdio_error); | 3061 | qeth_handle_send_error(card, buffer, qdio_error); |
3563 | 3062 | qeth_clear_output_buffer(queue, buffer); | |
3564 | if (queue->bufstates && | ||
3565 | (queue->bufstates[bidx].flags & | ||
3566 | QDIO_OUTBUF_STATE_FLAG_PENDING) != 0) { | ||
3567 | WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED); | ||
3568 | |||
3569 | if (atomic_cmpxchg(&buffer->state, | ||
3570 | QETH_QDIO_BUF_PRIMED, | ||
3571 | QETH_QDIO_BUF_PENDING) == | ||
3572 | QETH_QDIO_BUF_PRIMED) { | ||
3573 | qeth_notify_skbs(queue, buffer, | ||
3574 | TX_NOTIFY_PENDING); | ||
3575 | } | ||
3576 | buffer->aob = queue->bufstates[bidx].aob; | ||
3577 | QETH_CARD_TEXT_(queue->card, 5, "pel%d", bidx); | ||
3578 | QETH_CARD_TEXT(queue->card, 5, "aob"); | ||
3579 | QETH_CARD_TEXT_(queue->card, 5, "%lx", | ||
3580 | virt_to_phys(buffer->aob)); | ||
3581 | if (qeth_init_qdio_out_buf(queue, bidx)) { | ||
3582 | QETH_CARD_TEXT(card, 2, "outofbuf"); | ||
3583 | qeth_schedule_recovery(card); | ||
3584 | } | ||
3585 | } else { | ||
3586 | if (card->options.cq == QETH_CQ_ENABLED) { | ||
3587 | enum iucv_tx_notify n; | ||
3588 | |||
3589 | n = qeth_compute_cq_notification( | ||
3590 | buffer->buffer->element[15].sflags, 0); | ||
3591 | qeth_notify_skbs(queue, buffer, n); | ||
3592 | } | ||
3593 | |||
3594 | qeth_clear_output_buffer(queue, buffer, | ||
3595 | QETH_QDIO_BUF_EMPTY); | ||
3596 | } | ||
3597 | qeth_cleanup_handled_pending(queue, bidx, 0); | ||
3598 | } | 3063 | } |
3599 | atomic_sub(count, &queue->used_buffers); | 3064 | atomic_sub(count, &queue->used_buffers); |
3600 | /* check if we need to do something on this outbound queue */ | 3065 | /* check if we need to do something on this outbound queue */ |
@@ -3739,8 +3204,7 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb, | |||
3739 | 3204 | ||
3740 | for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) { | 3205 | for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) { |
3741 | frag = &skb_shinfo(skb)->frags[cnt]; | 3206 | frag = &skb_shinfo(skb)->frags[cnt]; |
3742 | buffer->element[element].addr = (char *) | 3207 | buffer->element[element].addr = (char *)page_to_phys(frag->page) |
3743 | page_to_phys(skb_frag_page(frag)) | ||
3744 | + frag->page_offset; | 3208 | + frag->page_offset; |
3745 | buffer->element[element].length = frag->size; | 3209 | buffer->element[element].length = frag->size; |
3746 | buffer->element[element].eflags = SBAL_EFLAGS_MIDDLE_FRAG; | 3210 | buffer->element[element].eflags = SBAL_EFLAGS_MIDDLE_FRAG; |
@@ -3827,7 +3291,7 @@ int qeth_do_send_packet_fast(struct qeth_card *card, | |||
3827 | QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); | 3291 | QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); |
3828 | /* ... now we've got the queue */ | 3292 | /* ... now we've got the queue */ |
3829 | index = queue->next_buf_to_fill; | 3293 | index = queue->next_buf_to_fill; |
3830 | buffer = queue->bufs[queue->next_buf_to_fill]; | 3294 | buffer = &queue->bufs[queue->next_buf_to_fill]; |
3831 | /* | 3295 | /* |
3832 | * check if buffer is empty to make sure that we do not 'overtake' | 3296 | * check if buffer is empty to make sure that we do not 'overtake' |
3833 | * ourselves and try to fill a buffer that is already primed | 3297 | * ourselves and try to fill a buffer that is already primed |
@@ -3861,7 +3325,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
3861 | while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, | 3325 | while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, |
3862 | QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); | 3326 | QETH_OUT_Q_LOCKED) != QETH_OUT_Q_UNLOCKED); |
3863 | start_index = queue->next_buf_to_fill; | 3327 | start_index = queue->next_buf_to_fill; |
3864 | buffer = queue->bufs[queue->next_buf_to_fill]; | 3328 | buffer = &queue->bufs[queue->next_buf_to_fill]; |
3865 | /* | 3329 | /* |
3866 | * check if buffer is empty to make sure that we do not 'overtake' | 3330 | * check if buffer is empty to make sure that we do not 'overtake' |
3867 | * ourselves and try to fill a buffer that is already primed | 3331 | * ourselves and try to fill a buffer that is already primed |
@@ -3883,7 +3347,7 @@ int qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | |||
3883 | queue->next_buf_to_fill = | 3347 | queue->next_buf_to_fill = |
3884 | (queue->next_buf_to_fill + 1) % | 3348 | (queue->next_buf_to_fill + 1) % |
3885 | QDIO_MAX_BUFFERS_PER_Q; | 3349 | QDIO_MAX_BUFFERS_PER_Q; |
3886 | buffer = queue->bufs[queue->next_buf_to_fill]; | 3350 | buffer = &queue->bufs[queue->next_buf_to_fill]; |
3887 | /* we did a step forward, so check buffer state | 3351 | /* we did a step forward, so check buffer state |
3888 | * again */ | 3352 | * again */ |
3889 | if (atomic_read(&buffer->state) != | 3353 | if (atomic_read(&buffer->state) != |
@@ -4334,7 +3798,7 @@ static int qeth_snmp_command_cb(struct qeth_card *card, | |||
4334 | /* check if there is enough room in userspace */ | 3798 | /* check if there is enough room in userspace */ |
4335 | if ((qinfo->udata_len - qinfo->udata_offset) < data_len) { | 3799 | if ((qinfo->udata_len - qinfo->udata_offset) < data_len) { |
4336 | QETH_CARD_TEXT_(card, 4, "scer3%i", -ENOMEM); | 3800 | QETH_CARD_TEXT_(card, 4, "scer3%i", -ENOMEM); |
4337 | cmd->hdr.return_code = IPA_RC_ENOMEM; | 3801 | cmd->hdr.return_code = -ENOMEM; |
4338 | return 0; | 3802 | return 0; |
4339 | } | 3803 | } |
4340 | QETH_CARD_TEXT_(card, 4, "snore%i", | 3804 | QETH_CARD_TEXT_(card, 4, "snore%i", |
@@ -4417,104 +3881,6 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) | |||
4417 | } | 3881 | } |
4418 | EXPORT_SYMBOL_GPL(qeth_snmp_command); | 3882 | EXPORT_SYMBOL_GPL(qeth_snmp_command); |
4419 | 3883 | ||
4420 | static int qeth_setadpparms_query_oat_cb(struct qeth_card *card, | ||
4421 | struct qeth_reply *reply, unsigned long data) | ||
4422 | { | ||
4423 | struct qeth_ipa_cmd *cmd; | ||
4424 | struct qeth_qoat_priv *priv; | ||
4425 | char *resdata; | ||
4426 | int resdatalen; | ||
4427 | |||
4428 | QETH_CARD_TEXT(card, 3, "qoatcb"); | ||
4429 | |||
4430 | cmd = (struct qeth_ipa_cmd *)data; | ||
4431 | priv = (struct qeth_qoat_priv *)reply->param; | ||
4432 | resdatalen = cmd->data.setadapterparms.hdr.cmdlength; | ||
4433 | resdata = (char *)data + 28; | ||
4434 | |||
4435 | if (resdatalen > (priv->buffer_len - priv->response_len)) { | ||
4436 | cmd->hdr.return_code = IPA_RC_FFFF; | ||
4437 | return 0; | ||
4438 | } | ||
4439 | |||
4440 | memcpy((priv->buffer + priv->response_len), resdata, | ||
4441 | resdatalen); | ||
4442 | priv->response_len += resdatalen; | ||
4443 | |||
4444 | if (cmd->data.setadapterparms.hdr.seq_no < | ||
4445 | cmd->data.setadapterparms.hdr.used_total) | ||
4446 | return 1; | ||
4447 | return 0; | ||
4448 | } | ||
4449 | |||
4450 | int qeth_query_oat_command(struct qeth_card *card, char __user *udata) | ||
4451 | { | ||
4452 | int rc = 0; | ||
4453 | struct qeth_cmd_buffer *iob; | ||
4454 | struct qeth_ipa_cmd *cmd; | ||
4455 | struct qeth_query_oat *oat_req; | ||
4456 | struct qeth_query_oat_data oat_data; | ||
4457 | struct qeth_qoat_priv priv; | ||
4458 | void __user *tmp; | ||
4459 | |||
4460 | QETH_CARD_TEXT(card, 3, "qoatcmd"); | ||
4461 | |||
4462 | if (!qeth_adp_supported(card, IPA_SETADP_QUERY_OAT)) { | ||
4463 | rc = -EOPNOTSUPP; | ||
4464 | goto out; | ||
4465 | } | ||
4466 | |||
4467 | if (copy_from_user(&oat_data, udata, | ||
4468 | sizeof(struct qeth_query_oat_data))) { | ||
4469 | rc = -EFAULT; | ||
4470 | goto out; | ||
4471 | } | ||
4472 | |||
4473 | priv.buffer_len = oat_data.buffer_len; | ||
4474 | priv.response_len = 0; | ||
4475 | priv.buffer = kzalloc(oat_data.buffer_len, GFP_KERNEL); | ||
4476 | if (!priv.buffer) { | ||
4477 | rc = -ENOMEM; | ||
4478 | goto out; | ||
4479 | } | ||
4480 | |||
4481 | iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_OAT, | ||
4482 | sizeof(struct qeth_ipacmd_setadpparms_hdr) + | ||
4483 | sizeof(struct qeth_query_oat)); | ||
4484 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
4485 | oat_req = &cmd->data.setadapterparms.data.query_oat; | ||
4486 | oat_req->subcmd_code = oat_data.command; | ||
4487 | |||
4488 | rc = qeth_send_ipa_cmd(card, iob, qeth_setadpparms_query_oat_cb, | ||
4489 | &priv); | ||
4490 | if (!rc) { | ||
4491 | if (is_compat_task()) | ||
4492 | tmp = compat_ptr(oat_data.ptr); | ||
4493 | else | ||
4494 | tmp = (void __user *)(unsigned long)oat_data.ptr; | ||
4495 | |||
4496 | if (copy_to_user(tmp, priv.buffer, | ||
4497 | priv.response_len)) { | ||
4498 | rc = -EFAULT; | ||
4499 | goto out_free; | ||
4500 | } | ||
4501 | |||
4502 | oat_data.response_len = priv.response_len; | ||
4503 | |||
4504 | if (copy_to_user(udata, &oat_data, | ||
4505 | sizeof(struct qeth_query_oat_data))) | ||
4506 | rc = -EFAULT; | ||
4507 | } else | ||
4508 | if (rc == IPA_RC_FFFF) | ||
4509 | rc = -EFAULT; | ||
4510 | |||
4511 | out_free: | ||
4512 | kfree(priv.buffer); | ||
4513 | out: | ||
4514 | return rc; | ||
4515 | } | ||
4516 | EXPORT_SYMBOL_GPL(qeth_query_oat_command); | ||
4517 | |||
4518 | static inline int qeth_get_qdio_q_format(struct qeth_card *card) | 3884 | static inline int qeth_get_qdio_q_format(struct qeth_card *card) |
4519 | { | 3885 | { |
4520 | switch (card->info.type) { | 3886 | switch (card->info.type) { |
@@ -4552,28 +3918,13 @@ static void qeth_determine_capabilities(struct qeth_card *card) | |||
4552 | goto out_offline; | 3918 | goto out_offline; |
4553 | } | 3919 | } |
4554 | qeth_configure_unitaddr(card, prcd); | 3920 | qeth_configure_unitaddr(card, prcd); |
4555 | if (ddev_offline) | 3921 | qeth_configure_blkt_default(card, prcd); |
4556 | qeth_configure_blkt_default(card, prcd); | ||
4557 | kfree(prcd); | 3922 | kfree(prcd); |
4558 | 3923 | ||
4559 | rc = qdio_get_ssqd_desc(ddev, &card->ssqd); | 3924 | rc = qdio_get_ssqd_desc(ddev, &card->ssqd); |
4560 | if (rc) | 3925 | if (rc) |
4561 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); | 3926 | QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc); |
4562 | 3927 | ||
4563 | QETH_DBF_TEXT_(SETUP, 2, "qfmt%d", card->ssqd.qfmt); | ||
4564 | QETH_DBF_TEXT_(SETUP, 2, "%d", card->ssqd.qdioac1); | ||
4565 | QETH_DBF_TEXT_(SETUP, 2, "%d", card->ssqd.qdioac3); | ||
4566 | QETH_DBF_TEXT_(SETUP, 2, "icnt%d", card->ssqd.icnt); | ||
4567 | if (!((card->ssqd.qfmt != QDIO_IQDIO_QFMT) || | ||
4568 | ((card->ssqd.qdioac1 & CHSC_AC1_INITIATE_INPUTQ) == 0) || | ||
4569 | ((card->ssqd.qdioac3 & CHSC_AC3_FORMAT2_CQ_AVAILABLE) == 0))) { | ||
4570 | dev_info(&card->gdev->dev, | ||
4571 | "Completion Queueing supported\n"); | ||
4572 | } else { | ||
4573 | card->options.cq = QETH_CQ_NOTAVAILABLE; | ||
4574 | } | ||
4575 | |||
4576 | |||
4577 | out_offline: | 3928 | out_offline: |
4578 | if (ddev_offline == 1) | 3929 | if (ddev_offline == 1) |
4579 | ccw_device_set_offline(ddev); | 3930 | ccw_device_set_offline(ddev); |
@@ -4581,30 +3932,11 @@ out: | |||
4581 | return; | 3932 | return; |
4582 | } | 3933 | } |
4583 | 3934 | ||
4584 | static inline void qeth_qdio_establish_cq(struct qeth_card *card, | ||
4585 | struct qdio_buffer **in_sbal_ptrs, | ||
4586 | void (**queue_start_poll) (struct ccw_device *, int, unsigned long)) { | ||
4587 | int i; | ||
4588 | |||
4589 | if (card->options.cq == QETH_CQ_ENABLED) { | ||
4590 | int offset = QDIO_MAX_BUFFERS_PER_Q * | ||
4591 | (card->qdio.no_in_queues - 1); | ||
4592 | i = QDIO_MAX_BUFFERS_PER_Q * (card->qdio.no_in_queues - 1); | ||
4593 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) { | ||
4594 | in_sbal_ptrs[offset + i] = (struct qdio_buffer *) | ||
4595 | virt_to_phys(card->qdio.c_q->bufs[i].buffer); | ||
4596 | } | ||
4597 | |||
4598 | queue_start_poll[card->qdio.no_in_queues - 1] = NULL; | ||
4599 | } | ||
4600 | } | ||
4601 | |||
4602 | static int qeth_qdio_establish(struct qeth_card *card) | 3935 | static int qeth_qdio_establish(struct qeth_card *card) |
4603 | { | 3936 | { |
4604 | struct qdio_initialize init_data; | 3937 | struct qdio_initialize init_data; |
4605 | char *qib_param_field; | 3938 | char *qib_param_field; |
4606 | struct qdio_buffer **in_sbal_ptrs; | 3939 | struct qdio_buffer **in_sbal_ptrs; |
4607 | void (**queue_start_poll) (struct ccw_device *, int, unsigned long); | ||
4608 | struct qdio_buffer **out_sbal_ptrs; | 3940 | struct qdio_buffer **out_sbal_ptrs; |
4609 | int i, j, k; | 3941 | int i, j, k; |
4610 | int rc = 0; | 3942 | int rc = 0; |
@@ -4613,48 +3945,34 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
4613 | 3945 | ||
4614 | qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char), | 3946 | qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char), |
4615 | GFP_KERNEL); | 3947 | GFP_KERNEL); |
4616 | if (!qib_param_field) { | 3948 | if (!qib_param_field) |
4617 | rc = -ENOMEM; | 3949 | return -ENOMEM; |
4618 | goto out_free_nothing; | ||
4619 | } | ||
4620 | 3950 | ||
4621 | qeth_create_qib_param_field(card, qib_param_field); | 3951 | qeth_create_qib_param_field(card, qib_param_field); |
4622 | qeth_create_qib_param_field_blkt(card, qib_param_field); | 3952 | qeth_create_qib_param_field_blkt(card, qib_param_field); |
4623 | 3953 | ||
4624 | in_sbal_ptrs = kzalloc(card->qdio.no_in_queues * | 3954 | in_sbal_ptrs = kmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(void *), |
4625 | QDIO_MAX_BUFFERS_PER_Q * sizeof(void *), | ||
4626 | GFP_KERNEL); | 3955 | GFP_KERNEL); |
4627 | if (!in_sbal_ptrs) { | 3956 | if (!in_sbal_ptrs) { |
4628 | rc = -ENOMEM; | 3957 | kfree(qib_param_field); |
4629 | goto out_free_qib_param; | 3958 | return -ENOMEM; |
4630 | } | 3959 | } |
4631 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) { | 3960 | for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) |
4632 | in_sbal_ptrs[i] = (struct qdio_buffer *) | 3961 | in_sbal_ptrs[i] = (struct qdio_buffer *) |
4633 | virt_to_phys(card->qdio.in_q->bufs[i].buffer); | 3962 | virt_to_phys(card->qdio.in_q->bufs[i].buffer); |
4634 | } | ||
4635 | |||
4636 | queue_start_poll = kzalloc(sizeof(void *) * card->qdio.no_in_queues, | ||
4637 | GFP_KERNEL); | ||
4638 | if (!queue_start_poll) { | ||
4639 | rc = -ENOMEM; | ||
4640 | goto out_free_in_sbals; | ||
4641 | } | ||
4642 | for (i = 0; i < card->qdio.no_in_queues; ++i) | ||
4643 | queue_start_poll[i] = card->discipline->start_poll; | ||
4644 | |||
4645 | qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll); | ||
4646 | 3963 | ||
4647 | out_sbal_ptrs = | 3964 | out_sbal_ptrs = |
4648 | kzalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q * | 3965 | kmalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q * |
4649 | sizeof(void *), GFP_KERNEL); | 3966 | sizeof(void *), GFP_KERNEL); |
4650 | if (!out_sbal_ptrs) { | 3967 | if (!out_sbal_ptrs) { |
4651 | rc = -ENOMEM; | 3968 | kfree(in_sbal_ptrs); |
4652 | goto out_free_queue_start_poll; | 3969 | kfree(qib_param_field); |
3970 | return -ENOMEM; | ||
4653 | } | 3971 | } |
4654 | for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i) | 3972 | for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i) |
4655 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) { | 3973 | for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) { |
4656 | out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys( | 3974 | out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys( |
4657 | card->qdio.out_qs[i]->bufs[j]->buffer); | 3975 | card->qdio.out_qs[i]->bufs[j].buffer); |
4658 | } | 3976 | } |
4659 | 3977 | ||
4660 | memset(&init_data, 0, sizeof(struct qdio_initialize)); | 3978 | memset(&init_data, 0, sizeof(struct qdio_initialize)); |
@@ -4662,15 +3980,14 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
4662 | init_data.q_format = qeth_get_qdio_q_format(card); | 3980 | init_data.q_format = qeth_get_qdio_q_format(card); |
4663 | init_data.qib_param_field_format = 0; | 3981 | init_data.qib_param_field_format = 0; |
4664 | init_data.qib_param_field = qib_param_field; | 3982 | init_data.qib_param_field = qib_param_field; |
4665 | init_data.no_input_qs = card->qdio.no_in_queues; | 3983 | init_data.no_input_qs = 1; |
4666 | init_data.no_output_qs = card->qdio.no_out_queues; | 3984 | init_data.no_output_qs = card->qdio.no_out_queues; |
4667 | init_data.input_handler = card->discipline->input_handler; | 3985 | init_data.input_handler = card->discipline.input_handler; |
4668 | init_data.output_handler = card->discipline->output_handler; | 3986 | init_data.output_handler = card->discipline.output_handler; |
4669 | init_data.queue_start_poll_array = queue_start_poll; | 3987 | init_data.queue_start_poll = card->discipline.start_poll; |
4670 | init_data.int_parm = (unsigned long) card; | 3988 | init_data.int_parm = (unsigned long) card; |
4671 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; | 3989 | init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; |
4672 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; | 3990 | init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; |
4673 | init_data.output_sbal_state_array = card->qdio.out_bufstates; | ||
4674 | init_data.scan_threshold = | 3991 | init_data.scan_threshold = |
4675 | (card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32; | 3992 | (card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32; |
4676 | 3993 | ||
@@ -4687,26 +4004,10 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
4687 | qdio_free(CARD_DDEV(card)); | 4004 | qdio_free(CARD_DDEV(card)); |
4688 | } | 4005 | } |
4689 | } | 4006 | } |
4690 | |||
4691 | switch (card->options.cq) { | ||
4692 | case QETH_CQ_ENABLED: | ||
4693 | dev_info(&card->gdev->dev, "Completion Queue support enabled"); | ||
4694 | break; | ||
4695 | case QETH_CQ_DISABLED: | ||
4696 | dev_info(&card->gdev->dev, "Completion Queue support disabled"); | ||
4697 | break; | ||
4698 | default: | ||
4699 | break; | ||
4700 | } | ||
4701 | out: | 4007 | out: |
4702 | kfree(out_sbal_ptrs); | 4008 | kfree(out_sbal_ptrs); |
4703 | out_free_queue_start_poll: | ||
4704 | kfree(queue_start_poll); | ||
4705 | out_free_in_sbals: | ||
4706 | kfree(in_sbal_ptrs); | 4009 | kfree(in_sbal_ptrs); |
4707 | out_free_qib_param: | ||
4708 | kfree(qib_param_field); | 4010 | kfree(qib_param_field); |
4709 | out_free_nothing: | ||
4710 | return rc; | 4011 | return rc; |
4711 | } | 4012 | } |
4712 | 4013 | ||
@@ -4725,19 +4026,6 @@ static void qeth_core_free_card(struct qeth_card *card) | |||
4725 | kfree(card); | 4026 | kfree(card); |
4726 | } | 4027 | } |
4727 | 4028 | ||
4728 | void qeth_trace_features(struct qeth_card *card) | ||
4729 | { | ||
4730 | QETH_CARD_TEXT(card, 2, "features"); | ||
4731 | QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.supported_funcs); | ||
4732 | QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.enabled_funcs); | ||
4733 | QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.supported_funcs); | ||
4734 | QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.enabled_funcs); | ||
4735 | QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.supported_funcs); | ||
4736 | QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.enabled_funcs); | ||
4737 | QETH_CARD_TEXT_(card, 2, "%x", card->info.diagass_support); | ||
4738 | } | ||
4739 | EXPORT_SYMBOL_GPL(qeth_trace_features); | ||
4740 | |||
4741 | static struct ccw_device_id qeth_ids[] = { | 4029 | static struct ccw_device_id qeth_ids[] = { |
4742 | {CCW_DEVICE_DEVTYPE(0x1731, 0x01, 0x1732, 0x01), | 4030 | {CCW_DEVICE_DEVTYPE(0x1731, 0x01, 0x1732, 0x01), |
4743 | .driver_info = QETH_CARD_TYPE_OSD}, | 4031 | .driver_info = QETH_CARD_TYPE_OSD}, |
@@ -4763,6 +4051,13 @@ static struct ccw_driver qeth_ccw_driver = { | |||
4763 | .remove = ccwgroup_remove_ccwdev, | 4051 | .remove = ccwgroup_remove_ccwdev, |
4764 | }; | 4052 | }; |
4765 | 4053 | ||
4054 | static int qeth_core_driver_group(const char *buf, struct device *root_dev, | ||
4055 | unsigned long driver_id) | ||
4056 | { | ||
4057 | return ccwgroup_create_from_string(root_dev, driver_id, | ||
4058 | &qeth_ccw_driver, 3, buf); | ||
4059 | } | ||
4060 | |||
4766 | int qeth_core_hardsetup_card(struct qeth_card *card) | 4061 | int qeth_core_hardsetup_card(struct qeth_card *card) |
4767 | { | 4062 | { |
4768 | int retries = 0; | 4063 | int retries = 0; |
@@ -4770,7 +4065,7 @@ int qeth_core_hardsetup_card(struct qeth_card *card) | |||
4770 | 4065 | ||
4771 | QETH_DBF_TEXT(SETUP, 2, "hrdsetup"); | 4066 | QETH_DBF_TEXT(SETUP, 2, "hrdsetup"); |
4772 | atomic_set(&card->force_alloc_skb, 0); | 4067 | atomic_set(&card->force_alloc_skb, 0); |
4773 | qeth_update_from_chp_desc(card); | 4068 | qeth_get_channel_path_desc(card); |
4774 | retry: | 4069 | retry: |
4775 | if (retries) | 4070 | if (retries) |
4776 | QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", | 4071 | QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", |
@@ -4849,36 +4144,29 @@ out: | |||
4849 | } | 4144 | } |
4850 | EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card); | 4145 | EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card); |
4851 | 4146 | ||
4852 | static inline int qeth_create_skb_frag(struct qeth_qdio_buffer *qethbuffer, | 4147 | static inline int qeth_create_skb_frag(struct qdio_buffer_element *element, |
4853 | struct qdio_buffer_element *element, | ||
4854 | struct sk_buff **pskb, int offset, int *pfrag, int data_len) | 4148 | struct sk_buff **pskb, int offset, int *pfrag, int data_len) |
4855 | { | 4149 | { |
4856 | struct page *page = virt_to_page(element->addr); | 4150 | struct page *page = virt_to_page(element->addr); |
4857 | if (*pskb == NULL) { | 4151 | if (*pskb == NULL) { |
4858 | if (qethbuffer->rx_skb) { | 4152 | /* the upper protocol layers assume that there is data in the |
4859 | /* only if qeth_card.options.cq == QETH_CQ_ENABLED */ | 4153 | * skb itself. Copy a small amount (64 bytes) to make them |
4860 | *pskb = qethbuffer->rx_skb; | 4154 | * happy. */ |
4861 | qethbuffer->rx_skb = NULL; | 4155 | *pskb = dev_alloc_skb(64 + ETH_HLEN); |
4862 | } else { | 4156 | if (!(*pskb)) |
4863 | *pskb = dev_alloc_skb(QETH_RX_PULL_LEN + ETH_HLEN); | 4157 | return -ENOMEM; |
4864 | if (!(*pskb)) | ||
4865 | return -ENOMEM; | ||
4866 | } | ||
4867 | |||
4868 | skb_reserve(*pskb, ETH_HLEN); | 4158 | skb_reserve(*pskb, ETH_HLEN); |
4869 | if (data_len <= QETH_RX_PULL_LEN) { | 4159 | if (data_len <= 64) { |
4870 | memcpy(skb_put(*pskb, data_len), element->addr + offset, | 4160 | memcpy(skb_put(*pskb, data_len), element->addr + offset, |
4871 | data_len); | 4161 | data_len); |
4872 | } else { | 4162 | } else { |
4873 | get_page(page); | 4163 | get_page(page); |
4874 | memcpy(skb_put(*pskb, QETH_RX_PULL_LEN), | 4164 | memcpy(skb_put(*pskb, 64), element->addr + offset, 64); |
4875 | element->addr + offset, QETH_RX_PULL_LEN); | 4165 | skb_fill_page_desc(*pskb, *pfrag, page, offset + 64, |
4876 | skb_fill_page_desc(*pskb, *pfrag, page, | 4166 | data_len - 64); |
4877 | offset + QETH_RX_PULL_LEN, | 4167 | (*pskb)->data_len += data_len - 64; |
4878 | data_len - QETH_RX_PULL_LEN); | 4168 | (*pskb)->len += data_len - 64; |
4879 | (*pskb)->data_len += data_len - QETH_RX_PULL_LEN; | 4169 | (*pskb)->truesize += data_len - 64; |
4880 | (*pskb)->len += data_len - QETH_RX_PULL_LEN; | ||
4881 | (*pskb)->truesize += data_len - QETH_RX_PULL_LEN; | ||
4882 | (*pfrag)++; | 4170 | (*pfrag)++; |
4883 | } | 4171 | } |
4884 | } else { | 4172 | } else { |
@@ -4889,18 +4177,15 @@ static inline int qeth_create_skb_frag(struct qeth_qdio_buffer *qethbuffer, | |||
4889 | (*pskb)->truesize += data_len; | 4177 | (*pskb)->truesize += data_len; |
4890 | (*pfrag)++; | 4178 | (*pfrag)++; |
4891 | } | 4179 | } |
4892 | |||
4893 | |||
4894 | return 0; | 4180 | return 0; |
4895 | } | 4181 | } |
4896 | 4182 | ||
4897 | struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, | 4183 | struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, |
4898 | struct qeth_qdio_buffer *qethbuffer, | 4184 | struct qdio_buffer *buffer, |
4899 | struct qdio_buffer_element **__element, int *__offset, | 4185 | struct qdio_buffer_element **__element, int *__offset, |
4900 | struct qeth_hdr **hdr) | 4186 | struct qeth_hdr **hdr) |
4901 | { | 4187 | { |
4902 | struct qdio_buffer_element *element = *__element; | 4188 | struct qdio_buffer_element *element = *__element; |
4903 | struct qdio_buffer *buffer = qethbuffer->buffer; | ||
4904 | int offset = *__offset; | 4189 | int offset = *__offset; |
4905 | struct sk_buff *skb = NULL; | 4190 | struct sk_buff *skb = NULL; |
4906 | int skb_len = 0; | 4191 | int skb_len = 0; |
@@ -4928,7 +4213,11 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, | |||
4928 | break; | 4213 | break; |
4929 | case QETH_HEADER_TYPE_LAYER3: | 4214 | case QETH_HEADER_TYPE_LAYER3: |
4930 | skb_len = (*hdr)->hdr.l3.length; | 4215 | skb_len = (*hdr)->hdr.l3.length; |
4931 | headroom = ETH_HLEN; | 4216 | if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) || |
4217 | (card->info.link_type == QETH_LINK_TYPE_HSTR)) | ||
4218 | headroom = TR_HLEN; | ||
4219 | else | ||
4220 | headroom = ETH_HLEN; | ||
4932 | break; | 4221 | break; |
4933 | case QETH_HEADER_TYPE_OSN: | 4222 | case QETH_HEADER_TYPE_OSN: |
4934 | skb_len = (*hdr)->hdr.osn.pdu_length; | 4223 | skb_len = (*hdr)->hdr.osn.pdu_length; |
@@ -4941,10 +4230,9 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, | |||
4941 | if (!skb_len) | 4230 | if (!skb_len) |
4942 | return NULL; | 4231 | return NULL; |
4943 | 4232 | ||
4944 | if (((skb_len >= card->options.rx_sg_cb) && | 4233 | if ((skb_len >= card->options.rx_sg_cb) && |
4945 | (!(card->info.type == QETH_CARD_TYPE_OSN)) && | 4234 | (!(card->info.type == QETH_CARD_TYPE_OSN)) && |
4946 | (!atomic_read(&card->force_alloc_skb))) || | 4235 | (!atomic_read(&card->force_alloc_skb))) { |
4947 | (card->options.cq == QETH_CQ_ENABLED)) { | ||
4948 | use_rx_sg = 1; | 4236 | use_rx_sg = 1; |
4949 | } else { | 4237 | } else { |
4950 | skb = dev_alloc_skb(skb_len + headroom); | 4238 | skb = dev_alloc_skb(skb_len + headroom); |
@@ -4959,8 +4247,8 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *card, | |||
4959 | data_len = min(skb_len, (int)(element->length - offset)); | 4247 | data_len = min(skb_len, (int)(element->length - offset)); |
4960 | if (data_len) { | 4248 | if (data_len) { |
4961 | if (use_rx_sg) { | 4249 | if (use_rx_sg) { |
4962 | if (qeth_create_skb_frag(qethbuffer, element, | 4250 | if (qeth_create_skb_frag(element, &skb, offset, |
4963 | &skb, offset, &frag, data_len)) | 4251 | &frag, data_len)) |
4964 | goto no_mem; | 4252 | goto no_mem; |
4965 | } else { | 4253 | } else { |
4966 | memcpy(skb_put(skb, data_len), data_ptr, | 4254 | memcpy(skb_put(skb, data_len), data_ptr, |
@@ -5056,44 +4344,35 @@ int qeth_core_load_discipline(struct qeth_card *card, | |||
5056 | enum qeth_discipline_id discipline) | 4344 | enum qeth_discipline_id discipline) |
5057 | { | 4345 | { |
5058 | int rc = 0; | 4346 | int rc = 0; |
5059 | mutex_lock(&qeth_mod_mutex); | ||
5060 | switch (discipline) { | 4347 | switch (discipline) { |
5061 | case QETH_DISCIPLINE_LAYER3: | 4348 | case QETH_DISCIPLINE_LAYER3: |
5062 | card->discipline = try_then_request_module( | 4349 | card->discipline.ccwgdriver = try_then_request_module( |
5063 | symbol_get(qeth_l3_discipline), "qeth_l3"); | 4350 | symbol_get(qeth_l3_ccwgroup_driver), |
4351 | "qeth_l3"); | ||
5064 | break; | 4352 | break; |
5065 | case QETH_DISCIPLINE_LAYER2: | 4353 | case QETH_DISCIPLINE_LAYER2: |
5066 | card->discipline = try_then_request_module( | 4354 | card->discipline.ccwgdriver = try_then_request_module( |
5067 | symbol_get(qeth_l2_discipline), "qeth_l2"); | 4355 | symbol_get(qeth_l2_ccwgroup_driver), |
4356 | "qeth_l2"); | ||
5068 | break; | 4357 | break; |
5069 | } | 4358 | } |
5070 | if (!card->discipline) { | 4359 | if (!card->discipline.ccwgdriver) { |
5071 | dev_err(&card->gdev->dev, "There is no kernel module to " | 4360 | dev_err(&card->gdev->dev, "There is no kernel module to " |
5072 | "support discipline %d\n", discipline); | 4361 | "support discipline %d\n", discipline); |
5073 | rc = -EINVAL; | 4362 | rc = -EINVAL; |
5074 | } | 4363 | } |
5075 | mutex_unlock(&qeth_mod_mutex); | ||
5076 | return rc; | 4364 | return rc; |
5077 | } | 4365 | } |
5078 | 4366 | ||
5079 | void qeth_core_free_discipline(struct qeth_card *card) | 4367 | void qeth_core_free_discipline(struct qeth_card *card) |
5080 | { | 4368 | { |
5081 | if (card->options.layer2) | 4369 | if (card->options.layer2) |
5082 | symbol_put(qeth_l2_discipline); | 4370 | symbol_put(qeth_l2_ccwgroup_driver); |
5083 | else | 4371 | else |
5084 | symbol_put(qeth_l3_discipline); | 4372 | symbol_put(qeth_l3_ccwgroup_driver); |
5085 | card->discipline = NULL; | 4373 | card->discipline.ccwgdriver = NULL; |
5086 | } | 4374 | } |
5087 | 4375 | ||
5088 | static const struct device_type qeth_generic_devtype = { | ||
5089 | .name = "qeth_generic", | ||
5090 | .groups = qeth_generic_attr_groups, | ||
5091 | }; | ||
5092 | static const struct device_type qeth_osn_devtype = { | ||
5093 | .name = "qeth_osn", | ||
5094 | .groups = qeth_osn_attr_groups, | ||
5095 | }; | ||
5096 | |||
5097 | static int qeth_core_probe_device(struct ccwgroup_device *gdev) | 4376 | static int qeth_core_probe_device(struct ccwgroup_device *gdev) |
5098 | { | 4377 | { |
5099 | struct qeth_card *card; | 4378 | struct qeth_card *card; |
@@ -5148,17 +4427,18 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev) | |||
5148 | } | 4427 | } |
5149 | 4428 | ||
5150 | if (card->info.type == QETH_CARD_TYPE_OSN) | 4429 | if (card->info.type == QETH_CARD_TYPE_OSN) |
5151 | gdev->dev.type = &qeth_osn_devtype; | 4430 | rc = qeth_core_create_osn_attributes(dev); |
5152 | else | 4431 | else |
5153 | gdev->dev.type = &qeth_generic_devtype; | 4432 | rc = qeth_core_create_device_attributes(dev); |
5154 | 4433 | if (rc) | |
4434 | goto err_dbf; | ||
5155 | switch (card->info.type) { | 4435 | switch (card->info.type) { |
5156 | case QETH_CARD_TYPE_OSN: | 4436 | case QETH_CARD_TYPE_OSN: |
5157 | case QETH_CARD_TYPE_OSM: | 4437 | case QETH_CARD_TYPE_OSM: |
5158 | rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2); | 4438 | rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2); |
5159 | if (rc) | 4439 | if (rc) |
5160 | goto err_dbf; | 4440 | goto err_attr; |
5161 | rc = card->discipline->setup(card->gdev); | 4441 | rc = card->discipline.ccwgdriver->probe(card->gdev); |
5162 | if (rc) | 4442 | if (rc) |
5163 | goto err_disc; | 4443 | goto err_disc; |
5164 | case QETH_CARD_TYPE_OSD: | 4444 | case QETH_CARD_TYPE_OSD: |
@@ -5176,6 +4456,11 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev) | |||
5176 | 4456 | ||
5177 | err_disc: | 4457 | err_disc: |
5178 | qeth_core_free_discipline(card); | 4458 | qeth_core_free_discipline(card); |
4459 | err_attr: | ||
4460 | if (card->info.type == QETH_CARD_TYPE_OSN) | ||
4461 | qeth_core_remove_osn_attributes(dev); | ||
4462 | else | ||
4463 | qeth_core_remove_device_attributes(dev); | ||
5179 | err_dbf: | 4464 | err_dbf: |
5180 | debug_unregister(card->debug); | 4465 | debug_unregister(card->debug); |
5181 | err_card: | 4466 | err_card: |
@@ -5192,8 +4477,14 @@ static void qeth_core_remove_device(struct ccwgroup_device *gdev) | |||
5192 | 4477 | ||
5193 | QETH_DBF_TEXT(SETUP, 2, "removedv"); | 4478 | QETH_DBF_TEXT(SETUP, 2, "removedv"); |
5194 | 4479 | ||
5195 | if (card->discipline) { | 4480 | if (card->info.type == QETH_CARD_TYPE_OSN) { |
5196 | card->discipline->remove(gdev); | 4481 | qeth_core_remove_osn_attributes(&gdev->dev); |
4482 | } else { | ||
4483 | qeth_core_remove_device_attributes(&gdev->dev); | ||
4484 | } | ||
4485 | |||
4486 | if (card->discipline.ccwgdriver) { | ||
4487 | card->discipline.ccwgdriver->remove(gdev); | ||
5197 | qeth_core_free_discipline(card); | 4488 | qeth_core_free_discipline(card); |
5198 | } | 4489 | } |
5199 | 4490 | ||
@@ -5213,7 +4504,7 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev) | |||
5213 | int rc = 0; | 4504 | int rc = 0; |
5214 | int def_discipline; | 4505 | int def_discipline; |
5215 | 4506 | ||
5216 | if (!card->discipline) { | 4507 | if (!card->discipline.ccwgdriver) { |
5217 | if (card->info.type == QETH_CARD_TYPE_IQD) | 4508 | if (card->info.type == QETH_CARD_TYPE_IQD) |
5218 | def_discipline = QETH_DISCIPLINE_LAYER3; | 4509 | def_discipline = QETH_DISCIPLINE_LAYER3; |
5219 | else | 4510 | else |
@@ -5221,11 +4512,11 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev) | |||
5221 | rc = qeth_core_load_discipline(card, def_discipline); | 4512 | rc = qeth_core_load_discipline(card, def_discipline); |
5222 | if (rc) | 4513 | if (rc) |
5223 | goto err; | 4514 | goto err; |
5224 | rc = card->discipline->setup(card->gdev); | 4515 | rc = card->discipline.ccwgdriver->probe(card->gdev); |
5225 | if (rc) | 4516 | if (rc) |
5226 | goto err; | 4517 | goto err; |
5227 | } | 4518 | } |
5228 | rc = card->discipline->set_online(gdev); | 4519 | rc = card->discipline.ccwgdriver->set_online(gdev); |
5229 | err: | 4520 | err: |
5230 | return rc; | 4521 | return rc; |
5231 | } | 4522 | } |
@@ -5233,52 +4524,58 @@ err: | |||
5233 | static int qeth_core_set_offline(struct ccwgroup_device *gdev) | 4524 | static int qeth_core_set_offline(struct ccwgroup_device *gdev) |
5234 | { | 4525 | { |
5235 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 4526 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5236 | return card->discipline->set_offline(gdev); | 4527 | return card->discipline.ccwgdriver->set_offline(gdev); |
5237 | } | 4528 | } |
5238 | 4529 | ||
5239 | static void qeth_core_shutdown(struct ccwgroup_device *gdev) | 4530 | static void qeth_core_shutdown(struct ccwgroup_device *gdev) |
5240 | { | 4531 | { |
5241 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 4532 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5242 | if (card->discipline && card->discipline->shutdown) | 4533 | if (card->discipline.ccwgdriver && |
5243 | card->discipline->shutdown(gdev); | 4534 | card->discipline.ccwgdriver->shutdown) |
4535 | card->discipline.ccwgdriver->shutdown(gdev); | ||
5244 | } | 4536 | } |
5245 | 4537 | ||
5246 | static int qeth_core_prepare(struct ccwgroup_device *gdev) | 4538 | static int qeth_core_prepare(struct ccwgroup_device *gdev) |
5247 | { | 4539 | { |
5248 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 4540 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5249 | if (card->discipline && card->discipline->prepare) | 4541 | if (card->discipline.ccwgdriver && |
5250 | return card->discipline->prepare(gdev); | 4542 | card->discipline.ccwgdriver->prepare) |
4543 | return card->discipline.ccwgdriver->prepare(gdev); | ||
5251 | return 0; | 4544 | return 0; |
5252 | } | 4545 | } |
5253 | 4546 | ||
5254 | static void qeth_core_complete(struct ccwgroup_device *gdev) | 4547 | static void qeth_core_complete(struct ccwgroup_device *gdev) |
5255 | { | 4548 | { |
5256 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 4549 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5257 | if (card->discipline && card->discipline->complete) | 4550 | if (card->discipline.ccwgdriver && |
5258 | card->discipline->complete(gdev); | 4551 | card->discipline.ccwgdriver->complete) |
4552 | card->discipline.ccwgdriver->complete(gdev); | ||
5259 | } | 4553 | } |
5260 | 4554 | ||
5261 | static int qeth_core_freeze(struct ccwgroup_device *gdev) | 4555 | static int qeth_core_freeze(struct ccwgroup_device *gdev) |
5262 | { | 4556 | { |
5263 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 4557 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5264 | if (card->discipline && card->discipline->freeze) | 4558 | if (card->discipline.ccwgdriver && |
5265 | return card->discipline->freeze(gdev); | 4559 | card->discipline.ccwgdriver->freeze) |
4560 | return card->discipline.ccwgdriver->freeze(gdev); | ||
5266 | return 0; | 4561 | return 0; |
5267 | } | 4562 | } |
5268 | 4563 | ||
5269 | static int qeth_core_thaw(struct ccwgroup_device *gdev) | 4564 | static int qeth_core_thaw(struct ccwgroup_device *gdev) |
5270 | { | 4565 | { |
5271 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 4566 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5272 | if (card->discipline && card->discipline->thaw) | 4567 | if (card->discipline.ccwgdriver && |
5273 | return card->discipline->thaw(gdev); | 4568 | card->discipline.ccwgdriver->thaw) |
4569 | return card->discipline.ccwgdriver->thaw(gdev); | ||
5274 | return 0; | 4570 | return 0; |
5275 | } | 4571 | } |
5276 | 4572 | ||
5277 | static int qeth_core_restore(struct ccwgroup_device *gdev) | 4573 | static int qeth_core_restore(struct ccwgroup_device *gdev) |
5278 | { | 4574 | { |
5279 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 4575 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
5280 | if (card->discipline && card->discipline->restore) | 4576 | if (card->discipline.ccwgdriver && |
5281 | return card->discipline->restore(gdev); | 4577 | card->discipline.ccwgdriver->restore) |
4578 | return card->discipline.ccwgdriver->restore(gdev); | ||
5282 | return 0; | 4579 | return 0; |
5283 | } | 4580 | } |
5284 | 4581 | ||
@@ -5287,7 +4584,8 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = { | |||
5287 | .owner = THIS_MODULE, | 4584 | .owner = THIS_MODULE, |
5288 | .name = "qeth", | 4585 | .name = "qeth", |
5289 | }, | 4586 | }, |
5290 | .setup = qeth_core_probe_device, | 4587 | .driver_id = 0xD8C5E3C8, |
4588 | .probe = qeth_core_probe_device, | ||
5291 | .remove = qeth_core_remove_device, | 4589 | .remove = qeth_core_remove_device, |
5292 | .set_online = qeth_core_set_online, | 4590 | .set_online = qeth_core_set_online, |
5293 | .set_offline = qeth_core_set_offline, | 4591 | .set_offline = qeth_core_set_offline, |
@@ -5299,29 +4597,20 @@ static struct ccwgroup_driver qeth_core_ccwgroup_driver = { | |||
5299 | .restore = qeth_core_restore, | 4597 | .restore = qeth_core_restore, |
5300 | }; | 4598 | }; |
5301 | 4599 | ||
5302 | static ssize_t qeth_core_driver_group_store(struct device_driver *ddrv, | 4600 | static ssize_t |
5303 | const char *buf, size_t count) | 4601 | qeth_core_driver_group_store(struct device_driver *ddrv, const char *buf, |
4602 | size_t count) | ||
5304 | { | 4603 | { |
5305 | int err; | 4604 | int err; |
5306 | 4605 | err = qeth_core_driver_group(buf, qeth_core_root_dev, | |
5307 | err = ccwgroup_create_dev(qeth_core_root_dev, | 4606 | qeth_core_ccwgroup_driver.driver_id); |
5308 | &qeth_core_ccwgroup_driver, 3, buf); | 4607 | if (err) |
5309 | 4608 | return err; | |
5310 | return err ? err : count; | 4609 | else |
4610 | return count; | ||
5311 | } | 4611 | } |
5312 | static DRIVER_ATTR(group, 0200, NULL, qeth_core_driver_group_store); | ||
5313 | 4612 | ||
5314 | static struct attribute *qeth_drv_attrs[] = { | 4613 | static DRIVER_ATTR(group, 0200, NULL, qeth_core_driver_group_store); |
5315 | &driver_attr_group.attr, | ||
5316 | NULL, | ||
5317 | }; | ||
5318 | static struct attribute_group qeth_drv_attr_group = { | ||
5319 | .attrs = qeth_drv_attrs, | ||
5320 | }; | ||
5321 | static const struct attribute_group *qeth_drv_attr_groups[] = { | ||
5322 | &qeth_drv_attr_group, | ||
5323 | NULL, | ||
5324 | }; | ||
5325 | 4614 | ||
5326 | static struct { | 4615 | static struct { |
5327 | const char str[ETH_GSTRING_LEN]; | 4616 | const char str[ETH_GSTRING_LEN]; |
@@ -5361,8 +4650,6 @@ static struct { | |||
5361 | {"tx do_QDIO count"}, | 4650 | {"tx do_QDIO count"}, |
5362 | {"tx csum"}, | 4651 | {"tx csum"}, |
5363 | {"tx lin"}, | 4652 | {"tx lin"}, |
5364 | {"cq handler count"}, | ||
5365 | {"cq handler time"} | ||
5366 | }; | 4653 | }; |
5367 | 4654 | ||
5368 | int qeth_core_get_sset_count(struct net_device *dev, int stringset) | 4655 | int qeth_core_get_sset_count(struct net_device *dev, int stringset) |
@@ -5421,8 +4708,6 @@ void qeth_core_get_ethtool_stats(struct net_device *dev, | |||
5421 | data[32] = card->perf_stats.outbound_do_qdio_cnt; | 4708 | data[32] = card->perf_stats.outbound_do_qdio_cnt; |
5422 | data[33] = card->perf_stats.tx_csum; | 4709 | data[33] = card->perf_stats.tx_csum; |
5423 | data[34] = card->perf_stats.tx_lin; | 4710 | data[34] = card->perf_stats.tx_lin; |
5424 | data[35] = card->perf_stats.cq_cnt; | ||
5425 | data[36] = card->perf_stats.cq_time; | ||
5426 | } | 4711 | } |
5427 | EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats); | 4712 | EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats); |
5428 | 4713 | ||
@@ -5555,46 +4840,44 @@ static int __init qeth_core_init(void) | |||
5555 | pr_info("loading core functions\n"); | 4840 | pr_info("loading core functions\n"); |
5556 | INIT_LIST_HEAD(&qeth_core_card_list.list); | 4841 | INIT_LIST_HEAD(&qeth_core_card_list.list); |
5557 | rwlock_init(&qeth_core_card_list.rwlock); | 4842 | rwlock_init(&qeth_core_card_list.rwlock); |
5558 | mutex_init(&qeth_mod_mutex); | ||
5559 | 4843 | ||
5560 | rc = qeth_register_dbf_views(); | 4844 | rc = qeth_register_dbf_views(); |
5561 | if (rc) | 4845 | if (rc) |
5562 | goto out_err; | 4846 | goto out_err; |
4847 | rc = ccw_driver_register(&qeth_ccw_driver); | ||
4848 | if (rc) | ||
4849 | goto ccw_err; | ||
4850 | rc = ccwgroup_driver_register(&qeth_core_ccwgroup_driver); | ||
4851 | if (rc) | ||
4852 | goto ccwgroup_err; | ||
4853 | rc = driver_create_file(&qeth_core_ccwgroup_driver.driver, | ||
4854 | &driver_attr_group); | ||
4855 | if (rc) | ||
4856 | goto driver_err; | ||
5563 | qeth_core_root_dev = root_device_register("qeth"); | 4857 | qeth_core_root_dev = root_device_register("qeth"); |
5564 | rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0; | 4858 | rc = IS_ERR(qeth_core_root_dev) ? PTR_ERR(qeth_core_root_dev) : 0; |
5565 | if (rc) | 4859 | if (rc) |
5566 | goto register_err; | 4860 | goto register_err; |
4861 | |||
5567 | qeth_core_header_cache = kmem_cache_create("qeth_hdr", | 4862 | qeth_core_header_cache = kmem_cache_create("qeth_hdr", |
5568 | sizeof(struct qeth_hdr) + ETH_HLEN, 64, 0, NULL); | 4863 | sizeof(struct qeth_hdr) + ETH_HLEN, 64, 0, NULL); |
5569 | if (!qeth_core_header_cache) { | 4864 | if (!qeth_core_header_cache) { |
5570 | rc = -ENOMEM; | 4865 | rc = -ENOMEM; |
5571 | goto slab_err; | 4866 | goto slab_err; |
5572 | } | 4867 | } |
5573 | qeth_qdio_outbuf_cache = kmem_cache_create("qeth_buf", | ||
5574 | sizeof(struct qeth_qdio_out_buffer), 0, 0, NULL); | ||
5575 | if (!qeth_qdio_outbuf_cache) { | ||
5576 | rc = -ENOMEM; | ||
5577 | goto cqslab_err; | ||
5578 | } | ||
5579 | rc = ccw_driver_register(&qeth_ccw_driver); | ||
5580 | if (rc) | ||
5581 | goto ccw_err; | ||
5582 | qeth_core_ccwgroup_driver.driver.groups = qeth_drv_attr_groups; | ||
5583 | rc = ccwgroup_driver_register(&qeth_core_ccwgroup_driver); | ||
5584 | if (rc) | ||
5585 | goto ccwgroup_err; | ||
5586 | 4868 | ||
5587 | return 0; | 4869 | return 0; |
5588 | |||
5589 | ccwgroup_err: | ||
5590 | ccw_driver_unregister(&qeth_ccw_driver); | ||
5591 | ccw_err: | ||
5592 | kmem_cache_destroy(qeth_qdio_outbuf_cache); | ||
5593 | cqslab_err: | ||
5594 | kmem_cache_destroy(qeth_core_header_cache); | ||
5595 | slab_err: | 4870 | slab_err: |
5596 | root_device_unregister(qeth_core_root_dev); | 4871 | root_device_unregister(qeth_core_root_dev); |
5597 | register_err: | 4872 | register_err: |
4873 | driver_remove_file(&qeth_core_ccwgroup_driver.driver, | ||
4874 | &driver_attr_group); | ||
4875 | driver_err: | ||
4876 | ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver); | ||
4877 | ccwgroup_err: | ||
4878 | ccw_driver_unregister(&qeth_ccw_driver); | ||
4879 | ccw_err: | ||
4880 | QETH_DBF_MESSAGE(2, "Initialization failed with code %d\n", rc); | ||
5598 | qeth_unregister_dbf_views(); | 4881 | qeth_unregister_dbf_views(); |
5599 | out_err: | 4882 | out_err: |
5600 | pr_err("Initializing the qeth device driver failed\n"); | 4883 | pr_err("Initializing the qeth device driver failed\n"); |
@@ -5603,11 +4886,12 @@ out_err: | |||
5603 | 4886 | ||
5604 | static void __exit qeth_core_exit(void) | 4887 | static void __exit qeth_core_exit(void) |
5605 | { | 4888 | { |
4889 | root_device_unregister(qeth_core_root_dev); | ||
4890 | driver_remove_file(&qeth_core_ccwgroup_driver.driver, | ||
4891 | &driver_attr_group); | ||
5606 | ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver); | 4892 | ccwgroup_driver_unregister(&qeth_core_ccwgroup_driver); |
5607 | ccw_driver_unregister(&qeth_ccw_driver); | 4893 | ccw_driver_unregister(&qeth_ccw_driver); |
5608 | kmem_cache_destroy(qeth_qdio_outbuf_cache); | ||
5609 | kmem_cache_destroy(qeth_core_header_cache); | 4894 | kmem_cache_destroy(qeth_core_header_cache); |
5610 | root_device_unregister(qeth_core_root_dev); | ||
5611 | qeth_unregister_dbf_views(); | 4895 | qeth_unregister_dbf_views(); |
5612 | pr_info("core functions removed\n"); | 4896 | pr_info("core functions removed\n"); |
5613 | } | 4897 | } |
diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c index 5cebfddb86b..ec24901c802 100644 --- a/drivers/s390/net/qeth_core_mpc.c +++ b/drivers/s390/net/qeth_core_mpc.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/qeth_core_mpc.c | ||
3 | * | ||
2 | * Copyright IBM Corp. 2007 | 4 | * Copyright IBM Corp. 2007 |
3 | * Author(s): Frank Pavlic <fpavlic@de.ibm.com>, | 5 | * Author(s): Frank Pavlic <fpavlic@de.ibm.com>, |
4 | * Thomas Spatzier <tspat@de.ibm.com>, | 6 | * Thomas Spatzier <tspat@de.ibm.com>, |
@@ -205,7 +207,6 @@ static struct ipa_rc_msg qeth_ipa_rc_msg[] = { | |||
205 | {IPA_RC_MC_ADDR_ALREADY_DEFINED, "Multicast address already defined"}, | 207 | {IPA_RC_MC_ADDR_ALREADY_DEFINED, "Multicast address already defined"}, |
206 | {IPA_RC_LAN_OFFLINE, "STRTLAN_LAN_DISABLED - LAN offline"}, | 208 | {IPA_RC_LAN_OFFLINE, "STRTLAN_LAN_DISABLED - LAN offline"}, |
207 | {IPA_RC_INVALID_IP_VERSION2, "Invalid IP version"}, | 209 | {IPA_RC_INVALID_IP_VERSION2, "Invalid IP version"}, |
208 | {IPA_RC_ENOMEM, "Memory problem"}, | ||
209 | {IPA_RC_FFFF, "Unknown Error"} | 210 | {IPA_RC_FFFF, "Unknown Error"} |
210 | }; | 211 | }; |
211 | 212 | ||
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 3690bbf2cb3..e5a9d1c0383 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/qeth_core_mpc.h | ||
3 | * | ||
2 | * Copyright IBM Corp. 2007 | 4 | * Copyright IBM Corp. 2007 |
3 | * Author(s): Frank Pavlic <fpavlic@de.ibm.com>, | 5 | * Author(s): Frank Pavlic <fpavlic@de.ibm.com>, |
4 | * Thomas Spatzier <tspat@de.ibm.com>, | 6 | * Thomas Spatzier <tspat@de.ibm.com>, |
@@ -68,6 +70,16 @@ enum qeth_link_types { | |||
68 | QETH_LINK_TYPE_ATM_NATIVE = 0x90, | 70 | QETH_LINK_TYPE_ATM_NATIVE = 0x90, |
69 | }; | 71 | }; |
70 | 72 | ||
73 | enum qeth_tr_macaddr_modes { | ||
74 | QETH_TR_MACADDR_NONCANONICAL = 0, | ||
75 | QETH_TR_MACADDR_CANONICAL = 1, | ||
76 | }; | ||
77 | |||
78 | enum qeth_tr_broadcast_modes { | ||
79 | QETH_TR_BROADCAST_ALLRINGS = 0, | ||
80 | QETH_TR_BROADCAST_LOCAL = 1, | ||
81 | }; | ||
82 | |||
71 | /* | 83 | /* |
72 | * Routing stuff | 84 | * Routing stuff |
73 | */ | 85 | */ |
@@ -178,7 +190,6 @@ enum qeth_ipa_return_codes { | |||
178 | IPA_RC_MC_ADDR_ALREADY_DEFINED = 0xe013, | 190 | IPA_RC_MC_ADDR_ALREADY_DEFINED = 0xe013, |
179 | IPA_RC_LAN_OFFLINE = 0xe080, | 191 | IPA_RC_LAN_OFFLINE = 0xe080, |
180 | IPA_RC_INVALID_IP_VERSION2 = 0xf001, | 192 | IPA_RC_INVALID_IP_VERSION2 = 0xf001, |
181 | IPA_RC_ENOMEM = 0xfffe, | ||
182 | IPA_RC_FFFF = 0xffff | 193 | IPA_RC_FFFF = 0xffff |
183 | }; | 194 | }; |
184 | /* for DELIP */ | 195 | /* for DELIP */ |
@@ -238,7 +249,6 @@ enum qeth_ipa_setadp_cmd { | |||
238 | IPA_SETADP_SET_PROMISC_MODE = 0x00000800L, | 249 | IPA_SETADP_SET_PROMISC_MODE = 0x00000800L, |
239 | IPA_SETADP_SET_DIAG_ASSIST = 0x00002000L, | 250 | IPA_SETADP_SET_DIAG_ASSIST = 0x00002000L, |
240 | IPA_SETADP_SET_ACCESS_CONTROL = 0x00010000L, | 251 | IPA_SETADP_SET_ACCESS_CONTROL = 0x00010000L, |
241 | IPA_SETADP_QUERY_OAT = 0x00080000L, | ||
242 | }; | 252 | }; |
243 | enum qeth_ipa_mac_ops { | 253 | enum qeth_ipa_mac_ops { |
244 | CHANGE_ADDR_READ_MAC = 0, | 254 | CHANGE_ADDR_READ_MAC = 0, |
@@ -388,17 +398,6 @@ struct qeth_set_access_ctrl { | |||
388 | __u32 subcmd_code; | 398 | __u32 subcmd_code; |
389 | } __attribute__((packed)); | 399 | } __attribute__((packed)); |
390 | 400 | ||
391 | struct qeth_query_oat { | ||
392 | __u32 subcmd_code; | ||
393 | __u8 reserved[12]; | ||
394 | } __packed; | ||
395 | |||
396 | struct qeth_qoat_priv { | ||
397 | __u32 buffer_len; | ||
398 | __u32 response_len; | ||
399 | char *buffer; | ||
400 | }; | ||
401 | |||
402 | struct qeth_ipacmd_setadpparms_hdr { | 401 | struct qeth_ipacmd_setadpparms_hdr { |
403 | __u32 supp_hw_cmds; | 402 | __u32 supp_hw_cmds; |
404 | __u32 reserved1; | 403 | __u32 reserved1; |
@@ -418,7 +417,6 @@ struct qeth_ipacmd_setadpparms { | |||
418 | struct qeth_change_addr change_addr; | 417 | struct qeth_change_addr change_addr; |
419 | struct qeth_snmp_cmd snmp; | 418 | struct qeth_snmp_cmd snmp; |
420 | struct qeth_set_access_ctrl set_access_ctrl; | 419 | struct qeth_set_access_ctrl set_access_ctrl; |
421 | struct qeth_query_oat query_oat; | ||
422 | __u32 mode; | 420 | __u32 mode; |
423 | } data; | 421 | } data; |
424 | } __attribute__ ((packed)); | 422 | } __attribute__ ((packed)); |
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 9655dc0ea0e..0a8e86c1b0e 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/qeth_core_sys.c | ||
3 | * | ||
2 | * Copyright IBM Corp. 2007 | 4 | * Copyright IBM Corp. 2007 |
3 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, | 5 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, |
4 | * Frank Pavlic <fpavlic@de.ibm.com>, | 6 | * Frank Pavlic <fpavlic@de.ibm.com>, |
@@ -432,8 +434,8 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, | |||
432 | goto out; | 434 | goto out; |
433 | else { | 435 | else { |
434 | card->info.mac_bits = 0; | 436 | card->info.mac_bits = 0; |
435 | if (card->discipline) { | 437 | if (card->discipline.ccwgdriver) { |
436 | card->discipline->remove(card->gdev); | 438 | card->discipline.ccwgdriver->remove(card->gdev); |
437 | qeth_core_free_discipline(card); | 439 | qeth_core_free_discipline(card); |
438 | } | 440 | } |
439 | } | 441 | } |
@@ -442,7 +444,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev, | |||
442 | if (rc) | 444 | if (rc) |
443 | goto out; | 445 | goto out; |
444 | 446 | ||
445 | rc = card->discipline->setup(card->gdev); | 447 | rc = card->discipline.ccwgdriver->probe(card->gdev); |
446 | out: | 448 | out: |
447 | mutex_unlock(&card->discipline_mutex); | 449 | mutex_unlock(&card->discipline_mutex); |
448 | return rc ? rc : count; | 450 | return rc ? rc : count; |
@@ -691,6 +693,7 @@ static struct attribute *qeth_blkt_device_attrs[] = { | |||
691 | &dev_attr_inter_jumbo.attr, | 693 | &dev_attr_inter_jumbo.attr, |
692 | NULL, | 694 | NULL, |
693 | }; | 695 | }; |
696 | |||
694 | static struct attribute_group qeth_device_blkt_group = { | 697 | static struct attribute_group qeth_device_blkt_group = { |
695 | .name = "blkt", | 698 | .name = "blkt", |
696 | .attrs = qeth_blkt_device_attrs, | 699 | .attrs = qeth_blkt_device_attrs, |
@@ -713,16 +716,11 @@ static struct attribute *qeth_device_attrs[] = { | |||
713 | &dev_attr_hw_trap.attr, | 716 | &dev_attr_hw_trap.attr, |
714 | NULL, | 717 | NULL, |
715 | }; | 718 | }; |
719 | |||
716 | static struct attribute_group qeth_device_attr_group = { | 720 | static struct attribute_group qeth_device_attr_group = { |
717 | .attrs = qeth_device_attrs, | 721 | .attrs = qeth_device_attrs, |
718 | }; | 722 | }; |
719 | 723 | ||
720 | const struct attribute_group *qeth_generic_attr_groups[] = { | ||
721 | &qeth_device_attr_group, | ||
722 | &qeth_device_blkt_group, | ||
723 | NULL, | ||
724 | }; | ||
725 | |||
726 | static struct attribute *qeth_osn_device_attrs[] = { | 724 | static struct attribute *qeth_osn_device_attrs[] = { |
727 | &dev_attr_state.attr, | 725 | &dev_attr_state.attr, |
728 | &dev_attr_chpid.attr, | 726 | &dev_attr_chpid.attr, |
@@ -732,10 +730,37 @@ static struct attribute *qeth_osn_device_attrs[] = { | |||
732 | &dev_attr_recover.attr, | 730 | &dev_attr_recover.attr, |
733 | NULL, | 731 | NULL, |
734 | }; | 732 | }; |
733 | |||
735 | static struct attribute_group qeth_osn_device_attr_group = { | 734 | static struct attribute_group qeth_osn_device_attr_group = { |
736 | .attrs = qeth_osn_device_attrs, | 735 | .attrs = qeth_osn_device_attrs, |
737 | }; | 736 | }; |
738 | const struct attribute_group *qeth_osn_attr_groups[] = { | 737 | |
739 | &qeth_osn_device_attr_group, | 738 | int qeth_core_create_device_attributes(struct device *dev) |
740 | NULL, | 739 | { |
741 | }; | 740 | int ret; |
741 | ret = sysfs_create_group(&dev->kobj, &qeth_device_attr_group); | ||
742 | if (ret) | ||
743 | return ret; | ||
744 | ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group); | ||
745 | if (ret) | ||
746 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); | ||
747 | |||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | void qeth_core_remove_device_attributes(struct device *dev) | ||
752 | { | ||
753 | sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); | ||
754 | sysfs_remove_group(&dev->kobj, &qeth_device_blkt_group); | ||
755 | } | ||
756 | |||
757 | int qeth_core_create_osn_attributes(struct device *dev) | ||
758 | { | ||
759 | return sysfs_create_group(&dev->kobj, &qeth_osn_device_attr_group); | ||
760 | } | ||
761 | |||
762 | void qeth_core_remove_osn_attributes(struct device *dev) | ||
763 | { | ||
764 | sysfs_remove_group(&dev->kobj, &qeth_osn_device_attr_group); | ||
765 | return; | ||
766 | } | ||
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 73195553f84..b70b47fbd6c 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/qeth_l2_main.c | ||
3 | * | ||
2 | * Copyright IBM Corp. 2007, 2009 | 4 | * Copyright IBM Corp. 2007, 2009 |
3 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, | 5 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, |
4 | * Frank Pavlic <fpavlic@de.ibm.com>, | 6 | * Frank Pavlic <fpavlic@de.ibm.com>, |
@@ -73,9 +75,6 @@ static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
73 | mii_data->val_out = qeth_mdio_read(dev, | 75 | mii_data->val_out = qeth_mdio_read(dev, |
74 | mii_data->phy_id, mii_data->reg_num); | 76 | mii_data->phy_id, mii_data->reg_num); |
75 | break; | 77 | break; |
76 | case SIOC_QETH_QUERY_OAT: | ||
77 | rc = qeth_query_oat_command(card, rq->ifr_ifru.ifru_data); | ||
78 | break; | ||
79 | default: | 78 | default: |
80 | rc = -EOPNOTSUPP; | 79 | rc = -EOPNOTSUPP; |
81 | } | 80 | } |
@@ -302,21 +301,21 @@ static void qeth_l2_process_vlans(struct qeth_card *card) | |||
302 | spin_unlock_bh(&card->vlanlock); | 301 | spin_unlock_bh(&card->vlanlock); |
303 | } | 302 | } |
304 | 303 | ||
305 | static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) | 304 | static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) |
306 | { | 305 | { |
307 | struct qeth_card *card = dev->ml_priv; | 306 | struct qeth_card *card = dev->ml_priv; |
308 | struct qeth_vlan_vid *id; | 307 | struct qeth_vlan_vid *id; |
309 | 308 | ||
310 | QETH_CARD_TEXT_(card, 4, "aid:%d", vid); | 309 | QETH_CARD_TEXT_(card, 4, "aid:%d", vid); |
311 | if (!vid) | 310 | if (!vid) |
312 | return 0; | 311 | return; |
313 | if (card->info.type == QETH_CARD_TYPE_OSM) { | 312 | if (card->info.type == QETH_CARD_TYPE_OSM) { |
314 | QETH_CARD_TEXT(card, 3, "aidOSM"); | 313 | QETH_CARD_TEXT(card, 3, "aidOSM"); |
315 | return 0; | 314 | return; |
316 | } | 315 | } |
317 | if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { | 316 | if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { |
318 | QETH_CARD_TEXT(card, 3, "aidREC"); | 317 | QETH_CARD_TEXT(card, 3, "aidREC"); |
319 | return 0; | 318 | return; |
320 | } | 319 | } |
321 | id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC); | 320 | id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC); |
322 | if (id) { | 321 | if (id) { |
@@ -325,13 +324,10 @@ static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) | |||
325 | spin_lock_bh(&card->vlanlock); | 324 | spin_lock_bh(&card->vlanlock); |
326 | list_add_tail(&id->list, &card->vid_list); | 325 | list_add_tail(&id->list, &card->vid_list); |
327 | spin_unlock_bh(&card->vlanlock); | 326 | spin_unlock_bh(&card->vlanlock); |
328 | } else { | ||
329 | return -ENOMEM; | ||
330 | } | 327 | } |
331 | return 0; | ||
332 | } | 328 | } |
333 | 329 | ||
334 | static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | 330 | static void qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) |
335 | { | 331 | { |
336 | struct qeth_vlan_vid *id, *tmpid = NULL; | 332 | struct qeth_vlan_vid *id, *tmpid = NULL; |
337 | struct qeth_card *card = dev->ml_priv; | 333 | struct qeth_card *card = dev->ml_priv; |
@@ -339,11 +335,11 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
339 | QETH_CARD_TEXT_(card, 4, "kid:%d", vid); | 335 | QETH_CARD_TEXT_(card, 4, "kid:%d", vid); |
340 | if (card->info.type == QETH_CARD_TYPE_OSM) { | 336 | if (card->info.type == QETH_CARD_TYPE_OSM) { |
341 | QETH_CARD_TEXT(card, 3, "kidOSM"); | 337 | QETH_CARD_TEXT(card, 3, "kidOSM"); |
342 | return 0; | 338 | return; |
343 | } | 339 | } |
344 | if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { | 340 | if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { |
345 | QETH_CARD_TEXT(card, 3, "kidREC"); | 341 | QETH_CARD_TEXT(card, 3, "kidREC"); |
346 | return 0; | 342 | return; |
347 | } | 343 | } |
348 | spin_lock_bh(&card->vlanlock); | 344 | spin_lock_bh(&card->vlanlock); |
349 | list_for_each_entry(id, &card->vid_list, list) { | 345 | list_for_each_entry(id, &card->vid_list, list) { |
@@ -359,7 +355,6 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
359 | kfree(tmpid); | 355 | kfree(tmpid); |
360 | } | 356 | } |
361 | qeth_l2_set_multicast_list(card->dev); | 357 | qeth_l2_set_multicast_list(card->dev); |
362 | return 0; | ||
363 | } | 358 | } |
364 | 359 | ||
365 | static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) | 360 | static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode) |
@@ -411,10 +406,10 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card, | |||
411 | unsigned int len; | 406 | unsigned int len; |
412 | 407 | ||
413 | *done = 0; | 408 | *done = 0; |
414 | WARN_ON_ONCE(!budget); | 409 | BUG_ON(!budget); |
415 | while (budget) { | 410 | while (budget) { |
416 | skb = qeth_core_get_next_skb(card, | 411 | skb = qeth_core_get_next_skb(card, |
417 | &card->qdio.in_q->bufs[card->rx.b_index], | 412 | card->qdio.in_q->bufs[card->rx.b_index].buffer, |
418 | &card->rx.b_element, &card->rx.e_offset, &hdr); | 413 | &card->rx.b_element, &card->rx.e_offset, &hdr); |
419 | if (!skb) { | 414 | if (!skb) { |
420 | *done = 1; | 415 | *done = 1; |
@@ -574,6 +569,7 @@ static int qeth_l2_send_setmac_cb(struct qeth_card *card, | |||
574 | default: | 569 | default: |
575 | break; | 570 | break; |
576 | } | 571 | } |
572 | cmd->hdr.return_code = -EIO; | ||
577 | } else { | 573 | } else { |
578 | card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; | 574 | card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED; |
579 | memcpy(card->dev->dev_addr, cmd->data.setdelmac.mac, | 575 | memcpy(card->dev->dev_addr, cmd->data.setdelmac.mac, |
@@ -602,6 +598,7 @@ static int qeth_l2_send_delmac_cb(struct qeth_card *card, | |||
602 | cmd = (struct qeth_ipa_cmd *) data; | 598 | cmd = (struct qeth_ipa_cmd *) data; |
603 | if (cmd->hdr.return_code) { | 599 | if (cmd->hdr.return_code) { |
604 | QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code); | 600 | QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code); |
601 | cmd->hdr.return_code = -EIO; | ||
605 | return 0; | 602 | return 0; |
606 | } | 603 | } |
607 | card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; | 604 | card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED; |
@@ -626,13 +623,10 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) | |||
626 | QETH_DBF_TEXT(SETUP, 2, "doL2init"); | 623 | QETH_DBF_TEXT(SETUP, 2, "doL2init"); |
627 | QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card)); | 624 | QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card)); |
628 | 625 | ||
629 | if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) { | 626 | rc = qeth_query_setadapterparms(card); |
630 | rc = qeth_query_setadapterparms(card); | 627 | if (rc) { |
631 | if (rc) { | 628 | QETH_DBF_MESSAGE(2, "could not query adapter parameters on " |
632 | QETH_DBF_MESSAGE(2, "could not query adapter " | 629 | "device %s: x%x\n", CARD_BUS_ID(card), rc); |
633 | "parameters on device %s: x%x\n", | ||
634 | CARD_BUS_ID(card), rc); | ||
635 | } | ||
636 | } | 630 | } |
637 | 631 | ||
638 | if (card->info.type == QETH_CARD_TYPE_IQD || | 632 | if (card->info.type == QETH_CARD_TYPE_IQD || |
@@ -648,7 +642,7 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) | |||
648 | } | 642 | } |
649 | QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, OSA_ADDR_LEN); | 643 | QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, OSA_ADDR_LEN); |
650 | } else { | 644 | } else { |
651 | eth_random_addr(card->dev->dev_addr); | 645 | random_ether_addr(card->dev->dev_addr); |
652 | memcpy(card->dev->dev_addr, vendor_pre, 3); | 646 | memcpy(card->dev->dev_addr, vendor_pre, 3); |
653 | } | 647 | } |
654 | return 0; | 648 | return 0; |
@@ -679,9 +673,9 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) | |||
679 | return -ERESTARTSYS; | 673 | return -ERESTARTSYS; |
680 | } | 674 | } |
681 | rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]); | 675 | rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]); |
682 | if (!rc || (rc == IPA_RC_L2_MAC_NOT_FOUND)) | 676 | if (!rc) |
683 | rc = qeth_l2_send_setmac(card, addr->sa_data); | 677 | rc = qeth_l2_send_setmac(card, addr->sa_data); |
684 | return rc ? -EINVAL : 0; | 678 | return rc; |
685 | } | 679 | } |
686 | 680 | ||
687 | static void qeth_l2_set_multicast_list(struct net_device *dev) | 681 | static void qeth_l2_set_multicast_list(struct net_device *dev) |
@@ -883,6 +877,12 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) | |||
883 | INIT_LIST_HEAD(&card->mc_list); | 877 | INIT_LIST_HEAD(&card->mc_list); |
884 | card->options.layer2 = 1; | 878 | card->options.layer2 = 1; |
885 | card->info.hwtrap = 0; | 879 | card->info.hwtrap = 0; |
880 | card->discipline.start_poll = qeth_qdio_start_poll; | ||
881 | card->discipline.input_handler = (qdio_handler_t *) | ||
882 | qeth_qdio_input_handler; | ||
883 | card->discipline.output_handler = (qdio_handler_t *) | ||
884 | qeth_qdio_output_handler; | ||
885 | card->discipline.recover = qeth_l2_recover; | ||
886 | return 0; | 886 | return 0; |
887 | } | 887 | } |
888 | 888 | ||
@@ -925,7 +925,7 @@ static const struct net_device_ops qeth_l2_netdev_ops = { | |||
925 | .ndo_get_stats = qeth_get_stats, | 925 | .ndo_get_stats = qeth_get_stats, |
926 | .ndo_start_xmit = qeth_l2_hard_start_xmit, | 926 | .ndo_start_xmit = qeth_l2_hard_start_xmit, |
927 | .ndo_validate_addr = eth_validate_addr, | 927 | .ndo_validate_addr = eth_validate_addr, |
928 | .ndo_set_rx_mode = qeth_l2_set_multicast_list, | 928 | .ndo_set_multicast_list = qeth_l2_set_multicast_list, |
929 | .ndo_do_ioctl = qeth_l2_do_ioctl, | 929 | .ndo_do_ioctl = qeth_l2_do_ioctl, |
930 | .ndo_set_mac_address = qeth_l2_set_mac_address, | 930 | .ndo_set_mac_address = qeth_l2_set_mac_address, |
931 | .ndo_change_mtu = qeth_change_mtu, | 931 | .ndo_change_mtu = qeth_change_mtu, |
@@ -973,6 +973,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
973 | int rc = 0; | 973 | int rc = 0; |
974 | enum qeth_card_states recover_flag; | 974 | enum qeth_card_states recover_flag; |
975 | 975 | ||
976 | BUG_ON(!card); | ||
976 | mutex_lock(&card->discipline_mutex); | 977 | mutex_lock(&card->discipline_mutex); |
977 | mutex_lock(&card->conf_mutex); | 978 | mutex_lock(&card->conf_mutex); |
978 | QETH_DBF_TEXT(SETUP, 2, "setonlin"); | 979 | QETH_DBF_TEXT(SETUP, 2, "setonlin"); |
@@ -985,7 +986,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
985 | rc = -ENODEV; | 986 | rc = -ENODEV; |
986 | goto out_remove; | 987 | goto out_remove; |
987 | } | 988 | } |
988 | qeth_trace_features(card); | ||
989 | 989 | ||
990 | if (!card->dev && qeth_l2_setup_netdev(card)) { | 990 | if (!card->dev && qeth_l2_setup_netdev(card)) { |
991 | rc = -ENODEV; | 991 | rc = -ENODEV; |
@@ -1144,12 +1144,11 @@ static int qeth_l2_recover(void *ptr) | |||
1144 | dev_info(&card->gdev->dev, | 1144 | dev_info(&card->gdev->dev, |
1145 | "Device successfully recovered!\n"); | 1145 | "Device successfully recovered!\n"); |
1146 | else { | 1146 | else { |
1147 | if (rtnl_trylock()) { | 1147 | rtnl_lock(); |
1148 | dev_close(card->dev); | 1148 | dev_close(card->dev); |
1149 | rtnl_unlock(); | 1149 | rtnl_unlock(); |
1150 | dev_warn(&card->gdev->dev, "The qeth device driver " | 1150 | dev_warn(&card->gdev->dev, "The qeth device driver " |
1151 | "failed to recover an error on the device\n"); | 1151 | "failed to recover an error on the device\n"); |
1152 | } | ||
1153 | } | 1152 | } |
1154 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | 1153 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); |
1155 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | 1154 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); |
@@ -1170,7 +1169,6 @@ static void __exit qeth_l2_exit(void) | |||
1170 | static void qeth_l2_shutdown(struct ccwgroup_device *gdev) | 1169 | static void qeth_l2_shutdown(struct ccwgroup_device *gdev) |
1171 | { | 1170 | { |
1172 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 1171 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
1173 | qeth_set_allowed_threads(card, 0, 1); | ||
1174 | if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap) | 1172 | if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap) |
1175 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | 1173 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); |
1176 | qeth_qdio_clear_card(card, 0); | 1174 | qeth_qdio_clear_card(card, 0); |
@@ -1223,12 +1221,8 @@ out: | |||
1223 | return rc; | 1221 | return rc; |
1224 | } | 1222 | } |
1225 | 1223 | ||
1226 | struct qeth_discipline qeth_l2_discipline = { | 1224 | struct ccwgroup_driver qeth_l2_ccwgroup_driver = { |
1227 | .start_poll = qeth_qdio_start_poll, | 1225 | .probe = qeth_l2_probe_device, |
1228 | .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, | ||
1229 | .output_handler = (qdio_handler_t *) qeth_qdio_output_handler, | ||
1230 | .recover = qeth_l2_recover, | ||
1231 | .setup = qeth_l2_probe_device, | ||
1232 | .remove = qeth_l2_remove_device, | 1226 | .remove = qeth_l2_remove_device, |
1233 | .set_online = qeth_l2_set_online, | 1227 | .set_online = qeth_l2_set_online, |
1234 | .set_offline = qeth_l2_set_offline, | 1228 | .set_offline = qeth_l2_set_offline, |
@@ -1237,7 +1231,7 @@ struct qeth_discipline qeth_l2_discipline = { | |||
1237 | .thaw = qeth_l2_pm_resume, | 1231 | .thaw = qeth_l2_pm_resume, |
1238 | .restore = qeth_l2_pm_resume, | 1232 | .restore = qeth_l2_pm_resume, |
1239 | }; | 1233 | }; |
1240 | EXPORT_SYMBOL_GPL(qeth_l2_discipline); | 1234 | EXPORT_SYMBOL_GPL(qeth_l2_ccwgroup_driver); |
1241 | 1235 | ||
1242 | static int qeth_osn_send_control_data(struct qeth_card *card, int len, | 1236 | static int qeth_osn_send_control_data(struct qeth_card *card, int len, |
1243 | struct qeth_cmd_buffer *iob) | 1237 | struct qeth_cmd_buffer *iob) |
diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h index 29c1c00e3a0..14a43aeb0c2 100644 --- a/drivers/s390/net/qeth_l3.h +++ b/drivers/s390/net/qeth_l3.h | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/qeth_l3.h | ||
3 | * | ||
2 | * Copyright IBM Corp. 2007 | 4 | * Copyright IBM Corp. 2007 |
3 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, | 5 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, |
4 | * Frank Pavlic <fpavlic@de.ibm.com>, | 6 | * Frank Pavlic <fpavlic@de.ibm.com>, |
@@ -61,9 +63,5 @@ 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, | 63 | void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions, |
62 | const u8 *); | 64 | const u8 *); |
63 | int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *); | 65 | int qeth_l3_is_addr_covered_by_ipato(struct qeth_card *, struct qeth_ipaddr *); |
64 | struct qeth_ipaddr *qeth_l3_get_addr_buffer(enum qeth_prot_versions); | ||
65 | int qeth_l3_add_ip(struct qeth_card *, struct qeth_ipaddr *); | ||
66 | int qeth_l3_delete_ip(struct qeth_card *, struct qeth_ipaddr *); | ||
67 | void qeth_l3_set_ip_addr_list(struct qeth_card *); | ||
68 | 66 | ||
69 | #endif /* __QETH_L3_H__ */ | 67 | #endif /* __QETH_L3_H__ */ |
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 6e5eef01e66..c74e8670fab 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/qeth_l3_main.c | ||
3 | * | ||
2 | * Copyright IBM Corp. 2007, 2009 | 4 | * Copyright IBM Corp. 2007, 2009 |
3 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, | 5 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, |
4 | * Frank Pavlic <fpavlic@de.ibm.com>, | 6 | * Frank Pavlic <fpavlic@de.ibm.com>, |
@@ -26,10 +28,7 @@ | |||
26 | 28 | ||
27 | #include <net/ip.h> | 29 | #include <net/ip.h> |
28 | #include <net/arp.h> | 30 | #include <net/arp.h> |
29 | #include <net/route.h> | ||
30 | #include <net/ip6_fib.h> | ||
31 | #include <net/ip6_checksum.h> | 31 | #include <net/ip6_checksum.h> |
32 | #include <net/iucv/af_iucv.h> | ||
33 | 32 | ||
34 | #include "qeth_l3.h" | 33 | #include "qeth_l3.h" |
35 | 34 | ||
@@ -268,7 +267,7 @@ static int __qeth_l3_insert_ip_todo(struct qeth_card *card, | |||
268 | } | 267 | } |
269 | } | 268 | } |
270 | 269 | ||
271 | int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | 270 | static int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) |
272 | { | 271 | { |
273 | unsigned long flags; | 272 | unsigned long flags; |
274 | int rc = 0; | 273 | int rc = 0; |
@@ -287,7 +286,7 @@ int qeth_l3_delete_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | |||
287 | return rc; | 286 | return rc; |
288 | } | 287 | } |
289 | 288 | ||
290 | int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | 289 | static int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) |
291 | { | 290 | { |
292 | unsigned long flags; | 291 | unsigned long flags; |
293 | int rc = 0; | 292 | int rc = 0; |
@@ -306,7 +305,7 @@ int qeth_l3_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | |||
306 | } | 305 | } |
307 | 306 | ||
308 | 307 | ||
309 | struct qeth_ipaddr *qeth_l3_get_addr_buffer( | 308 | static struct qeth_ipaddr *qeth_l3_get_addr_buffer( |
310 | enum qeth_prot_versions prot) | 309 | enum qeth_prot_versions prot) |
311 | { | 310 | { |
312 | struct qeth_ipaddr *addr; | 311 | struct qeth_ipaddr *addr; |
@@ -422,7 +421,7 @@ again: | |||
422 | list_splice(&fail_list, &card->ip_list); | 421 | list_splice(&fail_list, &card->ip_list); |
423 | } | 422 | } |
424 | 423 | ||
425 | void qeth_l3_set_ip_addr_list(struct qeth_card *card) | 424 | static void qeth_l3_set_ip_addr_list(struct qeth_card *card) |
426 | { | 425 | { |
427 | struct list_head *tbd_list; | 426 | struct list_head *tbd_list; |
428 | struct qeth_ipaddr *todo, *addr; | 427 | struct qeth_ipaddr *todo, *addr; |
@@ -439,7 +438,7 @@ void qeth_l3_set_ip_addr_list(struct qeth_card *card) | |||
439 | 438 | ||
440 | spin_lock_irqsave(&card->ip_lock, flags); | 439 | spin_lock_irqsave(&card->ip_lock, flags); |
441 | tbd_list = card->ip_tbd_list; | 440 | tbd_list = card->ip_tbd_list; |
442 | card->ip_tbd_list = kzalloc(sizeof(struct list_head), GFP_ATOMIC); | 441 | card->ip_tbd_list = kmalloc(sizeof(struct list_head), GFP_ATOMIC); |
443 | if (!card->ip_tbd_list) { | 442 | if (!card->ip_tbd_list) { |
444 | QETH_CARD_TEXT(card, 0, "silnomem"); | 443 | QETH_CARD_TEXT(card, 0, "silnomem"); |
445 | card->ip_tbd_list = tbd_list; | 444 | card->ip_tbd_list = tbd_list; |
@@ -794,7 +793,6 @@ int qeth_l3_add_vipa(struct qeth_card *card, enum qeth_prot_versions proto, | |||
794 | rc = -EEXIST; | 793 | rc = -EEXIST; |
795 | spin_unlock_irqrestore(&card->ip_lock, flags); | 794 | spin_unlock_irqrestore(&card->ip_lock, flags); |
796 | if (rc) { | 795 | if (rc) { |
797 | kfree(ipaddr); | ||
798 | return rc; | 796 | return rc; |
799 | } | 797 | } |
800 | if (!qeth_l3_add_ip(card, ipaddr)) | 798 | if (!qeth_l3_add_ip(card, ipaddr)) |
@@ -859,7 +857,6 @@ int qeth_l3_add_rxip(struct qeth_card *card, enum qeth_prot_versions proto, | |||
859 | rc = -EEXIST; | 857 | rc = -EEXIST; |
860 | spin_unlock_irqrestore(&card->ip_lock, flags); | 858 | spin_unlock_irqrestore(&card->ip_lock, flags); |
861 | if (rc) { | 859 | if (rc) { |
862 | kfree(ipaddr); | ||
863 | return rc; | 860 | return rc; |
864 | } | 861 | } |
865 | if (!qeth_l3_add_ip(card, ipaddr)) | 862 | if (!qeth_l3_add_ip(card, ipaddr)) |
@@ -976,6 +973,57 @@ static inline u8 qeth_l3_get_qeth_hdr_flags6(int cast_type) | |||
976 | return ct | QETH_CAST_UNICAST; | 973 | return ct | QETH_CAST_UNICAST; |
977 | } | 974 | } |
978 | 975 | ||
976 | static int qeth_l3_send_setadp_mode(struct qeth_card *card, __u32 command, | ||
977 | __u32 mode) | ||
978 | { | ||
979 | int rc; | ||
980 | struct qeth_cmd_buffer *iob; | ||
981 | struct qeth_ipa_cmd *cmd; | ||
982 | |||
983 | QETH_CARD_TEXT(card, 4, "adpmode"); | ||
984 | |||
985 | iob = qeth_get_adapter_cmd(card, command, | ||
986 | sizeof(struct qeth_ipacmd_setadpparms)); | ||
987 | cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE); | ||
988 | cmd->data.setadapterparms.data.mode = mode; | ||
989 | rc = qeth_send_ipa_cmd(card, iob, qeth_default_setadapterparms_cb, | ||
990 | NULL); | ||
991 | return rc; | ||
992 | } | ||
993 | |||
994 | static int qeth_l3_setadapter_hstr(struct qeth_card *card) | ||
995 | { | ||
996 | int rc; | ||
997 | |||
998 | QETH_CARD_TEXT(card, 4, "adphstr"); | ||
999 | |||
1000 | if (qeth_adp_supported(card, IPA_SETADP_SET_BROADCAST_MODE)) { | ||
1001 | rc = qeth_l3_send_setadp_mode(card, | ||
1002 | IPA_SETADP_SET_BROADCAST_MODE, | ||
1003 | card->options.broadcast_mode); | ||
1004 | if (rc) | ||
1005 | QETH_DBF_MESSAGE(2, "couldn't set broadcast mode on " | ||
1006 | "device %s: x%x\n", | ||
1007 | CARD_BUS_ID(card), rc); | ||
1008 | rc = qeth_l3_send_setadp_mode(card, | ||
1009 | IPA_SETADP_ALTER_MAC_ADDRESS, | ||
1010 | card->options.macaddr_mode); | ||
1011 | if (rc) | ||
1012 | QETH_DBF_MESSAGE(2, "couldn't set macaddr mode on " | ||
1013 | "device %s: x%x\n", CARD_BUS_ID(card), rc); | ||
1014 | return rc; | ||
1015 | } | ||
1016 | if (card->options.broadcast_mode == QETH_TR_BROADCAST_LOCAL) | ||
1017 | QETH_DBF_MESSAGE(2, "set adapter parameters not available " | ||
1018 | "to set broadcast mode, using ALLRINGS " | ||
1019 | "on device %s:\n", CARD_BUS_ID(card)); | ||
1020 | if (card->options.macaddr_mode == QETH_TR_MACADDR_CANONICAL) | ||
1021 | QETH_DBF_MESSAGE(2, "set adapter parameters not available " | ||
1022 | "to set macaddr mode, using NONCANONICAL " | ||
1023 | "on device %s:\n", CARD_BUS_ID(card)); | ||
1024 | return 0; | ||
1025 | } | ||
1026 | |||
979 | static int qeth_l3_setadapter_parms(struct qeth_card *card) | 1027 | static int qeth_l3_setadapter_parms(struct qeth_card *card) |
980 | { | 1028 | { |
981 | int rc; | 1029 | int rc; |
@@ -1001,6 +1049,10 @@ static int qeth_l3_setadapter_parms(struct qeth_card *card) | |||
1001 | " address failed\n"); | 1049 | " address failed\n"); |
1002 | } | 1050 | } |
1003 | 1051 | ||
1052 | if ((card->info.link_type == QETH_LINK_TYPE_HSTR) || | ||
1053 | (card->info.link_type == QETH_LINK_TYPE_LANE_TR)) | ||
1054 | rc = qeth_l3_setadapter_hstr(card); | ||
1055 | |||
1004 | return rc; | 1056 | return rc; |
1005 | } | 1057 | } |
1006 | 1058 | ||
@@ -1362,7 +1414,7 @@ static int qeth_l3_send_checksum_command(struct qeth_card *card) | |||
1362 | return 0; | 1414 | return 0; |
1363 | } | 1415 | } |
1364 | 1416 | ||
1365 | static int qeth_l3_set_rx_csum(struct qeth_card *card, int on) | 1417 | int qeth_l3_set_rx_csum(struct qeth_card *card, int on) |
1366 | { | 1418 | { |
1367 | int rc = 0; | 1419 | int rc = 0; |
1368 | 1420 | ||
@@ -1473,7 +1525,7 @@ static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card, | |||
1473 | memcpy(card->dev->dev_addr, | 1525 | memcpy(card->dev->dev_addr, |
1474 | cmd->data.create_destroy_addr.unique_id, ETH_ALEN); | 1526 | cmd->data.create_destroy_addr.unique_id, ETH_ALEN); |
1475 | else | 1527 | else |
1476 | eth_random_addr(card->dev->dev_addr); | 1528 | random_ether_addr(card->dev->dev_addr); |
1477 | 1529 | ||
1478 | return 0; | 1530 | return 0; |
1479 | } | 1531 | } |
@@ -1616,7 +1668,10 @@ qeth_diags_trace(struct qeth_card *card, enum qeth_diags_trace_cmds diags_cmd) | |||
1616 | static void qeth_l3_get_mac_for_ipm(__u32 ipm, char *mac, | 1668 | static void qeth_l3_get_mac_for_ipm(__u32 ipm, char *mac, |
1617 | struct net_device *dev) | 1669 | struct net_device *dev) |
1618 | { | 1670 | { |
1619 | ip_eth_mc_map(ipm, mac); | 1671 | if (dev->type == ARPHRD_IEEE802_TR) |
1672 | ip_tr_mc_map(ipm, mac); | ||
1673 | else | ||
1674 | ip_eth_mc_map(ipm, mac); | ||
1620 | } | 1675 | } |
1621 | 1676 | ||
1622 | static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev) | 1677 | static void qeth_l3_add_mc(struct qeth_card *card, struct in_device *in4_dev) |
@@ -1760,8 +1815,6 @@ static void qeth_l3_free_vlan_addresses4(struct qeth_card *card, | |||
1760 | QETH_CARD_TEXT(card, 4, "frvaddr4"); | 1815 | QETH_CARD_TEXT(card, 4, "frvaddr4"); |
1761 | 1816 | ||
1762 | netdev = __vlan_find_dev_deep(card->dev, vid); | 1817 | netdev = __vlan_find_dev_deep(card->dev, vid); |
1763 | if (!netdev) | ||
1764 | return; | ||
1765 | in_dev = in_dev_get(netdev); | 1818 | in_dev = in_dev_get(netdev); |
1766 | if (!in_dev) | 1819 | if (!in_dev) |
1767 | return; | 1820 | return; |
@@ -1790,8 +1843,6 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card, | |||
1790 | QETH_CARD_TEXT(card, 4, "frvaddr6"); | 1843 | QETH_CARD_TEXT(card, 4, "frvaddr6"); |
1791 | 1844 | ||
1792 | netdev = __vlan_find_dev_deep(card->dev, vid); | 1845 | netdev = __vlan_find_dev_deep(card->dev, vid); |
1793 | if (!netdev) | ||
1794 | return; | ||
1795 | in6_dev = in6_dev_get(netdev); | 1846 | in6_dev = in6_dev_get(netdev); |
1796 | if (!in6_dev) | 1847 | if (!in6_dev) |
1797 | return; | 1848 | return; |
@@ -1817,15 +1868,15 @@ static void qeth_l3_free_vlan_addresses(struct qeth_card *card, | |||
1817 | qeth_l3_free_vlan_addresses6(card, vid); | 1868 | qeth_l3_free_vlan_addresses6(card, vid); |
1818 | } | 1869 | } |
1819 | 1870 | ||
1820 | static int qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) | 1871 | static void qeth_l3_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) |
1821 | { | 1872 | { |
1822 | struct qeth_card *card = dev->ml_priv; | 1873 | struct qeth_card *card = dev->ml_priv; |
1823 | 1874 | ||
1824 | set_bit(vid, card->active_vlans); | 1875 | set_bit(vid, card->active_vlans); |
1825 | return 0; | 1876 | return; |
1826 | } | 1877 | } |
1827 | 1878 | ||
1828 | static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | 1879 | static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) |
1829 | { | 1880 | { |
1830 | struct qeth_card *card = dev->ml_priv; | 1881 | struct qeth_card *card = dev->ml_priv; |
1831 | unsigned long flags; | 1882 | unsigned long flags; |
@@ -1833,7 +1884,7 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
1833 | QETH_CARD_TEXT_(card, 4, "kid:%d", vid); | 1884 | QETH_CARD_TEXT_(card, 4, "kid:%d", vid); |
1834 | if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { | 1885 | if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) { |
1835 | QETH_CARD_TEXT(card, 3, "kidREC"); | 1886 | QETH_CARD_TEXT(card, 3, "kidREC"); |
1836 | return 0; | 1887 | return; |
1837 | } | 1888 | } |
1838 | spin_lock_irqsave(&card->vlanlock, flags); | 1889 | spin_lock_irqsave(&card->vlanlock, flags); |
1839 | /* unregister IP addresses of vlan device */ | 1890 | /* unregister IP addresses of vlan device */ |
@@ -1841,7 +1892,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
1841 | clear_bit(vid, card->active_vlans); | 1892 | clear_bit(vid, card->active_vlans); |
1842 | spin_unlock_irqrestore(&card->vlanlock, flags); | 1893 | spin_unlock_irqrestore(&card->vlanlock, flags); |
1843 | qeth_l3_set_multicast_list(card->dev); | 1894 | qeth_l3_set_multicast_list(card->dev); |
1844 | return 0; | ||
1845 | } | 1895 | } |
1846 | 1896 | ||
1847 | static inline int qeth_l3_rebuild_skb(struct qeth_card *card, | 1897 | static inline int qeth_l3_rebuild_skb(struct qeth_card *card, |
@@ -1868,6 +1918,8 @@ static inline int qeth_l3_rebuild_skb(struct qeth_card *card, | |||
1868 | #endif | 1918 | #endif |
1869 | case __constant_htons(ETH_P_IP): | 1919 | case __constant_htons(ETH_P_IP): |
1870 | ip_hdr = (struct iphdr *)skb->data; | 1920 | ip_hdr = (struct iphdr *)skb->data; |
1921 | (card->dev->type == ARPHRD_IEEE802_TR) ? | ||
1922 | ip_tr_mc_map(ip_hdr->daddr, tg_addr): | ||
1871 | ip_eth_mc_map(ip_hdr->daddr, tg_addr); | 1923 | ip_eth_mc_map(ip_hdr->daddr, tg_addr); |
1872 | break; | 1924 | break; |
1873 | default: | 1925 | default: |
@@ -1903,7 +1955,12 @@ static inline int qeth_l3_rebuild_skb(struct qeth_card *card, | |||
1903 | tg_addr, "FAKELL", card->dev->addr_len); | 1955 | tg_addr, "FAKELL", card->dev->addr_len); |
1904 | } | 1956 | } |
1905 | 1957 | ||
1906 | skb->protocol = eth_type_trans(skb, card->dev); | 1958 | #ifdef CONFIG_TR |
1959 | if (card->dev->type == ARPHRD_IEEE802_TR) | ||
1960 | skb->protocol = tr_type_trans(skb, card->dev); | ||
1961 | else | ||
1962 | #endif | ||
1963 | skb->protocol = eth_type_trans(skb, card->dev); | ||
1907 | 1964 | ||
1908 | if (hdr->hdr.l3.ext_flags & | 1965 | if (hdr->hdr.l3.ext_flags & |
1909 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { | 1966 | (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { |
@@ -1936,13 +1993,12 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, | |||
1936 | __u16 vlan_tag = 0; | 1993 | __u16 vlan_tag = 0; |
1937 | int is_vlan; | 1994 | int is_vlan; |
1938 | unsigned int len; | 1995 | unsigned int len; |
1939 | __u16 magic; | ||
1940 | 1996 | ||
1941 | *done = 0; | 1997 | *done = 0; |
1942 | WARN_ON_ONCE(!budget); | 1998 | BUG_ON(!budget); |
1943 | while (budget) { | 1999 | while (budget) { |
1944 | skb = qeth_core_get_next_skb(card, | 2000 | skb = qeth_core_get_next_skb(card, |
1945 | &card->qdio.in_q->bufs[card->rx.b_index], | 2001 | card->qdio.in_q->bufs[card->rx.b_index].buffer, |
1946 | &card->rx.b_element, &card->rx.e_offset, &hdr); | 2002 | &card->rx.b_element, &card->rx.e_offset, &hdr); |
1947 | if (!skb) { | 2003 | if (!skb) { |
1948 | *done = 1; | 2004 | *done = 1; |
@@ -1951,26 +2007,12 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, | |||
1951 | skb->dev = card->dev; | 2007 | skb->dev = card->dev; |
1952 | switch (hdr->hdr.l3.id) { | 2008 | switch (hdr->hdr.l3.id) { |
1953 | case QETH_HEADER_TYPE_LAYER3: | 2009 | case QETH_HEADER_TYPE_LAYER3: |
1954 | magic = *(__u16 *)skb->data; | 2010 | is_vlan = qeth_l3_rebuild_skb(card, skb, hdr, |
1955 | if ((card->info.type == QETH_CARD_TYPE_IQD) && | ||
1956 | (magic == ETH_P_AF_IUCV)) { | ||
1957 | skb->protocol = ETH_P_AF_IUCV; | ||
1958 | skb->pkt_type = PACKET_HOST; | ||
1959 | skb->mac_header = NET_SKB_PAD; | ||
1960 | skb->dev = card->dev; | ||
1961 | len = skb->len; | ||
1962 | card->dev->header_ops->create(skb, card->dev, 0, | ||
1963 | card->dev->dev_addr, "FAKELL", | ||
1964 | card->dev->addr_len); | ||
1965 | netif_receive_skb(skb); | ||
1966 | } else { | ||
1967 | is_vlan = qeth_l3_rebuild_skb(card, skb, hdr, | ||
1968 | &vlan_tag); | 2011 | &vlan_tag); |
1969 | len = skb->len; | 2012 | len = skb->len; |
1970 | if (is_vlan && !card->options.sniffer) | 2013 | if (is_vlan && !card->options.sniffer) |
1971 | __vlan_hwaccel_put_tag(skb, vlan_tag); | 2014 | __vlan_hwaccel_put_tag(skb, vlan_tag); |
1972 | napi_gro_receive(&card->napi, skb); | 2015 | napi_gro_receive(&card->napi, skb); |
1973 | } | ||
1974 | break; | 2016 | break; |
1975 | case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ | 2017 | case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ |
1976 | skb->pkt_type = PACKET_HOST; | 2018 | skb->pkt_type = PACKET_HOST; |
@@ -2077,7 +2119,7 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev, | |||
2077 | struct net_device *netdev; | 2119 | struct net_device *netdev; |
2078 | 2120 | ||
2079 | rcu_read_lock(); | 2121 | rcu_read_lock(); |
2080 | netdev = __vlan_find_dev_deep(card->dev, vid); | 2122 | netdev = __vlan_find_dev_deep(dev, vid); |
2081 | rcu_read_unlock(); | 2123 | rcu_read_unlock(); |
2082 | if (netdev == dev) { | 2124 | if (netdev == dev) { |
2083 | rc = QETH_VLAN_CARD; | 2125 | rc = QETH_VLAN_CARD; |
@@ -2369,7 +2411,7 @@ static int qeth_l3_arp_query_cb(struct qeth_card *card, | |||
2369 | 2411 | ||
2370 | if ((qinfo->udata_len - qinfo->udata_offset) < esize) { | 2412 | if ((qinfo->udata_len - qinfo->udata_offset) < esize) { |
2371 | QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOMEM); | 2413 | QETH_CARD_TEXT_(card, 4, "qaer3%i", -ENOMEM); |
2372 | cmd->hdr.return_code = IPA_RC_ENOMEM; | 2414 | cmd->hdr.return_code = -ENOMEM; |
2373 | goto out_error; | 2415 | goto out_error; |
2374 | } | 2416 | } |
2375 | 2417 | ||
@@ -2684,9 +2726,6 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
2684 | mii_data->phy_id, | 2726 | mii_data->phy_id, |
2685 | mii_data->reg_num); | 2727 | mii_data->reg_num); |
2686 | break; | 2728 | break; |
2687 | case SIOC_QETH_QUERY_OAT: | ||
2688 | rc = qeth_query_oat_command(card, rq->ifr_ifru.ifru_data); | ||
2689 | break; | ||
2690 | default: | 2729 | default: |
2691 | rc = -EOPNOTSUPP; | 2730 | rc = -EOPNOTSUPP; |
2692 | } | 2731 | } |
@@ -2704,11 +2743,10 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb) | |||
2704 | rcu_read_lock(); | 2743 | rcu_read_lock(); |
2705 | dst = skb_dst(skb); | 2744 | dst = skb_dst(skb); |
2706 | if (dst) | 2745 | if (dst) |
2707 | n = dst_neigh_lookup_skb(dst, skb); | 2746 | n = dst_get_neighbour(dst); |
2708 | if (n) { | 2747 | if (n) { |
2709 | cast_type = n->type; | 2748 | cast_type = n->type; |
2710 | rcu_read_unlock(); | 2749 | rcu_read_unlock(); |
2711 | neigh_release(n); | ||
2712 | if ((cast_type == RTN_BROADCAST) || | 2750 | if ((cast_type == RTN_BROADCAST) || |
2713 | (cast_type == RTN_MULTICAST) || | 2751 | (cast_type == RTN_MULTICAST) || |
2714 | (cast_type == RTN_ANYCAST)) | 2752 | (cast_type == RTN_ANYCAST)) |
@@ -2750,33 +2788,10 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb) | |||
2750 | return cast_type; | 2788 | return cast_type; |
2751 | } | 2789 | } |
2752 | 2790 | ||
2753 | static void qeth_l3_fill_af_iucv_hdr(struct qeth_card *card, | ||
2754 | struct qeth_hdr *hdr, struct sk_buff *skb) | ||
2755 | { | ||
2756 | char daddr[16]; | ||
2757 | struct af_iucv_trans_hdr *iucv_hdr; | ||
2758 | |||
2759 | skb_pull(skb, 14); | ||
2760 | card->dev->header_ops->create(skb, card->dev, 0, | ||
2761 | card->dev->dev_addr, card->dev->dev_addr, | ||
2762 | card->dev->addr_len); | ||
2763 | skb_pull(skb, 14); | ||
2764 | iucv_hdr = (struct af_iucv_trans_hdr *)skb->data; | ||
2765 | memset(hdr, 0, sizeof(struct qeth_hdr)); | ||
2766 | hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3; | ||
2767 | hdr->hdr.l3.ext_flags = 0; | ||
2768 | hdr->hdr.l3.length = skb->len; | ||
2769 | hdr->hdr.l3.flags = QETH_HDR_IPV6 | QETH_CAST_UNICAST; | ||
2770 | memset(daddr, 0, sizeof(daddr)); | ||
2771 | daddr[0] = 0xfe; | ||
2772 | daddr[1] = 0x80; | ||
2773 | memcpy(&daddr[8], iucv_hdr->destUserID, 8); | ||
2774 | memcpy(hdr->hdr.l3.dest_addr, daddr, 16); | ||
2775 | } | ||
2776 | |||
2777 | static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, | 2791 | static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, |
2778 | struct sk_buff *skb, int ipv, int cast_type) | 2792 | struct sk_buff *skb, int ipv, int cast_type) |
2779 | { | 2793 | { |
2794 | struct neighbour *n = NULL; | ||
2780 | struct dst_entry *dst; | 2795 | struct dst_entry *dst; |
2781 | 2796 | ||
2782 | memset(hdr, 0, sizeof(struct qeth_hdr)); | 2797 | memset(hdr, 0, sizeof(struct qeth_hdr)); |
@@ -2799,31 +2814,41 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, | |||
2799 | 2814 | ||
2800 | rcu_read_lock(); | 2815 | rcu_read_lock(); |
2801 | dst = skb_dst(skb); | 2816 | dst = skb_dst(skb); |
2817 | if (dst) | ||
2818 | n = dst_get_neighbour(dst); | ||
2802 | if (ipv == 4) { | 2819 | if (ipv == 4) { |
2803 | struct rtable *rt = (struct rtable *) dst; | ||
2804 | __be32 *pkey = &ip_hdr(skb)->daddr; | ||
2805 | |||
2806 | if (rt->rt_gateway) | ||
2807 | pkey = &rt->rt_gateway; | ||
2808 | |||
2809 | /* IPv4 */ | 2820 | /* IPv4 */ |
2810 | hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type); | 2821 | hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type); |
2811 | memset(hdr->hdr.l3.dest_addr, 0, 12); | 2822 | memset(hdr->hdr.l3.dest_addr, 0, 12); |
2812 | *((__be32 *) (&hdr->hdr.l3.dest_addr[12])) = *pkey; | 2823 | if (n) { |
2824 | *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = | ||
2825 | *((u32 *) n->primary_key); | ||
2826 | } else { | ||
2827 | /* fill in destination address used in ip header */ | ||
2828 | *((u32 *) (&hdr->hdr.l3.dest_addr[12])) = | ||
2829 | ip_hdr(skb)->daddr; | ||
2830 | } | ||
2813 | } else if (ipv == 6) { | 2831 | } else if (ipv == 6) { |
2814 | struct rt6_info *rt = (struct rt6_info *) dst; | ||
2815 | struct in6_addr *pkey = &ipv6_hdr(skb)->daddr; | ||
2816 | |||
2817 | if (!ipv6_addr_any(&rt->rt6i_gateway)) | ||
2818 | pkey = &rt->rt6i_gateway; | ||
2819 | |||
2820 | /* IPv6 */ | 2832 | /* IPv6 */ |
2821 | hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type); | 2833 | hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type); |
2822 | if (card->info.type == QETH_CARD_TYPE_IQD) | 2834 | if (card->info.type == QETH_CARD_TYPE_IQD) |
2823 | hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU; | 2835 | hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU; |
2824 | memcpy(hdr->hdr.l3.dest_addr, pkey, 16); | 2836 | if (n) { |
2837 | memcpy(hdr->hdr.l3.dest_addr, | ||
2838 | n->primary_key, 16); | ||
2839 | } else { | ||
2840 | /* fill in destination address used in ip header */ | ||
2841 | memcpy(hdr->hdr.l3.dest_addr, | ||
2842 | &ipv6_hdr(skb)->daddr, 16); | ||
2843 | } | ||
2825 | } else { | 2844 | } else { |
2826 | if (!memcmp(skb->data + sizeof(struct qeth_hdr), | 2845 | /* passthrough */ |
2846 | if ((skb->dev->type == ARPHRD_IEEE802_TR) && | ||
2847 | !memcmp(skb->data + sizeof(struct qeth_hdr) + | ||
2848 | sizeof(__u16), skb->dev->broadcast, 6)) { | ||
2849 | hdr->hdr.l3.flags = QETH_CAST_BROADCAST | | ||
2850 | QETH_HDR_PASSTHRU; | ||
2851 | } else if (!memcmp(skb->data + sizeof(struct qeth_hdr), | ||
2827 | skb->dev->broadcast, 6)) { | 2852 | skb->dev->broadcast, 6)) { |
2828 | /* broadcast? */ | 2853 | /* broadcast? */ |
2829 | hdr->hdr.l3.flags = QETH_CAST_BROADCAST | | 2854 | hdr->hdr.l3.flags = QETH_CAST_BROADCAST | |
@@ -2918,11 +2943,8 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2918 | int data_offset = -1; | 2943 | int data_offset = -1; |
2919 | int nr_frags; | 2944 | int nr_frags; |
2920 | 2945 | ||
2921 | if (((card->info.type == QETH_CARD_TYPE_IQD) && | 2946 | if (((card->info.type == QETH_CARD_TYPE_IQD) && (!ipv)) || |
2922 | (((card->options.cq != QETH_CQ_ENABLED) && !ipv) || | 2947 | card->options.sniffer) |
2923 | ((card->options.cq == QETH_CQ_ENABLED) && | ||
2924 | (skb->protocol != ETH_P_AF_IUCV)))) || | ||
2925 | card->options.sniffer) | ||
2926 | goto tx_drop; | 2948 | goto tx_drop; |
2927 | 2949 | ||
2928 | if ((card->state != CARD_STATE_UP) || !card->lan_online) { | 2950 | if ((card->state != CARD_STATE_UP) || !card->lan_online) { |
@@ -2944,10 +2966,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2944 | if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && | 2966 | if ((card->info.type == QETH_CARD_TYPE_IQD) && (!large_send) && |
2945 | (skb_shinfo(skb)->nr_frags == 0)) { | 2967 | (skb_shinfo(skb)->nr_frags == 0)) { |
2946 | new_skb = skb; | 2968 | new_skb = skb; |
2947 | if (new_skb->protocol == ETH_P_AF_IUCV) | 2969 | data_offset = ETH_HLEN; |
2948 | data_offset = 0; | ||
2949 | else | ||
2950 | data_offset = ETH_HLEN; | ||
2951 | hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC); | 2970 | hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC); |
2952 | if (!hdr) | 2971 | if (!hdr) |
2953 | goto tx_drop; | 2972 | goto tx_drop; |
@@ -2965,7 +2984,10 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2965 | skb_pull(new_skb, ETH_HLEN); | 2984 | skb_pull(new_skb, ETH_HLEN); |
2966 | } else { | 2985 | } else { |
2967 | if (ipv == 4) { | 2986 | if (ipv == 4) { |
2968 | skb_pull(new_skb, ETH_HLEN); | 2987 | if (card->dev->type == ARPHRD_IEEE802_TR) |
2988 | skb_pull(new_skb, TR_HLEN); | ||
2989 | else | ||
2990 | skb_pull(new_skb, ETH_HLEN); | ||
2969 | } | 2991 | } |
2970 | 2992 | ||
2971 | if (ipv != 4 && vlan_tx_tag_present(new_skb)) { | 2993 | if (ipv != 4 && vlan_tx_tag_present(new_skb)) { |
@@ -2978,6 +3000,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2978 | tag = (u16 *)(new_skb->data + 12); | 3000 | tag = (u16 *)(new_skb->data + 12); |
2979 | *tag = __constant_htons(ETH_P_8021Q); | 3001 | *tag = __constant_htons(ETH_P_8021Q); |
2980 | *(tag + 1) = htons(vlan_tx_tag_get(new_skb)); | 3002 | *(tag + 1) = htons(vlan_tx_tag_get(new_skb)); |
3003 | new_skb->vlan_tci = 0; | ||
2981 | } | 3004 | } |
2982 | } | 3005 | } |
2983 | 3006 | ||
@@ -3009,13 +3032,9 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3009 | qeth_l3_fill_header(card, hdr, new_skb, ipv, | 3032 | qeth_l3_fill_header(card, hdr, new_skb, ipv, |
3010 | cast_type); | 3033 | cast_type); |
3011 | } else { | 3034 | } else { |
3012 | if (new_skb->protocol == ETH_P_AF_IUCV) | 3035 | qeth_l3_fill_header(card, hdr, new_skb, ipv, |
3013 | qeth_l3_fill_af_iucv_hdr(card, hdr, new_skb); | 3036 | cast_type); |
3014 | else { | 3037 | hdr->hdr.l3.length = new_skb->len - data_offset; |
3015 | qeth_l3_fill_header(card, hdr, new_skb, ipv, | ||
3016 | cast_type); | ||
3017 | hdr->hdr.l3.length = new_skb->len - data_offset; | ||
3018 | } | ||
3019 | } | 3038 | } |
3020 | 3039 | ||
3021 | if (skb->ip_summed == CHECKSUM_PARTIAL) | 3040 | if (skb->ip_summed == CHECKSUM_PARTIAL) |
@@ -3141,8 +3160,7 @@ static int qeth_l3_stop(struct net_device *dev) | |||
3141 | return 0; | 3160 | return 0; |
3142 | } | 3161 | } |
3143 | 3162 | ||
3144 | static netdev_features_t qeth_l3_fix_features(struct net_device *dev, | 3163 | static u32 qeth_l3_fix_features(struct net_device *dev, u32 features) |
3145 | netdev_features_t features) | ||
3146 | { | 3164 | { |
3147 | struct qeth_card *card = dev->ml_priv; | 3165 | struct qeth_card *card = dev->ml_priv; |
3148 | 3166 | ||
@@ -3156,8 +3174,7 @@ static netdev_features_t qeth_l3_fix_features(struct net_device *dev, | |||
3156 | return features; | 3174 | return features; |
3157 | } | 3175 | } |
3158 | 3176 | ||
3159 | static int qeth_l3_set_features(struct net_device *dev, | 3177 | static int qeth_l3_set_features(struct net_device *dev, u32 features) |
3160 | netdev_features_t features) | ||
3161 | { | 3178 | { |
3162 | struct qeth_card *card = dev->ml_priv; | 3179 | struct qeth_card *card = dev->ml_priv; |
3163 | u32 changed = dev->features ^ features; | 3180 | u32 changed = dev->features ^ features; |
@@ -3216,7 +3233,7 @@ static const struct net_device_ops qeth_l3_netdev_ops = { | |||
3216 | .ndo_get_stats = qeth_get_stats, | 3233 | .ndo_get_stats = qeth_get_stats, |
3217 | .ndo_start_xmit = qeth_l3_hard_start_xmit, | 3234 | .ndo_start_xmit = qeth_l3_hard_start_xmit, |
3218 | .ndo_validate_addr = eth_validate_addr, | 3235 | .ndo_validate_addr = eth_validate_addr, |
3219 | .ndo_set_rx_mode = qeth_l3_set_multicast_list, | 3236 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, |
3220 | .ndo_do_ioctl = qeth_l3_do_ioctl, | 3237 | .ndo_do_ioctl = qeth_l3_do_ioctl, |
3221 | .ndo_change_mtu = qeth_change_mtu, | 3238 | .ndo_change_mtu = qeth_change_mtu, |
3222 | .ndo_fix_features = qeth_l3_fix_features, | 3239 | .ndo_fix_features = qeth_l3_fix_features, |
@@ -3232,7 +3249,7 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = { | |||
3232 | .ndo_get_stats = qeth_get_stats, | 3249 | .ndo_get_stats = qeth_get_stats, |
3233 | .ndo_start_xmit = qeth_l3_hard_start_xmit, | 3250 | .ndo_start_xmit = qeth_l3_hard_start_xmit, |
3234 | .ndo_validate_addr = eth_validate_addr, | 3251 | .ndo_validate_addr = eth_validate_addr, |
3235 | .ndo_set_rx_mode = qeth_l3_set_multicast_list, | 3252 | .ndo_set_multicast_list = qeth_l3_set_multicast_list, |
3236 | .ndo_do_ioctl = qeth_l3_do_ioctl, | 3253 | .ndo_do_ioctl = qeth_l3_do_ioctl, |
3237 | .ndo_change_mtu = qeth_change_mtu, | 3254 | .ndo_change_mtu = qeth_change_mtu, |
3238 | .ndo_fix_features = qeth_l3_fix_features, | 3255 | .ndo_fix_features = qeth_l3_fix_features, |
@@ -3249,8 +3266,12 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) | |||
3249 | card->info.type == QETH_CARD_TYPE_OSX) { | 3266 | card->info.type == QETH_CARD_TYPE_OSX) { |
3250 | if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) || | 3267 | if ((card->info.link_type == QETH_LINK_TYPE_LANE_TR) || |
3251 | (card->info.link_type == QETH_LINK_TYPE_HSTR)) { | 3268 | (card->info.link_type == QETH_LINK_TYPE_HSTR)) { |
3252 | pr_info("qeth_l3: ignoring TR device\n"); | 3269 | #ifdef CONFIG_TR |
3253 | return -ENODEV; | 3270 | card->dev = alloc_trdev(0); |
3271 | #endif | ||
3272 | if (!card->dev) | ||
3273 | return -ENODEV; | ||
3274 | card->dev->netdev_ops = &qeth_l3_netdev_ops; | ||
3254 | } else { | 3275 | } else { |
3255 | card->dev = alloc_etherdev(0); | 3276 | card->dev = alloc_etherdev(0); |
3256 | if (!card->dev) | 3277 | if (!card->dev) |
@@ -3276,8 +3297,6 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) | |||
3276 | card->dev->flags |= IFF_NOARP; | 3297 | card->dev->flags |= IFF_NOARP; |
3277 | card->dev->netdev_ops = &qeth_l3_netdev_ops; | 3298 | card->dev->netdev_ops = &qeth_l3_netdev_ops; |
3278 | qeth_l3_iqd_read_initial_mac(card); | 3299 | qeth_l3_iqd_read_initial_mac(card); |
3279 | if (card->options.hsuid[0]) | ||
3280 | memcpy(card->dev->perm_addr, card->options.hsuid, 9); | ||
3281 | } else | 3300 | } else |
3282 | return -ENODEV; | 3301 | return -ENODEV; |
3283 | 3302 | ||
@@ -3303,6 +3322,12 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev) | |||
3303 | qeth_l3_create_device_attributes(&gdev->dev); | 3322 | qeth_l3_create_device_attributes(&gdev->dev); |
3304 | card->options.layer2 = 0; | 3323 | card->options.layer2 = 0; |
3305 | card->info.hwtrap = 0; | 3324 | card->info.hwtrap = 0; |
3325 | card->discipline.start_poll = qeth_qdio_start_poll; | ||
3326 | card->discipline.input_handler = (qdio_handler_t *) | ||
3327 | qeth_qdio_input_handler; | ||
3328 | card->discipline.output_handler = (qdio_handler_t *) | ||
3329 | qeth_qdio_output_handler; | ||
3330 | card->discipline.recover = qeth_l3_recover; | ||
3306 | return 0; | 3331 | return 0; |
3307 | } | 3332 | } |
3308 | 3333 | ||
@@ -3334,6 +3359,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3334 | int rc = 0; | 3359 | int rc = 0; |
3335 | enum qeth_card_states recover_flag; | 3360 | enum qeth_card_states recover_flag; |
3336 | 3361 | ||
3362 | BUG_ON(!card); | ||
3337 | mutex_lock(&card->discipline_mutex); | 3363 | mutex_lock(&card->discipline_mutex); |
3338 | mutex_lock(&card->conf_mutex); | 3364 | mutex_lock(&card->conf_mutex); |
3339 | QETH_DBF_TEXT(SETUP, 2, "setonlin"); | 3365 | QETH_DBF_TEXT(SETUP, 2, "setonlin"); |
@@ -3346,7 +3372,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3346 | rc = -ENODEV; | 3372 | rc = -ENODEV; |
3347 | goto out_remove; | 3373 | goto out_remove; |
3348 | } | 3374 | } |
3349 | qeth_trace_features(card); | ||
3350 | 3375 | ||
3351 | if (!card->dev && qeth_l3_setup_netdev(card)) { | 3376 | if (!card->dev && qeth_l3_setup_netdev(card)) { |
3352 | rc = -ENODEV; | 3377 | rc = -ENODEV; |
@@ -3413,13 +3438,14 @@ contin: | |||
3413 | else | 3438 | else |
3414 | netif_carrier_off(card->dev); | 3439 | netif_carrier_off(card->dev); |
3415 | if (recover_flag == CARD_STATE_RECOVER) { | 3440 | if (recover_flag == CARD_STATE_RECOVER) { |
3416 | rtnl_lock(); | ||
3417 | if (recovery_mode) | 3441 | if (recovery_mode) |
3418 | __qeth_l3_open(card->dev); | 3442 | __qeth_l3_open(card->dev); |
3419 | else | 3443 | else { |
3444 | rtnl_lock(); | ||
3420 | dev_open(card->dev); | 3445 | dev_open(card->dev); |
3446 | rtnl_unlock(); | ||
3447 | } | ||
3421 | qeth_l3_set_multicast_list(card->dev); | 3448 | qeth_l3_set_multicast_list(card->dev); |
3422 | rtnl_unlock(); | ||
3423 | } | 3449 | } |
3424 | /* let user_space know that device is online */ | 3450 | /* let user_space know that device is online */ |
3425 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); | 3451 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); |
@@ -3465,11 +3491,6 @@ static int __qeth_l3_set_offline(struct ccwgroup_device *cgdev, | |||
3465 | card->info.hwtrap = 1; | 3491 | card->info.hwtrap = 1; |
3466 | } | 3492 | } |
3467 | qeth_l3_stop_card(card, recovery_mode); | 3493 | qeth_l3_stop_card(card, recovery_mode); |
3468 | if ((card->options.cq == QETH_CQ_ENABLED) && card->dev) { | ||
3469 | rtnl_lock(); | ||
3470 | call_netdevice_notifiers(NETDEV_REBOOT, card->dev); | ||
3471 | rtnl_unlock(); | ||
3472 | } | ||
3473 | rc = ccw_device_set_offline(CARD_DDEV(card)); | 3494 | rc = ccw_device_set_offline(CARD_DDEV(card)); |
3474 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); | 3495 | rc2 = ccw_device_set_offline(CARD_WDEV(card)); |
3475 | rc3 = ccw_device_set_offline(CARD_RDEV(card)); | 3496 | rc3 = ccw_device_set_offline(CARD_RDEV(card)); |
@@ -3510,12 +3531,11 @@ static int qeth_l3_recover(void *ptr) | |||
3510 | dev_info(&card->gdev->dev, | 3531 | dev_info(&card->gdev->dev, |
3511 | "Device successfully recovered!\n"); | 3532 | "Device successfully recovered!\n"); |
3512 | else { | 3533 | else { |
3513 | if (rtnl_trylock()) { | 3534 | rtnl_lock(); |
3514 | dev_close(card->dev); | 3535 | dev_close(card->dev); |
3515 | rtnl_unlock(); | 3536 | rtnl_unlock(); |
3516 | dev_warn(&card->gdev->dev, "The qeth device driver " | 3537 | dev_warn(&card->gdev->dev, "The qeth device driver " |
3517 | "failed to recover an error on the device\n"); | 3538 | "failed to recover an error on the device\n"); |
3518 | } | ||
3519 | } | 3539 | } |
3520 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); | 3540 | qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD); |
3521 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); | 3541 | qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD); |
@@ -3525,7 +3545,6 @@ static int qeth_l3_recover(void *ptr) | |||
3525 | static void qeth_l3_shutdown(struct ccwgroup_device *gdev) | 3545 | static void qeth_l3_shutdown(struct ccwgroup_device *gdev) |
3526 | { | 3546 | { |
3527 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); | 3547 | struct qeth_card *card = dev_get_drvdata(&gdev->dev); |
3528 | qeth_set_allowed_threads(card, 0, 1); | ||
3529 | if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap) | 3548 | if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap) |
3530 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); | 3549 | qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM); |
3531 | qeth_qdio_clear_card(card, 0); | 3550 | qeth_qdio_clear_card(card, 0); |
@@ -3578,12 +3597,8 @@ out: | |||
3578 | return rc; | 3597 | return rc; |
3579 | } | 3598 | } |
3580 | 3599 | ||
3581 | struct qeth_discipline qeth_l3_discipline = { | 3600 | struct ccwgroup_driver qeth_l3_ccwgroup_driver = { |
3582 | .start_poll = qeth_qdio_start_poll, | 3601 | .probe = qeth_l3_probe_device, |
3583 | .input_handler = (qdio_handler_t *) qeth_qdio_input_handler, | ||
3584 | .output_handler = (qdio_handler_t *) qeth_qdio_output_handler, | ||
3585 | .recover = qeth_l3_recover, | ||
3586 | .setup = qeth_l3_probe_device, | ||
3587 | .remove = qeth_l3_remove_device, | 3602 | .remove = qeth_l3_remove_device, |
3588 | .set_online = qeth_l3_set_online, | 3603 | .set_online = qeth_l3_set_online, |
3589 | .set_offline = qeth_l3_set_offline, | 3604 | .set_offline = qeth_l3_set_offline, |
@@ -3592,7 +3607,7 @@ struct qeth_discipline qeth_l3_discipline = { | |||
3592 | .thaw = qeth_l3_pm_resume, | 3607 | .thaw = qeth_l3_pm_resume, |
3593 | .restore = qeth_l3_pm_resume, | 3608 | .restore = qeth_l3_pm_resume, |
3594 | }; | 3609 | }; |
3595 | EXPORT_SYMBOL_GPL(qeth_l3_discipline); | 3610 | EXPORT_SYMBOL_GPL(qeth_l3_ccwgroup_driver); |
3596 | 3611 | ||
3597 | static int qeth_l3_ip_event(struct notifier_block *this, | 3612 | static int qeth_l3_ip_event(struct notifier_block *this, |
3598 | unsigned long event, void *ptr) | 3613 | unsigned long event, void *ptr) |
@@ -3606,9 +3621,9 @@ static int qeth_l3_ip_event(struct notifier_block *this, | |||
3606 | return NOTIFY_DONE; | 3621 | return NOTIFY_DONE; |
3607 | 3622 | ||
3608 | card = qeth_l3_get_card_from_dev(dev); | 3623 | card = qeth_l3_get_card_from_dev(dev); |
3624 | QETH_CARD_TEXT(card, 3, "ipevent"); | ||
3609 | if (!card) | 3625 | if (!card) |
3610 | return NOTIFY_DONE; | 3626 | return NOTIFY_DONE; |
3611 | QETH_CARD_TEXT(card, 3, "ipevent"); | ||
3612 | 3627 | ||
3613 | addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); | 3628 | addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV4); |
3614 | if (addr != NULL) { | 3629 | if (addr != NULL) { |
@@ -3652,6 +3667,7 @@ static int qeth_l3_ip6_event(struct notifier_block *this, | |||
3652 | struct qeth_ipaddr *addr; | 3667 | struct qeth_ipaddr *addr; |
3653 | struct qeth_card *card; | 3668 | struct qeth_card *card; |
3654 | 3669 | ||
3670 | |||
3655 | card = qeth_l3_get_card_from_dev(dev); | 3671 | card = qeth_l3_get_card_from_dev(dev); |
3656 | if (!card) | 3672 | if (!card) |
3657 | return NOTIFY_DONE; | 3673 | return NOTIFY_DONE; |
@@ -3714,9 +3730,9 @@ static void qeth_l3_unregister_notifiers(void) | |||
3714 | { | 3730 | { |
3715 | 3731 | ||
3716 | QETH_DBF_TEXT(SETUP, 5, "unregnot"); | 3732 | QETH_DBF_TEXT(SETUP, 5, "unregnot"); |
3717 | WARN_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier)); | 3733 | BUG_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier)); |
3718 | #ifdef CONFIG_QETH_IPV6 | 3734 | #ifdef CONFIG_QETH_IPV6 |
3719 | WARN_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier)); | 3735 | BUG_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier)); |
3720 | #endif /* QETH_IPV6 */ | 3736 | #endif /* QETH_IPV6 */ |
3721 | } | 3737 | } |
3722 | 3738 | ||
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index ebc37948626..cd99210296e 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/net/qeth_l3_sys.c | ||
3 | * | ||
2 | * Copyright IBM Corp. 2007 | 4 | * Copyright IBM Corp. 2007 |
3 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, | 5 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com>, |
4 | * Frank Pavlic <fpavlic@de.ibm.com>, | 6 | * Frank Pavlic <fpavlic@de.ibm.com>, |
@@ -7,7 +9,7 @@ | |||
7 | */ | 9 | */ |
8 | 10 | ||
9 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
10 | #include <asm/ebcdic.h> | 12 | |
11 | #include "qeth_l3.h" | 13 | #include "qeth_l3.h" |
12 | 14 | ||
13 | #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \ | 15 | #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \ |
@@ -173,32 +175,33 @@ out: | |||
173 | static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show, | 175 | static DEVICE_ATTR(fake_broadcast, 0644, qeth_l3_dev_fake_broadcast_show, |
174 | qeth_l3_dev_fake_broadcast_store); | 176 | qeth_l3_dev_fake_broadcast_store); |
175 | 177 | ||
176 | static ssize_t qeth_l3_dev_sniffer_show(struct device *dev, | 178 | static ssize_t qeth_l3_dev_broadcast_mode_show(struct device *dev, |
177 | struct device_attribute *attr, char *buf) | 179 | struct device_attribute *attr, char *buf) |
178 | { | 180 | { |
179 | struct qeth_card *card = dev_get_drvdata(dev); | 181 | struct qeth_card *card = dev_get_drvdata(dev); |
180 | 182 | ||
181 | if (!card) | 183 | if (!card) |
182 | return -EINVAL; | 184 | return -EINVAL; |
183 | 185 | ||
184 | return sprintf(buf, "%i\n", card->options.sniffer ? 1 : 0); | 186 | if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || |
187 | (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) | ||
188 | return sprintf(buf, "n/a\n"); | ||
189 | |||
190 | return sprintf(buf, "%s\n", (card->options.broadcast_mode == | ||
191 | QETH_TR_BROADCAST_ALLRINGS)? | ||
192 | "all rings":"local"); | ||
185 | } | 193 | } |
186 | 194 | ||
187 | static ssize_t qeth_l3_dev_sniffer_store(struct device *dev, | 195 | static ssize_t qeth_l3_dev_broadcast_mode_store(struct device *dev, |
188 | struct device_attribute *attr, const char *buf, size_t count) | 196 | struct device_attribute *attr, const char *buf, size_t count) |
189 | { | 197 | { |
190 | struct qeth_card *card = dev_get_drvdata(dev); | 198 | struct qeth_card *card = dev_get_drvdata(dev); |
199 | char *tmp; | ||
191 | int rc = 0; | 200 | int rc = 0; |
192 | unsigned long i; | ||
193 | 201 | ||
194 | if (!card) | 202 | if (!card) |
195 | return -EINVAL; | 203 | return -EINVAL; |
196 | 204 | ||
197 | if (card->info.type != QETH_CARD_TYPE_IQD) | ||
198 | return -EPERM; | ||
199 | if (card->options.cq == QETH_CQ_ENABLED) | ||
200 | return -EPERM; | ||
201 | |||
202 | mutex_lock(&card->conf_mutex); | 205 | mutex_lock(&card->conf_mutex); |
203 | if ((card->state != CARD_STATE_DOWN) && | 206 | if ((card->state != CARD_STATE_DOWN) && |
204 | (card->state != CARD_STATE_RECOVER)) { | 207 | (card->state != CARD_STATE_RECOVER)) { |
@@ -206,148 +209,151 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev, | |||
206 | goto out; | 209 | goto out; |
207 | } | 210 | } |
208 | 211 | ||
209 | rc = strict_strtoul(buf, 16, &i); | 212 | if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || |
210 | if (rc) { | 213 | (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) { |
211 | rc = -EINVAL; | 214 | rc = -EINVAL; |
212 | goto out; | 215 | goto out; |
213 | } | 216 | } |
214 | switch (i) { | 217 | |
215 | case 0: | 218 | tmp = strsep((char **) &buf, "\n"); |
216 | card->options.sniffer = i; | 219 | |
217 | break; | 220 | if (!strcmp(tmp, "local")) |
218 | case 1: | 221 | card->options.broadcast_mode = QETH_TR_BROADCAST_LOCAL; |
219 | qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd); | 222 | else if (!strcmp(tmp, "all_rings")) |
220 | if (card->ssqd.qdioac2 & QETH_SNIFF_AVAIL) { | 223 | card->options.broadcast_mode = QETH_TR_BROADCAST_ALLRINGS; |
221 | card->options.sniffer = i; | 224 | else |
222 | if (card->qdio.init_pool.buf_count != | ||
223 | QETH_IN_BUF_COUNT_MAX) | ||
224 | qeth_realloc_buffer_pool(card, | ||
225 | QETH_IN_BUF_COUNT_MAX); | ||
226 | } else | ||
227 | rc = -EPERM; | ||
228 | break; | ||
229 | default: | ||
230 | rc = -EINVAL; | 225 | rc = -EINVAL; |
231 | } | ||
232 | out: | 226 | out: |
233 | mutex_unlock(&card->conf_mutex); | 227 | mutex_unlock(&card->conf_mutex); |
234 | return rc ? rc : count; | 228 | return rc ? rc : count; |
235 | } | 229 | } |
236 | 230 | ||
237 | static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show, | 231 | static DEVICE_ATTR(broadcast_mode, 0644, qeth_l3_dev_broadcast_mode_show, |
238 | qeth_l3_dev_sniffer_store); | 232 | qeth_l3_dev_broadcast_mode_store); |
239 | 233 | ||
240 | 234 | static ssize_t qeth_l3_dev_canonical_macaddr_show(struct device *dev, | |
241 | static ssize_t qeth_l3_dev_hsuid_show(struct device *dev, | 235 | struct device_attribute *attr, char *buf) |
242 | struct device_attribute *attr, char *buf) | ||
243 | { | 236 | { |
244 | struct qeth_card *card = dev_get_drvdata(dev); | 237 | struct qeth_card *card = dev_get_drvdata(dev); |
245 | char tmp_hsuid[9]; | ||
246 | 238 | ||
247 | if (!card) | 239 | if (!card) |
248 | return -EINVAL; | 240 | return -EINVAL; |
249 | 241 | ||
250 | if (card->info.type != QETH_CARD_TYPE_IQD) | 242 | if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || |
251 | return -EPERM; | 243 | (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) |
252 | 244 | return sprintf(buf, "n/a\n"); | |
253 | if (card->state == CARD_STATE_DOWN) | ||
254 | return -EPERM; | ||
255 | 245 | ||
256 | memcpy(tmp_hsuid, card->options.hsuid, sizeof(tmp_hsuid)); | 246 | return sprintf(buf, "%i\n", (card->options.macaddr_mode == |
257 | EBCASC(tmp_hsuid, 8); | 247 | QETH_TR_MACADDR_CANONICAL)? 1:0); |
258 | return sprintf(buf, "%s\n", tmp_hsuid); | ||
259 | } | 248 | } |
260 | 249 | ||
261 | static ssize_t qeth_l3_dev_hsuid_store(struct device *dev, | 250 | static ssize_t qeth_l3_dev_canonical_macaddr_store(struct device *dev, |
262 | struct device_attribute *attr, const char *buf, size_t count) | 251 | struct device_attribute *attr, const char *buf, size_t count) |
263 | { | 252 | { |
264 | struct qeth_card *card = dev_get_drvdata(dev); | 253 | struct qeth_card *card = dev_get_drvdata(dev); |
265 | struct qeth_ipaddr *addr; | ||
266 | char *tmp; | 254 | char *tmp; |
267 | int i; | 255 | int i, rc = 0; |
268 | 256 | ||
269 | if (!card) | 257 | if (!card) |
270 | return -EINVAL; | 258 | return -EINVAL; |
271 | 259 | ||
272 | if (card->info.type != QETH_CARD_TYPE_IQD) | 260 | mutex_lock(&card->conf_mutex); |
273 | return -EPERM; | 261 | if ((card->state != CARD_STATE_DOWN) && |
274 | if (card->state != CARD_STATE_DOWN && | 262 | (card->state != CARD_STATE_RECOVER)) { |
275 | card->state != CARD_STATE_RECOVER) | 263 | rc = -EPERM; |
276 | return -EPERM; | 264 | goto out; |
277 | if (card->options.sniffer) | 265 | } |
278 | return -EPERM; | 266 | |
279 | if (card->options.cq == QETH_CQ_NOTAVAILABLE) | 267 | if (!((card->info.link_type == QETH_LINK_TYPE_HSTR) || |
280 | return -EPERM; | 268 | (card->info.link_type == QETH_LINK_TYPE_LANE_TR))) { |
269 | rc = -EINVAL; | ||
270 | goto out; | ||
271 | } | ||
281 | 272 | ||
282 | tmp = strsep((char **)&buf, "\n"); | 273 | i = simple_strtoul(buf, &tmp, 16); |
283 | if (strlen(tmp) > 8) | 274 | if ((i == 0) || (i == 1)) |
275 | card->options.macaddr_mode = i? | ||
276 | QETH_TR_MACADDR_CANONICAL : | ||
277 | QETH_TR_MACADDR_NONCANONICAL; | ||
278 | else | ||
279 | rc = -EINVAL; | ||
280 | out: | ||
281 | mutex_unlock(&card->conf_mutex); | ||
282 | return rc ? rc : count; | ||
283 | } | ||
284 | |||
285 | static DEVICE_ATTR(canonical_macaddr, 0644, qeth_l3_dev_canonical_macaddr_show, | ||
286 | qeth_l3_dev_canonical_macaddr_store); | ||
287 | |||
288 | static ssize_t qeth_l3_dev_sniffer_show(struct device *dev, | ||
289 | struct device_attribute *attr, char *buf) | ||
290 | { | ||
291 | struct qeth_card *card = dev_get_drvdata(dev); | ||
292 | |||
293 | if (!card) | ||
284 | return -EINVAL; | 294 | return -EINVAL; |
285 | 295 | ||
286 | if (card->options.hsuid[0]) { | 296 | return sprintf(buf, "%i\n", card->options.sniffer ? 1 : 0); |
287 | /* delete old ip address */ | 297 | } |
288 | addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6); | ||
289 | if (addr != NULL) { | ||
290 | addr->u.a6.addr.s6_addr32[0] = 0xfe800000; | ||
291 | addr->u.a6.addr.s6_addr32[1] = 0x00000000; | ||
292 | for (i = 8; i < 16; i++) | ||
293 | addr->u.a6.addr.s6_addr[i] = | ||
294 | card->options.hsuid[i - 8]; | ||
295 | addr->u.a6.pfxlen = 0; | ||
296 | addr->type = QETH_IP_TYPE_NORMAL; | ||
297 | } else | ||
298 | return -ENOMEM; | ||
299 | if (!qeth_l3_delete_ip(card, addr)) | ||
300 | kfree(addr); | ||
301 | qeth_l3_set_ip_addr_list(card); | ||
302 | } | ||
303 | 298 | ||
304 | if (strlen(tmp) == 0) { | 299 | static ssize_t qeth_l3_dev_sniffer_store(struct device *dev, |
305 | /* delete ip address only */ | 300 | struct device_attribute *attr, const char *buf, size_t count) |
306 | card->options.hsuid[0] = '\0'; | 301 | { |
307 | if (card->dev) | 302 | struct qeth_card *card = dev_get_drvdata(dev); |
308 | memcpy(card->dev->perm_addr, card->options.hsuid, 9); | 303 | int rc = 0; |
309 | qeth_configure_cq(card, QETH_CQ_DISABLED); | 304 | unsigned long i; |
310 | return count; | ||
311 | } | ||
312 | 305 | ||
313 | if (qeth_configure_cq(card, QETH_CQ_ENABLED)) | 306 | if (!card) |
307 | return -EINVAL; | ||
308 | |||
309 | if (card->info.type != QETH_CARD_TYPE_IQD) | ||
314 | return -EPERM; | 310 | return -EPERM; |
315 | 311 | ||
316 | for (i = 0; i < 8; i++) | 312 | mutex_lock(&card->conf_mutex); |
317 | card->options.hsuid[i] = ' '; | 313 | if ((card->state != CARD_STATE_DOWN) && |
318 | card->options.hsuid[8] = '\0'; | 314 | (card->state != CARD_STATE_RECOVER)) { |
319 | strncpy(card->options.hsuid, tmp, strlen(tmp)); | 315 | rc = -EPERM; |
320 | ASCEBC(card->options.hsuid, 8); | 316 | goto out; |
321 | if (card->dev) | 317 | } |
322 | memcpy(card->dev->perm_addr, card->options.hsuid, 9); | ||
323 | |||
324 | addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6); | ||
325 | if (addr != NULL) { | ||
326 | addr->u.a6.addr.s6_addr32[0] = 0xfe800000; | ||
327 | addr->u.a6.addr.s6_addr32[1] = 0x00000000; | ||
328 | for (i = 8; i < 16; i++) | ||
329 | addr->u.a6.addr.s6_addr[i] = card->options.hsuid[i - 8]; | ||
330 | addr->u.a6.pfxlen = 0; | ||
331 | addr->type = QETH_IP_TYPE_NORMAL; | ||
332 | } else | ||
333 | return -ENOMEM; | ||
334 | if (!qeth_l3_add_ip(card, addr)) | ||
335 | kfree(addr); | ||
336 | qeth_l3_set_ip_addr_list(card); | ||
337 | 318 | ||
338 | return count; | 319 | rc = strict_strtoul(buf, 16, &i); |
320 | if (rc) { | ||
321 | rc = -EINVAL; | ||
322 | goto out; | ||
323 | } | ||
324 | switch (i) { | ||
325 | case 0: | ||
326 | card->options.sniffer = i; | ||
327 | break; | ||
328 | case 1: | ||
329 | qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd); | ||
330 | if (card->ssqd.qdioac2 & QETH_SNIFF_AVAIL) { | ||
331 | card->options.sniffer = i; | ||
332 | if (card->qdio.init_pool.buf_count != | ||
333 | QETH_IN_BUF_COUNT_MAX) | ||
334 | qeth_realloc_buffer_pool(card, | ||
335 | QETH_IN_BUF_COUNT_MAX); | ||
336 | break; | ||
337 | } else | ||
338 | rc = -EPERM; | ||
339 | default: /* fall through */ | ||
340 | rc = -EINVAL; | ||
341 | } | ||
342 | out: | ||
343 | mutex_unlock(&card->conf_mutex); | ||
344 | return rc ? rc : count; | ||
339 | } | 345 | } |
340 | 346 | ||
341 | static DEVICE_ATTR(hsuid, 0644, qeth_l3_dev_hsuid_show, | 347 | static DEVICE_ATTR(sniffer, 0644, qeth_l3_dev_sniffer_show, |
342 | qeth_l3_dev_hsuid_store); | 348 | qeth_l3_dev_sniffer_store); |
343 | |||
344 | 349 | ||
345 | static struct attribute *qeth_l3_device_attrs[] = { | 350 | static struct attribute *qeth_l3_device_attrs[] = { |
346 | &dev_attr_route4.attr, | 351 | &dev_attr_route4.attr, |
347 | &dev_attr_route6.attr, | 352 | &dev_attr_route6.attr, |
348 | &dev_attr_fake_broadcast.attr, | 353 | &dev_attr_fake_broadcast.attr, |
354 | &dev_attr_broadcast_mode.attr, | ||
355 | &dev_attr_canonical_macaddr.attr, | ||
349 | &dev_attr_sniffer.attr, | 356 | &dev_attr_sniffer.attr, |
350 | &dev_attr_hsuid.attr, | ||
351 | NULL, | 357 | NULL, |
352 | }; | 358 | }; |
353 | 359 | ||
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index d8f990b6b33..207b7d74244 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c | |||
@@ -157,7 +157,7 @@ static int smsg_pm_restore_thaw(struct device *dev) | |||
157 | #ifdef CONFIG_PM_DEBUG | 157 | #ifdef CONFIG_PM_DEBUG |
158 | printk(KERN_WARNING "smsg_pm_restore_thaw\n"); | 158 | printk(KERN_WARNING "smsg_pm_restore_thaw\n"); |
159 | #endif | 159 | #endif |
160 | if (smsg_path && !iucv_path_connected) { | 160 | if (smsg_path && iucv_path_connected) { |
161 | memset(smsg_path, 0, sizeof(*smsg_path)); | 161 | memset(smsg_path, 0, sizeof(*smsg_path)); |
162 | smsg_path->msglim = 255; | 162 | smsg_path->msglim = 255; |
163 | smsg_path->flags = 0; | 163 | smsg_path->flags = 0; |
diff --git a/drivers/s390/net/smsgiucv.h b/drivers/s390/net/smsgiucv.h index 45bc925928c..149a1151608 100644 --- a/drivers/s390/net/smsgiucv.h +++ b/drivers/s390/net/smsgiucv.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * IUCV special message driver | 2 | * IUCV special message driver |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2003 | 4 | * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation |
5 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) | 5 | * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) |
6 | */ | 6 | */ |
7 | 7 | ||
diff --git a/drivers/s390/net/smsgiucv_app.c b/drivers/s390/net/smsgiucv_app.c index 32515a201bb..4d2ea400042 100644 --- a/drivers/s390/net/smsgiucv_app.c +++ b/drivers/s390/net/smsgiucv_app.c | |||
@@ -168,7 +168,7 @@ static int __init smsgiucv_app_init(void) | |||
168 | rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); | 168 | rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); |
169 | if (rc) { | 169 | if (rc) { |
170 | kfree(smsg_app_dev); | 170 | kfree(smsg_app_dev); |
171 | goto fail; | 171 | goto fail_put_driver; |
172 | } | 172 | } |
173 | smsg_app_dev->bus = &iucv_bus; | 173 | smsg_app_dev->bus = &iucv_bus; |
174 | smsg_app_dev->parent = iucv_root; | 174 | smsg_app_dev->parent = iucv_root; |
@@ -177,7 +177,7 @@ static int __init smsgiucv_app_init(void) | |||
177 | rc = device_register(smsg_app_dev); | 177 | rc = device_register(smsg_app_dev); |
178 | if (rc) { | 178 | if (rc) { |
179 | put_device(smsg_app_dev); | 179 | put_device(smsg_app_dev); |
180 | goto fail; | 180 | goto fail_put_driver; |
181 | } | 181 | } |
182 | 182 | ||
183 | /* convert sender to uppercase characters */ | 183 | /* convert sender to uppercase characters */ |
@@ -191,11 +191,12 @@ static int __init smsgiucv_app_init(void) | |||
191 | rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); | 191 | rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); |
192 | if (rc) { | 192 | if (rc) { |
193 | device_unregister(smsg_app_dev); | 193 | device_unregister(smsg_app_dev); |
194 | goto fail; | 194 | goto fail_put_driver; |
195 | } | 195 | } |
196 | 196 | ||
197 | rc = 0; | 197 | rc = 0; |
198 | fail: | 198 | fail_put_driver: |
199 | put_driver(smsgiucv_drv); | ||
199 | return rc; | 200 | return rc; |
200 | } | 201 | } |
201 | module_init(smsgiucv_app_init); | 202 | module_init(smsgiucv_app_init); |