diff options
64 files changed, 1417 insertions, 937 deletions
diff --git a/arch/sparc/include/asm/termbits.h b/arch/sparc/include/asm/termbits.h index d6ca3e2754f5..d72dfed1f9d7 100644 --- a/arch/sparc/include/asm/termbits.h +++ b/arch/sparc/include/asm/termbits.h | |||
| @@ -29,10 +29,11 @@ struct termios { | |||
| 29 | tcflag_t c_cflag; /* control mode flags */ | 29 | tcflag_t c_cflag; /* control mode flags */ |
| 30 | tcflag_t c_lflag; /* local mode flags */ | 30 | tcflag_t c_lflag; /* local mode flags */ |
| 31 | cc_t c_line; /* line discipline */ | 31 | cc_t c_line; /* line discipline */ |
| 32 | #ifndef __KERNEL__ | ||
| 32 | cc_t c_cc[NCCS]; /* control characters */ | 33 | cc_t c_cc[NCCS]; /* control characters */ |
| 33 | #ifdef __KERNEL__ | 34 | #else |
| 35 | cc_t c_cc[NCCS+2]; /* kernel needs 2 more to hold vmin/vtime */ | ||
| 34 | #define SIZEOF_USER_TERMIOS sizeof (struct termios) - (2*sizeof (cc_t)) | 36 | #define SIZEOF_USER_TERMIOS sizeof (struct termios) - (2*sizeof (cc_t)) |
| 35 | cc_t _x_cc[2]; /* We need them to hold vmin/vtime */ | ||
| 36 | #endif | 37 | #endif |
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| @@ -42,8 +43,7 @@ struct termios2 { | |||
| 42 | tcflag_t c_cflag; /* control mode flags */ | 43 | tcflag_t c_cflag; /* control mode flags */ |
| 43 | tcflag_t c_lflag; /* local mode flags */ | 44 | tcflag_t c_lflag; /* local mode flags */ |
| 44 | cc_t c_line; /* line discipline */ | 45 | cc_t c_line; /* line discipline */ |
| 45 | cc_t c_cc[NCCS]; /* control characters */ | 46 | cc_t c_cc[NCCS+2]; /* control characters */ |
| 46 | cc_t _x_cc[2]; /* padding to match ktermios */ | ||
| 47 | speed_t c_ispeed; /* input speed */ | 47 | speed_t c_ispeed; /* input speed */ |
| 48 | speed_t c_ospeed; /* output speed */ | 48 | speed_t c_ospeed; /* output speed */ |
| 49 | }; | 49 | }; |
| @@ -54,8 +54,7 @@ struct ktermios { | |||
| 54 | tcflag_t c_cflag; /* control mode flags */ | 54 | tcflag_t c_cflag; /* control mode flags */ |
| 55 | tcflag_t c_lflag; /* local mode flags */ | 55 | tcflag_t c_lflag; /* local mode flags */ |
| 56 | cc_t c_line; /* line discipline */ | 56 | cc_t c_line; /* line discipline */ |
| 57 | cc_t c_cc[NCCS]; /* control characters */ | 57 | cc_t c_cc[NCCS+2]; /* control characters */ |
| 58 | cc_t _x_cc[2]; /* We need them to hold vmin/vtime */ | ||
| 59 | speed_t c_ispeed; /* input speed */ | 58 | speed_t c_ispeed; /* input speed */ |
| 60 | speed_t c_ospeed; /* output speed */ | 59 | speed_t c_ospeed; /* output speed */ |
| 61 | }; | 60 | }; |
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 0837bd52e28f..0a83bd737654 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c | |||
| @@ -563,9 +563,9 @@ build_resources: | |||
| 563 | op->dev.parent = parent; | 563 | op->dev.parent = parent; |
| 564 | op->dev.bus = &of_platform_bus_type; | 564 | op->dev.bus = &of_platform_bus_type; |
| 565 | if (!parent) | 565 | if (!parent) |
| 566 | strcpy(op->dev.bus_id, "root"); | 566 | dev_set_name(&op->dev, "root"); |
| 567 | else | 567 | else |
| 568 | sprintf(op->dev.bus_id, "%08x", dp->node); | 568 | dev_set_name(&op->dev, "%08x", dp->node); |
| 569 | 569 | ||
| 570 | if (of_device_register(op)) { | 570 | if (of_device_register(op)) { |
| 571 | printk("%s: Could not register of device.\n", | 571 | printk("%s: Could not register of device.\n", |
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c index 64e591ba86f2..4dbc2271acf5 100644 --- a/drivers/acpi/sleep/proc.c +++ b/drivers/acpi/sleep/proc.c | |||
| @@ -366,7 +366,7 @@ acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) | |||
| 366 | dev->wakeup.state.enabled ? "enabled" : "disabled"); | 366 | dev->wakeup.state.enabled ? "enabled" : "disabled"); |
| 367 | if (ldev) | 367 | if (ldev) |
| 368 | seq_printf(seq, "%s:%s", | 368 | seq_printf(seq, "%s:%s", |
| 369 | dev_name(ldev) ? ldev->bus->name : "no-bus", | 369 | ldev->bus ? ldev->bus->name : "no-bus", |
| 370 | dev_name(ldev)); | 370 | dev_name(ldev)); |
| 371 | seq_printf(seq, "\n"); | 371 | seq_printf(seq, "\n"); |
| 372 | put_device(ldev); | 372 | put_device(ldev); |
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index c6ab4ba60c52..9b97795e45ad 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c | |||
| @@ -55,10 +55,11 @@ struct apple_key_translation { | |||
| 55 | 55 | ||
| 56 | static struct apple_key_translation apple_fn_keys[] = { | 56 | static struct apple_key_translation apple_fn_keys[] = { |
| 57 | { KEY_BACKSPACE, KEY_DELETE }, | 57 | { KEY_BACKSPACE, KEY_DELETE }, |
| 58 | { KEY_ENTER, KEY_INSERT }, | ||
| 58 | { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, | 59 | { KEY_F1, KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY }, |
| 59 | { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, | 60 | { KEY_F2, KEY_BRIGHTNESSUP, APPLE_FLAG_FKEY }, |
| 60 | { KEY_F3, KEY_FN_F5, APPLE_FLAG_FKEY }, /* Exposé */ | 61 | { KEY_F3, KEY_SCALE, APPLE_FLAG_FKEY }, |
| 61 | { KEY_F4, KEY_FN_F4, APPLE_FLAG_FKEY }, /* Dashboard */ | 62 | { KEY_F4, KEY_DASHBOARD, APPLE_FLAG_FKEY }, |
| 62 | { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY }, | 63 | { KEY_F5, KEY_KBDILLUMDOWN, APPLE_FLAG_FKEY }, |
| 63 | { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY }, | 64 | { KEY_F6, KEY_KBDILLUMUP, APPLE_FLAG_FKEY }, |
| 64 | { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, | 65 | { KEY_F7, KEY_PREVIOUSSONG, APPLE_FLAG_FKEY }, |
| @@ -418,6 +419,12 @@ static const struct hid_device_id apple_devices[] = { | |||
| 418 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | 419 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, |
| 419 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), | 420 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS), |
| 420 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | 421 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, |
| 422 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI), | ||
| 423 | .driver_data = APPLE_HAS_FN }, | ||
| 424 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO), | ||
| 425 | .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, | ||
| 426 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS), | ||
| 427 | .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, | ||
| 421 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY), | 428 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY), |
| 422 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, | 429 | .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, |
| 423 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY), | 430 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY), |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d3671b4049c0..147ec591a806 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -1250,9 +1250,11 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1250 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, | 1250 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, |
| 1251 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, | 1251 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, |
| 1252 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, | 1252 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, |
| 1253 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, | ||
| 1254 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, | ||
| 1255 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, | ||
| 1253 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1256 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
| 1254 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1257 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
| 1255 | { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, | ||
| 1256 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1258 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
| 1257 | { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) }, | 1259 | { HID_USB_DEVICE(USB_VENDOR_ID_BRIGHT, USB_DEVICE_ID_BRIGHT_ABNT2) }, |
| 1258 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1260 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
| @@ -1265,7 +1267,6 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1265 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, | 1267 | { HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) }, |
| 1266 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, | 1268 | { HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) }, |
| 1267 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, | 1269 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, |
| 1268 | { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, | ||
| 1269 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1270 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
| 1270 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, | 1271 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
| 1271 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, | 1272 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, |
| @@ -1409,6 +1410,7 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
| 1409 | { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, | 1410 | { HID_USB_DEVICE(USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232) }, |
| 1410 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)}, | 1411 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM)}, |
| 1411 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)}, | 1412 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2)}, |
| 1413 | { HID_USB_DEVICE(USB_VENDOR_ID_AVERMEDIA, USB_DEVICE_ID_AVER_FM_MR800) }, | ||
| 1412 | { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, | 1414 | { HID_USB_DEVICE(USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD) }, |
| 1413 | { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, | 1415 | { HID_USB_DEVICE(USB_VENDOR_ID_CIDC, 0x0103) }, |
| 1414 | { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) }, | 1416 | { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X) }, |
| @@ -1486,6 +1488,7 @@ static const struct hid_device_id hid_ignore_list[] = { | |||
| 1486 | { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, | 1488 | { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, |
| 1487 | { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, | 1489 | { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, |
| 1488 | { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, | 1490 | { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, |
| 1491 | { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, | ||
| 1489 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, | 1492 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, |
| 1490 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, | 1493 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) }, |
| 1491 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, | 1494 | { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) }, |
| @@ -1573,6 +1576,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { | |||
| 1573 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, | 1576 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI) }, |
| 1574 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, | 1577 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_ISO) }, |
| 1575 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, | 1578 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING2_JIS) }, |
| 1579 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI) }, | ||
| 1580 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_ISO) }, | ||
| 1581 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING3_JIS) }, | ||
| 1576 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, | 1582 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, |
| 1577 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1583 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
| 1578 | { } | 1584 | { } |
| @@ -1730,7 +1736,7 @@ static int __init hid_init(void) | |||
| 1730 | goto err_bus; | 1736 | goto err_bus; |
| 1731 | 1737 | ||
| 1732 | #ifdef CONFIG_HID_COMPAT | 1738 | #ifdef CONFIG_HID_COMPAT |
| 1733 | hid_compat_wq = create_workqueue("hid_compat"); | 1739 | hid_compat_wq = create_singlethread_workqueue("hid_compat"); |
| 1734 | if (!hid_compat_wq) { | 1740 | if (!hid_compat_wq) { |
| 1735 | hidraw_exit(); | 1741 | hidraw_exit(); |
| 1736 | goto err; | 1742 | goto err; |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index f05bcbbbb0d5..d70075dd3d81 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -82,6 +82,9 @@ | |||
| 82 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 | 82 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230 |
| 83 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 | 83 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231 |
| 84 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 | 84 | #define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232 |
| 85 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236 | ||
| 86 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237 | ||
| 87 | #define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238 | ||
| 85 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a | 88 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a |
| 86 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b | 89 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b |
| 87 | #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 | 90 | #define USB_DEVICE_ID_APPLE_ATV_IRCONTROL 0x8241 |
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 894d52e05bf9..7685ae6808c4 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
| @@ -38,7 +38,7 @@ static int hidraw_major; | |||
| 38 | static struct cdev hidraw_cdev; | 38 | static struct cdev hidraw_cdev; |
| 39 | static struct class *hidraw_class; | 39 | static struct class *hidraw_class; |
| 40 | static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; | 40 | static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; |
| 41 | static DEFINE_SPINLOCK(minors_lock); | 41 | static DEFINE_MUTEX(minors_lock); |
| 42 | 42 | ||
| 43 | static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 43 | static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) |
| 44 | { | 44 | { |
| @@ -159,13 +159,13 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
| 159 | struct hidraw_list *list; | 159 | struct hidraw_list *list; |
| 160 | int err = 0; | 160 | int err = 0; |
| 161 | 161 | ||
| 162 | lock_kernel(); | ||
| 163 | if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { | 162 | if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) { |
| 164 | err = -ENOMEM; | 163 | err = -ENOMEM; |
| 165 | goto out; | 164 | goto out; |
| 166 | } | 165 | } |
| 167 | 166 | ||
| 168 | spin_lock(&minors_lock); | 167 | lock_kernel(); |
| 168 | mutex_lock(&minors_lock); | ||
| 169 | if (!hidraw_table[minor]) { | 169 | if (!hidraw_table[minor]) { |
| 170 | printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", | 170 | printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", |
| 171 | minor); | 171 | minor); |
| @@ -180,13 +180,16 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
| 180 | file->private_data = list; | 180 | file->private_data = list; |
| 181 | 181 | ||
| 182 | dev = hidraw_table[minor]; | 182 | dev = hidraw_table[minor]; |
| 183 | if (!dev->open++) | 183 | if (!dev->open++) { |
| 184 | dev->hid->ll_driver->open(dev->hid); | 184 | err = dev->hid->ll_driver->open(dev->hid); |
| 185 | if (err < 0) | ||
| 186 | dev->open--; | ||
| 187 | } | ||
| 185 | 188 | ||
| 186 | out_unlock: | 189 | out_unlock: |
| 187 | spin_unlock(&minors_lock); | 190 | mutex_unlock(&minors_lock); |
| 188 | out: | ||
| 189 | unlock_kernel(); | 191 | unlock_kernel(); |
| 192 | out: | ||
| 190 | return err; | 193 | return err; |
| 191 | 194 | ||
| 192 | } | 195 | } |
| @@ -310,7 +313,7 @@ int hidraw_connect(struct hid_device *hid) | |||
| 310 | 313 | ||
| 311 | result = -EINVAL; | 314 | result = -EINVAL; |
| 312 | 315 | ||
| 313 | spin_lock(&minors_lock); | 316 | mutex_lock(&minors_lock); |
| 314 | 317 | ||
| 315 | for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) { | 318 | for (minor = 0; minor < HIDRAW_MAX_DEVICES; minor++) { |
| 316 | if (hidraw_table[minor]) | 319 | if (hidraw_table[minor]) |
| @@ -320,9 +323,8 @@ int hidraw_connect(struct hid_device *hid) | |||
| 320 | break; | 323 | break; |
| 321 | } | 324 | } |
| 322 | 325 | ||
| 323 | spin_unlock(&minors_lock); | ||
| 324 | |||
| 325 | if (result) { | 326 | if (result) { |
| 327 | mutex_unlock(&minors_lock); | ||
| 326 | kfree(dev); | 328 | kfree(dev); |
| 327 | goto out; | 329 | goto out; |
| 328 | } | 330 | } |
| @@ -331,14 +333,14 @@ int hidraw_connect(struct hid_device *hid) | |||
| 331 | NULL, "%s%d", "hidraw", minor); | 333 | NULL, "%s%d", "hidraw", minor); |
| 332 | 334 | ||
| 333 | if (IS_ERR(dev->dev)) { | 335 | if (IS_ERR(dev->dev)) { |
| 334 | spin_lock(&minors_lock); | ||
| 335 | hidraw_table[minor] = NULL; | 336 | hidraw_table[minor] = NULL; |
| 336 | spin_unlock(&minors_lock); | 337 | mutex_unlock(&minors_lock); |
| 337 | result = PTR_ERR(dev->dev); | 338 | result = PTR_ERR(dev->dev); |
| 338 | kfree(dev); | 339 | kfree(dev); |
| 339 | goto out; | 340 | goto out; |
| 340 | } | 341 | } |
| 341 | 342 | ||
| 343 | mutex_unlock(&minors_lock); | ||
| 342 | init_waitqueue_head(&dev->wait); | 344 | init_waitqueue_head(&dev->wait); |
| 343 | INIT_LIST_HEAD(&dev->list); | 345 | INIT_LIST_HEAD(&dev->list); |
| 344 | 346 | ||
| @@ -360,9 +362,9 @@ void hidraw_disconnect(struct hid_device *hid) | |||
| 360 | 362 | ||
| 361 | hidraw->exist = 0; | 363 | hidraw->exist = 0; |
| 362 | 364 | ||
| 363 | spin_lock(&minors_lock); | 365 | mutex_lock(&minors_lock); |
| 364 | hidraw_table[hidraw->minor] = NULL; | 366 | hidraw_table[hidraw->minor] = NULL; |
| 365 | spin_unlock(&minors_lock); | 367 | mutex_unlock(&minors_lock); |
| 366 | 368 | ||
| 367 | device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); | 369 | device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); |
| 368 | 370 | ||
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 18e5ddd722cd..d746bf8284dd 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -781,6 +781,8 @@ static int usbhid_start(struct hid_device *hid) | |||
| 781 | unsigned int n, insize = 0; | 781 | unsigned int n, insize = 0; |
| 782 | int ret; | 782 | int ret; |
| 783 | 783 | ||
| 784 | clear_bit(HID_DISCONNECTED, &usbhid->iofl); | ||
| 785 | |||
| 784 | usbhid->bufsize = HID_MIN_BUFFER_SIZE; | 786 | usbhid->bufsize = HID_MIN_BUFFER_SIZE; |
| 785 | hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); | 787 | hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize); |
| 786 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); | 788 | hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize); |
| @@ -847,12 +849,6 @@ static int usbhid_start(struct hid_device *hid) | |||
| 847 | } | 849 | } |
| 848 | } | 850 | } |
| 849 | 851 | ||
| 850 | if (!usbhid->urbin) { | ||
| 851 | err_hid("couldn't find an input interrupt endpoint"); | ||
| 852 | ret = -ENODEV; | ||
| 853 | goto fail; | ||
| 854 | } | ||
| 855 | |||
| 856 | init_waitqueue_head(&usbhid->wait); | 852 | init_waitqueue_head(&usbhid->wait); |
| 857 | INIT_WORK(&usbhid->reset_work, hid_reset); | 853 | INIT_WORK(&usbhid->reset_work, hid_reset); |
| 858 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | 854 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); |
| @@ -888,6 +884,9 @@ fail: | |||
| 888 | usb_free_urb(usbhid->urbin); | 884 | usb_free_urb(usbhid->urbin); |
| 889 | usb_free_urb(usbhid->urbout); | 885 | usb_free_urb(usbhid->urbout); |
| 890 | usb_free_urb(usbhid->urbctrl); | 886 | usb_free_urb(usbhid->urbctrl); |
| 887 | usbhid->urbin = NULL; | ||
| 888 | usbhid->urbout = NULL; | ||
| 889 | usbhid->urbctrl = NULL; | ||
| 891 | hid_free_buffers(dev, hid); | 890 | hid_free_buffers(dev, hid); |
| 892 | mutex_unlock(&usbhid->setup); | 891 | mutex_unlock(&usbhid->setup); |
| 893 | return ret; | 892 | return ret; |
| @@ -924,6 +923,9 @@ static void usbhid_stop(struct hid_device *hid) | |||
| 924 | usb_free_urb(usbhid->urbin); | 923 | usb_free_urb(usbhid->urbin); |
| 925 | usb_free_urb(usbhid->urbctrl); | 924 | usb_free_urb(usbhid->urbctrl); |
| 926 | usb_free_urb(usbhid->urbout); | 925 | usb_free_urb(usbhid->urbout); |
| 926 | usbhid->urbin = NULL; /* don't mess up next start */ | ||
| 927 | usbhid->urbctrl = NULL; | ||
| 928 | usbhid->urbout = NULL; | ||
| 927 | 929 | ||
| 928 | hid_free_buffers(hid_to_usb_dev(hid), hid); | 930 | hid_free_buffers(hid_to_usb_dev(hid), hid); |
| 929 | mutex_unlock(&usbhid->setup); | 931 | mutex_unlock(&usbhid->setup); |
| @@ -940,15 +942,26 @@ static struct hid_ll_driver usb_hid_driver = { | |||
| 940 | 942 | ||
| 941 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | 943 | static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| 942 | { | 944 | { |
| 945 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
| 943 | struct usb_device *dev = interface_to_usbdev(intf); | 946 | struct usb_device *dev = interface_to_usbdev(intf); |
| 944 | struct usbhid_device *usbhid; | 947 | struct usbhid_device *usbhid; |
| 945 | struct hid_device *hid; | 948 | struct hid_device *hid; |
| 949 | unsigned int n, has_in = 0; | ||
| 946 | size_t len; | 950 | size_t len; |
| 947 | int ret; | 951 | int ret; |
| 948 | 952 | ||
| 949 | dbg_hid("HID probe called for ifnum %d\n", | 953 | dbg_hid("HID probe called for ifnum %d\n", |
| 950 | intf->altsetting->desc.bInterfaceNumber); | 954 | intf->altsetting->desc.bInterfaceNumber); |
| 951 | 955 | ||
| 956 | for (n = 0; n < interface->desc.bNumEndpoints; n++) | ||
| 957 | if (usb_endpoint_is_int_in(&interface->endpoint[n].desc)) | ||
| 958 | has_in++; | ||
| 959 | if (!has_in) { | ||
| 960 | dev_err(&intf->dev, "couldn't find an input interrupt " | ||
| 961 | "endpoint\n"); | ||
| 962 | return -ENODEV; | ||
| 963 | } | ||
| 964 | |||
| 952 | hid = hid_allocate_device(); | 965 | hid = hid_allocate_device(); |
| 953 | if (IS_ERR(hid)) | 966 | if (IS_ERR(hid)) |
| 954 | return PTR_ERR(hid); | 967 | return PTR_ERR(hid); |
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index cb199c815b53..f50210fe558f 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c | |||
| @@ -444,6 +444,7 @@ static struct pcmcia_device_id ide_ids[] = { | |||
| 444 | PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), | 444 | PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), |
| 445 | PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), | 445 | PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), |
| 446 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), | 446 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), |
| 447 | PCMCIA_DEVICE_PROD_ID2("Flash Card", 0x5a362506), | ||
| 447 | PCMCIA_DEVICE_NULL, | 448 | PCMCIA_DEVICE_NULL, |
| 448 | }; | 449 | }; |
| 449 | MODULE_DEVICE_TABLE(pcmcia, ide_ids); | 450 | MODULE_DEVICE_TABLE(pcmcia, ide_ids); |
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index bb904a0a98bd..1bfc55d7a26c 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c | |||
| @@ -1641,8 +1641,10 @@ isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp) | |||
| 1641 | /* slarp reply, send own ip/netmask; if values are nonsense remote | 1641 | /* slarp reply, send own ip/netmask; if values are nonsense remote |
| 1642 | * should think we are unable to provide it with an address via SLARP */ | 1642 | * should think we are unable to provide it with an address via SLARP */ |
| 1643 | p += put_u32(p, CISCO_SLARP_REPLY); | 1643 | p += put_u32(p, CISCO_SLARP_REPLY); |
| 1644 | p += put_u32(p, addr); // address | 1644 | *(__be32 *)p = addr; // address |
| 1645 | p += put_u32(p, mask); // netmask | 1645 | p += 4; |
| 1646 | *(__be32 *)p = mask; // netmask | ||
| 1647 | p += 4; | ||
| 1646 | p += put_u16(p, 0); // unused | 1648 | p += put_u16(p, 0); // unused |
| 1647 | 1649 | ||
| 1648 | isdn_net_write_super(lp, skb); | 1650 | isdn_net_write_super(lp, skb); |
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index b57326ae464d..0b5bd85dfcec 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c | |||
| @@ -267,7 +267,7 @@ static int da9030_mask_events(struct da903x_chip *chip, unsigned int events) | |||
| 267 | { | 267 | { |
| 268 | uint8_t v[3]; | 268 | uint8_t v[3]; |
| 269 | 269 | ||
| 270 | chip->events_mask &= ~events; | 270 | chip->events_mask |= events; |
| 271 | 271 | ||
| 272 | v[0] = (chip->events_mask & 0xff); | 272 | v[0] = (chip->events_mask & 0xff); |
| 273 | v[1] = (chip->events_mask >> 8) & 0xff; | 273 | v[1] = (chip->events_mask >> 8) & 0xff; |
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c index 8dfe21bb3bd1..3e0ce0e50ea2 100644 --- a/drivers/mfd/wm8350-i2c.c +++ b/drivers/mfd/wm8350-i2c.c | |||
| @@ -30,7 +30,12 @@ static int wm8350_i2c_read_device(struct wm8350 *wm8350, char reg, | |||
| 30 | ret = i2c_master_send(wm8350->i2c_client, ®, 1); | 30 | ret = i2c_master_send(wm8350->i2c_client, ®, 1); |
| 31 | if (ret < 0) | 31 | if (ret < 0) |
| 32 | return ret; | 32 | return ret; |
| 33 | return i2c_master_recv(wm8350->i2c_client, dest, bytes); | 33 | ret = i2c_master_recv(wm8350->i2c_client, dest, bytes); |
| 34 | if (ret < 0) | ||
| 35 | return ret; | ||
| 36 | if (ret != bytes) | ||
| 37 | return -EIO; | ||
| 38 | return 0; | ||
| 34 | } | 39 | } |
| 35 | 40 | ||
| 36 | static int wm8350_i2c_write_device(struct wm8350 *wm8350, char reg, | 41 | static int wm8350_i2c_write_device(struct wm8350 *wm8350, char reg, |
| @@ -38,13 +43,19 @@ static int wm8350_i2c_write_device(struct wm8350 *wm8350, char reg, | |||
| 38 | { | 43 | { |
| 39 | /* we add 1 byte for device register */ | 44 | /* we add 1 byte for device register */ |
| 40 | u8 msg[(WM8350_MAX_REGISTER << 1) + 1]; | 45 | u8 msg[(WM8350_MAX_REGISTER << 1) + 1]; |
| 46 | int ret; | ||
| 41 | 47 | ||
| 42 | if (bytes > ((WM8350_MAX_REGISTER << 1) + 1)) | 48 | if (bytes > ((WM8350_MAX_REGISTER << 1) + 1)) |
| 43 | return -EINVAL; | 49 | return -EINVAL; |
| 44 | 50 | ||
| 45 | msg[0] = reg; | 51 | msg[0] = reg; |
| 46 | memcpy(&msg[1], src, bytes); | 52 | memcpy(&msg[1], src, bytes); |
| 47 | return i2c_master_send(wm8350->i2c_client, msg, bytes + 1); | 53 | ret = i2c_master_send(wm8350->i2c_client, msg, bytes + 1); |
| 54 | if (ret < 0) | ||
| 55 | return ret; | ||
| 56 | if (ret != bytes + 1) | ||
| 57 | return -EIO; | ||
| 58 | return 0; | ||
| 48 | } | 59 | } |
| 49 | 60 | ||
| 50 | static int wm8350_i2c_probe(struct i2c_client *i2c, | 61 | static int wm8350_i2c_probe(struct i2c_client *i2c, |
diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/atl1e/atl1e_hw.c index 8cbc1b59bd62..4a7700620119 100644 --- a/drivers/net/atl1e/atl1e_hw.c +++ b/drivers/net/atl1e/atl1e_hw.c | |||
| @@ -163,9 +163,6 @@ int atl1e_read_mac_addr(struct atl1e_hw *hw) | |||
| 163 | * atl1e_hash_mc_addr | 163 | * atl1e_hash_mc_addr |
| 164 | * purpose | 164 | * purpose |
| 165 | * set hash value for a multicast address | 165 | * set hash value for a multicast address |
| 166 | * hash calcu processing : | ||
| 167 | * 1. calcu 32bit CRC for multicast address | ||
| 168 | * 2. reverse crc with MSB to LSB | ||
| 169 | */ | 166 | */ |
| 170 | u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr) | 167 | u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr) |
| 171 | { | 168 | { |
| @@ -174,7 +171,6 @@ u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr) | |||
| 174 | int i; | 171 | int i; |
| 175 | 172 | ||
| 176 | crc32 = ether_crc_le(6, mc_addr); | 173 | crc32 = ether_crc_le(6, mc_addr); |
| 177 | crc32 = ~crc32; | ||
| 178 | for (i = 0; i < 32; i++) | 174 | for (i = 0; i < 32; i++) |
| 179 | value |= (((crc32 >> i) & 1) << (31 - i)); | 175 | value |= (((crc32 >> i) & 1) << (31 - i)); |
| 180 | 176 | ||
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 246d92b42636..aef403d299ee 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c | |||
| @@ -3404,14 +3404,8 @@ static void atl1_get_wol(struct net_device *netdev, | |||
| 3404 | { | 3404 | { |
| 3405 | struct atl1_adapter *adapter = netdev_priv(netdev); | 3405 | struct atl1_adapter *adapter = netdev_priv(netdev); |
| 3406 | 3406 | ||
| 3407 | wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; | 3407 | wol->supported = WAKE_MAGIC; |
| 3408 | wol->wolopts = 0; | 3408 | wol->wolopts = 0; |
| 3409 | if (adapter->wol & ATLX_WUFC_EX) | ||
| 3410 | wol->wolopts |= WAKE_UCAST; | ||
| 3411 | if (adapter->wol & ATLX_WUFC_MC) | ||
| 3412 | wol->wolopts |= WAKE_MCAST; | ||
| 3413 | if (adapter->wol & ATLX_WUFC_BC) | ||
| 3414 | wol->wolopts |= WAKE_BCAST; | ||
| 3415 | if (adapter->wol & ATLX_WUFC_MAG) | 3409 | if (adapter->wol & ATLX_WUFC_MAG) |
| 3416 | wol->wolopts |= WAKE_MAGIC; | 3410 | wol->wolopts |= WAKE_MAGIC; |
| 3417 | return; | 3411 | return; |
| @@ -3422,15 +3416,10 @@ static int atl1_set_wol(struct net_device *netdev, | |||
| 3422 | { | 3416 | { |
| 3423 | struct atl1_adapter *adapter = netdev_priv(netdev); | 3417 | struct atl1_adapter *adapter = netdev_priv(netdev); |
| 3424 | 3418 | ||
| 3425 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) | 3419 | if (wol->wolopts & (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | |
| 3420 | WAKE_ARP | WAKE_MAGICSECURE)) | ||
| 3426 | return -EOPNOTSUPP; | 3421 | return -EOPNOTSUPP; |
| 3427 | adapter->wol = 0; | 3422 | adapter->wol = 0; |
| 3428 | if (wol->wolopts & WAKE_UCAST) | ||
| 3429 | adapter->wol |= ATLX_WUFC_EX; | ||
| 3430 | if (wol->wolopts & WAKE_MCAST) | ||
| 3431 | adapter->wol |= ATLX_WUFC_MC; | ||
| 3432 | if (wol->wolopts & WAKE_BCAST) | ||
| 3433 | adapter->wol |= ATLX_WUFC_BC; | ||
| 3434 | if (wol->wolopts & WAKE_MAGIC) | 3423 | if (wol->wolopts & WAKE_MAGIC) |
| 3435 | adapter->wol |= ATLX_WUFC_MAG; | 3424 | adapter->wol |= ATLX_WUFC_MAG; |
| 3436 | return 0; | 3425 | return 0; |
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 3d69fae781cf..e8bfcce6b319 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
| @@ -166,7 +166,7 @@ | |||
| 166 | 166 | ||
| 167 | #define DRV_NAME "e100" | 167 | #define DRV_NAME "e100" |
| 168 | #define DRV_EXT "-NAPI" | 168 | #define DRV_EXT "-NAPI" |
| 169 | #define DRV_VERSION "3.5.23-k4"DRV_EXT | 169 | #define DRV_VERSION "3.5.23-k6"DRV_EXT |
| 170 | #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" | 170 | #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" |
| 171 | #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" | 171 | #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" |
| 172 | #define PFX DRV_NAME ": " | 172 | #define PFX DRV_NAME ": " |
| @@ -1804,7 +1804,7 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) | |||
| 1804 | struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; | 1804 | struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; |
| 1805 | put_unaligned_le32(rx->dma_addr, &prev_rfd->link); | 1805 | put_unaligned_le32(rx->dma_addr, &prev_rfd->link); |
| 1806 | pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, | 1806 | pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, |
| 1807 | sizeof(struct rfd), PCI_DMA_TODEVICE); | 1807 | sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); |
| 1808 | } | 1808 | } |
| 1809 | 1809 | ||
| 1810 | return 0; | 1810 | return 0; |
| @@ -1823,7 +1823,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
| 1823 | 1823 | ||
| 1824 | /* Need to sync before taking a peek at cb_complete bit */ | 1824 | /* Need to sync before taking a peek at cb_complete bit */ |
| 1825 | pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, | 1825 | pci_dma_sync_single_for_cpu(nic->pdev, rx->dma_addr, |
| 1826 | sizeof(struct rfd), PCI_DMA_FROMDEVICE); | 1826 | sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); |
| 1827 | rfd_status = le16_to_cpu(rfd->status); | 1827 | rfd_status = le16_to_cpu(rfd->status); |
| 1828 | 1828 | ||
| 1829 | DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); | 1829 | DPRINTK(RX_STATUS, DEBUG, "status=0x%04X\n", rfd_status); |
| @@ -1850,7 +1850,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
| 1850 | 1850 | ||
| 1851 | /* Get data */ | 1851 | /* Get data */ |
| 1852 | pci_unmap_single(nic->pdev, rx->dma_addr, | 1852 | pci_unmap_single(nic->pdev, rx->dma_addr, |
| 1853 | RFD_BUF_LEN, PCI_DMA_FROMDEVICE); | 1853 | RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); |
| 1854 | 1854 | ||
| 1855 | /* If this buffer has the el bit, but we think the receiver | 1855 | /* If this buffer has the el bit, but we think the receiver |
| 1856 | * is still running, check to see if it really stopped while | 1856 | * is still running, check to see if it really stopped while |
| @@ -1943,7 +1943,7 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, | |||
| 1943 | new_before_last_rfd->command |= cpu_to_le16(cb_el); | 1943 | new_before_last_rfd->command |= cpu_to_le16(cb_el); |
| 1944 | pci_dma_sync_single_for_device(nic->pdev, | 1944 | pci_dma_sync_single_for_device(nic->pdev, |
| 1945 | new_before_last_rx->dma_addr, sizeof(struct rfd), | 1945 | new_before_last_rx->dma_addr, sizeof(struct rfd), |
| 1946 | PCI_DMA_TODEVICE); | 1946 | PCI_DMA_BIDIRECTIONAL); |
| 1947 | 1947 | ||
| 1948 | /* Now that we have a new stopping point, we can clear the old | 1948 | /* Now that we have a new stopping point, we can clear the old |
| 1949 | * stopping point. We must sync twice to get the proper | 1949 | * stopping point. We must sync twice to get the proper |
| @@ -1951,11 +1951,11 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done, | |||
| 1951 | old_before_last_rfd->command &= ~cpu_to_le16(cb_el); | 1951 | old_before_last_rfd->command &= ~cpu_to_le16(cb_el); |
| 1952 | pci_dma_sync_single_for_device(nic->pdev, | 1952 | pci_dma_sync_single_for_device(nic->pdev, |
| 1953 | old_before_last_rx->dma_addr, sizeof(struct rfd), | 1953 | old_before_last_rx->dma_addr, sizeof(struct rfd), |
| 1954 | PCI_DMA_TODEVICE); | 1954 | PCI_DMA_BIDIRECTIONAL); |
| 1955 | old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); | 1955 | old_before_last_rfd->size = cpu_to_le16(VLAN_ETH_FRAME_LEN); |
| 1956 | pci_dma_sync_single_for_device(nic->pdev, | 1956 | pci_dma_sync_single_for_device(nic->pdev, |
| 1957 | old_before_last_rx->dma_addr, sizeof(struct rfd), | 1957 | old_before_last_rx->dma_addr, sizeof(struct rfd), |
| 1958 | PCI_DMA_TODEVICE); | 1958 | PCI_DMA_BIDIRECTIONAL); |
| 1959 | } | 1959 | } |
| 1960 | 1960 | ||
| 1961 | if(restart_required) { | 1961 | if(restart_required) { |
| @@ -1978,7 +1978,7 @@ static void e100_rx_clean_list(struct nic *nic) | |||
| 1978 | for(rx = nic->rxs, i = 0; i < count; rx++, i++) { | 1978 | for(rx = nic->rxs, i = 0; i < count; rx++, i++) { |
| 1979 | if(rx->skb) { | 1979 | if(rx->skb) { |
| 1980 | pci_unmap_single(nic->pdev, rx->dma_addr, | 1980 | pci_unmap_single(nic->pdev, rx->dma_addr, |
| 1981 | RFD_BUF_LEN, PCI_DMA_FROMDEVICE); | 1981 | RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); |
| 1982 | dev_kfree_skb(rx->skb); | 1982 | dev_kfree_skb(rx->skb); |
| 1983 | } | 1983 | } |
| 1984 | } | 1984 | } |
| @@ -2021,7 +2021,7 @@ static int e100_rx_alloc_list(struct nic *nic) | |||
| 2021 | before_last->command |= cpu_to_le16(cb_el); | 2021 | before_last->command |= cpu_to_le16(cb_el); |
| 2022 | before_last->size = 0; | 2022 | before_last->size = 0; |
| 2023 | pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, | 2023 | pci_dma_sync_single_for_device(nic->pdev, rx->dma_addr, |
| 2024 | sizeof(struct rfd), PCI_DMA_TODEVICE); | 2024 | sizeof(struct rfd), PCI_DMA_BIDIRECTIONAL); |
| 2025 | 2025 | ||
| 2026 | nic->rx_to_use = nic->rx_to_clean = nic->rxs; | 2026 | nic->rx_to_use = nic->rx_to_clean = nic->rxs; |
| 2027 | nic->ru_running = RU_SUSPENDED; | 2027 | nic->ru_running = RU_SUSPENDED; |
| @@ -2222,7 +2222,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode) | |||
| 2222 | msleep(10); | 2222 | msleep(10); |
| 2223 | 2223 | ||
| 2224 | pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, | 2224 | pci_dma_sync_single_for_cpu(nic->pdev, nic->rx_to_clean->dma_addr, |
| 2225 | RFD_BUF_LEN, PCI_DMA_FROMDEVICE); | 2225 | RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL); |
| 2226 | 2226 | ||
| 2227 | if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), | 2227 | if(memcmp(nic->rx_to_clean->skb->data + sizeof(struct rfd), |
| 2228 | skb->data, ETH_DATA_LEN)) | 2228 | skb->data, ETH_DATA_LEN)) |
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 6a3893acfe04..c854c96f5ab3 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c | |||
| @@ -1774,7 +1774,8 @@ static void e1000_get_wol(struct net_device *netdev, | |||
| 1774 | 1774 | ||
| 1775 | /* this function will set ->supported = 0 and return 1 if wol is not | 1775 | /* this function will set ->supported = 0 and return 1 if wol is not |
| 1776 | * supported by this hardware */ | 1776 | * supported by this hardware */ |
| 1777 | if (e1000_wol_exclusion(adapter, wol)) | 1777 | if (e1000_wol_exclusion(adapter, wol) || |
| 1778 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1778 | return; | 1779 | return; |
| 1779 | 1780 | ||
| 1780 | /* apply any specific unsupported masks here */ | 1781 | /* apply any specific unsupported masks here */ |
| @@ -1811,7 +1812,8 @@ static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 1811 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) | 1812 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) |
| 1812 | return -EOPNOTSUPP; | 1813 | return -EOPNOTSUPP; |
| 1813 | 1814 | ||
| 1814 | if (e1000_wol_exclusion(adapter, wol)) | 1815 | if (e1000_wol_exclusion(adapter, wol) || |
| 1816 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1815 | return wol->wolopts ? -EOPNOTSUPP : 0; | 1817 | return wol->wolopts ? -EOPNOTSUPP : 0; |
| 1816 | 1818 | ||
| 1817 | switch (hw->device_id) { | 1819 | switch (hw->device_id) { |
| @@ -1838,6 +1840,8 @@ static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 1838 | if (wol->wolopts & WAKE_MAGIC) | 1840 | if (wol->wolopts & WAKE_MAGIC) |
| 1839 | adapter->wol |= E1000_WUFC_MAG; | 1841 | adapter->wol |= E1000_WUFC_MAG; |
| 1840 | 1842 | ||
| 1843 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 1844 | |||
| 1841 | return 0; | 1845 | return 0; |
| 1842 | } | 1846 | } |
| 1843 | 1847 | ||
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index fac82152e4c8..872799b746f5 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
| @@ -1179,6 +1179,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
| 1179 | 1179 | ||
| 1180 | /* initialize the wol settings based on the eeprom settings */ | 1180 | /* initialize the wol settings based on the eeprom settings */ |
| 1181 | adapter->wol = adapter->eeprom_wol; | 1181 | adapter->wol = adapter->eeprom_wol; |
| 1182 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 1182 | 1183 | ||
| 1183 | /* print bus type/speed/width info */ | 1184 | /* print bus type/speed/width info */ |
| 1184 | DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ", | 1185 | DPRINTK(PROBE, INFO, "(PCI%s:%s:%s) ", |
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index c55de1c027af..c55fd6fdb91c 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h | |||
| @@ -299,6 +299,7 @@ struct e1000_adapter { | |||
| 299 | unsigned long led_status; | 299 | unsigned long led_status; |
| 300 | 300 | ||
| 301 | unsigned int flags; | 301 | unsigned int flags; |
| 302 | unsigned int flags2; | ||
| 302 | struct work_struct downshift_task; | 303 | struct work_struct downshift_task; |
| 303 | struct work_struct update_phy_task; | 304 | struct work_struct update_phy_task; |
| 304 | }; | 305 | }; |
| @@ -306,6 +307,7 @@ struct e1000_adapter { | |||
| 306 | struct e1000_info { | 307 | struct e1000_info { |
| 307 | enum e1000_mac_type mac; | 308 | enum e1000_mac_type mac; |
| 308 | unsigned int flags; | 309 | unsigned int flags; |
| 310 | unsigned int flags2; | ||
| 309 | u32 pba; | 311 | u32 pba; |
| 310 | s32 (*get_variants)(struct e1000_adapter *); | 312 | s32 (*get_variants)(struct e1000_adapter *); |
| 311 | struct e1000_mac_operations *mac_ops; | 313 | struct e1000_mac_operations *mac_ops; |
| @@ -347,6 +349,9 @@ struct e1000_info { | |||
| 347 | #define FLAG_RX_RESTART_NOW (1 << 30) | 349 | #define FLAG_RX_RESTART_NOW (1 << 30) |
| 348 | #define FLAG_MSI_TEST_FAILED (1 << 31) | 350 | #define FLAG_MSI_TEST_FAILED (1 << 31) |
| 349 | 351 | ||
| 352 | /* CRC Stripping defines */ | ||
| 353 | #define FLAG2_CRC_STRIPPING (1 << 0) | ||
| 354 | |||
| 350 | #define E1000_RX_DESC_PS(R, i) \ | 355 | #define E1000_RX_DESC_PS(R, i) \ |
| 351 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) | 356 | (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) |
| 352 | #define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) | 357 | #define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) |
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 70c11c811a08..62421ce96311 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c | |||
| @@ -1713,7 +1713,8 @@ static void e1000_get_wol(struct net_device *netdev, | |||
| 1713 | wol->supported = 0; | 1713 | wol->supported = 0; |
| 1714 | wol->wolopts = 0; | 1714 | wol->wolopts = 0; |
| 1715 | 1715 | ||
| 1716 | if (!(adapter->flags & FLAG_HAS_WOL)) | 1716 | if (!(adapter->flags & FLAG_HAS_WOL) || |
| 1717 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1717 | return; | 1718 | return; |
| 1718 | 1719 | ||
| 1719 | wol->supported = WAKE_UCAST | WAKE_MCAST | | 1720 | wol->supported = WAKE_UCAST | WAKE_MCAST | |
| @@ -1751,7 +1752,8 @@ static int e1000_set_wol(struct net_device *netdev, | |||
| 1751 | if (wol->wolopts & WAKE_MAGICSECURE) | 1752 | if (wol->wolopts & WAKE_MAGICSECURE) |
| 1752 | return -EOPNOTSUPP; | 1753 | return -EOPNOTSUPP; |
| 1753 | 1754 | ||
| 1754 | if (!(adapter->flags & FLAG_HAS_WOL)) | 1755 | if (!(adapter->flags & FLAG_HAS_WOL) || |
| 1756 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1755 | return wol->wolopts ? -EOPNOTSUPP : 0; | 1757 | return wol->wolopts ? -EOPNOTSUPP : 0; |
| 1756 | 1758 | ||
| 1757 | /* these settings will always override what we currently have */ | 1759 | /* these settings will always override what we currently have */ |
| @@ -1770,6 +1772,8 @@ static int e1000_set_wol(struct net_device *netdev, | |||
| 1770 | if (wol->wolopts & WAKE_ARP) | 1772 | if (wol->wolopts & WAKE_ARP) |
| 1771 | adapter->wol |= E1000_WUFC_ARP; | 1773 | adapter->wol |= E1000_WUFC_ARP; |
| 1772 | 1774 | ||
| 1775 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 1776 | |||
| 1773 | return 0; | 1777 | return 0; |
| 1774 | } | 1778 | } |
| 1775 | 1779 | ||
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index abd492b7336d..91795f78c3e4 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
| @@ -499,6 +499,10 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, | |||
| 499 | goto next_desc; | 499 | goto next_desc; |
| 500 | } | 500 | } |
| 501 | 501 | ||
| 502 | /* adjust length to remove Ethernet CRC */ | ||
| 503 | if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) | ||
| 504 | length -= 4; | ||
| 505 | |||
| 502 | total_rx_bytes += length; | 506 | total_rx_bytes += length; |
| 503 | total_rx_packets++; | 507 | total_rx_packets++; |
| 504 | 508 | ||
| @@ -804,6 +808,10 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, | |||
| 804 | pci_dma_sync_single_for_device(pdev, ps_page->dma, | 808 | pci_dma_sync_single_for_device(pdev, ps_page->dma, |
| 805 | PAGE_SIZE, PCI_DMA_FROMDEVICE); | 809 | PAGE_SIZE, PCI_DMA_FROMDEVICE); |
| 806 | 810 | ||
| 811 | /* remove the CRC */ | ||
| 812 | if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) | ||
| 813 | l1 -= 4; | ||
| 814 | |||
| 807 | skb_put(skb, l1); | 815 | skb_put(skb, l1); |
| 808 | goto copydone; | 816 | goto copydone; |
| 809 | } /* if */ | 817 | } /* if */ |
| @@ -825,6 +833,12 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, | |||
| 825 | skb->truesize += length; | 833 | skb->truesize += length; |
| 826 | } | 834 | } |
| 827 | 835 | ||
| 836 | /* strip the ethernet crc, problem is we're using pages now so | ||
| 837 | * this whole operation can get a little cpu intensive | ||
| 838 | */ | ||
| 839 | if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) | ||
| 840 | pskb_trim(skb, skb->len - 4); | ||
| 841 | |||
| 828 | copydone: | 842 | copydone: |
| 829 | total_rx_bytes += skb->len; | 843 | total_rx_bytes += skb->len; |
| 830 | total_rx_packets++; | 844 | total_rx_packets++; |
| @@ -2301,8 +2315,12 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) | |||
| 2301 | else | 2315 | else |
| 2302 | rctl |= E1000_RCTL_LPE; | 2316 | rctl |= E1000_RCTL_LPE; |
| 2303 | 2317 | ||
| 2304 | /* Enable hardware CRC frame stripping */ | 2318 | /* Some systems expect that the CRC is included in SMBUS traffic. The |
| 2305 | rctl |= E1000_RCTL_SECRC; | 2319 | * hardware strips the CRC before sending to both SMBUS (BMC) and to |
| 2320 | * host memory when this is enabled | ||
| 2321 | */ | ||
| 2322 | if (adapter->flags2 & FLAG2_CRC_STRIPPING) | ||
| 2323 | rctl |= E1000_RCTL_SECRC; | ||
| 2306 | 2324 | ||
| 2307 | /* Setup buffer sizes */ | 2325 | /* Setup buffer sizes */ |
| 2308 | rctl &= ~E1000_RCTL_SZ_4096; | 2326 | rctl &= ~E1000_RCTL_SZ_4096; |
| @@ -4766,6 +4784,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
| 4766 | adapter->ei = ei; | 4784 | adapter->ei = ei; |
| 4767 | adapter->pba = ei->pba; | 4785 | adapter->pba = ei->pba; |
| 4768 | adapter->flags = ei->flags; | 4786 | adapter->flags = ei->flags; |
| 4787 | adapter->flags2 = ei->flags2; | ||
| 4769 | adapter->hw.adapter = adapter; | 4788 | adapter->hw.adapter = adapter; |
| 4770 | adapter->hw.mac.type = ei->mac; | 4789 | adapter->hw.mac.type = ei->mac; |
| 4771 | adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1; | 4790 | adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1; |
| @@ -4970,6 +4989,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
| 4970 | 4989 | ||
| 4971 | /* initialize the wol settings based on the eeprom settings */ | 4990 | /* initialize the wol settings based on the eeprom settings */ |
| 4972 | adapter->wol = adapter->eeprom_wol; | 4991 | adapter->wol = adapter->eeprom_wol; |
| 4992 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 4973 | 4993 | ||
| 4974 | /* reset the hardware with the new settings */ | 4994 | /* reset the hardware with the new settings */ |
| 4975 | e1000e_reset(adapter); | 4995 | e1000e_reset(adapter); |
| @@ -5008,6 +5028,7 @@ err_hw_init: | |||
| 5008 | err_sw_init: | 5028 | err_sw_init: |
| 5009 | if (adapter->hw.flash_address) | 5029 | if (adapter->hw.flash_address) |
| 5010 | iounmap(adapter->hw.flash_address); | 5030 | iounmap(adapter->hw.flash_address); |
| 5031 | e1000e_reset_interrupt_capability(adapter); | ||
| 5011 | err_flashmap: | 5032 | err_flashmap: |
| 5012 | iounmap(adapter->hw.hw_addr); | 5033 | iounmap(adapter->hw.hw_addr); |
| 5013 | err_ioremap: | 5034 | err_ioremap: |
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index 77a3d7207a5f..e909f96698e8 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c | |||
| @@ -151,6 +151,16 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); | |||
| 151 | */ | 151 | */ |
| 152 | E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); | 152 | E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); |
| 153 | 153 | ||
| 154 | /* | ||
| 155 | * Enable CRC Stripping | ||
| 156 | * | ||
| 157 | * Valid Range: 0, 1 | ||
| 158 | * | ||
| 159 | * Default Value: 1 (enabled) | ||
| 160 | */ | ||
| 161 | E1000_PARAM(CrcStripping, "Enable CRC Stripping, disable if your BMC needs " \ | ||
| 162 | "the CRC"); | ||
| 163 | |||
| 154 | struct e1000_option { | 164 | struct e1000_option { |
| 155 | enum { enable_option, range_option, list_option } type; | 165 | enum { enable_option, range_option, list_option } type; |
| 156 | const char *name; | 166 | const char *name; |
| @@ -404,6 +414,21 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) | |||
| 404 | adapter->flags |= FLAG_SMART_POWER_DOWN; | 414 | adapter->flags |= FLAG_SMART_POWER_DOWN; |
| 405 | } | 415 | } |
| 406 | } | 416 | } |
| 417 | { /* CRC Stripping */ | ||
| 418 | const struct e1000_option opt = { | ||
| 419 | .type = enable_option, | ||
| 420 | .name = "CRC Stripping", | ||
| 421 | .err = "defaulting to enabled", | ||
| 422 | .def = OPTION_ENABLED | ||
| 423 | }; | ||
| 424 | |||
| 425 | if (num_CrcStripping > bd) { | ||
| 426 | unsigned int crc_stripping = CrcStripping[bd]; | ||
| 427 | e1000_validate_option(&crc_stripping, &opt, adapter); | ||
| 428 | if (crc_stripping == OPTION_ENABLED) | ||
| 429 | adapter->flags2 |= FLAG2_CRC_STRIPPING; | ||
| 430 | } | ||
| 431 | } | ||
| 407 | { /* Kumeran Lock Loss Workaround */ | 432 | { /* Kumeran Lock Loss Workaround */ |
| 408 | const struct e1000_option opt = { | 433 | const struct e1000_option opt = { |
| 409 | .type = enable_option, | 434 | .type = enable_option, |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 83a5cb6aa23b..c4af949bf860 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
| @@ -1407,6 +1407,10 @@ static int gfar_clean_tx_ring(struct net_device *dev) | |||
| 1407 | if (bdp->status & TXBD_DEF) | 1407 | if (bdp->status & TXBD_DEF) |
| 1408 | dev->stats.collisions++; | 1408 | dev->stats.collisions++; |
| 1409 | 1409 | ||
| 1410 | /* Unmap the DMA memory */ | ||
| 1411 | dma_unmap_single(&priv->dev->dev, bdp->bufPtr, | ||
| 1412 | bdp->length, DMA_TO_DEVICE); | ||
| 1413 | |||
| 1410 | /* Free the sk buffer associated with this TxBD */ | 1414 | /* Free the sk buffer associated with this TxBD */ |
| 1411 | dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]); | 1415 | dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]); |
| 1412 | 1416 | ||
| @@ -1666,6 +1670,9 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) | |||
| 1666 | 1670 | ||
| 1667 | skb = priv->rx_skbuff[priv->skb_currx]; | 1671 | skb = priv->rx_skbuff[priv->skb_currx]; |
| 1668 | 1672 | ||
| 1673 | dma_unmap_single(&priv->dev->dev, bdp->bufPtr, | ||
| 1674 | priv->rx_buffer_size, DMA_FROM_DEVICE); | ||
| 1675 | |||
| 1669 | /* We drop the frame if we failed to allocate a new buffer */ | 1676 | /* We drop the frame if we failed to allocate a new buffer */ |
| 1670 | if (unlikely(!newskb || !(bdp->status & RXBD_LAST) || | 1677 | if (unlikely(!newskb || !(bdp->status & RXBD_LAST) || |
| 1671 | bdp->status & RXBD_ERR)) { | 1678 | bdp->status & RXBD_ERR)) { |
| @@ -1674,14 +1681,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) | |||
| 1674 | if (unlikely(!newskb)) | 1681 | if (unlikely(!newskb)) |
| 1675 | newskb = skb; | 1682 | newskb = skb; |
| 1676 | 1683 | ||
| 1677 | if (skb) { | 1684 | if (skb) |
| 1678 | dma_unmap_single(&priv->dev->dev, | ||
| 1679 | bdp->bufPtr, | ||
| 1680 | priv->rx_buffer_size, | ||
| 1681 | DMA_FROM_DEVICE); | ||
| 1682 | |||
| 1683 | dev_kfree_skb_any(skb); | 1685 | dev_kfree_skb_any(skb); |
| 1684 | } | ||
| 1685 | } else { | 1686 | } else { |
| 1686 | /* Increment the number of packets */ | 1687 | /* Increment the number of packets */ |
| 1687 | dev->stats.rx_packets++; | 1688 | dev->stats.rx_packets++; |
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 58906c984be9..89964fa739a0 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c | |||
| @@ -1776,7 +1776,8 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 1776 | 1776 | ||
| 1777 | /* this function will set ->supported = 0 and return 1 if wol is not | 1777 | /* this function will set ->supported = 0 and return 1 if wol is not |
| 1778 | * supported by this hardware */ | 1778 | * supported by this hardware */ |
| 1779 | if (igb_wol_exclusion(adapter, wol)) | 1779 | if (igb_wol_exclusion(adapter, wol) || |
| 1780 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1780 | return; | 1781 | return; |
| 1781 | 1782 | ||
| 1782 | /* apply any specific unsupported masks here */ | 1783 | /* apply any specific unsupported masks here */ |
| @@ -1805,7 +1806,8 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 1805 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) | 1806 | if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) |
| 1806 | return -EOPNOTSUPP; | 1807 | return -EOPNOTSUPP; |
| 1807 | 1808 | ||
| 1808 | if (igb_wol_exclusion(adapter, wol)) | 1809 | if (igb_wol_exclusion(adapter, wol) || |
| 1810 | !device_can_wakeup(&adapter->pdev->dev)) | ||
| 1809 | return wol->wolopts ? -EOPNOTSUPP : 0; | 1811 | return wol->wolopts ? -EOPNOTSUPP : 0; |
| 1810 | 1812 | ||
| 1811 | switch (hw->device_id) { | 1813 | switch (hw->device_id) { |
| @@ -1825,6 +1827,8 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) | |||
| 1825 | if (wol->wolopts & WAKE_MAGIC) | 1827 | if (wol->wolopts & WAKE_MAGIC) |
| 1826 | adapter->wol |= E1000_WUFC_MAG; | 1828 | adapter->wol |= E1000_WUFC_MAG; |
| 1827 | 1829 | ||
| 1830 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 1831 | |||
| 1828 | return 0; | 1832 | return 0; |
| 1829 | } | 1833 | } |
| 1830 | 1834 | ||
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 1f397cd99414..1cbae85b1426 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
| @@ -1019,10 +1019,9 @@ static int __devinit igb_probe(struct pci_dev *pdev, | |||
| 1019 | state &= ~PCIE_LINK_STATE_L0S; | 1019 | state &= ~PCIE_LINK_STATE_L0S; |
| 1020 | pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL, | 1020 | pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL, |
| 1021 | state); | 1021 | state); |
| 1022 | printk(KERN_INFO "Disabling ASPM L0s upstream switch " | 1022 | dev_info(&pdev->dev, |
| 1023 | "port %x:%x.%x\n", us_dev->bus->number, | 1023 | "Disabling ASPM L0s upstream switch port %s\n", |
| 1024 | PCI_SLOT(us_dev->devfn), | 1024 | pci_name(us_dev)); |
| 1025 | PCI_FUNC(us_dev->devfn)); | ||
| 1026 | } | 1025 | } |
| 1027 | default: | 1026 | default: |
| 1028 | break; | 1027 | break; |
| @@ -1244,6 +1243,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, | |||
| 1244 | 1243 | ||
| 1245 | /* initialize the wol settings based on the eeprom settings */ | 1244 | /* initialize the wol settings based on the eeprom settings */ |
| 1246 | adapter->wol = adapter->eeprom_wol; | 1245 | adapter->wol = adapter->eeprom_wol; |
| 1246 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | ||
| 1247 | 1247 | ||
| 1248 | /* reset the hardware with the new settings */ | 1248 | /* reset the hardware with the new settings */ |
| 1249 | igb_reset(adapter); | 1249 | igb_reset(adapter); |
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c index a3f732418c49..96e709d6440a 100644 --- a/drivers/net/mlx4/en_netdev.c +++ b/drivers/net/mlx4/en_netdev.c | |||
| @@ -656,10 +656,10 @@ static int mlx4_en_start_port(struct net_device *dev) | |||
| 656 | /* Configure port */ | 656 | /* Configure port */ |
| 657 | err = mlx4_SET_PORT_general(mdev->dev, priv->port, | 657 | err = mlx4_SET_PORT_general(mdev->dev, priv->port, |
| 658 | priv->rx_skb_size + ETH_FCS_LEN, | 658 | priv->rx_skb_size + ETH_FCS_LEN, |
| 659 | mdev->profile.tx_pause, | 659 | priv->prof->tx_pause, |
| 660 | mdev->profile.tx_ppp, | 660 | priv->prof->tx_ppp, |
| 661 | mdev->profile.rx_pause, | 661 | priv->prof->rx_pause, |
| 662 | mdev->profile.rx_ppp); | 662 | priv->prof->rx_ppp); |
| 663 | if (err) { | 663 | if (err) { |
| 664 | mlx4_err(mdev, "Failed setting port general configurations" | 664 | mlx4_err(mdev, "Failed setting port general configurations" |
| 665 | " for port %d, with error %d\n", priv->port, err); | 665 | " for port %d, with error %d\n", priv->port, err); |
diff --git a/drivers/net/mlx4/en_params.c b/drivers/net/mlx4/en_params.c index c2e69b1bcd0a..95706ee1c019 100644 --- a/drivers/net/mlx4/en_params.c +++ b/drivers/net/mlx4/en_params.c | |||
| @@ -90,6 +90,7 @@ MLX4_EN_PARM_INT(rx_ring_size2, MLX4_EN_AUTO_CONF, "Rx ring size for port 2"); | |||
| 90 | int mlx4_en_get_profile(struct mlx4_en_dev *mdev) | 90 | int mlx4_en_get_profile(struct mlx4_en_dev *mdev) |
| 91 | { | 91 | { |
| 92 | struct mlx4_en_profile *params = &mdev->profile; | 92 | struct mlx4_en_profile *params = &mdev->profile; |
| 93 | int i; | ||
| 93 | 94 | ||
| 94 | params->rx_moder_cnt = min_t(int, rx_moder_cnt, MLX4_EN_AUTO_CONF); | 95 | params->rx_moder_cnt = min_t(int, rx_moder_cnt, MLX4_EN_AUTO_CONF); |
| 95 | params->rx_moder_time = min_t(int, rx_moder_time, MLX4_EN_AUTO_CONF); | 96 | params->rx_moder_time = min_t(int, rx_moder_time, MLX4_EN_AUTO_CONF); |
| @@ -97,11 +98,13 @@ int mlx4_en_get_profile(struct mlx4_en_dev *mdev) | |||
| 97 | params->rss_xor = (rss_xor != 0); | 98 | params->rss_xor = (rss_xor != 0); |
| 98 | params->rss_mask = rss_mask & 0x1f; | 99 | params->rss_mask = rss_mask & 0x1f; |
| 99 | params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS); | 100 | params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS); |
| 100 | params->rx_pause = pprx; | 101 | for (i = 1; i <= MLX4_MAX_PORTS; i++) { |
| 101 | params->rx_ppp = pfcrx; | 102 | params->prof[i].rx_pause = pprx; |
| 102 | params->tx_pause = pptx; | 103 | params->prof[i].rx_ppp = pfcrx; |
| 103 | params->tx_ppp = pfctx; | 104 | params->prof[i].tx_pause = pptx; |
| 104 | if (params->rx_ppp || params->tx_ppp) { | 105 | params->prof[i].tx_ppp = pfctx; |
| 106 | } | ||
| 107 | if (pfcrx || pfctx) { | ||
| 105 | params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM; | 108 | params->prof[1].tx_ring_num = MLX4_EN_TX_RING_NUM; |
| 106 | params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM; | 109 | params->prof[2].tx_ring_num = MLX4_EN_TX_RING_NUM; |
| 107 | } else { | 110 | } else { |
| @@ -407,14 +410,14 @@ static int mlx4_en_set_pauseparam(struct net_device *dev, | |||
| 407 | struct mlx4_en_dev *mdev = priv->mdev; | 410 | struct mlx4_en_dev *mdev = priv->mdev; |
| 408 | int err; | 411 | int err; |
| 409 | 412 | ||
| 410 | mdev->profile.tx_pause = pause->tx_pause != 0; | 413 | priv->prof->tx_pause = pause->tx_pause != 0; |
| 411 | mdev->profile.rx_pause = pause->rx_pause != 0; | 414 | priv->prof->rx_pause = pause->rx_pause != 0; |
| 412 | err = mlx4_SET_PORT_general(mdev->dev, priv->port, | 415 | err = mlx4_SET_PORT_general(mdev->dev, priv->port, |
| 413 | priv->rx_skb_size + ETH_FCS_LEN, | 416 | priv->rx_skb_size + ETH_FCS_LEN, |
| 414 | mdev->profile.tx_pause, | 417 | priv->prof->tx_pause, |
| 415 | mdev->profile.tx_ppp, | 418 | priv->prof->tx_ppp, |
| 416 | mdev->profile.rx_pause, | 419 | priv->prof->rx_pause, |
| 417 | mdev->profile.rx_ppp); | 420 | priv->prof->rx_ppp); |
| 418 | if (err) | 421 | if (err) |
| 419 | mlx4_err(mdev, "Failed setting pause params to\n"); | 422 | mlx4_err(mdev, "Failed setting pause params to\n"); |
| 420 | 423 | ||
| @@ -425,10 +428,9 @@ static void mlx4_en_get_pauseparam(struct net_device *dev, | |||
| 425 | struct ethtool_pauseparam *pause) | 428 | struct ethtool_pauseparam *pause) |
| 426 | { | 429 | { |
| 427 | struct mlx4_en_priv *priv = netdev_priv(dev); | 430 | struct mlx4_en_priv *priv = netdev_priv(dev); |
| 428 | struct mlx4_en_dev *mdev = priv->mdev; | ||
| 429 | 431 | ||
| 430 | pause->tx_pause = mdev->profile.tx_pause; | 432 | pause->tx_pause = priv->prof->tx_pause; |
| 431 | pause->rx_pause = mdev->profile.rx_pause; | 433 | pause->rx_pause = priv->prof->rx_pause; |
| 432 | } | 434 | } |
| 433 | 435 | ||
| 434 | static void mlx4_en_get_ringparam(struct net_device *dev, | 436 | static void mlx4_en_get_ringparam(struct net_device *dev, |
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h index 11fb17c6e97b..98ddc0811f93 100644 --- a/drivers/net/mlx4/mlx4_en.h +++ b/drivers/net/mlx4/mlx4_en.h | |||
| @@ -322,6 +322,10 @@ struct mlx4_en_port_profile { | |||
| 322 | u32 rx_ring_num; | 322 | u32 rx_ring_num; |
| 323 | u32 tx_ring_size; | 323 | u32 tx_ring_size; |
| 324 | u32 rx_ring_size; | 324 | u32 rx_ring_size; |
| 325 | u8 rx_pause; | ||
| 326 | u8 rx_ppp; | ||
| 327 | u8 tx_pause; | ||
| 328 | u8 tx_ppp; | ||
| 325 | }; | 329 | }; |
| 326 | 330 | ||
| 327 | struct mlx4_en_profile { | 331 | struct mlx4_en_profile { |
| @@ -333,10 +337,6 @@ struct mlx4_en_profile { | |||
| 333 | int rx_moder_cnt; | 337 | int rx_moder_cnt; |
| 334 | int rx_moder_time; | 338 | int rx_moder_time; |
| 335 | int auto_moder; | 339 | int auto_moder; |
| 336 | u8 rx_pause; | ||
| 337 | u8 rx_ppp; | ||
| 338 | u8 tx_pause; | ||
| 339 | u8 tx_ppp; | ||
| 340 | u8 no_reset; | 340 | u8 no_reset; |
| 341 | struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1]; | 341 | struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1]; |
| 342 | }; | 342 | }; |
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index d8463b1c3df3..1b6f548c4411 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
| @@ -33,8 +33,8 @@ | |||
| 33 | 33 | ||
| 34 | #define DRV_MODULE_NAME "niu" | 34 | #define DRV_MODULE_NAME "niu" |
| 35 | #define PFX DRV_MODULE_NAME ": " | 35 | #define PFX DRV_MODULE_NAME ": " |
| 36 | #define DRV_MODULE_VERSION "0.9" | 36 | #define DRV_MODULE_VERSION "1.0" |
| 37 | #define DRV_MODULE_RELDATE "May 4, 2008" | 37 | #define DRV_MODULE_RELDATE "Nov 14, 2008" |
| 38 | 38 | ||
| 39 | static char version[] __devinitdata = | 39 | static char version[] __devinitdata = |
| 40 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 40 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; |
| @@ -406,7 +406,7 @@ static int esr2_set_rx_cfg(struct niu *np, unsigned long channel, u32 val) | |||
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | /* Mode is always 10G fiber. */ | 408 | /* Mode is always 10G fiber. */ |
| 409 | static int serdes_init_niu(struct niu *np) | 409 | static int serdes_init_niu_10g_fiber(struct niu *np) |
| 410 | { | 410 | { |
| 411 | struct niu_link_config *lp = &np->link_config; | 411 | struct niu_link_config *lp = &np->link_config; |
| 412 | u32 tx_cfg, rx_cfg; | 412 | u32 tx_cfg, rx_cfg; |
| @@ -443,6 +443,223 @@ static int serdes_init_niu(struct niu *np) | |||
| 443 | return 0; | 443 | return 0; |
| 444 | } | 444 | } |
| 445 | 445 | ||
| 446 | static int serdes_init_niu_1g_serdes(struct niu *np) | ||
| 447 | { | ||
| 448 | struct niu_link_config *lp = &np->link_config; | ||
| 449 | u16 pll_cfg, pll_sts; | ||
| 450 | int max_retry = 100; | ||
| 451 | u64 sig, mask, val; | ||
| 452 | u32 tx_cfg, rx_cfg; | ||
| 453 | unsigned long i; | ||
| 454 | int err; | ||
| 455 | |||
| 456 | tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV | | ||
| 457 | PLL_TX_CFG_RATE_HALF); | ||
| 458 | rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT | | ||
| 459 | PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH | | ||
| 460 | PLL_RX_CFG_RATE_HALF); | ||
| 461 | |||
| 462 | if (np->port == 0) | ||
| 463 | rx_cfg |= PLL_RX_CFG_EQ_LP_ADAPTIVE; | ||
| 464 | |||
| 465 | if (lp->loopback_mode == LOOPBACK_PHY) { | ||
| 466 | u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS; | ||
| 467 | |||
| 468 | mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 469 | ESR2_TI_PLL_TEST_CFG_L, test_cfg); | ||
| 470 | |||
| 471 | tx_cfg |= PLL_TX_CFG_ENTEST; | ||
| 472 | rx_cfg |= PLL_RX_CFG_ENTEST; | ||
| 473 | } | ||
| 474 | |||
| 475 | /* Initialize PLL for 1G */ | ||
| 476 | pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_8X); | ||
| 477 | |||
| 478 | err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 479 | ESR2_TI_PLL_CFG_L, pll_cfg); | ||
| 480 | if (err) { | ||
| 481 | dev_err(np->device, PFX "NIU Port %d " | ||
| 482 | "serdes_init_niu_1g_serdes: " | ||
| 483 | "mdio write to ESR2_TI_PLL_CFG_L failed", np->port); | ||
| 484 | return err; | ||
| 485 | } | ||
| 486 | |||
| 487 | pll_sts = PLL_CFG_ENPLL; | ||
| 488 | |||
| 489 | err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 490 | ESR2_TI_PLL_STS_L, pll_sts); | ||
| 491 | if (err) { | ||
| 492 | dev_err(np->device, PFX "NIU Port %d " | ||
| 493 | "serdes_init_niu_1g_serdes: " | ||
| 494 | "mdio write to ESR2_TI_PLL_STS_L failed", np->port); | ||
| 495 | return err; | ||
| 496 | } | ||
| 497 | |||
| 498 | udelay(200); | ||
| 499 | |||
| 500 | /* Initialize all 4 lanes of the SERDES. */ | ||
| 501 | for (i = 0; i < 4; i++) { | ||
| 502 | err = esr2_set_tx_cfg(np, i, tx_cfg); | ||
| 503 | if (err) | ||
| 504 | return err; | ||
| 505 | } | ||
| 506 | |||
| 507 | for (i = 0; i < 4; i++) { | ||
| 508 | err = esr2_set_rx_cfg(np, i, rx_cfg); | ||
| 509 | if (err) | ||
| 510 | return err; | ||
| 511 | } | ||
| 512 | |||
| 513 | switch (np->port) { | ||
| 514 | case 0: | ||
| 515 | val = (ESR_INT_SRDY0_P0 | ESR_INT_DET0_P0); | ||
| 516 | mask = val; | ||
| 517 | break; | ||
| 518 | |||
| 519 | case 1: | ||
| 520 | val = (ESR_INT_SRDY0_P1 | ESR_INT_DET0_P1); | ||
| 521 | mask = val; | ||
| 522 | break; | ||
| 523 | |||
| 524 | default: | ||
| 525 | return -EINVAL; | ||
| 526 | } | ||
| 527 | |||
| 528 | while (max_retry--) { | ||
| 529 | sig = nr64(ESR_INT_SIGNALS); | ||
| 530 | if ((sig & mask) == val) | ||
| 531 | break; | ||
| 532 | |||
| 533 | mdelay(500); | ||
| 534 | } | ||
| 535 | |||
| 536 | if ((sig & mask) != val) { | ||
| 537 | dev_err(np->device, PFX "Port %u signal bits [%08x] are not " | ||
| 538 | "[%08x]\n", np->port, (int) (sig & mask), (int) val); | ||
| 539 | return -ENODEV; | ||
| 540 | } | ||
| 541 | |||
| 542 | return 0; | ||
| 543 | } | ||
| 544 | |||
| 545 | static int serdes_init_niu_10g_serdes(struct niu *np) | ||
| 546 | { | ||
| 547 | struct niu_link_config *lp = &np->link_config; | ||
| 548 | u32 tx_cfg, rx_cfg, pll_cfg, pll_sts; | ||
| 549 | int max_retry = 100; | ||
| 550 | u64 sig, mask, val; | ||
| 551 | unsigned long i; | ||
| 552 | int err; | ||
| 553 | |||
| 554 | tx_cfg = (PLL_TX_CFG_ENTX | PLL_TX_CFG_SWING_1375MV); | ||
| 555 | rx_cfg = (PLL_RX_CFG_ENRX | PLL_RX_CFG_TERM_0P8VDDT | | ||
| 556 | PLL_RX_CFG_ALIGN_ENA | PLL_RX_CFG_LOS_LTHRESH | | ||
| 557 | PLL_RX_CFG_EQ_LP_ADAPTIVE); | ||
| 558 | |||
| 559 | if (lp->loopback_mode == LOOPBACK_PHY) { | ||
| 560 | u16 test_cfg = PLL_TEST_CFG_LOOPBACK_CML_DIS; | ||
| 561 | |||
| 562 | mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 563 | ESR2_TI_PLL_TEST_CFG_L, test_cfg); | ||
| 564 | |||
| 565 | tx_cfg |= PLL_TX_CFG_ENTEST; | ||
| 566 | rx_cfg |= PLL_RX_CFG_ENTEST; | ||
| 567 | } | ||
| 568 | |||
| 569 | /* Initialize PLL for 10G */ | ||
| 570 | pll_cfg = (PLL_CFG_ENPLL | PLL_CFG_MPY_10X); | ||
| 571 | |||
| 572 | err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 573 | ESR2_TI_PLL_CFG_L, pll_cfg & 0xffff); | ||
| 574 | if (err) { | ||
| 575 | dev_err(np->device, PFX "NIU Port %d " | ||
| 576 | "serdes_init_niu_10g_serdes: " | ||
| 577 | "mdio write to ESR2_TI_PLL_CFG_L failed", np->port); | ||
| 578 | return err; | ||
| 579 | } | ||
| 580 | |||
| 581 | pll_sts = PLL_CFG_ENPLL; | ||
| 582 | |||
| 583 | err = mdio_write(np, np->port, NIU_ESR2_DEV_ADDR, | ||
| 584 | ESR2_TI_PLL_STS_L, pll_sts & 0xffff); | ||
| 585 | if (err) { | ||
| 586 | dev_err(np->device, PFX "NIU Port %d " | ||
| 587 | "serdes_init_niu_10g_serdes: " | ||
| 588 | "mdio write to ESR2_TI_PLL_STS_L failed", np->port); | ||
| 589 | return err; | ||
| 590 | } | ||
| 591 | |||
| 592 | udelay(200); | ||
| 593 | |||
| 594 | /* Initialize all 4 lanes of the SERDES. */ | ||
| 595 | for (i = 0; i < 4; i++) { | ||
| 596 | err = esr2_set_tx_cfg(np, i, tx_cfg); | ||
| 597 | if (err) | ||
| 598 | return err; | ||
| 599 | } | ||
| 600 | |||
| 601 | for (i = 0; i < 4; i++) { | ||
| 602 | err = esr2_set_rx_cfg(np, i, rx_cfg); | ||
| 603 | if (err) | ||
| 604 | return err; | ||
| 605 | } | ||
| 606 | |||
| 607 | /* check if serdes is ready */ | ||
| 608 | |||
| 609 | switch (np->port) { | ||
| 610 | case 0: | ||
| 611 | mask = ESR_INT_SIGNALS_P0_BITS; | ||
| 612 | val = (ESR_INT_SRDY0_P0 | | ||
| 613 | ESR_INT_DET0_P0 | | ||
| 614 | ESR_INT_XSRDY_P0 | | ||
| 615 | ESR_INT_XDP_P0_CH3 | | ||
| 616 | ESR_INT_XDP_P0_CH2 | | ||
| 617 | ESR_INT_XDP_P0_CH1 | | ||
| 618 | ESR_INT_XDP_P0_CH0); | ||
| 619 | break; | ||
| 620 | |||
| 621 | case 1: | ||
| 622 | mask = ESR_INT_SIGNALS_P1_BITS; | ||
| 623 | val = (ESR_INT_SRDY0_P1 | | ||
| 624 | ESR_INT_DET0_P1 | | ||
| 625 | ESR_INT_XSRDY_P1 | | ||
| 626 | ESR_INT_XDP_P1_CH3 | | ||
| 627 | ESR_INT_XDP_P1_CH2 | | ||
| 628 | ESR_INT_XDP_P1_CH1 | | ||
| 629 | ESR_INT_XDP_P1_CH0); | ||
| 630 | break; | ||
| 631 | |||
| 632 | default: | ||
| 633 | return -EINVAL; | ||
| 634 | } | ||
| 635 | |||
| 636 | while (max_retry--) { | ||
| 637 | sig = nr64(ESR_INT_SIGNALS); | ||
| 638 | if ((sig & mask) == val) | ||
| 639 | break; | ||
| 640 | |||
| 641 | mdelay(500); | ||
| 642 | } | ||
| 643 | |||
| 644 | if ((sig & mask) != val) { | ||
| 645 | pr_info(PFX "NIU Port %u signal bits [%08x] are not " | ||
| 646 | "[%08x] for 10G...trying 1G\n", | ||
| 647 | np->port, (int) (sig & mask), (int) val); | ||
| 648 | |||
| 649 | /* 10G failed, try initializing at 1G */ | ||
| 650 | err = serdes_init_niu_1g_serdes(np); | ||
| 651 | if (!err) { | ||
| 652 | np->flags &= ~NIU_FLAGS_10G; | ||
| 653 | np->mac_xcvr = MAC_XCVR_PCS; | ||
| 654 | } else { | ||
| 655 | dev_err(np->device, PFX "Port %u 10G/1G SERDES " | ||
| 656 | "Link Failed \n", np->port); | ||
| 657 | return -ENODEV; | ||
| 658 | } | ||
| 659 | } | ||
| 660 | return 0; | ||
| 661 | } | ||
| 662 | |||
| 446 | static int esr_read_rxtx_ctrl(struct niu *np, unsigned long chan, u32 *val) | 663 | static int esr_read_rxtx_ctrl(struct niu *np, unsigned long chan, u32 *val) |
| 447 | { | 664 | { |
| 448 | int err; | 665 | int err; |
| @@ -1954,13 +2171,23 @@ static const struct niu_phy_ops phy_ops_10g_serdes = { | |||
| 1954 | .link_status = link_status_10g_serdes, | 2171 | .link_status = link_status_10g_serdes, |
| 1955 | }; | 2172 | }; |
| 1956 | 2173 | ||
| 2174 | static const struct niu_phy_ops phy_ops_10g_serdes_niu = { | ||
| 2175 | .serdes_init = serdes_init_niu_10g_serdes, | ||
| 2176 | .link_status = link_status_10g_serdes, | ||
| 2177 | }; | ||
| 2178 | |||
| 2179 | static const struct niu_phy_ops phy_ops_1g_serdes_niu = { | ||
| 2180 | .serdes_init = serdes_init_niu_1g_serdes, | ||
| 2181 | .link_status = link_status_1g_serdes, | ||
| 2182 | }; | ||
| 2183 | |||
| 1957 | static const struct niu_phy_ops phy_ops_1g_rgmii = { | 2184 | static const struct niu_phy_ops phy_ops_1g_rgmii = { |
| 1958 | .xcvr_init = xcvr_init_1g_rgmii, | 2185 | .xcvr_init = xcvr_init_1g_rgmii, |
| 1959 | .link_status = link_status_1g_rgmii, | 2186 | .link_status = link_status_1g_rgmii, |
| 1960 | }; | 2187 | }; |
| 1961 | 2188 | ||
| 1962 | static const struct niu_phy_ops phy_ops_10g_fiber_niu = { | 2189 | static const struct niu_phy_ops phy_ops_10g_fiber_niu = { |
| 1963 | .serdes_init = serdes_init_niu, | 2190 | .serdes_init = serdes_init_niu_10g_fiber, |
| 1964 | .xcvr_init = xcvr_init_10g, | 2191 | .xcvr_init = xcvr_init_10g, |
| 1965 | .link_status = link_status_10g, | 2192 | .link_status = link_status_10g, |
| 1966 | }; | 2193 | }; |
| @@ -1998,11 +2225,21 @@ struct niu_phy_template { | |||
| 1998 | u32 phy_addr_base; | 2225 | u32 phy_addr_base; |
| 1999 | }; | 2226 | }; |
| 2000 | 2227 | ||
| 2001 | static const struct niu_phy_template phy_template_niu = { | 2228 | static const struct niu_phy_template phy_template_niu_10g_fiber = { |
| 2002 | .ops = &phy_ops_10g_fiber_niu, | 2229 | .ops = &phy_ops_10g_fiber_niu, |
| 2003 | .phy_addr_base = 16, | 2230 | .phy_addr_base = 16, |
| 2004 | }; | 2231 | }; |
| 2005 | 2232 | ||
| 2233 | static const struct niu_phy_template phy_template_niu_10g_serdes = { | ||
| 2234 | .ops = &phy_ops_10g_serdes_niu, | ||
| 2235 | .phy_addr_base = 0, | ||
| 2236 | }; | ||
| 2237 | |||
| 2238 | static const struct niu_phy_template phy_template_niu_1g_serdes = { | ||
| 2239 | .ops = &phy_ops_1g_serdes_niu, | ||
| 2240 | .phy_addr_base = 0, | ||
| 2241 | }; | ||
| 2242 | |||
| 2006 | static const struct niu_phy_template phy_template_10g_fiber = { | 2243 | static const struct niu_phy_template phy_template_10g_fiber = { |
| 2007 | .ops = &phy_ops_10g_fiber, | 2244 | .ops = &phy_ops_10g_fiber, |
| 2008 | .phy_addr_base = 8, | 2245 | .phy_addr_base = 8, |
| @@ -2182,8 +2419,25 @@ static int niu_determine_phy_disposition(struct niu *np) | |||
| 2182 | u32 phy_addr_off = 0; | 2419 | u32 phy_addr_off = 0; |
| 2183 | 2420 | ||
| 2184 | if (plat_type == PLAT_TYPE_NIU) { | 2421 | if (plat_type == PLAT_TYPE_NIU) { |
| 2185 | tp = &phy_template_niu; | 2422 | switch (np->flags & |
| 2186 | phy_addr_off += np->port; | 2423 | (NIU_FLAGS_10G | |
| 2424 | NIU_FLAGS_FIBER | | ||
| 2425 | NIU_FLAGS_XCVR_SERDES)) { | ||
| 2426 | case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES: | ||
| 2427 | /* 10G Serdes */ | ||
| 2428 | tp = &phy_template_niu_10g_serdes; | ||
| 2429 | break; | ||
| 2430 | case NIU_FLAGS_XCVR_SERDES: | ||
| 2431 | /* 1G Serdes */ | ||
| 2432 | tp = &phy_template_niu_1g_serdes; | ||
| 2433 | break; | ||
| 2434 | case NIU_FLAGS_10G | NIU_FLAGS_FIBER: | ||
| 2435 | /* 10G Fiber */ | ||
| 2436 | default: | ||
| 2437 | tp = &phy_template_niu_10g_fiber; | ||
| 2438 | phy_addr_off += np->port; | ||
| 2439 | break; | ||
| 2440 | } | ||
| 2187 | } else { | 2441 | } else { |
| 2188 | switch (np->flags & | 2442 | switch (np->flags & |
| 2189 | (NIU_FLAGS_10G | | 2443 | (NIU_FLAGS_10G | |
| @@ -7213,6 +7467,12 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np, | |||
| 7213 | np->flags |= NIU_FLAGS_10G; | 7467 | np->flags |= NIU_FLAGS_10G; |
| 7214 | np->flags &= ~NIU_FLAGS_FIBER; | 7468 | np->flags &= ~NIU_FLAGS_FIBER; |
| 7215 | np->mac_xcvr = MAC_XCVR_XPCS; | 7469 | np->mac_xcvr = MAC_XCVR_XPCS; |
| 7470 | } else if (!strcmp(phy_prop, "xgsd") || !strcmp(phy_prop, "gsd")) { | ||
| 7471 | /* 10G Serdes or 1G Serdes, default to 10G */ | ||
| 7472 | np->flags |= NIU_FLAGS_10G; | ||
| 7473 | np->flags &= ~NIU_FLAGS_FIBER; | ||
| 7474 | np->flags |= NIU_FLAGS_XCVR_SERDES; | ||
| 7475 | np->mac_xcvr = MAC_XCVR_XPCS; | ||
| 7216 | } else { | 7476 | } else { |
| 7217 | return -EINVAL; | 7477 | return -EINVAL; |
| 7218 | } | 7478 | } |
| @@ -7741,6 +8001,8 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) | |||
| 7741 | u32 val; | 8001 | u32 val; |
| 7742 | int err; | 8002 | int err; |
| 7743 | 8003 | ||
| 8004 | num_10g = num_1g = 0; | ||
| 8005 | |||
| 7744 | if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) || | 8006 | if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) || |
| 7745 | !strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) { | 8007 | !strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) { |
| 7746 | num_10g = 0; | 8008 | num_10g = 0; |
| @@ -7757,6 +8019,16 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) | |||
| 7757 | parent->num_ports = 2; | 8019 | parent->num_ports = 2; |
| 7758 | val = (phy_encode(PORT_TYPE_10G, 0) | | 8020 | val = (phy_encode(PORT_TYPE_10G, 0) | |
| 7759 | phy_encode(PORT_TYPE_10G, 1)); | 8021 | phy_encode(PORT_TYPE_10G, 1)); |
| 8022 | } else if ((np->flags & NIU_FLAGS_XCVR_SERDES) && | ||
| 8023 | (parent->plat_type == PLAT_TYPE_NIU)) { | ||
| 8024 | /* this is the Monza case */ | ||
| 8025 | if (np->flags & NIU_FLAGS_10G) { | ||
| 8026 | val = (phy_encode(PORT_TYPE_10G, 0) | | ||
| 8027 | phy_encode(PORT_TYPE_10G, 1)); | ||
| 8028 | } else { | ||
| 8029 | val = (phy_encode(PORT_TYPE_1G, 0) | | ||
| 8030 | phy_encode(PORT_TYPE_1G, 1)); | ||
| 8031 | } | ||
| 7760 | } else { | 8032 | } else { |
| 7761 | err = fill_phy_probe_info(np, parent, info); | 8033 | err = fill_phy_probe_info(np, parent, info); |
| 7762 | if (err) | 8034 | if (err) |
| @@ -8656,7 +8928,9 @@ static void __devinit niu_device_announce(struct niu *np) | |||
| 8656 | dev->name, | 8928 | dev->name, |
| 8657 | (np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"), | 8929 | (np->flags & NIU_FLAGS_XMAC ? "XMAC" : "BMAC"), |
| 8658 | (np->flags & NIU_FLAGS_10G ? "10G" : "1G"), | 8930 | (np->flags & NIU_FLAGS_10G ? "10G" : "1G"), |
| 8659 | (np->flags & NIU_FLAGS_FIBER ? "FIBER" : "COPPER"), | 8931 | (np->flags & NIU_FLAGS_FIBER ? "FIBER" : |
| 8932 | (np->flags & NIU_FLAGS_XCVR_SERDES ? "SERDES" : | ||
| 8933 | "COPPER")), | ||
| 8660 | (np->mac_xcvr == MAC_XCVR_MII ? "MII" : | 8934 | (np->mac_xcvr == MAC_XCVR_MII ? "MII" : |
| 8661 | (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")), | 8935 | (np->mac_xcvr == MAC_XCVR_PCS ? "PCS" : "XPCS")), |
| 8662 | np->vpd.phy_type); | 8936 | np->vpd.phy_type); |
diff --git a/drivers/net/niu.h b/drivers/net/niu.h index c6fa883daa22..180ca8ae93de 100644 --- a/drivers/net/niu.h +++ b/drivers/net/niu.h | |||
| @@ -1048,6 +1048,13 @@ | |||
| 1048 | #define PLL_CFG_LD_SHIFT 8 | 1048 | #define PLL_CFG_LD_SHIFT 8 |
| 1049 | #define PLL_CFG_MPY 0x0000001e | 1049 | #define PLL_CFG_MPY 0x0000001e |
| 1050 | #define PLL_CFG_MPY_SHIFT 1 | 1050 | #define PLL_CFG_MPY_SHIFT 1 |
| 1051 | #define PLL_CFG_MPY_4X 0x0 | ||
| 1052 | #define PLL_CFG_MPY_5X 0x00000002 | ||
| 1053 | #define PLL_CFG_MPY_6X 0x00000004 | ||
| 1054 | #define PLL_CFG_MPY_8X 0x00000008 | ||
| 1055 | #define PLL_CFG_MPY_10X 0x0000000a | ||
| 1056 | #define PLL_CFG_MPY_12X 0x0000000c | ||
| 1057 | #define PLL_CFG_MPY_12P5X 0x0000000e | ||
| 1051 | #define PLL_CFG_ENPLL 0x00000001 | 1058 | #define PLL_CFG_ENPLL 0x00000001 |
| 1052 | 1059 | ||
| 1053 | #define ESR2_TI_PLL_STS_L (ESR2_BASE + 0x002) | 1060 | #define ESR2_TI_PLL_STS_L (ESR2_BASE + 0x002) |
| @@ -1093,6 +1100,9 @@ | |||
| 1093 | #define PLL_TX_CFG_INVPAIR 0x00000080 | 1100 | #define PLL_TX_CFG_INVPAIR 0x00000080 |
| 1094 | #define PLL_TX_CFG_RATE 0x00000060 | 1101 | #define PLL_TX_CFG_RATE 0x00000060 |
| 1095 | #define PLL_TX_CFG_RATE_SHIFT 5 | 1102 | #define PLL_TX_CFG_RATE_SHIFT 5 |
| 1103 | #define PLL_TX_CFG_RATE_FULL 0x0 | ||
| 1104 | #define PLL_TX_CFG_RATE_HALF 0x20 | ||
| 1105 | #define PLL_TX_CFG_RATE_QUAD 0x40 | ||
| 1096 | #define PLL_TX_CFG_BUSWIDTH 0x0000001c | 1106 | #define PLL_TX_CFG_BUSWIDTH 0x0000001c |
| 1097 | #define PLL_TX_CFG_BUSWIDTH_SHIFT 2 | 1107 | #define PLL_TX_CFG_BUSWIDTH_SHIFT 2 |
| 1098 | #define PLL_TX_CFG_ENTEST 0x00000002 | 1108 | #define PLL_TX_CFG_ENTEST 0x00000002 |
| @@ -1132,6 +1142,9 @@ | |||
| 1132 | #define PLL_RX_CFG_INVPAIR 0x00000080 | 1142 | #define PLL_RX_CFG_INVPAIR 0x00000080 |
| 1133 | #define PLL_RX_CFG_RATE 0x00000060 | 1143 | #define PLL_RX_CFG_RATE 0x00000060 |
| 1134 | #define PLL_RX_CFG_RATE_SHIFT 5 | 1144 | #define PLL_RX_CFG_RATE_SHIFT 5 |
| 1145 | #define PLL_RX_CFG_RATE_FULL 0x0 | ||
| 1146 | #define PLL_RX_CFG_RATE_HALF 0x20 | ||
| 1147 | #define PLL_RX_CFG_RATE_QUAD 0x40 | ||
| 1135 | #define PLL_RX_CFG_BUSWIDTH 0x0000001c | 1148 | #define PLL_RX_CFG_BUSWIDTH 0x0000001c |
| 1136 | #define PLL_RX_CFG_BUSWIDTH_SHIFT 2 | 1149 | #define PLL_RX_CFG_BUSWIDTH_SHIFT 2 |
| 1137 | #define PLL_RX_CFG_ENTEST 0x00000002 | 1150 | #define PLL_RX_CFG_ENTEST 0x00000002 |
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 4aa547947040..eb6411c4694f 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c | |||
| @@ -227,6 +227,59 @@ static int m88e1111_config_init(struct phy_device *phydev) | |||
| 227 | return 0; | 227 | return 0; |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | static int m88e1118_config_aneg(struct phy_device *phydev) | ||
| 231 | { | ||
| 232 | int err; | ||
| 233 | |||
| 234 | err = phy_write(phydev, MII_BMCR, BMCR_RESET); | ||
| 235 | if (err < 0) | ||
| 236 | return err; | ||
| 237 | |||
| 238 | err = phy_write(phydev, MII_M1011_PHY_SCR, | ||
| 239 | MII_M1011_PHY_SCR_AUTO_CROSS); | ||
| 240 | if (err < 0) | ||
| 241 | return err; | ||
| 242 | |||
| 243 | err = genphy_config_aneg(phydev); | ||
| 244 | return 0; | ||
| 245 | } | ||
| 246 | |||
| 247 | static int m88e1118_config_init(struct phy_device *phydev) | ||
| 248 | { | ||
| 249 | int err; | ||
| 250 | |||
| 251 | /* Change address */ | ||
| 252 | err = phy_write(phydev, 0x16, 0x0002); | ||
| 253 | if (err < 0) | ||
| 254 | return err; | ||
| 255 | |||
| 256 | /* Enable 1000 Mbit */ | ||
| 257 | err = phy_write(phydev, 0x15, 0x1070); | ||
| 258 | if (err < 0) | ||
| 259 | return err; | ||
| 260 | |||
| 261 | /* Change address */ | ||
| 262 | err = phy_write(phydev, 0x16, 0x0003); | ||
| 263 | if (err < 0) | ||
| 264 | return err; | ||
| 265 | |||
| 266 | /* Adjust LED Control */ | ||
| 267 | err = phy_write(phydev, 0x10, 0x021e); | ||
| 268 | if (err < 0) | ||
| 269 | return err; | ||
| 270 | |||
| 271 | /* Reset address */ | ||
| 272 | err = phy_write(phydev, 0x16, 0x0); | ||
| 273 | if (err < 0) | ||
| 274 | return err; | ||
| 275 | |||
| 276 | err = phy_write(phydev, MII_BMCR, BMCR_RESET); | ||
| 277 | if (err < 0) | ||
| 278 | return err; | ||
| 279 | |||
| 280 | return 0; | ||
| 281 | } | ||
| 282 | |||
| 230 | static int m88e1145_config_init(struct phy_device *phydev) | 283 | static int m88e1145_config_init(struct phy_device *phydev) |
| 231 | { | 284 | { |
| 232 | int err; | 285 | int err; |
| @@ -416,6 +469,19 @@ static struct phy_driver marvell_drivers[] = { | |||
| 416 | .driver = { .owner = THIS_MODULE }, | 469 | .driver = { .owner = THIS_MODULE }, |
| 417 | }, | 470 | }, |
| 418 | { | 471 | { |
| 472 | .phy_id = 0x01410e10, | ||
| 473 | .phy_id_mask = 0xfffffff0, | ||
| 474 | .name = "Marvell 88E1118", | ||
| 475 | .features = PHY_GBIT_FEATURES, | ||
| 476 | .flags = PHY_HAS_INTERRUPT, | ||
| 477 | .config_init = &m88e1118_config_init, | ||
| 478 | .config_aneg = &m88e1118_config_aneg, | ||
| 479 | .read_status = &genphy_read_status, | ||
| 480 | .ack_interrupt = &marvell_ack_interrupt, | ||
| 481 | .config_intr = &marvell_config_intr, | ||
| 482 | .driver = {.owner = THIS_MODULE,}, | ||
| 483 | }, | ||
| 484 | { | ||
| 419 | .phy_id = 0x01410cd0, | 485 | .phy_id = 0x01410cd0, |
| 420 | .phy_id_mask = 0xfffffff0, | 486 | .phy_id_mask = 0xfffffff0, |
| 421 | .name = "Marvell 88E1145", | 487 | .name = "Marvell 88E1145", |
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index d0ed1ef284a8..536bda1f428b 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
| @@ -136,7 +136,7 @@ void mdiobus_unregister(struct mii_bus *bus) | |||
| 136 | BUG_ON(bus->state != MDIOBUS_REGISTERED); | 136 | BUG_ON(bus->state != MDIOBUS_REGISTERED); |
| 137 | bus->state = MDIOBUS_UNREGISTERED; | 137 | bus->state = MDIOBUS_UNREGISTERED; |
| 138 | 138 | ||
| 139 | device_unregister(&bus->dev); | 139 | device_del(&bus->dev); |
| 140 | for (i = 0; i < PHY_MAX_ADDR; i++) { | 140 | for (i = 0; i < PHY_MAX_ADDR; i++) { |
| 141 | if (bus->phy_map[i]) | 141 | if (bus->phy_map[i]) |
| 142 | device_unregister(&bus->phy_map[i]->dev); | 142 | device_unregister(&bus->phy_map[i]->dev); |
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index e11b03b2b25a..8fb1faca883a 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
| @@ -227,8 +227,8 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr) | |||
| 227 | if (r) | 227 | if (r) |
| 228 | return ERR_PTR(r); | 228 | return ERR_PTR(r); |
| 229 | 229 | ||
| 230 | /* If the phy_id is all Fs, there is no device there */ | 230 | /* If the phy_id is all Fs or all 0s, there is no device there */ |
| 231 | if (0xffffffff == phy_id) | 231 | if ((0xffff == phy_id) || (0x00 == phy_id)) |
| 232 | return NULL; | 232 | return NULL; |
| 233 | 233 | ||
| 234 | dev = phy_device_create(bus, addr, phy_id); | 234 | dev = phy_device_create(bus, addr, phy_id); |
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index 3cdd07c45b6d..508452c02151 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c | |||
| @@ -1515,9 +1515,6 @@ static u32 ql_get_link_state(struct ql3_adapter *qdev) | |||
| 1515 | linkState = LS_UP; | 1515 | linkState = LS_UP; |
| 1516 | } else { | 1516 | } else { |
| 1517 | linkState = LS_DOWN; | 1517 | linkState = LS_DOWN; |
| 1518 | if (netif_msg_link(qdev)) | ||
| 1519 | printk(KERN_WARNING PFX | ||
| 1520 | "%s: Link is down.\n", qdev->ndev->name); | ||
| 1521 | } | 1518 | } |
| 1522 | return linkState; | 1519 | return linkState; |
| 1523 | } | 1520 | } |
| @@ -1581,10 +1578,6 @@ static int ql_finish_auto_neg(struct ql3_adapter *qdev) | |||
| 1581 | ql_mac_enable(qdev, 1); | 1578 | ql_mac_enable(qdev, 1); |
| 1582 | } | 1579 | } |
| 1583 | 1580 | ||
| 1584 | if (netif_msg_link(qdev)) | ||
| 1585 | printk(KERN_DEBUG PFX | ||
| 1586 | "%s: Change port_link_state LS_DOWN to LS_UP.\n", | ||
| 1587 | qdev->ndev->name); | ||
| 1588 | qdev->port_link_state = LS_UP; | 1581 | qdev->port_link_state = LS_UP; |
| 1589 | netif_start_queue(qdev->ndev); | 1582 | netif_start_queue(qdev->ndev); |
| 1590 | netif_carrier_on(qdev->ndev); | 1583 | netif_carrier_on(qdev->ndev); |
| @@ -1655,14 +1648,9 @@ static void ql_link_state_machine_work(struct work_struct *work) | |||
| 1655 | /* Fall Through */ | 1648 | /* Fall Through */ |
| 1656 | 1649 | ||
| 1657 | case LS_DOWN: | 1650 | case LS_DOWN: |
| 1658 | if (netif_msg_link(qdev)) | ||
| 1659 | printk(KERN_DEBUG PFX | ||
| 1660 | "%s: port_link_state = LS_DOWN.\n", | ||
| 1661 | qdev->ndev->name); | ||
| 1662 | if (curr_link_state == LS_UP) { | 1651 | if (curr_link_state == LS_UP) { |
| 1663 | if (netif_msg_link(qdev)) | 1652 | if (netif_msg_link(qdev)) |
| 1664 | printk(KERN_DEBUG PFX | 1653 | printk(KERN_INFO PFX "%s: Link is up.\n", |
| 1665 | "%s: curr_link_state = LS_UP.\n", | ||
| 1666 | qdev->ndev->name); | 1654 | qdev->ndev->name); |
| 1667 | if (ql_is_auto_neg_complete(qdev)) | 1655 | if (ql_is_auto_neg_complete(qdev)) |
| 1668 | ql_finish_auto_neg(qdev); | 1656 | ql_finish_auto_neg(qdev); |
| @@ -1670,6 +1658,7 @@ static void ql_link_state_machine_work(struct work_struct *work) | |||
| 1670 | if (qdev->port_link_state == LS_UP) | 1658 | if (qdev->port_link_state == LS_UP) |
| 1671 | ql_link_down_detect_clear(qdev); | 1659 | ql_link_down_detect_clear(qdev); |
| 1672 | 1660 | ||
| 1661 | qdev->port_link_state = LS_UP; | ||
| 1673 | } | 1662 | } |
| 1674 | break; | 1663 | break; |
| 1675 | 1664 | ||
| @@ -1678,12 +1667,14 @@ static void ql_link_state_machine_work(struct work_struct *work) | |||
| 1678 | * See if the link is currently down or went down and came | 1667 | * See if the link is currently down or went down and came |
| 1679 | * back up | 1668 | * back up |
| 1680 | */ | 1669 | */ |
| 1681 | if ((curr_link_state == LS_DOWN) || ql_link_down_detect(qdev)) { | 1670 | if (curr_link_state == LS_DOWN) { |
| 1682 | if (netif_msg_link(qdev)) | 1671 | if (netif_msg_link(qdev)) |
| 1683 | printk(KERN_INFO PFX "%s: Link is down.\n", | 1672 | printk(KERN_INFO PFX "%s: Link is down.\n", |
| 1684 | qdev->ndev->name); | 1673 | qdev->ndev->name); |
| 1685 | qdev->port_link_state = LS_DOWN; | 1674 | qdev->port_link_state = LS_DOWN; |
| 1686 | } | 1675 | } |
| 1676 | if (ql_link_down_detect(qdev)) | ||
| 1677 | qdev->port_link_state = LS_DOWN; | ||
| 1687 | break; | 1678 | break; |
| 1688 | } | 1679 | } |
| 1689 | spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); | 1680 | spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); |
diff --git a/drivers/net/ucc_geth_ethtool.c b/drivers/net/ucc_geth_ethtool.c index 85f38a6b6a49..68a7f5414133 100644 --- a/drivers/net/ucc_geth_ethtool.c +++ b/drivers/net/ucc_geth_ethtool.c | |||
| @@ -323,17 +323,17 @@ static void uec_get_ethtool_stats(struct net_device *netdev, | |||
| 323 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) { | 323 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE) { |
| 324 | base = (u32 __iomem *)&ugeth->ug_regs->tx64; | 324 | base = (u32 __iomem *)&ugeth->ug_regs->tx64; |
| 325 | for (i = 0; i < UEC_HW_STATS_LEN; i++) | 325 | for (i = 0; i < UEC_HW_STATS_LEN; i++) |
| 326 | data[j++] = (u64)in_be32(&base[i]); | 326 | data[j++] = in_be32(&base[i]); |
| 327 | } | 327 | } |
| 328 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { | 328 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { |
| 329 | base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram; | 329 | base = (u32 __iomem *)ugeth->p_tx_fw_statistics_pram; |
| 330 | for (i = 0; i < UEC_TX_FW_STATS_LEN; i++) | 330 | for (i = 0; i < UEC_TX_FW_STATS_LEN; i++) |
| 331 | data[j++] = (u64)in_be32(&base[i]); | 331 | data[j++] = base ? in_be32(&base[i]) : 0; |
| 332 | } | 332 | } |
| 333 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { | 333 | if (stats_mode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { |
| 334 | base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram; | 334 | base = (u32 __iomem *)ugeth->p_rx_fw_statistics_pram; |
| 335 | for (i = 0; i < UEC_RX_FW_STATS_LEN; i++) | 335 | for (i = 0; i < UEC_RX_FW_STATS_LEN; i++) |
| 336 | data[j++] = (u64)in_be32(&base[i]); | 336 | data[j++] = base ? in_be32(&base[i]) : 0; |
| 337 | } | 337 | } |
| 338 | } | 338 | } |
| 339 | 339 | ||
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 3590ea5a902d..11cb3e504e1c 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c | |||
| @@ -2296,7 +2296,7 @@ static void velocity_set_multi(struct net_device *dev) | |||
| 2296 | } | 2296 | } |
| 2297 | 2297 | ||
| 2298 | mac_set_cam_mask(regs, vptr->mCAMmask); | 2298 | mac_set_cam_mask(regs, vptr->mCAMmask); |
| 2299 | rx_mode = (RCR_AM | RCR_AB); | 2299 | rx_mode = RCR_AM | RCR_AB | RCR_AP; |
| 2300 | } | 2300 | } |
| 2301 | if (dev->mtu > 1500) | 2301 | if (dev->mtu > 1500) |
| 2302 | rx_mode |= RCR_AL; | 2302 | rx_mode |= RCR_AL; |
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index dcce9f5d8465..4a110b7b2673 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c | |||
| @@ -351,10 +351,11 @@ int verify_cis_cache(struct pcmcia_socket *s) | |||
| 351 | char *buf; | 351 | char *buf; |
| 352 | 352 | ||
| 353 | buf = kmalloc(256, GFP_KERNEL); | 353 | buf = kmalloc(256, GFP_KERNEL); |
| 354 | if (buf == NULL) | 354 | if (buf == NULL) { |
| 355 | dev_printk(KERN_WARNING, &s->dev, | 355 | dev_printk(KERN_WARNING, &s->dev, |
| 356 | "no memory for verifying CIS\n"); | 356 | "no memory for verifying CIS\n"); |
| 357 | return -ENOMEM; | 357 | return -ENOMEM; |
| 358 | } | ||
| 358 | list_for_each_entry(cis, &s->cis_cache, node) { | 359 | list_for_each_entry(cis, &s->cis_cache, node) { |
| 359 | int len = cis->len; | 360 | int len = cis->len; |
| 360 | 361 | ||
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index c68c5d338285..0660ad182589 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
| @@ -186,12 +186,6 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) | |||
| 186 | 186 | ||
| 187 | spin_lock_init(&socket->lock); | 187 | spin_lock_init(&socket->lock); |
| 188 | 188 | ||
| 189 | if (socket->resource_ops->init) { | ||
| 190 | ret = socket->resource_ops->init(socket); | ||
| 191 | if (ret) | ||
| 192 | return (ret); | ||
| 193 | } | ||
| 194 | |||
| 195 | /* try to obtain a socket number [yes, it gets ugly if we | 189 | /* try to obtain a socket number [yes, it gets ugly if we |
| 196 | * register more than 2^sizeof(unsigned int) pcmcia | 190 | * register more than 2^sizeof(unsigned int) pcmcia |
| 197 | * sockets... but the socket number is deprecated | 191 | * sockets... but the socket number is deprecated |
| @@ -226,7 +220,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) | |||
| 226 | /* set proper values in socket->dev */ | 220 | /* set proper values in socket->dev */ |
| 227 | dev_set_drvdata(&socket->dev, socket); | 221 | dev_set_drvdata(&socket->dev, socket); |
| 228 | socket->dev.class = &pcmcia_socket_class; | 222 | socket->dev.class = &pcmcia_socket_class; |
| 229 | snprintf(socket->dev.bus_id, BUS_ID_SIZE, "pcmcia_socket%u", socket->sock); | 223 | dev_set_name(&socket->dev, "pcmcia_socket%u", socket->sock); |
| 230 | 224 | ||
| 231 | /* base address = 0, map = 0 */ | 225 | /* base address = 0, map = 0 */ |
| 232 | socket->cis_mem.flags = 0; | 226 | socket->cis_mem.flags = 0; |
| @@ -239,6 +233,12 @@ int pcmcia_register_socket(struct pcmcia_socket *socket) | |||
| 239 | mutex_init(&socket->skt_mutex); | 233 | mutex_init(&socket->skt_mutex); |
| 240 | spin_lock_init(&socket->thread_lock); | 234 | spin_lock_init(&socket->thread_lock); |
| 241 | 235 | ||
| 236 | if (socket->resource_ops->init) { | ||
| 237 | ret = socket->resource_ops->init(socket); | ||
| 238 | if (ret) | ||
| 239 | goto err; | ||
| 240 | } | ||
| 241 | |||
| 242 | tsk = kthread_run(pccardd, socket, "pccardd"); | 242 | tsk = kthread_run(pccardd, socket, "pccardd"); |
| 243 | if (IS_ERR(tsk)) { | 243 | if (IS_ERR(tsk)) { |
| 244 | ret = PTR_ERR(tsk); | 244 | ret = PTR_ERR(tsk); |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 795660255490..47cab31ff6e4 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
| @@ -622,7 +622,6 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
| 622 | { | 622 | { |
| 623 | struct pcmcia_device *p_dev, *tmp_dev; | 623 | struct pcmcia_device *p_dev, *tmp_dev; |
| 624 | unsigned long flags; | 624 | unsigned long flags; |
| 625 | int bus_id_len; | ||
| 626 | 625 | ||
| 627 | s = pcmcia_get_socket(s); | 626 | s = pcmcia_get_socket(s); |
| 628 | if (!s) | 627 | if (!s) |
| @@ -650,12 +649,12 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
| 650 | /* by default don't allow DMA */ | 649 | /* by default don't allow DMA */ |
| 651 | p_dev->dma_mask = DMA_MASK_NONE; | 650 | p_dev->dma_mask = DMA_MASK_NONE; |
| 652 | p_dev->dev.dma_mask = &p_dev->dma_mask; | 651 | p_dev->dev.dma_mask = &p_dev->dma_mask; |
| 653 | bus_id_len = sprintf (p_dev->dev.bus_id, "%d.%d", p_dev->socket->sock, p_dev->device_no); | 652 | dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no); |
| 654 | 653 | if (!dev_name(&p_dev->dev)) | |
| 655 | p_dev->devname = kmalloc(6 + bus_id_len + 1, GFP_KERNEL); | 654 | goto err_free; |
| 655 | p_dev->devname = kasprintf(GFP_KERNEL, "pcmcia%s", dev_name(&p_dev->dev)); | ||
| 656 | if (!p_dev->devname) | 656 | if (!p_dev->devname) |
| 657 | goto err_free; | 657 | goto err_free; |
| 658 | sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id); | ||
| 659 | ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname); | 658 | ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname); |
| 660 | 659 | ||
| 661 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 660 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
| @@ -668,6 +667,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
| 668 | list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) | 667 | list_for_each_entry(tmp_dev, &s->devices_list, socket_device_list) |
| 669 | if (p_dev->func == tmp_dev->func) { | 668 | if (p_dev->func == tmp_dev->func) { |
| 670 | p_dev->function_config = tmp_dev->function_config; | 669 | p_dev->function_config = tmp_dev->function_config; |
| 670 | p_dev->io = tmp_dev->io; | ||
| 671 | p_dev->irq = tmp_dev->irq; | ||
| 671 | kref_get(&p_dev->function_config->ref); | 672 | kref_get(&p_dev->function_config->ref); |
| 672 | } | 673 | } |
| 673 | 674 | ||
diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 76d4a98f0955..f5d0ba8e22d5 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c | |||
| @@ -302,9 +302,10 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev, | |||
| 302 | /* We only allow changing Vpp1 and Vpp2 to the same value */ | 302 | /* We only allow changing Vpp1 and Vpp2 to the same value */ |
| 303 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && | 303 | if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && |
| 304 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { | 304 | (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { |
| 305 | if (mod->Vpp1 != mod->Vpp2) | 305 | if (mod->Vpp1 != mod->Vpp2) { |
| 306 | ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n"); | 306 | ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n"); |
| 307 | return -EINVAL; | 307 | return -EINVAL; |
| 308 | } | ||
| 308 | s->socket.Vpp = mod->Vpp1; | 309 | s->socket.Vpp = mod->Vpp1; |
| 309 | if (s->ops->set_socket(s, &s->socket)) { | 310 | if (s->ops->set_socket(s, &s->socket)) { |
| 310 | dev_printk(KERN_WARNING, &s->dev, | 311 | dev_printk(KERN_WARNING, &s->dev, |
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 17f4ecf1c0c5..9ca22c7aafb2 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c | |||
| @@ -71,7 +71,7 @@ static DEFINE_MUTEX(rsrc_mutex); | |||
| 71 | ======================================================================*/ | 71 | ======================================================================*/ |
| 72 | 72 | ||
| 73 | static struct resource * | 73 | static struct resource * |
| 74 | make_resource(resource_size_t b, resource_size_t n, int flags, char *name) | 74 | make_resource(resource_size_t b, resource_size_t n, int flags, const char *name) |
| 75 | { | 75 | { |
| 76 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); | 76 | struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); |
| 77 | 77 | ||
| @@ -624,7 +624,7 @@ static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_star | |||
| 624 | static struct resource *nonstatic_find_io_region(unsigned long base, int num, | 624 | static struct resource *nonstatic_find_io_region(unsigned long base, int num, |
| 625 | unsigned long align, struct pcmcia_socket *s) | 625 | unsigned long align, struct pcmcia_socket *s) |
| 626 | { | 626 | { |
| 627 | struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.bus_id); | 627 | struct resource *res = make_resource(0, num, IORESOURCE_IO, dev_name(&s->dev)); |
| 628 | struct socket_data *s_data = s->resource_data; | 628 | struct socket_data *s_data = s->resource_data; |
| 629 | struct pcmcia_align_data data; | 629 | struct pcmcia_align_data data; |
| 630 | unsigned long min = base; | 630 | unsigned long min = base; |
| @@ -658,7 +658,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num, | |||
| 658 | static struct resource * nonstatic_find_mem_region(u_long base, u_long num, | 658 | static struct resource * nonstatic_find_mem_region(u_long base, u_long num, |
| 659 | u_long align, int low, struct pcmcia_socket *s) | 659 | u_long align, int low, struct pcmcia_socket *s) |
| 660 | { | 660 | { |
| 661 | struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.bus_id); | 661 | struct resource *res = make_resource(0, num, IORESOURCE_MEM, dev_name(&s->dev)); |
| 662 | struct socket_data *s_data = s->resource_data; | 662 | struct socket_data *s_data = s->resource_data; |
| 663 | struct pcmcia_align_data data; | 663 | struct pcmcia_align_data data; |
| 664 | unsigned long min, max; | 664 | unsigned long min, max; |
diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c index 2012ccbb4a53..5b2261052a65 100644 --- a/drivers/rtc/rtc-sun4v.c +++ b/drivers/rtc/rtc-sun4v.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* rtc-sun4c.c: Hypervisor based RTC for SUN4V systems. | 1 | /* rtc-sun4v.c: Hypervisor based RTC for SUN4V systems. |
| 2 | * | 2 | * |
| 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> |
| 4 | */ | 4 | */ |
| @@ -7,21 +7,11 @@ | |||
| 7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| 8 | #include <linux/delay.h> | 8 | #include <linux/delay.h> |
| 9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
| 10 | #include <linux/time.h> | ||
| 11 | #include <linux/rtc.h> | 10 | #include <linux/rtc.h> |
| 12 | #include <linux/platform_device.h> | 11 | #include <linux/platform_device.h> |
| 13 | 12 | ||
| 14 | #include <asm/hypervisor.h> | 13 | #include <asm/hypervisor.h> |
| 15 | 14 | ||
| 16 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
| 17 | MODULE_DESCRIPTION("SUN4V RTC driver"); | ||
| 18 | MODULE_LICENSE("GPL"); | ||
| 19 | |||
| 20 | struct sun4v_rtc { | ||
| 21 | struct rtc_device *rtc; | ||
| 22 | spinlock_t lock; | ||
| 23 | }; | ||
| 24 | |||
| 25 | static unsigned long hypervisor_get_time(void) | 15 | static unsigned long hypervisor_get_time(void) |
| 26 | { | 16 | { |
| 27 | unsigned long ret, time; | 17 | unsigned long ret, time; |
| @@ -45,15 +35,7 @@ retry: | |||
| 45 | 35 | ||
| 46 | static int sun4v_read_time(struct device *dev, struct rtc_time *tm) | 36 | static int sun4v_read_time(struct device *dev, struct rtc_time *tm) |
| 47 | { | 37 | { |
| 48 | struct sun4v_rtc *p = dev_get_drvdata(dev); | 38 | rtc_time_to_tm(hypervisor_get_time(), tm); |
| 49 | unsigned long flags, secs; | ||
| 50 | |||
| 51 | spin_lock_irqsave(&p->lock, flags); | ||
| 52 | secs = hypervisor_get_time(); | ||
| 53 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 54 | |||
| 55 | rtc_time_to_tm(secs, tm); | ||
| 56 | |||
| 57 | return 0; | 39 | return 0; |
| 58 | } | 40 | } |
| 59 | 41 | ||
| @@ -80,19 +62,14 @@ retry: | |||
| 80 | 62 | ||
| 81 | static int sun4v_set_time(struct device *dev, struct rtc_time *tm) | 63 | static int sun4v_set_time(struct device *dev, struct rtc_time *tm) |
| 82 | { | 64 | { |
| 83 | struct sun4v_rtc *p = dev_get_drvdata(dev); | 65 | unsigned long secs; |
| 84 | unsigned long flags, secs; | ||
| 85 | int err; | 66 | int err; |
| 86 | 67 | ||
| 87 | err = rtc_tm_to_time(tm, &secs); | 68 | err = rtc_tm_to_time(tm, &secs); |
| 88 | if (err) | 69 | if (err) |
| 89 | return err; | 70 | return err; |
| 90 | 71 | ||
| 91 | spin_lock_irqsave(&p->lock, flags); | 72 | return hypervisor_set_time(secs); |
| 92 | err = hypervisor_set_time(secs); | ||
| 93 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 94 | |||
| 95 | return err; | ||
| 96 | } | 73 | } |
| 97 | 74 | ||
| 98 | static const struct rtc_class_ops sun4v_rtc_ops = { | 75 | static const struct rtc_class_ops sun4v_rtc_ops = { |
| @@ -100,33 +77,22 @@ static const struct rtc_class_ops sun4v_rtc_ops = { | |||
| 100 | .set_time = sun4v_set_time, | 77 | .set_time = sun4v_set_time, |
| 101 | }; | 78 | }; |
| 102 | 79 | ||
| 103 | static int __devinit sun4v_rtc_probe(struct platform_device *pdev) | 80 | static int __init sun4v_rtc_probe(struct platform_device *pdev) |
| 104 | { | 81 | { |
| 105 | struct sun4v_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL); | 82 | struct rtc_device *rtc = rtc_device_register("sun4v", &pdev->dev, |
| 106 | |||
| 107 | if (!p) | ||
| 108 | return -ENOMEM; | ||
| 109 | |||
| 110 | spin_lock_init(&p->lock); | ||
| 111 | |||
| 112 | p->rtc = rtc_device_register("sun4v", &pdev->dev, | ||
| 113 | &sun4v_rtc_ops, THIS_MODULE); | 83 | &sun4v_rtc_ops, THIS_MODULE); |
| 114 | if (IS_ERR(p->rtc)) { | 84 | if (IS_ERR(rtc)) |
| 115 | int err = PTR_ERR(p->rtc); | 85 | return PTR_ERR(rtc); |
| 116 | kfree(p); | 86 | |
| 117 | return err; | 87 | platform_set_drvdata(pdev, rtc); |
| 118 | } | ||
| 119 | platform_set_drvdata(pdev, p); | ||
| 120 | return 0; | 88 | return 0; |
| 121 | } | 89 | } |
| 122 | 90 | ||
| 123 | static int __devexit sun4v_rtc_remove(struct platform_device *pdev) | 91 | static int __exit sun4v_rtc_remove(struct platform_device *pdev) |
| 124 | { | 92 | { |
| 125 | struct sun4v_rtc *p = platform_get_drvdata(pdev); | 93 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
| 126 | |||
| 127 | rtc_device_unregister(p->rtc); | ||
| 128 | kfree(p); | ||
| 129 | 94 | ||
| 95 | rtc_device_unregister(rtc); | ||
| 130 | return 0; | 96 | return 0; |
| 131 | } | 97 | } |
| 132 | 98 | ||
| @@ -135,13 +101,12 @@ static struct platform_driver sun4v_rtc_driver = { | |||
| 135 | .name = "rtc-sun4v", | 101 | .name = "rtc-sun4v", |
| 136 | .owner = THIS_MODULE, | 102 | .owner = THIS_MODULE, |
| 137 | }, | 103 | }, |
| 138 | .probe = sun4v_rtc_probe, | 104 | .remove = __exit_p(sun4v_rtc_remove), |
| 139 | .remove = __devexit_p(sun4v_rtc_remove), | ||
| 140 | }; | 105 | }; |
| 141 | 106 | ||
| 142 | static int __init sun4v_rtc_init(void) | 107 | static int __init sun4v_rtc_init(void) |
| 143 | { | 108 | { |
| 144 | return platform_driver_register(&sun4v_rtc_driver); | 109 | return platform_driver_probe(&sun4v_rtc_driver, sun4v_rtc_probe); |
| 145 | } | 110 | } |
| 146 | 111 | ||
| 147 | static void __exit sun4v_rtc_exit(void) | 112 | static void __exit sun4v_rtc_exit(void) |
| @@ -151,3 +116,7 @@ static void __exit sun4v_rtc_exit(void) | |||
| 151 | 116 | ||
| 152 | module_init(sun4v_rtc_init); | 117 | module_init(sun4v_rtc_init); |
| 153 | module_exit(sun4v_rtc_exit); | 118 | module_exit(sun4v_rtc_exit); |
| 119 | |||
| 120 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
| 121 | MODULE_DESCRIPTION("SUN4V RTC driver"); | ||
| 122 | MODULE_LICENSE("GPL"); | ||
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 69a12aae91d3..490e34bbf27a 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
| @@ -107,12 +107,13 @@ void cifs_dump_mids(struct TCP_Server_Info *server) | |||
| 107 | #ifdef CONFIG_PROC_FS | 107 | #ifdef CONFIG_PROC_FS |
| 108 | static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | 108 | static int cifs_debug_data_proc_show(struct seq_file *m, void *v) |
| 109 | { | 109 | { |
| 110 | struct list_head *tmp; | 110 | struct list_head *tmp1, *tmp2, *tmp3; |
| 111 | struct list_head *tmp1; | ||
| 112 | struct mid_q_entry *mid_entry; | 111 | struct mid_q_entry *mid_entry; |
| 112 | struct TCP_Server_Info *server; | ||
| 113 | struct cifsSesInfo *ses; | 113 | struct cifsSesInfo *ses; |
| 114 | struct cifsTconInfo *tcon; | 114 | struct cifsTconInfo *tcon; |
| 115 | int i; | 115 | int i, j; |
| 116 | __u32 dev_type; | ||
| 116 | 117 | ||
| 117 | seq_puts(m, | 118 | seq_puts(m, |
| 118 | "Display Internal CIFS Data Structures for Debugging\n" | 119 | "Display Internal CIFS Data Structures for Debugging\n" |
| @@ -122,46 +123,78 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
| 122 | seq_printf(m, "Servers:"); | 123 | seq_printf(m, "Servers:"); |
| 123 | 124 | ||
| 124 | i = 0; | 125 | i = 0; |
| 125 | read_lock(&GlobalSMBSeslock); | 126 | read_lock(&cifs_tcp_ses_lock); |
| 126 | list_for_each(tmp, &GlobalSMBSessionList) { | 127 | list_for_each(tmp1, &cifs_tcp_ses_list) { |
| 128 | server = list_entry(tmp1, struct TCP_Server_Info, | ||
| 129 | tcp_ses_list); | ||
| 127 | i++; | 130 | i++; |
| 128 | ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); | 131 | list_for_each(tmp2, &server->smb_ses_list) { |
| 129 | if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) || | 132 | ses = list_entry(tmp2, struct cifsSesInfo, |
| 130 | (ses->serverNOS == NULL)) { | 133 | smb_ses_list); |
| 131 | seq_printf(m, "\nentry for %s not fully " | 134 | if ((ses->serverDomain == NULL) || |
| 132 | "displayed\n\t", ses->serverName); | 135 | (ses->serverOS == NULL) || |
| 133 | } else { | 136 | (ses->serverNOS == NULL)) { |
| 134 | seq_printf(m, | 137 | seq_printf(m, "\n%d) entry for %s not fully " |
| 135 | "\n%d) Name: %s Domain: %s Mounts: %d OS:" | 138 | "displayed\n\t", i, ses->serverName); |
| 136 | " %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB" | 139 | } else { |
| 140 | seq_printf(m, | ||
| 141 | "\n%d) Name: %s Domain: %s Uses: %d OS:" | ||
| 142 | " %s\n\tNOS: %s\tCapability: 0x%x\n\tSMB" | ||
| 137 | " session status: %d\t", | 143 | " session status: %d\t", |
| 138 | i, ses->serverName, ses->serverDomain, | 144 | i, ses->serverName, ses->serverDomain, |
| 139 | atomic_read(&ses->inUse), | 145 | ses->ses_count, ses->serverOS, ses->serverNOS, |
| 140 | ses->serverOS, ses->serverNOS, | ||
| 141 | ses->capabilities, ses->status); | 146 | ses->capabilities, ses->status); |
| 142 | } | 147 | } |
| 143 | if (ses->server) { | ||
| 144 | seq_printf(m, "TCP status: %d\n\tLocal Users To " | 148 | seq_printf(m, "TCP status: %d\n\tLocal Users To " |
| 145 | "Server: %d SecMode: 0x%x Req On Wire: %d", | 149 | "Server: %d SecMode: 0x%x Req On Wire: %d", |
| 146 | ses->server->tcpStatus, | 150 | server->tcpStatus, server->srv_count, |
| 147 | atomic_read(&ses->server->socketUseCount), | 151 | server->secMode, |
| 148 | ses->server->secMode, | 152 | atomic_read(&server->inFlight)); |
| 149 | atomic_read(&ses->server->inFlight)); | ||
| 150 | 153 | ||
| 151 | #ifdef CONFIG_CIFS_STATS2 | 154 | #ifdef CONFIG_CIFS_STATS2 |
| 152 | seq_printf(m, " In Send: %d In MaxReq Wait: %d", | 155 | seq_printf(m, " In Send: %d In MaxReq Wait: %d", |
| 153 | atomic_read(&ses->server->inSend), | 156 | atomic_read(&server->inSend), |
| 154 | atomic_read(&ses->server->num_waiters)); | 157 | atomic_read(&server->num_waiters)); |
| 155 | #endif | 158 | #endif |
| 156 | 159 | ||
| 157 | seq_puts(m, "\nMIDs:\n"); | 160 | seq_puts(m, "\n\tShares:"); |
| 161 | j = 0; | ||
| 162 | list_for_each(tmp3, &ses->tcon_list) { | ||
| 163 | tcon = list_entry(tmp3, struct cifsTconInfo, | ||
| 164 | tcon_list); | ||
| 165 | ++j; | ||
| 166 | dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); | ||
| 167 | seq_printf(m, "\n\t%d) %s Mounts: %d ", j, | ||
| 168 | tcon->treeName, tcon->tc_count); | ||
| 169 | if (tcon->nativeFileSystem) { | ||
| 170 | seq_printf(m, "Type: %s ", | ||
| 171 | tcon->nativeFileSystem); | ||
| 172 | } | ||
| 173 | seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x" | ||
| 174 | "\nPathComponentMax: %d Status: 0x%d", | ||
| 175 | le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), | ||
| 176 | le32_to_cpu(tcon->fsAttrInfo.Attributes), | ||
| 177 | le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), | ||
| 178 | tcon->tidStatus); | ||
| 179 | if (dev_type == FILE_DEVICE_DISK) | ||
| 180 | seq_puts(m, " type: DISK "); | ||
| 181 | else if (dev_type == FILE_DEVICE_CD_ROM) | ||
| 182 | seq_puts(m, " type: CDROM "); | ||
| 183 | else | ||
| 184 | seq_printf(m, " type: %d ", dev_type); | ||
| 185 | |||
| 186 | if (tcon->need_reconnect) | ||
| 187 | seq_puts(m, "\tDISCONNECTED "); | ||
| 188 | seq_putc(m, '\n'); | ||
| 189 | } | ||
| 190 | |||
| 191 | seq_puts(m, "\n\tMIDs:\n"); | ||
| 158 | 192 | ||
| 159 | spin_lock(&GlobalMid_Lock); | 193 | spin_lock(&GlobalMid_Lock); |
| 160 | list_for_each(tmp1, &ses->server->pending_mid_q) { | 194 | list_for_each(tmp3, &server->pending_mid_q) { |
| 161 | mid_entry = list_entry(tmp1, struct | 195 | mid_entry = list_entry(tmp3, struct mid_q_entry, |
| 162 | mid_q_entry, | ||
| 163 | qhead); | 196 | qhead); |
| 164 | seq_printf(m, "State: %d com: %d pid:" | 197 | seq_printf(m, "\tState: %d com: %d pid:" |
| 165 | " %d tsk: %p mid %d\n", | 198 | " %d tsk: %p mid %d\n", |
| 166 | mid_entry->midState, | 199 | mid_entry->midState, |
| 167 | (int)mid_entry->command, | 200 | (int)mid_entry->command, |
| @@ -171,44 +204,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
| 171 | } | 204 | } |
| 172 | spin_unlock(&GlobalMid_Lock); | 205 | spin_unlock(&GlobalMid_Lock); |
| 173 | } | 206 | } |
| 174 | |||
| 175 | } | ||
| 176 | read_unlock(&GlobalSMBSeslock); | ||
| 177 | seq_putc(m, '\n'); | ||
| 178 | |||
| 179 | seq_puts(m, "Shares:"); | ||
| 180 | |||
| 181 | i = 0; | ||
| 182 | read_lock(&GlobalSMBSeslock); | ||
| 183 | list_for_each(tmp, &GlobalTreeConnectionList) { | ||
| 184 | __u32 dev_type; | ||
| 185 | i++; | ||
| 186 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | ||
| 187 | dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); | ||
| 188 | seq_printf(m, "\n%d) %s Uses: %d ", i, | ||
| 189 | tcon->treeName, atomic_read(&tcon->useCount)); | ||
| 190 | if (tcon->nativeFileSystem) { | ||
| 191 | seq_printf(m, "Type: %s ", | ||
| 192 | tcon->nativeFileSystem); | ||
| 193 | } | ||
| 194 | seq_printf(m, "DevInfo: 0x%x Attributes: 0x%x" | ||
| 195 | "\nPathComponentMax: %d Status: %d", | ||
| 196 | le32_to_cpu(tcon->fsDevInfo.DeviceCharacteristics), | ||
| 197 | le32_to_cpu(tcon->fsAttrInfo.Attributes), | ||
| 198 | le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), | ||
| 199 | tcon->tidStatus); | ||
| 200 | if (dev_type == FILE_DEVICE_DISK) | ||
| 201 | seq_puts(m, " type: DISK "); | ||
| 202 | else if (dev_type == FILE_DEVICE_CD_ROM) | ||
| 203 | seq_puts(m, " type: CDROM "); | ||
| 204 | else | ||
| 205 | seq_printf(m, " type: %d ", dev_type); | ||
| 206 | |||
| 207 | if (tcon->tidStatus == CifsNeedReconnect) | ||
| 208 | seq_puts(m, "\tDISCONNECTED "); | ||
| 209 | } | 207 | } |
| 210 | read_unlock(&GlobalSMBSeslock); | 208 | read_unlock(&cifs_tcp_ses_lock); |
| 211 | |||
| 212 | seq_putc(m, '\n'); | 209 | seq_putc(m, '\n'); |
| 213 | 210 | ||
| 214 | /* BB add code to dump additional info such as TCP session info now */ | 211 | /* BB add code to dump additional info such as TCP session info now */ |
| @@ -234,7 +231,9 @@ static ssize_t cifs_stats_proc_write(struct file *file, | |||
| 234 | { | 231 | { |
| 235 | char c; | 232 | char c; |
| 236 | int rc; | 233 | int rc; |
| 237 | struct list_head *tmp; | 234 | struct list_head *tmp1, *tmp2, *tmp3; |
| 235 | struct TCP_Server_Info *server; | ||
| 236 | struct cifsSesInfo *ses; | ||
| 238 | struct cifsTconInfo *tcon; | 237 | struct cifsTconInfo *tcon; |
| 239 | 238 | ||
| 240 | rc = get_user(c, buffer); | 239 | rc = get_user(c, buffer); |
| @@ -242,33 +241,42 @@ static ssize_t cifs_stats_proc_write(struct file *file, | |||
| 242 | return rc; | 241 | return rc; |
| 243 | 242 | ||
| 244 | if (c == '1' || c == 'y' || c == 'Y' || c == '0') { | 243 | if (c == '1' || c == 'y' || c == 'Y' || c == '0') { |
| 245 | read_lock(&GlobalSMBSeslock); | ||
| 246 | #ifdef CONFIG_CIFS_STATS2 | 244 | #ifdef CONFIG_CIFS_STATS2 |
| 247 | atomic_set(&totBufAllocCount, 0); | 245 | atomic_set(&totBufAllocCount, 0); |
| 248 | atomic_set(&totSmBufAllocCount, 0); | 246 | atomic_set(&totSmBufAllocCount, 0); |
| 249 | #endif /* CONFIG_CIFS_STATS2 */ | 247 | #endif /* CONFIG_CIFS_STATS2 */ |
| 250 | list_for_each(tmp, &GlobalTreeConnectionList) { | 248 | read_lock(&cifs_tcp_ses_lock); |
| 251 | tcon = list_entry(tmp, struct cifsTconInfo, | 249 | list_for_each(tmp1, &cifs_tcp_ses_list) { |
| 252 | cifsConnectionList); | 250 | server = list_entry(tmp1, struct TCP_Server_Info, |
| 253 | atomic_set(&tcon->num_smbs_sent, 0); | 251 | tcp_ses_list); |
| 254 | atomic_set(&tcon->num_writes, 0); | 252 | list_for_each(tmp2, &server->smb_ses_list) { |
| 255 | atomic_set(&tcon->num_reads, 0); | 253 | ses = list_entry(tmp2, struct cifsSesInfo, |
| 256 | atomic_set(&tcon->num_oplock_brks, 0); | 254 | smb_ses_list); |
| 257 | atomic_set(&tcon->num_opens, 0); | 255 | list_for_each(tmp3, &ses->tcon_list) { |
| 258 | atomic_set(&tcon->num_closes, 0); | 256 | tcon = list_entry(tmp3, |
| 259 | atomic_set(&tcon->num_deletes, 0); | 257 | struct cifsTconInfo, |
| 260 | atomic_set(&tcon->num_mkdirs, 0); | 258 | tcon_list); |
| 261 | atomic_set(&tcon->num_rmdirs, 0); | 259 | atomic_set(&tcon->num_smbs_sent, 0); |
| 262 | atomic_set(&tcon->num_renames, 0); | 260 | atomic_set(&tcon->num_writes, 0); |
| 263 | atomic_set(&tcon->num_t2renames, 0); | 261 | atomic_set(&tcon->num_reads, 0); |
| 264 | atomic_set(&tcon->num_ffirst, 0); | 262 | atomic_set(&tcon->num_oplock_brks, 0); |
| 265 | atomic_set(&tcon->num_fnext, 0); | 263 | atomic_set(&tcon->num_opens, 0); |
| 266 | atomic_set(&tcon->num_fclose, 0); | 264 | atomic_set(&tcon->num_closes, 0); |
| 267 | atomic_set(&tcon->num_hardlinks, 0); | 265 | atomic_set(&tcon->num_deletes, 0); |
| 268 | atomic_set(&tcon->num_symlinks, 0); | 266 | atomic_set(&tcon->num_mkdirs, 0); |
| 269 | atomic_set(&tcon->num_locks, 0); | 267 | atomic_set(&tcon->num_rmdirs, 0); |
| 268 | atomic_set(&tcon->num_renames, 0); | ||
| 269 | atomic_set(&tcon->num_t2renames, 0); | ||
| 270 | atomic_set(&tcon->num_ffirst, 0); | ||
| 271 | atomic_set(&tcon->num_fnext, 0); | ||
| 272 | atomic_set(&tcon->num_fclose, 0); | ||
| 273 | atomic_set(&tcon->num_hardlinks, 0); | ||
| 274 | atomic_set(&tcon->num_symlinks, 0); | ||
| 275 | atomic_set(&tcon->num_locks, 0); | ||
| 276 | } | ||
| 277 | } | ||
| 270 | } | 278 | } |
| 271 | read_unlock(&GlobalSMBSeslock); | 279 | read_unlock(&cifs_tcp_ses_lock); |
| 272 | } | 280 | } |
| 273 | 281 | ||
| 274 | return count; | 282 | return count; |
| @@ -277,7 +285,9 @@ static ssize_t cifs_stats_proc_write(struct file *file, | |||
| 277 | static int cifs_stats_proc_show(struct seq_file *m, void *v) | 285 | static int cifs_stats_proc_show(struct seq_file *m, void *v) |
| 278 | { | 286 | { |
| 279 | int i; | 287 | int i; |
| 280 | struct list_head *tmp; | 288 | struct list_head *tmp1, *tmp2, *tmp3; |
| 289 | struct TCP_Server_Info *server; | ||
| 290 | struct cifsSesInfo *ses; | ||
| 281 | struct cifsTconInfo *tcon; | 291 | struct cifsTconInfo *tcon; |
| 282 | 292 | ||
| 283 | seq_printf(m, | 293 | seq_printf(m, |
| @@ -306,44 +316,55 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v) | |||
| 306 | GlobalCurrentXid, GlobalMaxActiveXid); | 316 | GlobalCurrentXid, GlobalMaxActiveXid); |
| 307 | 317 | ||
| 308 | i = 0; | 318 | i = 0; |
| 309 | read_lock(&GlobalSMBSeslock); | 319 | read_lock(&cifs_tcp_ses_lock); |
| 310 | list_for_each(tmp, &GlobalTreeConnectionList) { | 320 | list_for_each(tmp1, &cifs_tcp_ses_list) { |
| 311 | i++; | 321 | server = list_entry(tmp1, struct TCP_Server_Info, |
| 312 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | 322 | tcp_ses_list); |
| 313 | seq_printf(m, "\n%d) %s", i, tcon->treeName); | 323 | list_for_each(tmp2, &server->smb_ses_list) { |
| 314 | if (tcon->tidStatus == CifsNeedReconnect) | 324 | ses = list_entry(tmp2, struct cifsSesInfo, |
| 315 | seq_puts(m, "\tDISCONNECTED "); | 325 | smb_ses_list); |
| 316 | seq_printf(m, "\nSMBs: %d Oplock Breaks: %d", | 326 | list_for_each(tmp3, &ses->tcon_list) { |
| 317 | atomic_read(&tcon->num_smbs_sent), | 327 | tcon = list_entry(tmp3, |
| 318 | atomic_read(&tcon->num_oplock_brks)); | 328 | struct cifsTconInfo, |
| 319 | seq_printf(m, "\nReads: %d Bytes: %lld", | 329 | tcon_list); |
| 320 | atomic_read(&tcon->num_reads), | 330 | i++; |
| 321 | (long long)(tcon->bytes_read)); | 331 | seq_printf(m, "\n%d) %s", i, tcon->treeName); |
| 322 | seq_printf(m, "\nWrites: %d Bytes: %lld", | 332 | if (tcon->need_reconnect) |
| 323 | atomic_read(&tcon->num_writes), | 333 | seq_puts(m, "\tDISCONNECTED "); |
| 324 | (long long)(tcon->bytes_written)); | 334 | seq_printf(m, "\nSMBs: %d Oplock Breaks: %d", |
| 325 | seq_printf(m, | 335 | atomic_read(&tcon->num_smbs_sent), |
| 326 | "\nLocks: %d HardLinks: %d Symlinks: %d", | 336 | atomic_read(&tcon->num_oplock_brks)); |
| 327 | atomic_read(&tcon->num_locks), | 337 | seq_printf(m, "\nReads: %d Bytes: %lld", |
| 328 | atomic_read(&tcon->num_hardlinks), | 338 | atomic_read(&tcon->num_reads), |
| 329 | atomic_read(&tcon->num_symlinks)); | 339 | (long long)(tcon->bytes_read)); |
| 330 | 340 | seq_printf(m, "\nWrites: %d Bytes: %lld", | |
| 331 | seq_printf(m, "\nOpens: %d Closes: %d Deletes: %d", | 341 | atomic_read(&tcon->num_writes), |
| 332 | atomic_read(&tcon->num_opens), | 342 | (long long)(tcon->bytes_written)); |
| 333 | atomic_read(&tcon->num_closes), | 343 | seq_printf(m, "\nLocks: %d HardLinks: %d " |
| 334 | atomic_read(&tcon->num_deletes)); | 344 | "Symlinks: %d", |
| 335 | seq_printf(m, "\nMkdirs: %d Rmdirs: %d", | 345 | atomic_read(&tcon->num_locks), |
| 336 | atomic_read(&tcon->num_mkdirs), | 346 | atomic_read(&tcon->num_hardlinks), |
| 337 | atomic_read(&tcon->num_rmdirs)); | 347 | atomic_read(&tcon->num_symlinks)); |
| 338 | seq_printf(m, "\nRenames: %d T2 Renames %d", | 348 | seq_printf(m, "\nOpens: %d Closes: %d" |
| 339 | atomic_read(&tcon->num_renames), | 349 | "Deletes: %d", |
| 340 | atomic_read(&tcon->num_t2renames)); | 350 | atomic_read(&tcon->num_opens), |
| 341 | seq_printf(m, "\nFindFirst: %d FNext %d FClose %d", | 351 | atomic_read(&tcon->num_closes), |
| 342 | atomic_read(&tcon->num_ffirst), | 352 | atomic_read(&tcon->num_deletes)); |
| 343 | atomic_read(&tcon->num_fnext), | 353 | seq_printf(m, "\nMkdirs: %d Rmdirs: %d", |
| 344 | atomic_read(&tcon->num_fclose)); | 354 | atomic_read(&tcon->num_mkdirs), |
| 355 | atomic_read(&tcon->num_rmdirs)); | ||
| 356 | seq_printf(m, "\nRenames: %d T2 Renames %d", | ||
| 357 | atomic_read(&tcon->num_renames), | ||
| 358 | atomic_read(&tcon->num_t2renames)); | ||
| 359 | seq_printf(m, "\nFindFirst: %d FNext %d " | ||
| 360 | "FClose %d", | ||
| 361 | atomic_read(&tcon->num_ffirst), | ||
| 362 | atomic_read(&tcon->num_fnext), | ||
| 363 | atomic_read(&tcon->num_fclose)); | ||
| 364 | } | ||
| 365 | } | ||
| 345 | } | 366 | } |
| 346 | read_unlock(&GlobalSMBSeslock); | 367 | read_unlock(&cifs_tcp_ses_lock); |
| 347 | 368 | ||
| 348 | seq_putc(m, '\n'); | 369 | seq_putc(m, '\n'); |
| 349 | return 0; | 370 | return 0; |
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index d2c8eef84f3c..e1c18362ba46 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
| @@ -106,7 +106,8 @@ static char *cifs_get_share_name(const char *node_name) | |||
| 106 | /** | 106 | /** |
| 107 | * compose_mount_options - creates mount options for refferral | 107 | * compose_mount_options - creates mount options for refferral |
| 108 | * @sb_mountdata: parent/root DFS mount options (template) | 108 | * @sb_mountdata: parent/root DFS mount options (template) |
| 109 | * @ref_unc: refferral server UNC | 109 | * @dentry: point where we are going to mount |
| 110 | * @ref: server's referral | ||
| 110 | * @devname: pointer for saving device name | 111 | * @devname: pointer for saving device name |
| 111 | * | 112 | * |
| 112 | * creates mount options for submount based on template options sb_mountdata | 113 | * creates mount options for submount based on template options sb_mountdata |
| @@ -116,7 +117,8 @@ static char *cifs_get_share_name(const char *node_name) | |||
| 116 | * Caller is responcible for freeing retunrned value if it is not error. | 117 | * Caller is responcible for freeing retunrned value if it is not error. |
| 117 | */ | 118 | */ |
| 118 | static char *compose_mount_options(const char *sb_mountdata, | 119 | static char *compose_mount_options(const char *sb_mountdata, |
| 119 | const char *ref_unc, | 120 | struct dentry *dentry, |
| 121 | const struct dfs_info3_param *ref, | ||
| 120 | char **devname) | 122 | char **devname) |
| 121 | { | 123 | { |
| 122 | int rc; | 124 | int rc; |
| @@ -126,11 +128,12 @@ static char *compose_mount_options(const char *sb_mountdata, | |||
| 126 | char *srvIP = NULL; | 128 | char *srvIP = NULL; |
| 127 | char sep = ','; | 129 | char sep = ','; |
| 128 | int off, noff; | 130 | int off, noff; |
| 131 | char *fullpath; | ||
| 129 | 132 | ||
| 130 | if (sb_mountdata == NULL) | 133 | if (sb_mountdata == NULL) |
| 131 | return ERR_PTR(-EINVAL); | 134 | return ERR_PTR(-EINVAL); |
| 132 | 135 | ||
| 133 | *devname = cifs_get_share_name(ref_unc); | 136 | *devname = cifs_get_share_name(ref->node_name); |
| 134 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); | 137 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); |
| 135 | if (rc != 0) { | 138 | if (rc != 0) { |
| 136 | cERROR(1, ("%s: Failed to resolve server part of %s to IP", | 139 | cERROR(1, ("%s: Failed to resolve server part of %s to IP", |
| @@ -138,7 +141,12 @@ static char *compose_mount_options(const char *sb_mountdata, | |||
| 138 | mountdata = ERR_PTR(rc); | 141 | mountdata = ERR_PTR(rc); |
| 139 | goto compose_mount_options_out; | 142 | goto compose_mount_options_out; |
| 140 | } | 143 | } |
| 141 | md_len = strlen(sb_mountdata) + strlen(srvIP) + strlen(ref_unc) + 3; | 144 | /* md_len = strlen(...) + 12 for 'sep+prefixpath=' |
| 145 | * assuming that we have 'unc=' and 'ip=' in | ||
| 146 | * the original sb_mountdata | ||
| 147 | */ | ||
| 148 | md_len = strlen(sb_mountdata) + strlen(srvIP) + | ||
| 149 | strlen(ref->node_name) + 12; | ||
| 142 | mountdata = kzalloc(md_len+1, GFP_KERNEL); | 150 | mountdata = kzalloc(md_len+1, GFP_KERNEL); |
| 143 | if (mountdata == NULL) { | 151 | if (mountdata == NULL) { |
| 144 | mountdata = ERR_PTR(-ENOMEM); | 152 | mountdata = ERR_PTR(-ENOMEM); |
| @@ -152,41 +160,56 @@ static char *compose_mount_options(const char *sb_mountdata, | |||
| 152 | strncpy(mountdata, sb_mountdata, 5); | 160 | strncpy(mountdata, sb_mountdata, 5); |
| 153 | off += 5; | 161 | off += 5; |
| 154 | } | 162 | } |
| 155 | while ((tkn_e = strchr(sb_mountdata+off, sep))) { | 163 | |
| 156 | noff = (tkn_e - (sb_mountdata+off)) + 1; | 164 | do { |
| 157 | if (strnicmp(sb_mountdata+off, "unc=", 4) == 0) { | 165 | tkn_e = strchr(sb_mountdata + off, sep); |
| 166 | if (tkn_e == NULL) | ||
| 167 | noff = strlen(sb_mountdata + off); | ||
| 168 | else | ||
| 169 | noff = tkn_e - (sb_mountdata + off) + 1; | ||
| 170 | |||
| 171 | if (strnicmp(sb_mountdata + off, "unc=", 4) == 0) { | ||
| 158 | off += noff; | 172 | off += noff; |
| 159 | continue; | 173 | continue; |
| 160 | } | 174 | } |
| 161 | if (strnicmp(sb_mountdata+off, "ip=", 3) == 0) { | 175 | if (strnicmp(sb_mountdata + off, "ip=", 3) == 0) { |
| 162 | off += noff; | 176 | off += noff; |
| 163 | continue; | 177 | continue; |
| 164 | } | 178 | } |
| 165 | if (strnicmp(sb_mountdata+off, "prefixpath=", 3) == 0) { | 179 | if (strnicmp(sb_mountdata + off, "prefixpath=", 11) == 0) { |
| 166 | off += noff; | 180 | off += noff; |
| 167 | continue; | 181 | continue; |
| 168 | } | 182 | } |
| 169 | strncat(mountdata, sb_mountdata+off, noff); | 183 | strncat(mountdata, sb_mountdata + off, noff); |
| 170 | off += noff; | 184 | off += noff; |
| 171 | } | 185 | } while (tkn_e); |
| 172 | strcat(mountdata, sb_mountdata+off); | 186 | strcat(mountdata, sb_mountdata + off); |
| 173 | mountdata[md_len] = '\0'; | 187 | mountdata[md_len] = '\0'; |
| 174 | 188 | ||
| 175 | /* copy new IP and ref share name */ | 189 | /* copy new IP and ref share name */ |
| 176 | strcat(mountdata, ",ip="); | 190 | if (mountdata[strlen(mountdata) - 1] != sep) |
| 191 | strncat(mountdata, &sep, 1); | ||
| 192 | strcat(mountdata, "ip="); | ||
| 177 | strcat(mountdata, srvIP); | 193 | strcat(mountdata, srvIP); |
| 178 | strcat(mountdata, ",unc="); | 194 | strncat(mountdata, &sep, 1); |
| 195 | strcat(mountdata, "unc="); | ||
| 179 | strcat(mountdata, *devname); | 196 | strcat(mountdata, *devname); |
| 180 | 197 | ||
| 181 | /* find & copy prefixpath */ | 198 | /* find & copy prefixpath */ |
| 182 | tkn_e = strchr(ref_unc+2, '\\'); | 199 | tkn_e = strchr(ref->node_name + 2, '\\'); |
| 183 | if (tkn_e) { | 200 | if (tkn_e == NULL) /* invalid unc, missing share name*/ |
| 184 | tkn_e = strchr(tkn_e+1, '\\'); | 201 | goto compose_mount_options_out; |
| 185 | if (tkn_e) { | 202 | |
| 186 | strcat(mountdata, ",prefixpath="); | 203 | fullpath = build_path_from_dentry(dentry); |
| 187 | strcat(mountdata, tkn_e+1); | 204 | tkn_e = strchr(tkn_e + 1, '\\'); |
| 188 | } | 205 | if (tkn_e || strlen(fullpath) - (ref->path_consumed)) { |
| 206 | strncat(mountdata, &sep, 1); | ||
| 207 | strcat(mountdata, "prefixpath="); | ||
| 208 | if (tkn_e) | ||
| 209 | strcat(mountdata, tkn_e + 1); | ||
| 210 | strcat(mountdata, fullpath + (ref->path_consumed)); | ||
| 189 | } | 211 | } |
| 212 | kfree(fullpath); | ||
| 190 | 213 | ||
| 191 | /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/ | 214 | /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/ |
| 192 | /*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/ | 215 | /*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/ |
| @@ -198,7 +221,7 @@ compose_mount_options_out: | |||
| 198 | 221 | ||
| 199 | 222 | ||
| 200 | static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent, | 223 | static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent, |
| 201 | struct dentry *dentry, char *ref_unc) | 224 | struct dentry *dentry, const struct dfs_info3_param *ref) |
| 202 | { | 225 | { |
| 203 | struct cifs_sb_info *cifs_sb; | 226 | struct cifs_sb_info *cifs_sb; |
| 204 | struct vfsmount *mnt; | 227 | struct vfsmount *mnt; |
| @@ -207,7 +230,7 @@ static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent, | |||
| 207 | 230 | ||
| 208 | cifs_sb = CIFS_SB(dentry->d_inode->i_sb); | 231 | cifs_sb = CIFS_SB(dentry->d_inode->i_sb); |
| 209 | mountdata = compose_mount_options(cifs_sb->mountdata, | 232 | mountdata = compose_mount_options(cifs_sb->mountdata, |
| 210 | ref_unc, &devname); | 233 | dentry, ref, &devname); |
| 211 | 234 | ||
| 212 | if (IS_ERR(mountdata)) | 235 | if (IS_ERR(mountdata)) |
| 213 | return (struct vfsmount *)mountdata; | 236 | return (struct vfsmount *)mountdata; |
| @@ -310,7 +333,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
| 310 | } | 333 | } |
| 311 | mnt = cifs_dfs_do_refmount(nd->path.mnt, | 334 | mnt = cifs_dfs_do_refmount(nd->path.mnt, |
| 312 | nd->path.dentry, | 335 | nd->path.dentry, |
| 313 | referrals[i].node_name); | 336 | referrals + i); |
| 314 | cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", | 337 | cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", |
| 315 | __func__, | 338 | __func__, |
| 316 | referrals[i].node_name, mnt)); | 339 | referrals[i].node_name, mnt)); |
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index fcee9298b620..0ab2fb5afef1 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
| @@ -73,8 +73,8 @@ struct key_type cifs_spnego_key_type = { | |||
| 73 | * strlen(";sec=ntlmsspi") */ | 73 | * strlen(";sec=ntlmsspi") */ |
| 74 | #define MAX_MECH_STR_LEN 13 | 74 | #define MAX_MECH_STR_LEN 13 |
| 75 | 75 | ||
| 76 | /* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/60 */ | 76 | /* max possible addr len eg FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/128 */ |
| 77 | #define MAX_IPV6_ADDR_LEN 42 | 77 | #define MAX_IPV6_ADDR_LEN 43 |
| 78 | 78 | ||
| 79 | /* strlen of "host=" */ | 79 | /* strlen of "host=" */ |
| 80 | #define HOST_KEY_LEN 5 | 80 | #define HOST_KEY_LEN 5 |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ac5915d61dca..d9cf467309e8 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -514,10 +514,11 @@ static void cifs_umount_begin(struct super_block *sb) | |||
| 514 | tcon = cifs_sb->tcon; | 514 | tcon = cifs_sb->tcon; |
| 515 | if (tcon == NULL) | 515 | if (tcon == NULL) |
| 516 | return; | 516 | return; |
| 517 | down(&tcon->tconSem); | 517 | |
| 518 | if (atomic_read(&tcon->useCount) == 1) | 518 | read_lock(&cifs_tcp_ses_lock); |
| 519 | if (tcon->tc_count == 1) | ||
| 519 | tcon->tidStatus = CifsExiting; | 520 | tcon->tidStatus = CifsExiting; |
| 520 | up(&tcon->tconSem); | 521 | read_unlock(&cifs_tcp_ses_lock); |
| 521 | 522 | ||
| 522 | /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */ | 523 | /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */ |
| 523 | /* cancel_notify_requests(tcon); */ | 524 | /* cancel_notify_requests(tcon); */ |
| @@ -1013,7 +1014,7 @@ static int cifs_oplock_thread(void *dummyarg) | |||
| 1013 | not bother sending an oplock release if session | 1014 | not bother sending an oplock release if session |
| 1014 | to server still is disconnected since oplock | 1015 | to server still is disconnected since oplock |
| 1015 | already released by the server in that case */ | 1016 | already released by the server in that case */ |
| 1016 | if (pTcon->tidStatus != CifsNeedReconnect) { | 1017 | if (!pTcon->need_reconnect) { |
| 1017 | rc = CIFSSMBLock(0, pTcon, netfid, | 1018 | rc = CIFSSMBLock(0, pTcon, netfid, |
| 1018 | 0 /* len */ , 0 /* offset */, 0, | 1019 | 0 /* len */ , 0 /* offset */, 0, |
| 1019 | 0, LOCKING_ANDX_OPLOCK_RELEASE, | 1020 | 0, LOCKING_ANDX_OPLOCK_RELEASE, |
| @@ -1031,24 +1032,24 @@ static int cifs_oplock_thread(void *dummyarg) | |||
| 1031 | static int cifs_dnotify_thread(void *dummyarg) | 1032 | static int cifs_dnotify_thread(void *dummyarg) |
| 1032 | { | 1033 | { |
| 1033 | struct list_head *tmp; | 1034 | struct list_head *tmp; |
| 1034 | struct cifsSesInfo *ses; | 1035 | struct TCP_Server_Info *server; |
| 1035 | 1036 | ||
| 1036 | do { | 1037 | do { |
| 1037 | if (try_to_freeze()) | 1038 | if (try_to_freeze()) |
| 1038 | continue; | 1039 | continue; |
| 1039 | set_current_state(TASK_INTERRUPTIBLE); | 1040 | set_current_state(TASK_INTERRUPTIBLE); |
| 1040 | schedule_timeout(15*HZ); | 1041 | schedule_timeout(15*HZ); |
| 1041 | read_lock(&GlobalSMBSeslock); | ||
| 1042 | /* check if any stuck requests that need | 1042 | /* check if any stuck requests that need |
| 1043 | to be woken up and wakeq so the | 1043 | to be woken up and wakeq so the |
| 1044 | thread can wake up and error out */ | 1044 | thread can wake up and error out */ |
| 1045 | list_for_each(tmp, &GlobalSMBSessionList) { | 1045 | read_lock(&cifs_tcp_ses_lock); |
| 1046 | ses = list_entry(tmp, struct cifsSesInfo, | 1046 | list_for_each(tmp, &cifs_tcp_ses_list) { |
| 1047 | cifsSessionList); | 1047 | server = list_entry(tmp, struct TCP_Server_Info, |
| 1048 | if (ses->server && atomic_read(&ses->server->inFlight)) | 1048 | tcp_ses_list); |
| 1049 | wake_up_all(&ses->server->response_q); | 1049 | if (atomic_read(&server->inFlight)) |
| 1050 | wake_up_all(&server->response_q); | ||
| 1050 | } | 1051 | } |
| 1051 | read_unlock(&GlobalSMBSeslock); | 1052 | read_unlock(&cifs_tcp_ses_lock); |
| 1052 | } while (!kthread_should_stop()); | 1053 | } while (!kthread_should_stop()); |
| 1053 | 1054 | ||
| 1054 | return 0; | 1055 | return 0; |
| @@ -1059,9 +1060,7 @@ init_cifs(void) | |||
| 1059 | { | 1060 | { |
| 1060 | int rc = 0; | 1061 | int rc = 0; |
| 1061 | cifs_proc_init(); | 1062 | cifs_proc_init(); |
| 1062 | /* INIT_LIST_HEAD(&GlobalServerList);*/ /* BB not implemented yet */ | 1063 | INIT_LIST_HEAD(&cifs_tcp_ses_list); |
| 1063 | INIT_LIST_HEAD(&GlobalSMBSessionList); | ||
| 1064 | INIT_LIST_HEAD(&GlobalTreeConnectionList); | ||
| 1065 | INIT_LIST_HEAD(&GlobalOplock_Q); | 1064 | INIT_LIST_HEAD(&GlobalOplock_Q); |
| 1066 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1065 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 1067 | INIT_LIST_HEAD(&GlobalDnotifyReqList); | 1066 | INIT_LIST_HEAD(&GlobalDnotifyReqList); |
| @@ -1089,6 +1088,7 @@ init_cifs(void) | |||
| 1089 | GlobalMaxActiveXid = 0; | 1088 | GlobalMaxActiveXid = 0; |
| 1090 | memset(Local_System_Name, 0, 15); | 1089 | memset(Local_System_Name, 0, 15); |
| 1091 | rwlock_init(&GlobalSMBSeslock); | 1090 | rwlock_init(&GlobalSMBSeslock); |
| 1091 | rwlock_init(&cifs_tcp_ses_lock); | ||
| 1092 | spin_lock_init(&GlobalMid_Lock); | 1092 | spin_lock_init(&GlobalMid_Lock); |
| 1093 | 1093 | ||
| 1094 | if (cifs_max_pending < 2) { | 1094 | if (cifs_max_pending < 2) { |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 1cb1189f24e0..f1ae1f57c30d 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -85,8 +85,7 @@ enum securityEnum { | |||
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | enum protocolEnum { | 87 | enum protocolEnum { |
| 88 | IPV4 = 0, | 88 | TCP = 0, |
| 89 | IPV6, | ||
| 90 | SCTP | 89 | SCTP |
| 91 | /* Netbios frames protocol not supported at this time */ | 90 | /* Netbios frames protocol not supported at this time */ |
| 92 | }; | 91 | }; |
| @@ -122,6 +121,9 @@ struct cifs_cred { | |||
| 122 | */ | 121 | */ |
| 123 | 122 | ||
| 124 | struct TCP_Server_Info { | 123 | struct TCP_Server_Info { |
| 124 | struct list_head tcp_ses_list; | ||
| 125 | struct list_head smb_ses_list; | ||
| 126 | int srv_count; /* reference counter */ | ||
| 125 | /* 15 character server name + 0x20 16th byte indicating type = srv */ | 127 | /* 15 character server name + 0x20 16th byte indicating type = srv */ |
| 126 | char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; | 128 | char server_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; |
| 127 | char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; | 129 | char unicode_server_Name[SERVER_NAME_LEN_WITH_NULL * 2]; |
| @@ -143,7 +145,6 @@ struct TCP_Server_Info { | |||
| 143 | bool svlocal:1; /* local server or remote */ | 145 | bool svlocal:1; /* local server or remote */ |
| 144 | bool noblocksnd; /* use blocking sendmsg */ | 146 | bool noblocksnd; /* use blocking sendmsg */ |
| 145 | bool noautotune; /* do not autotune send buf sizes */ | 147 | bool noautotune; /* do not autotune send buf sizes */ |
| 146 | atomic_t socketUseCount; /* number of open cifs sessions on socket */ | ||
| 147 | atomic_t inFlight; /* number of requests on the wire to server */ | 148 | atomic_t inFlight; /* number of requests on the wire to server */ |
| 148 | #ifdef CONFIG_CIFS_STATS2 | 149 | #ifdef CONFIG_CIFS_STATS2 |
| 149 | atomic_t inSend; /* requests trying to send */ | 150 | atomic_t inSend; /* requests trying to send */ |
| @@ -194,13 +195,14 @@ struct cifsUidInfo { | |||
| 194 | * Session structure. One of these for each uid session with a particular host | 195 | * Session structure. One of these for each uid session with a particular host |
| 195 | */ | 196 | */ |
| 196 | struct cifsSesInfo { | 197 | struct cifsSesInfo { |
| 197 | struct list_head cifsSessionList; | 198 | struct list_head smb_ses_list; |
| 199 | struct list_head tcon_list; | ||
| 198 | struct semaphore sesSem; | 200 | struct semaphore sesSem; |
| 199 | #if 0 | 201 | #if 0 |
| 200 | struct cifsUidInfo *uidInfo; /* pointer to user info */ | 202 | struct cifsUidInfo *uidInfo; /* pointer to user info */ |
| 201 | #endif | 203 | #endif |
| 202 | struct TCP_Server_Info *server; /* pointer to server info */ | 204 | struct TCP_Server_Info *server; /* pointer to server info */ |
| 203 | atomic_t inUse; /* # of mounts (tree connections) on this ses */ | 205 | int ses_count; /* reference counter */ |
| 204 | enum statusEnum status; | 206 | enum statusEnum status; |
| 205 | unsigned overrideSecFlg; /* if non-zero override global sec flags */ | 207 | unsigned overrideSecFlg; /* if non-zero override global sec flags */ |
| 206 | __u16 ipc_tid; /* special tid for connection to IPC share */ | 208 | __u16 ipc_tid; /* special tid for connection to IPC share */ |
| @@ -216,6 +218,7 @@ struct cifsSesInfo { | |||
| 216 | char userName[MAX_USERNAME_SIZE + 1]; | 218 | char userName[MAX_USERNAME_SIZE + 1]; |
| 217 | char *domainName; | 219 | char *domainName; |
| 218 | char *password; | 220 | char *password; |
| 221 | bool need_reconnect:1; /* connection reset, uid now invalid */ | ||
| 219 | }; | 222 | }; |
| 220 | /* no more than one of the following three session flags may be set */ | 223 | /* no more than one of the following three session flags may be set */ |
| 221 | #define CIFS_SES_NT4 1 | 224 | #define CIFS_SES_NT4 1 |
| @@ -230,16 +233,15 @@ struct cifsSesInfo { | |||
| 230 | * session | 233 | * session |
| 231 | */ | 234 | */ |
| 232 | struct cifsTconInfo { | 235 | struct cifsTconInfo { |
| 233 | struct list_head cifsConnectionList; | 236 | struct list_head tcon_list; |
| 237 | int tc_count; | ||
| 234 | struct list_head openFileList; | 238 | struct list_head openFileList; |
| 235 | struct semaphore tconSem; | ||
| 236 | struct cifsSesInfo *ses; /* pointer to session associated with */ | 239 | struct cifsSesInfo *ses; /* pointer to session associated with */ |
| 237 | char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */ | 240 | char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */ |
| 238 | char *nativeFileSystem; | 241 | char *nativeFileSystem; |
| 239 | __u16 tid; /* The 2 byte tree id */ | 242 | __u16 tid; /* The 2 byte tree id */ |
| 240 | __u16 Flags; /* optional support bits */ | 243 | __u16 Flags; /* optional support bits */ |
| 241 | enum statusEnum tidStatus; | 244 | enum statusEnum tidStatus; |
| 242 | atomic_t useCount; /* how many explicit/implicit mounts to share */ | ||
| 243 | #ifdef CONFIG_CIFS_STATS | 245 | #ifdef CONFIG_CIFS_STATS |
| 244 | atomic_t num_smbs_sent; | 246 | atomic_t num_smbs_sent; |
| 245 | atomic_t num_writes; | 247 | atomic_t num_writes; |
| @@ -288,6 +290,7 @@ struct cifsTconInfo { | |||
| 288 | bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol | 290 | bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol |
| 289 | for this mount even if server would support */ | 291 | for this mount even if server would support */ |
| 290 | bool local_lease:1; /* check leases (only) on local system not remote */ | 292 | bool local_lease:1; /* check leases (only) on local system not remote */ |
| 293 | bool need_reconnect:1; /* connection reset, tid now invalid */ | ||
| 291 | /* BB add field for back pointer to sb struct(s)? */ | 294 | /* BB add field for back pointer to sb struct(s)? */ |
| 292 | }; | 295 | }; |
| 293 | 296 | ||
| @@ -588,21 +591,21 @@ require use of the stronger protocol */ | |||
| 588 | #endif | 591 | #endif |
| 589 | 592 | ||
| 590 | /* | 593 | /* |
| 591 | * The list of servers that did not respond with NT LM 0.12. | 594 | * the list of TCP_Server_Info structures, ie each of the sockets |
| 592 | * This list helps improve performance and eliminate the messages indicating | 595 | * connecting our client to a distinct server (ip address), is |
| 593 | * that we had a communications error talking to the server in this list. | 596 | * chained together by cifs_tcp_ses_list. The list of all our SMB |
| 597 | * sessions (and from that the tree connections) can be found | ||
| 598 | * by iterating over cifs_tcp_ses_list | ||
| 594 | */ | 599 | */ |
| 595 | /* Feature not supported */ | 600 | GLOBAL_EXTERN struct list_head cifs_tcp_ses_list; |
| 596 | /* GLOBAL_EXTERN struct servers_not_supported *NotSuppList; */ | ||
| 597 | 601 | ||
| 598 | /* | 602 | /* |
| 599 | * The following is a hash table of all the users we know about. | 603 | * This lock protects the cifs_tcp_ses_list, the list of smb sessions per |
| 604 | * tcp session, and the list of tcon's per smb session. It also protects | ||
| 605 | * the reference counters for the server, smb session, and tcon. Finally, | ||
| 606 | * changes to the tcon->tidStatus should be done while holding this lock. | ||
| 600 | */ | 607 | */ |
| 601 | GLOBAL_EXTERN struct smbUidInfo *GlobalUidList[UID_HASH]; | 608 | GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock; |
| 602 | |||
| 603 | /* GLOBAL_EXTERN struct list_head GlobalServerList; BB not implemented yet */ | ||
| 604 | GLOBAL_EXTERN struct list_head GlobalSMBSessionList; | ||
| 605 | GLOBAL_EXTERN struct list_head GlobalTreeConnectionList; | ||
| 606 | GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ | 609 | GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */ |
| 607 | 610 | ||
| 608 | GLOBAL_EXTERN struct list_head GlobalOplock_Q; | 611 | GLOBAL_EXTERN struct list_head GlobalOplock_Q; |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index d5eac48fc415..bdda46dd435a 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -190,10 +190,10 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
| 190 | /* need to prevent multiple threads trying to | 190 | /* need to prevent multiple threads trying to |
| 191 | simultaneously reconnect the same SMB session */ | 191 | simultaneously reconnect the same SMB session */ |
| 192 | down(&tcon->ses->sesSem); | 192 | down(&tcon->ses->sesSem); |
| 193 | if (tcon->ses->status == CifsNeedReconnect) | 193 | if (tcon->ses->need_reconnect) |
| 194 | rc = cifs_setup_session(0, tcon->ses, | 194 | rc = cifs_setup_session(0, tcon->ses, |
| 195 | nls_codepage); | 195 | nls_codepage); |
| 196 | if (!rc && (tcon->tidStatus == CifsNeedReconnect)) { | 196 | if (!rc && (tcon->need_reconnect)) { |
| 197 | mark_open_files_invalid(tcon); | 197 | mark_open_files_invalid(tcon); |
| 198 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, | 198 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, |
| 199 | tcon, nls_codepage); | 199 | tcon, nls_codepage); |
| @@ -295,7 +295,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
| 295 | check for tcp and smb session status done differently | 295 | check for tcp and smb session status done differently |
| 296 | for those three - in the calling routine */ | 296 | for those three - in the calling routine */ |
| 297 | if (tcon) { | 297 | if (tcon) { |
| 298 | if (tcon->tidStatus == CifsExiting) { | 298 | if (tcon->need_reconnect) { |
| 299 | /* only tree disconnect, open, and write, | 299 | /* only tree disconnect, open, and write, |
| 300 | (and ulogoff which does not have tcon) | 300 | (and ulogoff which does not have tcon) |
| 301 | are allowed as we start force umount */ | 301 | are allowed as we start force umount */ |
| @@ -337,10 +337,10 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
| 337 | /* need to prevent multiple threads trying to | 337 | /* need to prevent multiple threads trying to |
| 338 | simultaneously reconnect the same SMB session */ | 338 | simultaneously reconnect the same SMB session */ |
| 339 | down(&tcon->ses->sesSem); | 339 | down(&tcon->ses->sesSem); |
| 340 | if (tcon->ses->status == CifsNeedReconnect) | 340 | if (tcon->ses->need_reconnect) |
| 341 | rc = cifs_setup_session(0, tcon->ses, | 341 | rc = cifs_setup_session(0, tcon->ses, |
| 342 | nls_codepage); | 342 | nls_codepage); |
| 343 | if (!rc && (tcon->tidStatus == CifsNeedReconnect)) { | 343 | if (!rc && (tcon->need_reconnect)) { |
| 344 | mark_open_files_invalid(tcon); | 344 | mark_open_files_invalid(tcon); |
| 345 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, | 345 | rc = CIFSTCon(0, tcon->ses, tcon->treeName, |
| 346 | tcon, nls_codepage); | 346 | tcon, nls_codepage); |
| @@ -664,8 +664,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
| 664 | rc = -EIO; | 664 | rc = -EIO; |
| 665 | goto neg_err_exit; | 665 | goto neg_err_exit; |
| 666 | } | 666 | } |
| 667 | 667 | read_lock(&cifs_tcp_ses_lock); | |
| 668 | if (server->socketUseCount.counter > 1) { | 668 | if (server->srv_count > 1) { |
| 669 | read_unlock(&cifs_tcp_ses_lock); | ||
| 669 | if (memcmp(server->server_GUID, | 670 | if (memcmp(server->server_GUID, |
| 670 | pSMBr->u.extended_response. | 671 | pSMBr->u.extended_response. |
| 671 | GUID, 16) != 0) { | 672 | GUID, 16) != 0) { |
| @@ -674,9 +675,11 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
| 674 | pSMBr->u.extended_response.GUID, | 675 | pSMBr->u.extended_response.GUID, |
| 675 | 16); | 676 | 16); |
| 676 | } | 677 | } |
| 677 | } else | 678 | } else { |
| 679 | read_unlock(&cifs_tcp_ses_lock); | ||
| 678 | memcpy(server->server_GUID, | 680 | memcpy(server->server_GUID, |
| 679 | pSMBr->u.extended_response.GUID, 16); | 681 | pSMBr->u.extended_response.GUID, 16); |
| 682 | } | ||
| 680 | 683 | ||
| 681 | if (count == 16) { | 684 | if (count == 16) { |
| 682 | server->secType = RawNTLMSSP; | 685 | server->secType = RawNTLMSSP; |
| @@ -739,50 +742,31 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | |||
| 739 | int rc = 0; | 742 | int rc = 0; |
| 740 | 743 | ||
| 741 | cFYI(1, ("In tree disconnect")); | 744 | cFYI(1, ("In tree disconnect")); |
| 742 | /* | ||
| 743 | * If last user of the connection and | ||
| 744 | * connection alive - disconnect it | ||
| 745 | * If this is the last connection on the server session disconnect it | ||
| 746 | * (and inside session disconnect we should check if tcp socket needs | ||
| 747 | * to be freed and kernel thread woken up). | ||
| 748 | */ | ||
| 749 | if (tcon) | ||
| 750 | down(&tcon->tconSem); | ||
| 751 | else | ||
| 752 | return -EIO; | ||
| 753 | 745 | ||
| 754 | atomic_dec(&tcon->useCount); | 746 | /* BB: do we need to check this? These should never be NULL. */ |
| 755 | if (atomic_read(&tcon->useCount) > 0) { | 747 | if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) |
| 756 | up(&tcon->tconSem); | 748 | return -EIO; |
| 757 | return -EBUSY; | ||
| 758 | } | ||
| 759 | 749 | ||
| 760 | /* No need to return error on this operation if tid invalidated and | 750 | /* |
| 761 | closed on server already e.g. due to tcp session crashing */ | 751 | * No need to return error on this operation if tid invalidated and |
| 762 | if (tcon->tidStatus == CifsNeedReconnect) { | 752 | * closed on server already e.g. due to tcp session crashing. Also, |
| 763 | up(&tcon->tconSem); | 753 | * the tcon is no longer on the list, so no need to take lock before |
| 754 | * checking this. | ||
| 755 | */ | ||
| 756 | if (tcon->need_reconnect) | ||
| 764 | return 0; | 757 | return 0; |
| 765 | } | ||
| 766 | 758 | ||
| 767 | if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) { | ||
| 768 | up(&tcon->tconSem); | ||
| 769 | return -EIO; | ||
| 770 | } | ||
| 771 | rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, | 759 | rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, |
| 772 | (void **)&smb_buffer); | 760 | (void **)&smb_buffer); |
| 773 | if (rc) { | 761 | if (rc) |
| 774 | up(&tcon->tconSem); | ||
| 775 | return rc; | 762 | return rc; |
| 776 | } | ||
| 777 | 763 | ||
| 778 | rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0); | 764 | rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0); |
| 779 | if (rc) | 765 | if (rc) |
| 780 | cFYI(1, ("Tree disconnect failed %d", rc)); | 766 | cFYI(1, ("Tree disconnect failed %d", rc)); |
| 781 | 767 | ||
| 782 | up(&tcon->tconSem); | ||
| 783 | |||
| 784 | /* No need to return error on this operation if tid invalidated and | 768 | /* No need to return error on this operation if tid invalidated and |
| 785 | closed on server already e.g. due to tcp session crashing */ | 769 | closed on server already e.g. due to tcp session crashing */ |
| 786 | if (rc == -EAGAIN) | 770 | if (rc == -EAGAIN) |
| 787 | rc = 0; | 771 | rc = 0; |
| 788 | 772 | ||
| @@ -796,43 +780,36 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
| 796 | int rc = 0; | 780 | int rc = 0; |
| 797 | 781 | ||
| 798 | cFYI(1, ("In SMBLogoff for session disconnect")); | 782 | cFYI(1, ("In SMBLogoff for session disconnect")); |
| 799 | if (ses) | 783 | |
| 800 | down(&ses->sesSem); | 784 | /* |
| 801 | else | 785 | * BB: do we need to check validity of ses and server? They should |
| 786 | * always be valid since we have an active reference. If not, that | ||
| 787 | * should probably be a BUG() | ||
| 788 | */ | ||
| 789 | if (!ses || !ses->server) | ||
| 802 | return -EIO; | 790 | return -EIO; |
| 803 | 791 | ||
| 804 | atomic_dec(&ses->inUse); | 792 | down(&ses->sesSem); |
| 805 | if (atomic_read(&ses->inUse) > 0) { | 793 | if (ses->need_reconnect) |
| 806 | up(&ses->sesSem); | 794 | goto session_already_dead; /* no need to send SMBlogoff if uid |
| 807 | return -EBUSY; | 795 | already closed due to reconnect */ |
| 808 | } | ||
| 809 | rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB); | 796 | rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB); |
| 810 | if (rc) { | 797 | if (rc) { |
| 811 | up(&ses->sesSem); | 798 | up(&ses->sesSem); |
| 812 | return rc; | 799 | return rc; |
| 813 | } | 800 | } |
| 814 | 801 | ||
| 815 | if (ses->server) { | 802 | pSMB->hdr.Mid = GetNextMid(ses->server); |
| 816 | pSMB->hdr.Mid = GetNextMid(ses->server); | ||
| 817 | 803 | ||
| 818 | if (ses->server->secMode & | 804 | if (ses->server->secMode & |
| 819 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | 805 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) |
| 820 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | 806 | pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; |
| 821 | } | ||
| 822 | 807 | ||
| 823 | pSMB->hdr.Uid = ses->Suid; | 808 | pSMB->hdr.Uid = ses->Suid; |
| 824 | 809 | ||
| 825 | pSMB->AndXCommand = 0xFF; | 810 | pSMB->AndXCommand = 0xFF; |
| 826 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); | 811 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); |
| 827 | if (ses->server) { | 812 | session_already_dead: |
| 828 | atomic_dec(&ses->server->socketUseCount); | ||
| 829 | if (atomic_read(&ses->server->socketUseCount) == 0) { | ||
| 830 | spin_lock(&GlobalMid_Lock); | ||
| 831 | ses->server->tcpStatus = CifsExiting; | ||
| 832 | spin_unlock(&GlobalMid_Lock); | ||
| 833 | rc = -ESHUTDOWN; | ||
| 834 | } | ||
| 835 | } | ||
| 836 | up(&ses->sesSem); | 813 | up(&ses->sesSem); |
| 837 | 814 | ||
| 838 | /* if session dead then we do not need to do ulogoff, | 815 | /* if session dead then we do not need to do ulogoff, |
| @@ -3922,6 +3899,27 @@ GetInodeNumOut: | |||
| 3922 | return rc; | 3899 | return rc; |
| 3923 | } | 3900 | } |
| 3924 | 3901 | ||
| 3902 | /* computes length of UCS string converted to host codepage | ||
| 3903 | * @src: UCS string | ||
| 3904 | * @maxlen: length of the input string in UCS characters | ||
| 3905 | * (not in bytes) | ||
| 3906 | * | ||
| 3907 | * return: size of input string in host codepage | ||
| 3908 | */ | ||
| 3909 | static int hostlen_fromUCS(const __le16 *src, const int maxlen, | ||
| 3910 | const struct nls_table *nls_codepage) { | ||
| 3911 | int i; | ||
| 3912 | int hostlen = 0; | ||
| 3913 | char to[4]; | ||
| 3914 | int charlen; | ||
| 3915 | for (i = 0; (i < maxlen) && src[i]; ++i) { | ||
| 3916 | charlen = nls_codepage->uni2char(le16_to_cpu(src[i]), | ||
| 3917 | to, NLS_MAX_CHARSET_SIZE); | ||
| 3918 | hostlen += charlen > 0 ? charlen : 1; | ||
| 3919 | } | ||
| 3920 | return hostlen; | ||
| 3921 | } | ||
| 3922 | |||
| 3925 | /* parses DFS refferal V3 structure | 3923 | /* parses DFS refferal V3 structure |
| 3926 | * caller is responsible for freeing target_nodes | 3924 | * caller is responsible for freeing target_nodes |
| 3927 | * returns: | 3925 | * returns: |
| @@ -3932,7 +3930,8 @@ static int | |||
| 3932 | parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | 3930 | parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, |
| 3933 | unsigned int *num_of_nodes, | 3931 | unsigned int *num_of_nodes, |
| 3934 | struct dfs_info3_param **target_nodes, | 3932 | struct dfs_info3_param **target_nodes, |
| 3935 | const struct nls_table *nls_codepage) | 3933 | const struct nls_table *nls_codepage, int remap, |
| 3934 | const char *searchName) | ||
| 3936 | { | 3935 | { |
| 3937 | int i, rc = 0; | 3936 | int i, rc = 0; |
| 3938 | char *data_end; | 3937 | char *data_end; |
| @@ -3983,7 +3982,17 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | |||
| 3983 | struct dfs_info3_param *node = (*target_nodes)+i; | 3982 | struct dfs_info3_param *node = (*target_nodes)+i; |
| 3984 | 3983 | ||
| 3985 | node->flags = le16_to_cpu(pSMBr->DFSFlags); | 3984 | node->flags = le16_to_cpu(pSMBr->DFSFlags); |
| 3986 | node->path_consumed = le16_to_cpu(pSMBr->PathConsumed); | 3985 | if (is_unicode) { |
| 3986 | __le16 *tmp = kmalloc(strlen(searchName)*2, GFP_KERNEL); | ||
| 3987 | cifsConvertToUCS((__le16 *) tmp, searchName, | ||
| 3988 | PATH_MAX, nls_codepage, remap); | ||
| 3989 | node->path_consumed = hostlen_fromUCS(tmp, | ||
| 3990 | le16_to_cpu(pSMBr->PathConsumed)/2, | ||
| 3991 | nls_codepage); | ||
| 3992 | kfree(tmp); | ||
| 3993 | } else | ||
| 3994 | node->path_consumed = le16_to_cpu(pSMBr->PathConsumed); | ||
| 3995 | |||
| 3987 | node->server_type = le16_to_cpu(ref->ServerType); | 3996 | node->server_type = le16_to_cpu(ref->ServerType); |
| 3988 | node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); | 3997 | node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); |
| 3989 | 3998 | ||
| @@ -4116,7 +4125,8 @@ getDFSRetry: | |||
| 4116 | 4125 | ||
| 4117 | /* parse returned result into more usable form */ | 4126 | /* parse returned result into more usable form */ |
| 4118 | rc = parse_DFS_referrals(pSMBr, num_of_nodes, | 4127 | rc = parse_DFS_referrals(pSMBr, num_of_nodes, |
| 4119 | target_nodes, nls_codepage); | 4128 | target_nodes, nls_codepage, remap, |
| 4129 | searchName); | ||
| 4120 | 4130 | ||
| 4121 | GetDFSRefExit: | 4131 | GetDFSRefExit: |
| 4122 | cifs_buf_release(pSMB); | 4132 | cifs_buf_release(pSMB); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e9f9248cb3fe..c7d341714586 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -124,7 +124,7 @@ static int | |||
| 124 | cifs_reconnect(struct TCP_Server_Info *server) | 124 | cifs_reconnect(struct TCP_Server_Info *server) |
| 125 | { | 125 | { |
| 126 | int rc = 0; | 126 | int rc = 0; |
| 127 | struct list_head *tmp; | 127 | struct list_head *tmp, *tmp2; |
| 128 | struct cifsSesInfo *ses; | 128 | struct cifsSesInfo *ses; |
| 129 | struct cifsTconInfo *tcon; | 129 | struct cifsTconInfo *tcon; |
| 130 | struct mid_q_entry *mid_entry; | 130 | struct mid_q_entry *mid_entry; |
| @@ -144,23 +144,17 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 144 | 144 | ||
| 145 | /* before reconnecting the tcp session, mark the smb session (uid) | 145 | /* before reconnecting the tcp session, mark the smb session (uid) |
| 146 | and the tid bad so they are not used until reconnected */ | 146 | and the tid bad so they are not used until reconnected */ |
| 147 | read_lock(&GlobalSMBSeslock); | 147 | read_lock(&cifs_tcp_ses_lock); |
| 148 | list_for_each(tmp, &GlobalSMBSessionList) { | 148 | list_for_each(tmp, &server->smb_ses_list) { |
| 149 | ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); | 149 | ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); |
| 150 | if (ses->server) { | 150 | ses->need_reconnect = true; |
| 151 | if (ses->server == server) { | 151 | ses->ipc_tid = 0; |
| 152 | ses->status = CifsNeedReconnect; | 152 | list_for_each(tmp2, &ses->tcon_list) { |
| 153 | ses->ipc_tid = 0; | 153 | tcon = list_entry(tmp2, struct cifsTconInfo, tcon_list); |
| 154 | } | 154 | tcon->need_reconnect = true; |
| 155 | } | 155 | } |
| 156 | /* else tcp and smb sessions need reconnection */ | ||
| 157 | } | ||
| 158 | list_for_each(tmp, &GlobalTreeConnectionList) { | ||
| 159 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | ||
| 160 | if ((tcon->ses) && (tcon->ses->server == server)) | ||
| 161 | tcon->tidStatus = CifsNeedReconnect; | ||
| 162 | } | 156 | } |
| 163 | read_unlock(&GlobalSMBSeslock); | 157 | read_unlock(&cifs_tcp_ses_lock); |
| 164 | /* do not want to be sending data on a socket we are freeing */ | 158 | /* do not want to be sending data on a socket we are freeing */ |
| 165 | down(&server->tcpSem); | 159 | down(&server->tcpSem); |
| 166 | if (server->ssocket) { | 160 | if (server->ssocket) { |
| @@ -193,7 +187,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 193 | while ((server->tcpStatus != CifsExiting) && | 187 | while ((server->tcpStatus != CifsExiting) && |
| 194 | (server->tcpStatus != CifsGood)) { | 188 | (server->tcpStatus != CifsGood)) { |
| 195 | try_to_freeze(); | 189 | try_to_freeze(); |
| 196 | if (server->protocolType == IPV6) { | 190 | if (server->addr.sockAddr6.sin6_family == AF_INET6) { |
| 197 | rc = ipv6_connect(&server->addr.sockAddr6, | 191 | rc = ipv6_connect(&server->addr.sockAddr6, |
| 198 | &server->ssocket, server->noautotune); | 192 | &server->ssocket, server->noautotune); |
| 199 | } else { | 193 | } else { |
| @@ -417,9 +411,14 @@ incomplete_rcv: | |||
| 417 | msleep(1); /* minimum sleep to prevent looping | 411 | msleep(1); /* minimum sleep to prevent looping |
| 418 | allowing socket to clear and app threads to set | 412 | allowing socket to clear and app threads to set |
| 419 | tcpStatus CifsNeedReconnect if server hung */ | 413 | tcpStatus CifsNeedReconnect if server hung */ |
| 420 | if (pdu_length < 4) | 414 | if (pdu_length < 4) { |
| 415 | iov.iov_base = (4 - pdu_length) + | ||
| 416 | (char *)smb_buffer; | ||
| 417 | iov.iov_len = pdu_length; | ||
| 418 | smb_msg.msg_control = NULL; | ||
| 419 | smb_msg.msg_controllen = 0; | ||
| 421 | goto incomplete_rcv; | 420 | goto incomplete_rcv; |
| 422 | else | 421 | } else |
| 423 | continue; | 422 | continue; |
| 424 | } else if (length <= 0) { | 423 | } else if (length <= 0) { |
| 425 | if (server->tcpStatus == CifsNew) { | 424 | if (server->tcpStatus == CifsNew) { |
| @@ -654,6 +653,11 @@ multi_t2_fnd: | |||
| 654 | } | 653 | } |
| 655 | } /* end while !EXITING */ | 654 | } /* end while !EXITING */ |
| 656 | 655 | ||
| 656 | /* take it off the list, if it's not already */ | ||
| 657 | write_lock(&cifs_tcp_ses_lock); | ||
| 658 | list_del_init(&server->tcp_ses_list); | ||
| 659 | write_unlock(&cifs_tcp_ses_lock); | ||
| 660 | |||
| 657 | spin_lock(&GlobalMid_Lock); | 661 | spin_lock(&GlobalMid_Lock); |
| 658 | server->tcpStatus = CifsExiting; | 662 | server->tcpStatus = CifsExiting; |
| 659 | spin_unlock(&GlobalMid_Lock); | 663 | spin_unlock(&GlobalMid_Lock); |
| @@ -686,29 +690,29 @@ multi_t2_fnd: | |||
| 686 | if (smallbuf) /* no sense logging a debug message if NULL */ | 690 | if (smallbuf) /* no sense logging a debug message if NULL */ |
| 687 | cifs_small_buf_release(smallbuf); | 691 | cifs_small_buf_release(smallbuf); |
| 688 | 692 | ||
| 689 | read_lock(&GlobalSMBSeslock); | 693 | /* |
| 694 | * BB: we shouldn't have to do any of this. It shouldn't be | ||
| 695 | * possible to exit from the thread with active SMB sessions | ||
| 696 | */ | ||
| 697 | read_lock(&cifs_tcp_ses_lock); | ||
| 690 | if (list_empty(&server->pending_mid_q)) { | 698 | if (list_empty(&server->pending_mid_q)) { |
| 691 | /* loop through server session structures attached to this and | 699 | /* loop through server session structures attached to this and |
| 692 | mark them dead */ | 700 | mark them dead */ |
| 693 | list_for_each(tmp, &GlobalSMBSessionList) { | 701 | list_for_each(tmp, &server->smb_ses_list) { |
| 694 | ses = | 702 | ses = list_entry(tmp, struct cifsSesInfo, |
| 695 | list_entry(tmp, struct cifsSesInfo, | 703 | smb_ses_list); |
| 696 | cifsSessionList); | 704 | ses->status = CifsExiting; |
| 697 | if (ses->server == server) { | 705 | ses->server = NULL; |
| 698 | ses->status = CifsExiting; | ||
| 699 | ses->server = NULL; | ||
| 700 | } | ||
| 701 | } | 706 | } |
| 702 | read_unlock(&GlobalSMBSeslock); | 707 | read_unlock(&cifs_tcp_ses_lock); |
| 703 | } else { | 708 | } else { |
| 704 | /* although we can not zero the server struct pointer yet, | 709 | /* although we can not zero the server struct pointer yet, |
| 705 | since there are active requests which may depnd on them, | 710 | since there are active requests which may depnd on them, |
| 706 | mark the corresponding SMB sessions as exiting too */ | 711 | mark the corresponding SMB sessions as exiting too */ |
| 707 | list_for_each(tmp, &GlobalSMBSessionList) { | 712 | list_for_each(tmp, &server->smb_ses_list) { |
| 708 | ses = list_entry(tmp, struct cifsSesInfo, | 713 | ses = list_entry(tmp, struct cifsSesInfo, |
| 709 | cifsSessionList); | 714 | smb_ses_list); |
| 710 | if (ses->server == server) | 715 | ses->status = CifsExiting; |
| 711 | ses->status = CifsExiting; | ||
| 712 | } | 716 | } |
| 713 | 717 | ||
| 714 | spin_lock(&GlobalMid_Lock); | 718 | spin_lock(&GlobalMid_Lock); |
| @@ -723,7 +727,7 @@ multi_t2_fnd: | |||
| 723 | } | 727 | } |
| 724 | } | 728 | } |
| 725 | spin_unlock(&GlobalMid_Lock); | 729 | spin_unlock(&GlobalMid_Lock); |
| 726 | read_unlock(&GlobalSMBSeslock); | 730 | read_unlock(&cifs_tcp_ses_lock); |
| 727 | /* 1/8th of sec is more than enough time for them to exit */ | 731 | /* 1/8th of sec is more than enough time for them to exit */ |
| 728 | msleep(125); | 732 | msleep(125); |
| 729 | } | 733 | } |
| @@ -745,14 +749,13 @@ multi_t2_fnd: | |||
| 745 | if there are any pointing to this (e.g | 749 | if there are any pointing to this (e.g |
| 746 | if a crazy root user tried to kill cifsd | 750 | if a crazy root user tried to kill cifsd |
| 747 | kernel thread explicitly this might happen) */ | 751 | kernel thread explicitly this might happen) */ |
| 748 | write_lock(&GlobalSMBSeslock); | 752 | /* BB: This shouldn't be necessary, see above */ |
| 749 | list_for_each(tmp, &GlobalSMBSessionList) { | 753 | read_lock(&cifs_tcp_ses_lock); |
| 750 | ses = list_entry(tmp, struct cifsSesInfo, | 754 | list_for_each(tmp, &server->smb_ses_list) { |
| 751 | cifsSessionList); | 755 | ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); |
| 752 | if (ses->server == server) | 756 | ses->server = NULL; |
| 753 | ses->server = NULL; | ||
| 754 | } | 757 | } |
| 755 | write_unlock(&GlobalSMBSeslock); | 758 | read_unlock(&cifs_tcp_ses_lock); |
| 756 | 759 | ||
| 757 | kfree(server->hostname); | 760 | kfree(server->hostname); |
| 758 | task_to_wake = xchg(&server->tsk, NULL); | 761 | task_to_wake = xchg(&server->tsk, NULL); |
| @@ -1352,94 +1355,158 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1352 | return 0; | 1355 | return 0; |
| 1353 | } | 1356 | } |
| 1354 | 1357 | ||
| 1355 | static struct cifsSesInfo * | 1358 | static struct TCP_Server_Info * |
| 1356 | cifs_find_tcp_session(struct in_addr *target_ip_addr, | 1359 | cifs_find_tcp_session(struct sockaddr *addr) |
| 1357 | struct in6_addr *target_ip6_addr, | ||
| 1358 | char *userName, struct TCP_Server_Info **psrvTcp) | ||
| 1359 | { | 1360 | { |
| 1360 | struct list_head *tmp; | 1361 | struct list_head *tmp; |
| 1361 | struct cifsSesInfo *ses; | 1362 | struct TCP_Server_Info *server; |
| 1362 | 1363 | struct sockaddr_in *addr4 = (struct sockaddr_in *) addr; | |
| 1363 | *psrvTcp = NULL; | 1364 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr; |
| 1365 | |||
| 1366 | write_lock(&cifs_tcp_ses_lock); | ||
| 1367 | list_for_each(tmp, &cifs_tcp_ses_list) { | ||
| 1368 | server = list_entry(tmp, struct TCP_Server_Info, | ||
| 1369 | tcp_ses_list); | ||
| 1370 | /* | ||
| 1371 | * the demux thread can exit on its own while still in CifsNew | ||
| 1372 | * so don't accept any sockets in that state. Since the | ||
| 1373 | * tcpStatus never changes back to CifsNew it's safe to check | ||
| 1374 | * for this without a lock. | ||
| 1375 | */ | ||
| 1376 | if (server->tcpStatus == CifsNew) | ||
| 1377 | continue; | ||
| 1364 | 1378 | ||
| 1365 | read_lock(&GlobalSMBSeslock); | 1379 | if (addr->sa_family == AF_INET && |
| 1366 | list_for_each(tmp, &GlobalSMBSessionList) { | 1380 | (addr4->sin_addr.s_addr != |
| 1367 | ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); | 1381 | server->addr.sockAddr.sin_addr.s_addr)) |
| 1368 | if (!ses->server) | 1382 | continue; |
| 1383 | else if (addr->sa_family == AF_INET6 && | ||
| 1384 | memcmp(&server->addr.sockAddr6.sin6_addr, | ||
| 1385 | &addr6->sin6_addr, sizeof(addr6->sin6_addr))) | ||
| 1369 | continue; | 1386 | continue; |
| 1370 | 1387 | ||
| 1371 | if (target_ip_addr && | 1388 | ++server->srv_count; |
| 1372 | ses->server->addr.sockAddr.sin_addr.s_addr != target_ip_addr->s_addr) | 1389 | write_unlock(&cifs_tcp_ses_lock); |
| 1373 | continue; | 1390 | cFYI(1, ("Existing tcp session with server found")); |
| 1374 | else if (target_ip6_addr && | 1391 | return server; |
| 1375 | memcmp(&ses->server->addr.sockAddr6.sin6_addr, | 1392 | } |
| 1376 | target_ip6_addr, sizeof(*target_ip6_addr))) | 1393 | write_unlock(&cifs_tcp_ses_lock); |
| 1377 | continue; | 1394 | return NULL; |
| 1378 | /* BB lock server and tcp session; increment use count here?? */ | 1395 | } |
| 1379 | 1396 | ||
| 1380 | /* found a match on the TCP session */ | 1397 | static void |
| 1381 | *psrvTcp = ses->server; | 1398 | cifs_put_tcp_session(struct TCP_Server_Info *server) |
| 1399 | { | ||
| 1400 | struct task_struct *task; | ||
| 1382 | 1401 | ||
| 1383 | /* BB check if reconnection needed */ | 1402 | write_lock(&cifs_tcp_ses_lock); |
| 1384 | if (strncmp(ses->userName, userName, MAX_USERNAME_SIZE) == 0) { | 1403 | if (--server->srv_count > 0) { |
| 1385 | read_unlock(&GlobalSMBSeslock); | 1404 | write_unlock(&cifs_tcp_ses_lock); |
| 1386 | /* Found exact match on both TCP and | 1405 | return; |
| 1387 | SMB sessions */ | ||
| 1388 | return ses; | ||
| 1389 | } | ||
| 1390 | /* else tcp and smb sessions need reconnection */ | ||
| 1391 | } | 1406 | } |
| 1392 | read_unlock(&GlobalSMBSeslock); | ||
| 1393 | 1407 | ||
| 1394 | return NULL; | 1408 | list_del_init(&server->tcp_ses_list); |
| 1409 | write_unlock(&cifs_tcp_ses_lock); | ||
| 1410 | |||
| 1411 | spin_lock(&GlobalMid_Lock); | ||
| 1412 | server->tcpStatus = CifsExiting; | ||
| 1413 | spin_unlock(&GlobalMid_Lock); | ||
| 1414 | |||
| 1415 | task = xchg(&server->tsk, NULL); | ||
| 1416 | if (task) | ||
| 1417 | force_sig(SIGKILL, task); | ||
| 1395 | } | 1418 | } |
| 1396 | 1419 | ||
| 1397 | static struct cifsTconInfo * | 1420 | static struct cifsSesInfo * |
| 1398 | find_unc(__be32 new_target_ip_addr, char *uncName, char *userName) | 1421 | cifs_find_smb_ses(struct TCP_Server_Info *server, char *username) |
| 1399 | { | 1422 | { |
| 1400 | struct list_head *tmp; | 1423 | struct list_head *tmp; |
| 1401 | struct cifsTconInfo *tcon; | 1424 | struct cifsSesInfo *ses; |
| 1402 | __be32 old_ip; | ||
| 1403 | |||
| 1404 | read_lock(&GlobalSMBSeslock); | ||
| 1405 | 1425 | ||
| 1406 | list_for_each(tmp, &GlobalTreeConnectionList) { | 1426 | write_lock(&cifs_tcp_ses_lock); |
| 1407 | cFYI(1, ("Next tcon")); | 1427 | list_for_each(tmp, &server->smb_ses_list) { |
| 1408 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | 1428 | ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); |
| 1409 | if (!tcon->ses || !tcon->ses->server) | 1429 | if (strncmp(ses->userName, username, MAX_USERNAME_SIZE)) |
| 1410 | continue; | 1430 | continue; |
| 1411 | 1431 | ||
| 1412 | old_ip = tcon->ses->server->addr.sockAddr.sin_addr.s_addr; | 1432 | ++ses->ses_count; |
| 1413 | cFYI(1, ("old ip addr: %x == new ip %x ?", | 1433 | write_unlock(&cifs_tcp_ses_lock); |
| 1414 | old_ip, new_target_ip_addr)); | 1434 | return ses; |
| 1435 | } | ||
| 1436 | write_unlock(&cifs_tcp_ses_lock); | ||
| 1437 | return NULL; | ||
| 1438 | } | ||
| 1415 | 1439 | ||
| 1416 | if (old_ip != new_target_ip_addr) | 1440 | static void |
| 1417 | continue; | 1441 | cifs_put_smb_ses(struct cifsSesInfo *ses) |
| 1442 | { | ||
| 1443 | int xid; | ||
| 1444 | struct TCP_Server_Info *server = ses->server; | ||
| 1418 | 1445 | ||
| 1419 | /* BB lock tcon, server, tcp session and increment use count? */ | 1446 | write_lock(&cifs_tcp_ses_lock); |
| 1420 | /* found a match on the TCP session */ | 1447 | if (--ses->ses_count > 0) { |
| 1421 | /* BB check if reconnection needed */ | 1448 | write_unlock(&cifs_tcp_ses_lock); |
| 1422 | cFYI(1, ("IP match, old UNC: %s new: %s", | 1449 | return; |
| 1423 | tcon->treeName, uncName)); | 1450 | } |
| 1424 | 1451 | ||
| 1425 | if (strncmp(tcon->treeName, uncName, MAX_TREE_SIZE)) | 1452 | list_del_init(&ses->smb_ses_list); |
| 1426 | continue; | 1453 | write_unlock(&cifs_tcp_ses_lock); |
| 1427 | 1454 | ||
| 1428 | cFYI(1, ("and old usr: %s new: %s", | 1455 | if (ses->status == CifsGood) { |
| 1429 | tcon->treeName, uncName)); | 1456 | xid = GetXid(); |
| 1457 | CIFSSMBLogoff(xid, ses); | ||
| 1458 | _FreeXid(xid); | ||
| 1459 | } | ||
| 1460 | sesInfoFree(ses); | ||
| 1461 | cifs_put_tcp_session(server); | ||
| 1462 | } | ||
| 1430 | 1463 | ||
| 1431 | if (strncmp(tcon->ses->userName, userName, MAX_USERNAME_SIZE)) | 1464 | static struct cifsTconInfo * |
| 1465 | cifs_find_tcon(struct cifsSesInfo *ses, const char *unc) | ||
| 1466 | { | ||
| 1467 | struct list_head *tmp; | ||
| 1468 | struct cifsTconInfo *tcon; | ||
| 1469 | |||
| 1470 | write_lock(&cifs_tcp_ses_lock); | ||
| 1471 | list_for_each(tmp, &ses->tcon_list) { | ||
| 1472 | tcon = list_entry(tmp, struct cifsTconInfo, tcon_list); | ||
| 1473 | if (tcon->tidStatus == CifsExiting) | ||
| 1474 | continue; | ||
| 1475 | if (strncmp(tcon->treeName, unc, MAX_TREE_SIZE)) | ||
| 1432 | continue; | 1476 | continue; |
| 1433 | 1477 | ||
| 1434 | /* matched smb session (user name) */ | 1478 | ++tcon->tc_count; |
| 1435 | read_unlock(&GlobalSMBSeslock); | 1479 | write_unlock(&cifs_tcp_ses_lock); |
| 1436 | return tcon; | 1480 | return tcon; |
| 1437 | } | 1481 | } |
| 1438 | 1482 | write_unlock(&cifs_tcp_ses_lock); | |
| 1439 | read_unlock(&GlobalSMBSeslock); | ||
| 1440 | return NULL; | 1483 | return NULL; |
| 1441 | } | 1484 | } |
| 1442 | 1485 | ||
| 1486 | static void | ||
| 1487 | cifs_put_tcon(struct cifsTconInfo *tcon) | ||
| 1488 | { | ||
| 1489 | int xid; | ||
| 1490 | struct cifsSesInfo *ses = tcon->ses; | ||
| 1491 | |||
| 1492 | write_lock(&cifs_tcp_ses_lock); | ||
| 1493 | if (--tcon->tc_count > 0) { | ||
| 1494 | write_unlock(&cifs_tcp_ses_lock); | ||
| 1495 | return; | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | list_del_init(&tcon->tcon_list); | ||
| 1499 | write_unlock(&cifs_tcp_ses_lock); | ||
| 1500 | |||
| 1501 | xid = GetXid(); | ||
| 1502 | CIFSSMBTDis(xid, tcon); | ||
| 1503 | _FreeXid(xid); | ||
| 1504 | |||
| 1505 | DeleteTconOplockQEntries(tcon); | ||
| 1506 | tconInfoFree(tcon); | ||
| 1507 | cifs_put_smb_ses(ses); | ||
| 1508 | } | ||
| 1509 | |||
| 1443 | int | 1510 | int |
| 1444 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, | 1511 | get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, |
| 1445 | const struct nls_table *nls_codepage, unsigned int *pnum_referrals, | 1512 | const struct nls_table *nls_codepage, unsigned int *pnum_referrals, |
| @@ -1876,14 +1943,90 @@ convert_delimiter(char *path, char delim) | |||
| 1876 | } | 1943 | } |
| 1877 | } | 1944 | } |
| 1878 | 1945 | ||
| 1879 | static void | 1946 | static void setup_cifs_sb(struct smb_vol *pvolume_info, |
| 1880 | kill_cifsd(struct TCP_Server_Info *server) | 1947 | struct cifs_sb_info *cifs_sb) |
| 1881 | { | 1948 | { |
| 1882 | struct task_struct *task; | 1949 | if (pvolume_info->rsize > CIFSMaxBufSize) { |
| 1883 | 1950 | cERROR(1, ("rsize %d too large, using MaxBufSize", | |
| 1884 | task = xchg(&server->tsk, NULL); | 1951 | pvolume_info->rsize)); |
| 1885 | if (task) | 1952 | cifs_sb->rsize = CIFSMaxBufSize; |
| 1886 | force_sig(SIGKILL, task); | 1953 | } else if ((pvolume_info->rsize) && |
| 1954 | (pvolume_info->rsize <= CIFSMaxBufSize)) | ||
| 1955 | cifs_sb->rsize = pvolume_info->rsize; | ||
| 1956 | else /* default */ | ||
| 1957 | cifs_sb->rsize = CIFSMaxBufSize; | ||
| 1958 | |||
| 1959 | if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) { | ||
| 1960 | cERROR(1, ("wsize %d too large, using 4096 instead", | ||
| 1961 | pvolume_info->wsize)); | ||
| 1962 | cifs_sb->wsize = 4096; | ||
| 1963 | } else if (pvolume_info->wsize) | ||
| 1964 | cifs_sb->wsize = pvolume_info->wsize; | ||
| 1965 | else | ||
| 1966 | cifs_sb->wsize = min_t(const int, | ||
| 1967 | PAGEVEC_SIZE * PAGE_CACHE_SIZE, | ||
| 1968 | 127*1024); | ||
| 1969 | /* old default of CIFSMaxBufSize was too small now | ||
| 1970 | that SMB Write2 can send multiple pages in kvec. | ||
| 1971 | RFC1001 does not describe what happens when frame | ||
| 1972 | bigger than 128K is sent so use that as max in | ||
| 1973 | conjunction with 52K kvec constraint on arch with 4K | ||
| 1974 | page size */ | ||
| 1975 | |||
| 1976 | if (cifs_sb->rsize < 2048) { | ||
| 1977 | cifs_sb->rsize = 2048; | ||
| 1978 | /* Windows ME may prefer this */ | ||
| 1979 | cFYI(1, ("readsize set to minimum: 2048")); | ||
| 1980 | } | ||
| 1981 | /* calculate prepath */ | ||
| 1982 | cifs_sb->prepath = pvolume_info->prepath; | ||
| 1983 | if (cifs_sb->prepath) { | ||
| 1984 | cifs_sb->prepathlen = strlen(cifs_sb->prepath); | ||
| 1985 | /* we can not convert the / to \ in the path | ||
| 1986 | separators in the prefixpath yet because we do not | ||
| 1987 | know (until reset_cifs_unix_caps is called later) | ||
| 1988 | whether POSIX PATH CAP is available. We normalize | ||
| 1989 | the / to \ after reset_cifs_unix_caps is called */ | ||
| 1990 | pvolume_info->prepath = NULL; | ||
| 1991 | } else | ||
| 1992 | cifs_sb->prepathlen = 0; | ||
| 1993 | cifs_sb->mnt_uid = pvolume_info->linux_uid; | ||
| 1994 | cifs_sb->mnt_gid = pvolume_info->linux_gid; | ||
| 1995 | cifs_sb->mnt_file_mode = pvolume_info->file_mode; | ||
| 1996 | cifs_sb->mnt_dir_mode = pvolume_info->dir_mode; | ||
| 1997 | cFYI(1, ("file mode: 0x%x dir mode: 0x%x", | ||
| 1998 | cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode)); | ||
| 1999 | |||
| 2000 | if (pvolume_info->noperm) | ||
| 2001 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; | ||
| 2002 | if (pvolume_info->setuids) | ||
| 2003 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; | ||
| 2004 | if (pvolume_info->server_ino) | ||
| 2005 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; | ||
| 2006 | if (pvolume_info->remap) | ||
| 2007 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
| 2008 | if (pvolume_info->no_xattr) | ||
| 2009 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; | ||
| 2010 | if (pvolume_info->sfu_emul) | ||
| 2011 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; | ||
| 2012 | if (pvolume_info->nobrl) | ||
| 2013 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; | ||
| 2014 | if (pvolume_info->cifs_acl) | ||
| 2015 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; | ||
| 2016 | if (pvolume_info->override_uid) | ||
| 2017 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; | ||
| 2018 | if (pvolume_info->override_gid) | ||
| 2019 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; | ||
| 2020 | if (pvolume_info->dynperm) | ||
| 2021 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; | ||
| 2022 | if (pvolume_info->direct_io) { | ||
| 2023 | cFYI(1, ("mounting share using direct i/o")); | ||
| 2024 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | ||
| 2025 | } | ||
| 2026 | |||
| 2027 | if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm)) | ||
| 2028 | cERROR(1, ("mount option dynperm ignored if cifsacl " | ||
| 2029 | "mount option supported")); | ||
| 1887 | } | 2030 | } |
| 1888 | 2031 | ||
| 1889 | int | 2032 | int |
| @@ -1892,13 +2035,12 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1892 | { | 2035 | { |
| 1893 | int rc = 0; | 2036 | int rc = 0; |
| 1894 | int xid; | 2037 | int xid; |
| 1895 | int address_type = AF_INET; | ||
| 1896 | struct socket *csocket = NULL; | 2038 | struct socket *csocket = NULL; |
| 1897 | struct sockaddr_in sin_server; | 2039 | struct sockaddr addr; |
| 1898 | struct sockaddr_in6 sin_server6; | 2040 | struct sockaddr_in *sin_server = (struct sockaddr_in *) &addr; |
| 2041 | struct sockaddr_in6 *sin_server6 = (struct sockaddr_in6 *) &addr; | ||
| 1899 | struct smb_vol volume_info; | 2042 | struct smb_vol volume_info; |
| 1900 | struct cifsSesInfo *pSesInfo = NULL; | 2043 | struct cifsSesInfo *pSesInfo = NULL; |
| 1901 | struct cifsSesInfo *existingCifsSes = NULL; | ||
| 1902 | struct cifsTconInfo *tcon = NULL; | 2044 | struct cifsTconInfo *tcon = NULL; |
| 1903 | struct TCP_Server_Info *srvTcp = NULL; | 2045 | struct TCP_Server_Info *srvTcp = NULL; |
| 1904 | 2046 | ||
| @@ -1906,6 +2048,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1906 | 2048 | ||
| 1907 | /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */ | 2049 | /* cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); */ |
| 1908 | 2050 | ||
| 2051 | memset(&addr, 0, sizeof(struct sockaddr)); | ||
| 1909 | memset(&volume_info, 0, sizeof(struct smb_vol)); | 2052 | memset(&volume_info, 0, sizeof(struct smb_vol)); |
| 1910 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { | 2053 | if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { |
| 1911 | rc = -EINVAL; | 2054 | rc = -EINVAL; |
| @@ -1928,16 +2071,16 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1928 | 2071 | ||
| 1929 | if (volume_info.UNCip && volume_info.UNC) { | 2072 | if (volume_info.UNCip && volume_info.UNC) { |
| 1930 | rc = cifs_inet_pton(AF_INET, volume_info.UNCip, | 2073 | rc = cifs_inet_pton(AF_INET, volume_info.UNCip, |
| 1931 | &sin_server.sin_addr.s_addr); | 2074 | &sin_server->sin_addr.s_addr); |
| 1932 | 2075 | ||
| 1933 | if (rc <= 0) { | 2076 | if (rc <= 0) { |
| 1934 | /* not ipv4 address, try ipv6 */ | 2077 | /* not ipv4 address, try ipv6 */ |
| 1935 | rc = cifs_inet_pton(AF_INET6, volume_info.UNCip, | 2078 | rc = cifs_inet_pton(AF_INET6, volume_info.UNCip, |
| 1936 | &sin_server6.sin6_addr.in6_u); | 2079 | &sin_server6->sin6_addr.in6_u); |
| 1937 | if (rc > 0) | 2080 | if (rc > 0) |
| 1938 | address_type = AF_INET6; | 2081 | addr.sa_family = AF_INET6; |
| 1939 | } else { | 2082 | } else { |
| 1940 | address_type = AF_INET; | 2083 | addr.sa_family = AF_INET; |
| 1941 | } | 2084 | } |
| 1942 | 2085 | ||
| 1943 | if (rc <= 0) { | 2086 | if (rc <= 0) { |
| @@ -1977,41 +2120,25 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1977 | } | 2120 | } |
| 1978 | } | 2121 | } |
| 1979 | 2122 | ||
| 1980 | if (address_type == AF_INET) | 2123 | srvTcp = cifs_find_tcp_session(&addr); |
| 1981 | existingCifsSes = cifs_find_tcp_session(&sin_server.sin_addr, | 2124 | if (!srvTcp) { /* create socket */ |
| 1982 | NULL /* no ipv6 addr */, | 2125 | if (addr.sa_family == AF_INET6) { |
| 1983 | volume_info.username, &srvTcp); | ||
| 1984 | else if (address_type == AF_INET6) { | ||
| 1985 | cFYI(1, ("looking for ipv6 address")); | ||
| 1986 | existingCifsSes = cifs_find_tcp_session(NULL /* no ipv4 addr */, | ||
| 1987 | &sin_server6.sin6_addr, | ||
| 1988 | volume_info.username, &srvTcp); | ||
| 1989 | } else { | ||
| 1990 | rc = -EINVAL; | ||
| 1991 | goto out; | ||
| 1992 | } | ||
| 1993 | |||
| 1994 | if (srvTcp) { | ||
| 1995 | cFYI(1, ("Existing tcp session with server found")); | ||
| 1996 | } else { /* create socket */ | ||
| 1997 | if (volume_info.port) | ||
| 1998 | sin_server.sin_port = htons(volume_info.port); | ||
| 1999 | else | ||
| 2000 | sin_server.sin_port = 0; | ||
| 2001 | if (address_type == AF_INET6) { | ||
| 2002 | cFYI(1, ("attempting ipv6 connect")); | 2126 | cFYI(1, ("attempting ipv6 connect")); |
| 2003 | /* BB should we allow ipv6 on port 139? */ | 2127 | /* BB should we allow ipv6 on port 139? */ |
| 2004 | /* other OS never observed in Wild doing 139 with v6 */ | 2128 | /* other OS never observed in Wild doing 139 with v6 */ |
| 2005 | rc = ipv6_connect(&sin_server6, &csocket, | 2129 | sin_server6->sin6_port = htons(volume_info.port); |
| 2130 | rc = ipv6_connect(sin_server6, &csocket, | ||
| 2006 | volume_info.noblocksnd); | 2131 | volume_info.noblocksnd); |
| 2007 | } else | 2132 | } else { |
| 2008 | rc = ipv4_connect(&sin_server, &csocket, | 2133 | sin_server->sin_port = htons(volume_info.port); |
| 2134 | rc = ipv4_connect(sin_server, &csocket, | ||
| 2009 | volume_info.source_rfc1001_name, | 2135 | volume_info.source_rfc1001_name, |
| 2010 | volume_info.target_rfc1001_name, | 2136 | volume_info.target_rfc1001_name, |
| 2011 | volume_info.noblocksnd, | 2137 | volume_info.noblocksnd, |
| 2012 | volume_info.noautotune); | 2138 | volume_info.noautotune); |
| 2139 | } | ||
| 2013 | if (rc < 0) { | 2140 | if (rc < 0) { |
| 2014 | cERROR(1, ("Error connecting to IPv4 socket. " | 2141 | cERROR(1, ("Error connecting to socket. " |
| 2015 | "Aborting operation")); | 2142 | "Aborting operation")); |
| 2016 | if (csocket != NULL) | 2143 | if (csocket != NULL) |
| 2017 | sock_release(csocket); | 2144 | sock_release(csocket); |
| @@ -2026,12 +2153,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2026 | } else { | 2153 | } else { |
| 2027 | srvTcp->noblocksnd = volume_info.noblocksnd; | 2154 | srvTcp->noblocksnd = volume_info.noblocksnd; |
| 2028 | srvTcp->noautotune = volume_info.noautotune; | 2155 | srvTcp->noautotune = volume_info.noautotune; |
| 2029 | memcpy(&srvTcp->addr.sockAddr, &sin_server, | 2156 | if (addr.sa_family == AF_INET6) |
| 2030 | sizeof(struct sockaddr_in)); | 2157 | memcpy(&srvTcp->addr.sockAddr6, sin_server6, |
| 2158 | sizeof(struct sockaddr_in6)); | ||
| 2159 | else | ||
| 2160 | memcpy(&srvTcp->addr.sockAddr, sin_server, | ||
| 2161 | sizeof(struct sockaddr_in)); | ||
| 2031 | atomic_set(&srvTcp->inFlight, 0); | 2162 | atomic_set(&srvTcp->inFlight, 0); |
| 2032 | /* BB Add code for ipv6 case too */ | 2163 | /* BB Add code for ipv6 case too */ |
| 2033 | srvTcp->ssocket = csocket; | 2164 | srvTcp->ssocket = csocket; |
| 2034 | srvTcp->protocolType = IPV4; | ||
| 2035 | srvTcp->hostname = extract_hostname(volume_info.UNC); | 2165 | srvTcp->hostname = extract_hostname(volume_info.UNC); |
| 2036 | if (IS_ERR(srvTcp->hostname)) { | 2166 | if (IS_ERR(srvTcp->hostname)) { |
| 2037 | rc = PTR_ERR(srvTcp->hostname); | 2167 | rc = PTR_ERR(srvTcp->hostname); |
| @@ -2061,15 +2191,28 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2061 | memcpy(srvTcp->server_RFC1001_name, | 2191 | memcpy(srvTcp->server_RFC1001_name, |
| 2062 | volume_info.target_rfc1001_name, 16); | 2192 | volume_info.target_rfc1001_name, 16); |
| 2063 | srvTcp->sequence_number = 0; | 2193 | srvTcp->sequence_number = 0; |
| 2194 | INIT_LIST_HEAD(&srvTcp->tcp_ses_list); | ||
| 2195 | INIT_LIST_HEAD(&srvTcp->smb_ses_list); | ||
| 2196 | ++srvTcp->srv_count; | ||
| 2197 | write_lock(&cifs_tcp_ses_lock); | ||
| 2198 | list_add(&srvTcp->tcp_ses_list, | ||
| 2199 | &cifs_tcp_ses_list); | ||
| 2200 | write_unlock(&cifs_tcp_ses_lock); | ||
| 2064 | } | 2201 | } |
| 2065 | } | 2202 | } |
| 2066 | 2203 | ||
| 2067 | if (existingCifsSes) { | 2204 | pSesInfo = cifs_find_smb_ses(srvTcp, volume_info.username); |
| 2068 | pSesInfo = existingCifsSes; | 2205 | if (pSesInfo) { |
| 2069 | cFYI(1, ("Existing smb sess found (status=%d)", | 2206 | cFYI(1, ("Existing smb sess found (status=%d)", |
| 2070 | pSesInfo->status)); | 2207 | pSesInfo->status)); |
| 2208 | /* | ||
| 2209 | * The existing SMB session already has a reference to srvTcp, | ||
| 2210 | * so we can put back the extra one we got before | ||
| 2211 | */ | ||
| 2212 | cifs_put_tcp_session(srvTcp); | ||
| 2213 | |||
| 2071 | down(&pSesInfo->sesSem); | 2214 | down(&pSesInfo->sesSem); |
| 2072 | if (pSesInfo->status == CifsNeedReconnect) { | 2215 | if (pSesInfo->need_reconnect) { |
| 2073 | cFYI(1, ("Session needs reconnect")); | 2216 | cFYI(1, ("Session needs reconnect")); |
| 2074 | rc = cifs_setup_session(xid, pSesInfo, | 2217 | rc = cifs_setup_session(xid, pSesInfo, |
| 2075 | cifs_sb->local_nls); | 2218 | cifs_sb->local_nls); |
| @@ -2078,187 +2221,101 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2078 | } else if (!rc) { | 2221 | } else if (!rc) { |
| 2079 | cFYI(1, ("Existing smb sess not found")); | 2222 | cFYI(1, ("Existing smb sess not found")); |
| 2080 | pSesInfo = sesInfoAlloc(); | 2223 | pSesInfo = sesInfoAlloc(); |
| 2081 | if (pSesInfo == NULL) | 2224 | if (pSesInfo == NULL) { |
| 2082 | rc = -ENOMEM; | 2225 | rc = -ENOMEM; |
| 2083 | else { | 2226 | goto mount_fail_check; |
| 2084 | pSesInfo->server = srvTcp; | 2227 | } |
| 2085 | sprintf(pSesInfo->serverName, "%u.%u.%u.%u", | 2228 | |
| 2086 | NIPQUAD(sin_server.sin_addr.s_addr)); | 2229 | /* new SMB session uses our srvTcp ref */ |
| 2087 | } | 2230 | pSesInfo->server = srvTcp; |
| 2231 | sprintf(pSesInfo->serverName, "%u.%u.%u.%u", | ||
| 2232 | NIPQUAD(sin_server->sin_addr.s_addr)); | ||
| 2233 | |||
| 2234 | write_lock(&cifs_tcp_ses_lock); | ||
| 2235 | list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list); | ||
| 2236 | write_unlock(&cifs_tcp_ses_lock); | ||
| 2237 | |||
| 2238 | /* volume_info.password freed at unmount */ | ||
| 2239 | if (volume_info.password) { | ||
| 2240 | pSesInfo->password = volume_info.password; | ||
| 2241 | /* set to NULL to prevent freeing on exit */ | ||
| 2242 | volume_info.password = NULL; | ||
| 2243 | } | ||
| 2244 | if (volume_info.username) | ||
| 2245 | strncpy(pSesInfo->userName, volume_info.username, | ||
| 2246 | MAX_USERNAME_SIZE); | ||
| 2247 | if (volume_info.domainname) { | ||
| 2248 | int len = strlen(volume_info.domainname); | ||
| 2249 | pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL); | ||
| 2250 | if (pSesInfo->domainName) | ||
| 2251 | strcpy(pSesInfo->domainName, | ||
| 2252 | volume_info.domainname); | ||
| 2253 | } | ||
| 2254 | pSesInfo->linux_uid = volume_info.linux_uid; | ||
| 2255 | pSesInfo->overrideSecFlg = volume_info.secFlg; | ||
| 2256 | down(&pSesInfo->sesSem); | ||
| 2088 | 2257 | ||
| 2089 | if (!rc) { | 2258 | /* BB FIXME need to pass vol->secFlgs BB */ |
| 2090 | /* volume_info.password freed at unmount */ | 2259 | rc = cifs_setup_session(xid, pSesInfo, |
| 2091 | if (volume_info.password) { | 2260 | cifs_sb->local_nls); |
| 2092 | pSesInfo->password = volume_info.password; | 2261 | up(&pSesInfo->sesSem); |
| 2093 | /* set to NULL to prevent freeing on exit */ | ||
| 2094 | volume_info.password = NULL; | ||
| 2095 | } | ||
| 2096 | if (volume_info.username) | ||
| 2097 | strncpy(pSesInfo->userName, | ||
| 2098 | volume_info.username, | ||
| 2099 | MAX_USERNAME_SIZE); | ||
| 2100 | if (volume_info.domainname) { | ||
| 2101 | int len = strlen(volume_info.domainname); | ||
| 2102 | pSesInfo->domainName = | ||
| 2103 | kmalloc(len + 1, GFP_KERNEL); | ||
| 2104 | if (pSesInfo->domainName) | ||
| 2105 | strcpy(pSesInfo->domainName, | ||
| 2106 | volume_info.domainname); | ||
| 2107 | } | ||
| 2108 | pSesInfo->linux_uid = volume_info.linux_uid; | ||
| 2109 | pSesInfo->overrideSecFlg = volume_info.secFlg; | ||
| 2110 | down(&pSesInfo->sesSem); | ||
| 2111 | /* BB FIXME need to pass vol->secFlgs BB */ | ||
| 2112 | rc = cifs_setup_session(xid, pSesInfo, | ||
| 2113 | cifs_sb->local_nls); | ||
| 2114 | up(&pSesInfo->sesSem); | ||
| 2115 | if (!rc) | ||
| 2116 | atomic_inc(&srvTcp->socketUseCount); | ||
| 2117 | } | ||
| 2118 | } | 2262 | } |
| 2119 | 2263 | ||
| 2120 | /* search for existing tcon to this server share */ | 2264 | /* search for existing tcon to this server share */ |
| 2121 | if (!rc) { | 2265 | if (!rc) { |
| 2122 | if (volume_info.rsize > CIFSMaxBufSize) { | 2266 | setup_cifs_sb(&volume_info, cifs_sb); |
| 2123 | cERROR(1, ("rsize %d too large, using MaxBufSize", | ||
| 2124 | volume_info.rsize)); | ||
| 2125 | cifs_sb->rsize = CIFSMaxBufSize; | ||
| 2126 | } else if ((volume_info.rsize) && | ||
| 2127 | (volume_info.rsize <= CIFSMaxBufSize)) | ||
| 2128 | cifs_sb->rsize = volume_info.rsize; | ||
| 2129 | else /* default */ | ||
| 2130 | cifs_sb->rsize = CIFSMaxBufSize; | ||
| 2131 | |||
| 2132 | if (volume_info.wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) { | ||
| 2133 | cERROR(1, ("wsize %d too large, using 4096 instead", | ||
| 2134 | volume_info.wsize)); | ||
| 2135 | cifs_sb->wsize = 4096; | ||
| 2136 | } else if (volume_info.wsize) | ||
| 2137 | cifs_sb->wsize = volume_info.wsize; | ||
| 2138 | else | ||
| 2139 | cifs_sb->wsize = | ||
| 2140 | min_t(const int, PAGEVEC_SIZE * PAGE_CACHE_SIZE, | ||
| 2141 | 127*1024); | ||
| 2142 | /* old default of CIFSMaxBufSize was too small now | ||
| 2143 | that SMB Write2 can send multiple pages in kvec. | ||
| 2144 | RFC1001 does not describe what happens when frame | ||
| 2145 | bigger than 128K is sent so use that as max in | ||
| 2146 | conjunction with 52K kvec constraint on arch with 4K | ||
| 2147 | page size */ | ||
| 2148 | |||
| 2149 | if (cifs_sb->rsize < 2048) { | ||
| 2150 | cifs_sb->rsize = 2048; | ||
| 2151 | /* Windows ME may prefer this */ | ||
| 2152 | cFYI(1, ("readsize set to minimum: 2048")); | ||
| 2153 | } | ||
| 2154 | /* calculate prepath */ | ||
| 2155 | cifs_sb->prepath = volume_info.prepath; | ||
| 2156 | if (cifs_sb->prepath) { | ||
| 2157 | cifs_sb->prepathlen = strlen(cifs_sb->prepath); | ||
| 2158 | /* we can not convert the / to \ in the path | ||
| 2159 | separators in the prefixpath yet because we do not | ||
| 2160 | know (until reset_cifs_unix_caps is called later) | ||
| 2161 | whether POSIX PATH CAP is available. We normalize | ||
| 2162 | the / to \ after reset_cifs_unix_caps is called */ | ||
| 2163 | volume_info.prepath = NULL; | ||
| 2164 | } else | ||
| 2165 | cifs_sb->prepathlen = 0; | ||
| 2166 | cifs_sb->mnt_uid = volume_info.linux_uid; | ||
| 2167 | cifs_sb->mnt_gid = volume_info.linux_gid; | ||
| 2168 | cifs_sb->mnt_file_mode = volume_info.file_mode; | ||
| 2169 | cifs_sb->mnt_dir_mode = volume_info.dir_mode; | ||
| 2170 | cFYI(1, ("file mode: 0x%x dir mode: 0x%x", | ||
| 2171 | cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode)); | ||
| 2172 | |||
| 2173 | if (volume_info.noperm) | ||
| 2174 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; | ||
| 2175 | if (volume_info.setuids) | ||
| 2176 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; | ||
| 2177 | if (volume_info.server_ino) | ||
| 2178 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; | ||
| 2179 | if (volume_info.remap) | ||
| 2180 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
| 2181 | if (volume_info.no_xattr) | ||
| 2182 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; | ||
| 2183 | if (volume_info.sfu_emul) | ||
| 2184 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_UNX_EMUL; | ||
| 2185 | if (volume_info.nobrl) | ||
| 2186 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_BRL; | ||
| 2187 | if (volume_info.cifs_acl) | ||
| 2188 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; | ||
| 2189 | if (volume_info.override_uid) | ||
| 2190 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; | ||
| 2191 | if (volume_info.override_gid) | ||
| 2192 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; | ||
| 2193 | if (volume_info.dynperm) | ||
| 2194 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; | ||
| 2195 | if (volume_info.direct_io) { | ||
| 2196 | cFYI(1, ("mounting share using direct i/o")); | ||
| 2197 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | ||
| 2198 | } | ||
| 2199 | 2267 | ||
| 2200 | if ((volume_info.cifs_acl) && (volume_info.dynperm)) | 2268 | tcon = cifs_find_tcon(pSesInfo, volume_info.UNC); |
| 2201 | cERROR(1, ("mount option dynperm ignored if cifsacl " | ||
| 2202 | "mount option supported")); | ||
| 2203 | |||
| 2204 | tcon = | ||
| 2205 | find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, | ||
| 2206 | volume_info.username); | ||
| 2207 | if (tcon) { | 2269 | if (tcon) { |
| 2208 | cFYI(1, ("Found match on UNC path")); | 2270 | cFYI(1, ("Found match on UNC path")); |
| 2209 | /* we can have only one retry value for a connection | 2271 | /* existing tcon already has a reference */ |
| 2210 | to a share so for resources mounted more than once | 2272 | cifs_put_smb_ses(pSesInfo); |
| 2211 | to the same server share the last value passed in | ||
| 2212 | for the retry flag is used */ | ||
| 2213 | tcon->retry = volume_info.retry; | ||
| 2214 | tcon->nocase = volume_info.nocase; | ||
| 2215 | tcon->local_lease = volume_info.local_lease; | ||
| 2216 | if (tcon->seal != volume_info.seal) | 2273 | if (tcon->seal != volume_info.seal) |
| 2217 | cERROR(1, ("transport encryption setting " | 2274 | cERROR(1, ("transport encryption setting " |
| 2218 | "conflicts with existing tid")); | 2275 | "conflicts with existing tid")); |
| 2219 | } else { | 2276 | } else { |
| 2220 | tcon = tconInfoAlloc(); | 2277 | tcon = tconInfoAlloc(); |
| 2221 | if (tcon == NULL) | 2278 | if (tcon == NULL) { |
| 2222 | rc = -ENOMEM; | 2279 | rc = -ENOMEM; |
| 2223 | else { | 2280 | goto mount_fail_check; |
| 2224 | /* check for null share name ie connecting to | 2281 | } |
| 2225 | * dfs root */ | 2282 | tcon->ses = pSesInfo; |
| 2226 | 2283 | ||
| 2227 | /* BB check if this works for exactly length | 2284 | /* check for null share name ie connect to dfs root */ |
| 2228 | * three strings */ | 2285 | if ((strchr(volume_info.UNC + 3, '\\') == NULL) |
| 2229 | if ((strchr(volume_info.UNC + 3, '\\') == NULL) | 2286 | && (strchr(volume_info.UNC + 3, '/') == NULL)) { |
| 2230 | && (strchr(volume_info.UNC + 3, '/') == | 2287 | /* rc = connect_to_dfs_path(...) */ |
| 2231 | NULL)) { | 2288 | cFYI(1, ("DFS root not supported")); |
| 2232 | /* rc = connect_to_dfs_path(xid, pSesInfo, | 2289 | rc = -ENODEV; |
| 2233 | "", cifs_sb->local_nls, | 2290 | goto mount_fail_check; |
| 2234 | cifs_sb->mnt_cifs_flags & | 2291 | } else { |
| 2235 | CIFS_MOUNT_MAP_SPECIAL_CHR);*/ | 2292 | /* BB Do we need to wrap sesSem around |
| 2236 | cFYI(1, ("DFS root not supported")); | 2293 | * this TCon call and Unix SetFS as |
| 2237 | rc = -ENODEV; | 2294 | * we do on SessSetup and reconnect? */ |
| 2238 | goto out; | 2295 | rc = CIFSTCon(xid, pSesInfo, volume_info.UNC, |
| 2239 | } else { | 2296 | tcon, cifs_sb->local_nls); |
| 2240 | /* BB Do we need to wrap sesSem around | 2297 | cFYI(1, ("CIFS Tcon rc = %d", rc)); |
| 2241 | * this TCon call and Unix SetFS as | 2298 | if (volume_info.nodfs) { |
| 2242 | * we do on SessSetup and reconnect? */ | 2299 | tcon->Flags &= ~SMB_SHARE_IS_IN_DFS; |
| 2243 | rc = CIFSTCon(xid, pSesInfo, | 2300 | cFYI(1, ("DFS disabled (%d)", |
| 2244 | volume_info.UNC, | 2301 | tcon->Flags)); |
| 2245 | tcon, cifs_sb->local_nls); | ||
| 2246 | cFYI(1, ("CIFS Tcon rc = %d", rc)); | ||
| 2247 | if (volume_info.nodfs) { | ||
| 2248 | tcon->Flags &= | ||
| 2249 | ~SMB_SHARE_IS_IN_DFS; | ||
| 2250 | cFYI(1, ("DFS disabled (%d)", | ||
| 2251 | tcon->Flags)); | ||
| 2252 | } | ||
| 2253 | } | ||
| 2254 | if (!rc) { | ||
| 2255 | atomic_inc(&pSesInfo->inUse); | ||
| 2256 | tcon->retry = volume_info.retry; | ||
| 2257 | tcon->nocase = volume_info.nocase; | ||
| 2258 | tcon->seal = volume_info.seal; | ||
| 2259 | } | 2302 | } |
| 2260 | } | 2303 | } |
| 2261 | } | 2304 | if (rc) |
| 2305 | goto mount_fail_check; | ||
| 2306 | tcon->seal = volume_info.seal; | ||
| 2307 | write_lock(&cifs_tcp_ses_lock); | ||
| 2308 | list_add(&tcon->tcon_list, &pSesInfo->tcon_list); | ||
| 2309 | write_unlock(&cifs_tcp_ses_lock); | ||
| 2310 | } | ||
| 2311 | |||
| 2312 | /* we can have only one retry value for a connection | ||
| 2313 | to a share so for resources mounted more than once | ||
| 2314 | to the same server share the last value passed in | ||
| 2315 | for the retry flag is used */ | ||
| 2316 | tcon->retry = volume_info.retry; | ||
| 2317 | tcon->nocase = volume_info.nocase; | ||
| 2318 | tcon->local_lease = volume_info.local_lease; | ||
| 2262 | } | 2319 | } |
| 2263 | if (pSesInfo) { | 2320 | if (pSesInfo) { |
| 2264 | if (pSesInfo->capabilities & CAP_LARGE_FILES) { | 2321 | if (pSesInfo->capabilities & CAP_LARGE_FILES) { |
| @@ -2270,80 +2327,49 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2270 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ | 2327 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ |
| 2271 | sb->s_time_gran = 100; | 2328 | sb->s_time_gran = 100; |
| 2272 | 2329 | ||
| 2273 | /* on error free sesinfo and tcon struct if needed */ | 2330 | mount_fail_check: |
| 2331 | /* on error free sesinfo and tcon struct if needed */ | ||
| 2274 | if (rc) { | 2332 | if (rc) { |
| 2275 | /* if session setup failed, use count is zero but | 2333 | /* If find_unc succeeded then rc == 0 so we can not end */ |
| 2276 | we still need to free cifsd thread */ | 2334 | /* up accidently freeing someone elses tcon struct */ |
| 2277 | if (atomic_read(&srvTcp->socketUseCount) == 0) { | 2335 | if (tcon) |
| 2278 | spin_lock(&GlobalMid_Lock); | 2336 | cifs_put_tcon(tcon); |
| 2279 | srvTcp->tcpStatus = CifsExiting; | 2337 | else if (pSesInfo) |
| 2280 | spin_unlock(&GlobalMid_Lock); | 2338 | cifs_put_smb_ses(pSesInfo); |
| 2281 | kill_cifsd(srvTcp); | ||
| 2282 | } | ||
| 2283 | /* If find_unc succeeded then rc == 0 so we can not end */ | ||
| 2284 | if (tcon) /* up accidently freeing someone elses tcon struct */ | ||
| 2285 | tconInfoFree(tcon); | ||
| 2286 | if (existingCifsSes == NULL) { | ||
| 2287 | if (pSesInfo) { | ||
| 2288 | if ((pSesInfo->server) && | ||
| 2289 | (pSesInfo->status == CifsGood)) { | ||
| 2290 | int temp_rc; | ||
| 2291 | temp_rc = CIFSSMBLogoff(xid, pSesInfo); | ||
| 2292 | /* if the socketUseCount is now zero */ | ||
| 2293 | if ((temp_rc == -ESHUTDOWN) && | ||
| 2294 | (pSesInfo->server)) | ||
| 2295 | kill_cifsd(pSesInfo->server); | ||
| 2296 | } else { | ||
| 2297 | cFYI(1, ("No session or bad tcon")); | ||
| 2298 | if (pSesInfo->server) { | ||
| 2299 | spin_lock(&GlobalMid_Lock); | ||
| 2300 | srvTcp->tcpStatus = CifsExiting; | ||
| 2301 | spin_unlock(&GlobalMid_Lock); | ||
| 2302 | kill_cifsd(pSesInfo->server); | ||
| 2303 | } | ||
| 2304 | } | ||
| 2305 | sesInfoFree(pSesInfo); | ||
| 2306 | /* pSesInfo = NULL; */ | ||
| 2307 | } | ||
| 2308 | } | ||
| 2309 | } else { | ||
| 2310 | atomic_inc(&tcon->useCount); | ||
| 2311 | cifs_sb->tcon = tcon; | ||
| 2312 | tcon->ses = pSesInfo; | ||
| 2313 | |||
| 2314 | /* do not care if following two calls succeed - informational */ | ||
| 2315 | if (!tcon->ipc) { | ||
| 2316 | CIFSSMBQFSDeviceInfo(xid, tcon); | ||
| 2317 | CIFSSMBQFSAttributeInfo(xid, tcon); | ||
| 2318 | } | ||
| 2319 | |||
| 2320 | /* tell server which Unix caps we support */ | ||
| 2321 | if (tcon->ses->capabilities & CAP_UNIX) | ||
| 2322 | /* reset of caps checks mount to see if unix extensions | ||
| 2323 | disabled for just this mount */ | ||
| 2324 | reset_cifs_unix_caps(xid, tcon, sb, &volume_info); | ||
| 2325 | else | 2339 | else |
| 2326 | tcon->unix_ext = 0; /* server does not support them */ | 2340 | cifs_put_tcp_session(srvTcp); |
| 2341 | goto out; | ||
| 2342 | } | ||
| 2343 | cifs_sb->tcon = tcon; | ||
| 2327 | 2344 | ||
| 2328 | /* convert forward to back slashes in prepath here if needed */ | 2345 | /* do not care if following two calls succeed - informational */ |
| 2329 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) | 2346 | if (!tcon->ipc) { |
| 2330 | convert_delimiter(cifs_sb->prepath, | 2347 | CIFSSMBQFSDeviceInfo(xid, tcon); |
| 2331 | CIFS_DIR_SEP(cifs_sb)); | 2348 | CIFSSMBQFSAttributeInfo(xid, tcon); |
| 2349 | } | ||
| 2332 | 2350 | ||
| 2333 | if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) { | 2351 | /* tell server which Unix caps we support */ |
| 2334 | cifs_sb->rsize = 1024 * 127; | 2352 | if (tcon->ses->capabilities & CAP_UNIX) |
| 2335 | cFYI(DBG2, | 2353 | /* reset of caps checks mount to see if unix extensions |
| 2336 | ("no very large read support, rsize now 127K")); | 2354 | disabled for just this mount */ |
| 2337 | } | 2355 | reset_cifs_unix_caps(xid, tcon, sb, &volume_info); |
| 2338 | if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) | 2356 | else |
| 2339 | cifs_sb->wsize = min(cifs_sb->wsize, | 2357 | tcon->unix_ext = 0; /* server does not support them */ |
| 2340 | (tcon->ses->server->maxBuf - | 2358 | |
| 2341 | MAX_CIFS_HDR_SIZE)); | 2359 | /* convert forward to back slashes in prepath here if needed */ |
| 2342 | if (!(tcon->ses->capabilities & CAP_LARGE_READ_X)) | 2360 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0) |
| 2343 | cifs_sb->rsize = min(cifs_sb->rsize, | 2361 | convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb)); |
| 2344 | (tcon->ses->server->maxBuf - | 2362 | |
| 2345 | MAX_CIFS_HDR_SIZE)); | 2363 | if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) { |
| 2364 | cifs_sb->rsize = 1024 * 127; | ||
| 2365 | cFYI(DBG2, ("no very large read support, rsize now 127K")); | ||
| 2346 | } | 2366 | } |
| 2367 | if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) | ||
| 2368 | cifs_sb->wsize = min(cifs_sb->wsize, | ||
| 2369 | (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); | ||
| 2370 | if (!(tcon->ses->capabilities & CAP_LARGE_READ_X)) | ||
| 2371 | cifs_sb->rsize = min(cifs_sb->rsize, | ||
| 2372 | (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); | ||
| 2347 | 2373 | ||
| 2348 | /* volume_info.password is freed above when existing session found | 2374 | /* volume_info.password is freed above when existing session found |
| 2349 | (in which case it is not needed anymore) but when new sesion is created | 2375 | (in which case it is not needed anymore) but when new sesion is created |
| @@ -3513,6 +3539,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, | |||
| 3513 | /* above now done in SendReceive */ | 3539 | /* above now done in SendReceive */ |
| 3514 | if ((rc == 0) && (tcon != NULL)) { | 3540 | if ((rc == 0) && (tcon != NULL)) { |
| 3515 | tcon->tidStatus = CifsGood; | 3541 | tcon->tidStatus = CifsGood; |
| 3542 | tcon->need_reconnect = false; | ||
| 3516 | tcon->tid = smb_buffer_response->Tid; | 3543 | tcon->tid = smb_buffer_response->Tid; |
| 3517 | bcc_ptr = pByteArea(smb_buffer_response); | 3544 | bcc_ptr = pByteArea(smb_buffer_response); |
| 3518 | length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); | 3545 | length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2); |
| @@ -3584,48 +3611,17 @@ int | |||
| 3584 | cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | 3611 | cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) |
| 3585 | { | 3612 | { |
| 3586 | int rc = 0; | 3613 | int rc = 0; |
| 3587 | int xid; | ||
| 3588 | struct cifsSesInfo *ses = NULL; | ||
| 3589 | char *tmp; | 3614 | char *tmp; |
| 3590 | 3615 | ||
| 3591 | xid = GetXid(); | 3616 | if (cifs_sb->tcon) |
| 3592 | 3617 | cifs_put_tcon(cifs_sb->tcon); | |
| 3593 | if (cifs_sb->tcon) { | ||
| 3594 | ses = cifs_sb->tcon->ses; /* save ptr to ses before delete tcon!*/ | ||
| 3595 | rc = CIFSSMBTDis(xid, cifs_sb->tcon); | ||
| 3596 | if (rc == -EBUSY) { | ||
| 3597 | FreeXid(xid); | ||
| 3598 | return 0; | ||
| 3599 | } | ||
| 3600 | DeleteTconOplockQEntries(cifs_sb->tcon); | ||
| 3601 | tconInfoFree(cifs_sb->tcon); | ||
| 3602 | if ((ses) && (ses->server)) { | ||
| 3603 | /* save off task so we do not refer to ses later */ | ||
| 3604 | cFYI(1, ("About to do SMBLogoff ")); | ||
| 3605 | rc = CIFSSMBLogoff(xid, ses); | ||
| 3606 | if (rc == -EBUSY) { | ||
| 3607 | FreeXid(xid); | ||
| 3608 | return 0; | ||
| 3609 | } else if (rc == -ESHUTDOWN) { | ||
| 3610 | cFYI(1, ("Waking up socket by sending signal")); | ||
| 3611 | if (ses->server) | ||
| 3612 | kill_cifsd(ses->server); | ||
| 3613 | rc = 0; | ||
| 3614 | } /* else - we have an smb session | ||
| 3615 | left on this socket do not kill cifsd */ | ||
| 3616 | } else | ||
| 3617 | cFYI(1, ("No session or bad tcon")); | ||
| 3618 | } | ||
| 3619 | 3618 | ||
| 3620 | cifs_sb->tcon = NULL; | 3619 | cifs_sb->tcon = NULL; |
| 3621 | tmp = cifs_sb->prepath; | 3620 | tmp = cifs_sb->prepath; |
| 3622 | cifs_sb->prepathlen = 0; | 3621 | cifs_sb->prepathlen = 0; |
| 3623 | cifs_sb->prepath = NULL; | 3622 | cifs_sb->prepath = NULL; |
| 3624 | kfree(tmp); | 3623 | kfree(tmp); |
| 3625 | if (ses) | ||
| 3626 | sesInfoFree(ses); | ||
| 3627 | 3624 | ||
| 3628 | FreeXid(xid); | ||
| 3629 | return rc; | 3625 | return rc; |
| 3630 | } | 3626 | } |
| 3631 | 3627 | ||
| @@ -3741,6 +3737,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, | |||
| 3741 | cFYI(1, ("CIFS Session Established successfully")); | 3737 | cFYI(1, ("CIFS Session Established successfully")); |
| 3742 | spin_lock(&GlobalMid_Lock); | 3738 | spin_lock(&GlobalMid_Lock); |
| 3743 | pSesInfo->status = CifsGood; | 3739 | pSesInfo->status = CifsGood; |
| 3740 | pSesInfo->need_reconnect = false; | ||
| 3744 | spin_unlock(&GlobalMid_Lock); | 3741 | spin_unlock(&GlobalMid_Lock); |
| 3745 | } | 3742 | } |
| 3746 | 3743 | ||
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ead1a3bb0256..6449e1aae621 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -493,7 +493,7 @@ int cifs_close(struct inode *inode, struct file *file) | |||
| 493 | if (pTcon) { | 493 | if (pTcon) { |
| 494 | /* no sense reconnecting to close a file that is | 494 | /* no sense reconnecting to close a file that is |
| 495 | already closed */ | 495 | already closed */ |
| 496 | if (pTcon->tidStatus != CifsNeedReconnect) { | 496 | if (!pTcon->need_reconnect) { |
| 497 | timeout = 2; | 497 | timeout = 2; |
| 498 | while ((atomic_read(&pSMBFile->wrtPending) != 0) | 498 | while ((atomic_read(&pSMBFile->wrtPending) != 0) |
| 499 | && (timeout <= 2048)) { | 499 | && (timeout <= 2048)) { |
| @@ -1404,7 +1404,10 @@ retry: | |||
| 1404 | if ((wbc->nr_to_write -= n_iov) <= 0) | 1404 | if ((wbc->nr_to_write -= n_iov) <= 0) |
| 1405 | done = 1; | 1405 | done = 1; |
| 1406 | index = next; | 1406 | index = next; |
| 1407 | } | 1407 | } else |
| 1408 | /* Need to re-find the pages we skipped */ | ||
| 1409 | index = pvec.pages[0]->index + 1; | ||
| 1410 | |||
| 1408 | pagevec_release(&pvec); | 1411 | pagevec_release(&pvec); |
| 1409 | } | 1412 | } |
| 1410 | if (!scanned && !done) { | 1413 | if (!scanned && !done) { |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 88786ba02d27..addd1dcc2d79 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
| @@ -75,12 +75,12 @@ sesInfoAlloc(void) | |||
| 75 | 75 | ||
| 76 | ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL); | 76 | ret_buf = kzalloc(sizeof(struct cifsSesInfo), GFP_KERNEL); |
| 77 | if (ret_buf) { | 77 | if (ret_buf) { |
| 78 | write_lock(&GlobalSMBSeslock); | ||
| 79 | atomic_inc(&sesInfoAllocCount); | 78 | atomic_inc(&sesInfoAllocCount); |
| 80 | ret_buf->status = CifsNew; | 79 | ret_buf->status = CifsNew; |
| 81 | list_add(&ret_buf->cifsSessionList, &GlobalSMBSessionList); | 80 | ++ret_buf->ses_count; |
| 81 | INIT_LIST_HEAD(&ret_buf->smb_ses_list); | ||
| 82 | INIT_LIST_HEAD(&ret_buf->tcon_list); | ||
| 82 | init_MUTEX(&ret_buf->sesSem); | 83 | init_MUTEX(&ret_buf->sesSem); |
| 83 | write_unlock(&GlobalSMBSeslock); | ||
| 84 | } | 84 | } |
| 85 | return ret_buf; | 85 | return ret_buf; |
| 86 | } | 86 | } |
| @@ -93,10 +93,7 @@ sesInfoFree(struct cifsSesInfo *buf_to_free) | |||
| 93 | return; | 93 | return; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | write_lock(&GlobalSMBSeslock); | ||
| 97 | atomic_dec(&sesInfoAllocCount); | 96 | atomic_dec(&sesInfoAllocCount); |
| 98 | list_del(&buf_to_free->cifsSessionList); | ||
| 99 | write_unlock(&GlobalSMBSeslock); | ||
| 100 | kfree(buf_to_free->serverOS); | 97 | kfree(buf_to_free->serverOS); |
| 101 | kfree(buf_to_free->serverDomain); | 98 | kfree(buf_to_free->serverDomain); |
| 102 | kfree(buf_to_free->serverNOS); | 99 | kfree(buf_to_free->serverNOS); |
| @@ -111,17 +108,14 @@ tconInfoAlloc(void) | |||
| 111 | struct cifsTconInfo *ret_buf; | 108 | struct cifsTconInfo *ret_buf; |
| 112 | ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL); | 109 | ret_buf = kzalloc(sizeof(struct cifsTconInfo), GFP_KERNEL); |
| 113 | if (ret_buf) { | 110 | if (ret_buf) { |
| 114 | write_lock(&GlobalSMBSeslock); | ||
| 115 | atomic_inc(&tconInfoAllocCount); | 111 | atomic_inc(&tconInfoAllocCount); |
| 116 | list_add(&ret_buf->cifsConnectionList, | ||
| 117 | &GlobalTreeConnectionList); | ||
| 118 | ret_buf->tidStatus = CifsNew; | 112 | ret_buf->tidStatus = CifsNew; |
| 113 | ++ret_buf->tc_count; | ||
| 119 | INIT_LIST_HEAD(&ret_buf->openFileList); | 114 | INIT_LIST_HEAD(&ret_buf->openFileList); |
| 120 | init_MUTEX(&ret_buf->tconSem); | 115 | INIT_LIST_HEAD(&ret_buf->tcon_list); |
| 121 | #ifdef CONFIG_CIFS_STATS | 116 | #ifdef CONFIG_CIFS_STATS |
| 122 | spin_lock_init(&ret_buf->stat_lock); | 117 | spin_lock_init(&ret_buf->stat_lock); |
| 123 | #endif | 118 | #endif |
| 124 | write_unlock(&GlobalSMBSeslock); | ||
| 125 | } | 119 | } |
| 126 | return ret_buf; | 120 | return ret_buf; |
| 127 | } | 121 | } |
| @@ -133,10 +127,7 @@ tconInfoFree(struct cifsTconInfo *buf_to_free) | |||
| 133 | cFYI(1, ("Null buffer passed to tconInfoFree")); | 127 | cFYI(1, ("Null buffer passed to tconInfoFree")); |
| 134 | return; | 128 | return; |
| 135 | } | 129 | } |
| 136 | write_lock(&GlobalSMBSeslock); | ||
| 137 | atomic_dec(&tconInfoAllocCount); | 130 | atomic_dec(&tconInfoAllocCount); |
| 138 | list_del(&buf_to_free->cifsConnectionList); | ||
| 139 | write_unlock(&GlobalSMBSeslock); | ||
| 140 | kfree(buf_to_free->nativeFileSystem); | 131 | kfree(buf_to_free->nativeFileSystem); |
| 141 | kfree(buf_to_free); | 132 | kfree(buf_to_free); |
| 142 | } | 133 | } |
| @@ -350,9 +341,9 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
| 350 | if (current->fsuid != treeCon->ses->linux_uid) { | 341 | if (current->fsuid != treeCon->ses->linux_uid) { |
| 351 | cFYI(1, ("Multiuser mode and UID " | 342 | cFYI(1, ("Multiuser mode and UID " |
| 352 | "did not match tcon uid")); | 343 | "did not match tcon uid")); |
| 353 | read_lock(&GlobalSMBSeslock); | 344 | read_lock(&cifs_tcp_ses_lock); |
| 354 | list_for_each(temp_item, &GlobalSMBSessionList) { | 345 | list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) { |
| 355 | ses = list_entry(temp_item, struct cifsSesInfo, cifsSessionList); | 346 | ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list); |
| 356 | if (ses->linux_uid == current->fsuid) { | 347 | if (ses->linux_uid == current->fsuid) { |
| 357 | if (ses->server == treeCon->ses->server) { | 348 | if (ses->server == treeCon->ses->server) { |
| 358 | cFYI(1, ("found matching uid substitute right smb_uid")); | 349 | cFYI(1, ("found matching uid substitute right smb_uid")); |
| @@ -364,7 +355,7 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , | |||
| 364 | } | 355 | } |
| 365 | } | 356 | } |
| 366 | } | 357 | } |
| 367 | read_unlock(&GlobalSMBSeslock); | 358 | read_unlock(&cifs_tcp_ses_lock); |
| 368 | } | 359 | } |
| 369 | } | 360 | } |
| 370 | } | 361 | } |
| @@ -497,9 +488,10 @@ bool | |||
| 497 | is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | 488 | is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) |
| 498 | { | 489 | { |
| 499 | struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf; | 490 | struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf; |
| 500 | struct list_head *tmp; | 491 | struct list_head *tmp, *tmp1, *tmp2; |
| 501 | struct list_head *tmp1; | 492 | struct cifsSesInfo *ses; |
| 502 | struct cifsTconInfo *tcon; | 493 | struct cifsTconInfo *tcon; |
| 494 | struct cifsInodeInfo *pCifsInode; | ||
| 503 | struct cifsFileInfo *netfile; | 495 | struct cifsFileInfo *netfile; |
| 504 | 496 | ||
| 505 | cFYI(1, ("Checking for oplock break or dnotify response")); | 497 | cFYI(1, ("Checking for oplock break or dnotify response")); |
| @@ -554,42 +546,42 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
| 554 | return false; | 546 | return false; |
| 555 | 547 | ||
| 556 | /* look up tcon based on tid & uid */ | 548 | /* look up tcon based on tid & uid */ |
| 557 | read_lock(&GlobalSMBSeslock); | 549 | read_lock(&cifs_tcp_ses_lock); |
| 558 | list_for_each(tmp, &GlobalTreeConnectionList) { | 550 | list_for_each(tmp, &srv->smb_ses_list) { |
| 559 | tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); | 551 | ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); |
| 560 | if ((tcon->tid == buf->Tid) && (srv == tcon->ses->server)) { | 552 | list_for_each(tmp1, &ses->tcon_list) { |
| 553 | tcon = list_entry(tmp1, struct cifsTconInfo, tcon_list); | ||
| 554 | if (tcon->tid != buf->Tid) | ||
| 555 | continue; | ||
| 556 | |||
| 561 | cifs_stats_inc(&tcon->num_oplock_brks); | 557 | cifs_stats_inc(&tcon->num_oplock_brks); |
| 562 | list_for_each(tmp1, &tcon->openFileList) { | 558 | list_for_each(tmp2, &tcon->openFileList) { |
| 563 | netfile = list_entry(tmp1, struct cifsFileInfo, | 559 | netfile = list_entry(tmp2, struct cifsFileInfo, |
| 564 | tlist); | 560 | tlist); |
| 565 | if (pSMB->Fid == netfile->netfid) { | 561 | if (pSMB->Fid != netfile->netfid) |
| 566 | struct cifsInodeInfo *pCifsInode; | 562 | continue; |
| 567 | read_unlock(&GlobalSMBSeslock); | 563 | |
| 568 | cFYI(1, | 564 | read_unlock(&cifs_tcp_ses_lock); |
| 569 | ("file id match, oplock break")); | 565 | cFYI(1, ("file id match, oplock break")); |
| 570 | pCifsInode = | 566 | pCifsInode = CIFS_I(netfile->pInode); |
| 571 | CIFS_I(netfile->pInode); | 567 | pCifsInode->clientCanCacheAll = false; |
| 572 | pCifsInode->clientCanCacheAll = false; | 568 | if (pSMB->OplockLevel == 0) |
| 573 | if (pSMB->OplockLevel == 0) | 569 | pCifsInode->clientCanCacheRead = false; |
| 574 | pCifsInode->clientCanCacheRead | 570 | pCifsInode->oplockPending = true; |
| 575 | = false; | 571 | AllocOplockQEntry(netfile->pInode, |
| 576 | pCifsInode->oplockPending = true; | 572 | netfile->netfid, tcon); |
| 577 | AllocOplockQEntry(netfile->pInode, | 573 | cFYI(1, ("about to wake up oplock thread")); |
| 578 | netfile->netfid, | 574 | if (oplockThread) |
| 579 | tcon); | 575 | wake_up_process(oplockThread); |
| 580 | cFYI(1, | 576 | |
| 581 | ("about to wake up oplock thread")); | 577 | return true; |
| 582 | if (oplockThread) | ||
| 583 | wake_up_process(oplockThread); | ||
| 584 | return true; | ||
| 585 | } | ||
| 586 | } | 578 | } |
| 587 | read_unlock(&GlobalSMBSeslock); | 579 | read_unlock(&cifs_tcp_ses_lock); |
| 588 | cFYI(1, ("No matching file for oplock break")); | 580 | cFYI(1, ("No matching file for oplock break")); |
| 589 | return true; | 581 | return true; |
| 590 | } | 582 | } |
| 591 | } | 583 | } |
| 592 | read_unlock(&GlobalSMBSeslock); | 584 | read_unlock(&cifs_tcp_ses_lock); |
| 593 | cFYI(1, ("Can not process oplock break for non-existent connection")); | 585 | cFYI(1, ("Can not process oplock break for non-existent connection")); |
| 594 | return true; | 586 | return true; |
| 595 | } | 587 | } |
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 94fcfff6863a..06ed10b7da9e 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
| @@ -31,6 +31,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb, | |||
| 31 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 31 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
| 32 | inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */ | 32 | inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */ |
| 33 | inode->i_mode = table->mode; | 33 | inode->i_mode = table->mode; |
| 34 | inode->i_uid = inode->i_gid = 0; | ||
| 34 | if (!table->child) { | 35 | if (!table->child) { |
| 35 | inode->i_mode |= S_IFREG; | 36 | inode->i_mode |= S_IFREG; |
| 36 | inode->i_op = &proc_sys_inode_operations; | 37 | inode->i_op = &proc_sys_inode_operations; |
diff --git a/include/linux/input.h b/include/linux/input.h index b86fb5581ce6..5341e8251f8c 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
| @@ -238,6 +238,7 @@ struct input_absinfo { | |||
| 238 | #define KEY_KPEQUAL 117 | 238 | #define KEY_KPEQUAL 117 |
| 239 | #define KEY_KPPLUSMINUS 118 | 239 | #define KEY_KPPLUSMINUS 118 |
| 240 | #define KEY_PAUSE 119 | 240 | #define KEY_PAUSE 119 |
| 241 | #define KEY_SCALE 120 /* AL Compiz Scale (Expose) */ | ||
| 241 | 242 | ||
| 242 | #define KEY_KPCOMMA 121 | 243 | #define KEY_KPCOMMA 121 |
| 243 | #define KEY_HANGEUL 122 | 244 | #define KEY_HANGEUL 122 |
| @@ -322,6 +323,7 @@ struct input_absinfo { | |||
| 322 | #define KEY_PAUSECD 201 | 323 | #define KEY_PAUSECD 201 |
| 323 | #define KEY_PROG3 202 | 324 | #define KEY_PROG3 202 |
| 324 | #define KEY_PROG4 203 | 325 | #define KEY_PROG4 203 |
| 326 | #define KEY_DASHBOARD 204 /* AL Dashboard */ | ||
| 325 | #define KEY_SUSPEND 205 | 327 | #define KEY_SUSPEND 205 |
| 326 | #define KEY_CLOSE 206 /* AC Close */ | 328 | #define KEY_CLOSE 206 /* AC Close */ |
| 327 | #define KEY_PLAY 207 | 329 | #define KEY_PLAY 207 |
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 331e5f1c2d8e..29aec6e10020 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h | |||
| @@ -331,10 +331,11 @@ static inline void lockdep_on(void) | |||
| 331 | # define lock_set_subclass(l, s, i) do { } while (0) | 331 | # define lock_set_subclass(l, s, i) do { } while (0) |
| 332 | # define lockdep_init() do { } while (0) | 332 | # define lockdep_init() do { } while (0) |
| 333 | # define lockdep_info() do { } while (0) | 333 | # define lockdep_info() do { } while (0) |
| 334 | # define lockdep_init_map(lock, name, key, sub) do { (void)(key); } while (0) | 334 | # define lockdep_init_map(lock, name, key, sub) \ |
| 335 | do { (void)(name); (void)(key); } while (0) | ||
| 335 | # define lockdep_set_class(lock, key) do { (void)(key); } while (0) | 336 | # define lockdep_set_class(lock, key) do { (void)(key); } while (0) |
| 336 | # define lockdep_set_class_and_name(lock, key, name) \ | 337 | # define lockdep_set_class_and_name(lock, key, name) \ |
| 337 | do { (void)(key); } while (0) | 338 | do { (void)(key); (void)(name); } while (0) |
| 338 | #define lockdep_set_class_and_subclass(lock, key, sub) \ | 339 | #define lockdep_set_class_and_subclass(lock, key, sub) \ |
| 339 | do { (void)(key); } while (0) | 340 | do { (void)(key); } while (0) |
| 340 | #define lockdep_set_subclass(lock, sub) do { } while (0) | 341 | #define lockdep_set_subclass(lock, sub) do { } while (0) |
diff --git a/include/net/sock.h b/include/net/sock.h index c04f9e18ea22..2f47107f6d0f 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
| @@ -815,7 +815,7 @@ static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb) | |||
| 815 | */ | 815 | */ |
| 816 | #define sock_lock_init_class_and_name(sk, sname, skey, name, key) \ | 816 | #define sock_lock_init_class_and_name(sk, sname, skey, name, key) \ |
| 817 | do { \ | 817 | do { \ |
| 818 | sk->sk_lock.owned = 0; \ | 818 | sk->sk_lock.owned = 0; \ |
| 819 | init_waitqueue_head(&sk->sk_lock.wq); \ | 819 | init_waitqueue_head(&sk->sk_lock.wq); \ |
| 820 | spin_lock_init(&(sk)->sk_lock.slock); \ | 820 | spin_lock_init(&(sk)->sk_lock.slock); \ |
| 821 | debug_check_no_locks_freed((void *)&(sk)->sk_lock, \ | 821 | debug_check_no_locks_freed((void *)&(sk)->sk_lock, \ |
diff --git a/kernel/Makefile b/kernel/Makefile index 9a3ec66a9d84..19fad003b19d 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
| @@ -11,8 +11,6 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ | |||
| 11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ | 11 | hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ |
| 12 | notifier.o ksysfs.o pm_qos_params.o sched_clock.o | 12 | notifier.o ksysfs.o pm_qos_params.o sched_clock.o |
| 13 | 13 | ||
| 14 | CFLAGS_REMOVE_sched.o = -mno-spe | ||
| 15 | |||
| 16 | ifdef CONFIG_FUNCTION_TRACER | 14 | ifdef CONFIG_FUNCTION_TRACER |
| 17 | # Do not trace debug files and internal ftrace files | 15 | # Do not trace debug files and internal ftrace files |
| 18 | CFLAGS_REMOVE_lockdep.o = -pg | 16 | CFLAGS_REMOVE_lockdep.o = -pg |
| @@ -21,7 +19,7 @@ CFLAGS_REMOVE_mutex-debug.o = -pg | |||
| 21 | CFLAGS_REMOVE_rtmutex-debug.o = -pg | 19 | CFLAGS_REMOVE_rtmutex-debug.o = -pg |
| 22 | CFLAGS_REMOVE_cgroup-debug.o = -pg | 20 | CFLAGS_REMOVE_cgroup-debug.o = -pg |
| 23 | CFLAGS_REMOVE_sched_clock.o = -pg | 21 | CFLAGS_REMOVE_sched_clock.o = -pg |
| 24 | CFLAGS_REMOVE_sched.o = -mno-spe -pg | 22 | CFLAGS_REMOVE_sched.o = -pg |
| 25 | endif | 23 | endif |
| 26 | 24 | ||
| 27 | obj-$(CONFIG_FREEZER) += freezer.o | 25 | obj-$(CONFIG_FREEZER) += freezer.o |
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 9bc4c00872c9..24e8ceacc388 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c | |||
| @@ -112,7 +112,7 @@ static int chill(void *unused) | |||
| 112 | int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus) | 112 | int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus) |
| 113 | { | 113 | { |
| 114 | struct work_struct *sm_work; | 114 | struct work_struct *sm_work; |
| 115 | int i; | 115 | int i, ret; |
| 116 | 116 | ||
| 117 | /* Set up initial state. */ | 117 | /* Set up initial state. */ |
| 118 | mutex_lock(&lock); | 118 | mutex_lock(&lock); |
| @@ -137,8 +137,9 @@ int __stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus) | |||
| 137 | /* This will release the thread on our CPU. */ | 137 | /* This will release the thread on our CPU. */ |
| 138 | put_cpu(); | 138 | put_cpu(); |
| 139 | flush_workqueue(stop_machine_wq); | 139 | flush_workqueue(stop_machine_wq); |
| 140 | ret = active.fnret; | ||
| 140 | mutex_unlock(&lock); | 141 | mutex_unlock(&lock); |
| 141 | return active.fnret; | 142 | return ret; |
| 142 | } | 143 | } |
| 143 | 144 | ||
| 144 | int stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus) | 145 | int stop_machine(int (*fn)(void *), void *data, const cpumask_t *cpus) |
diff --git a/mm/mlock.c b/mm/mlock.c index a6da2aee940a..1ada366570cb 100644 --- a/mm/mlock.c +++ b/mm/mlock.c | |||
| @@ -162,7 +162,7 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma, | |||
| 162 | unsigned long addr = start; | 162 | unsigned long addr = start; |
| 163 | struct page *pages[16]; /* 16 gives a reasonable batch */ | 163 | struct page *pages[16]; /* 16 gives a reasonable batch */ |
| 164 | int nr_pages = (end - start) / PAGE_SIZE; | 164 | int nr_pages = (end - start) / PAGE_SIZE; |
| 165 | int ret; | 165 | int ret = 0; |
| 166 | int gup_flags = 0; | 166 | int gup_flags = 0; |
| 167 | 167 | ||
| 168 | VM_BUG_ON(start & ~PAGE_MASK); | 168 | VM_BUG_ON(start & ~PAGE_MASK); |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 31f29d2989fd..4dfb6b4d4559 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -878,7 +878,9 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
| 878 | if (ifm->ifi_change) | 878 | if (ifm->ifi_change) |
| 879 | flags = (flags & ifm->ifi_change) | | 879 | flags = (flags & ifm->ifi_change) | |
| 880 | (dev->flags & ~ifm->ifi_change); | 880 | (dev->flags & ~ifm->ifi_change); |
| 881 | dev_change_flags(dev, flags); | 881 | err = dev_change_flags(dev, flags); |
| 882 | if (err < 0) | ||
| 883 | goto errout; | ||
| 882 | } | 884 | } |
| 883 | 885 | ||
| 884 | if (tb[IFLA_TXQLEN]) | 886 | if (tb[IFLA_TXQLEN]) |
diff --git a/net/core/scm.c b/net/core/scm.c index ab242cc1acca..b12303dd39d9 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
| @@ -75,7 +75,6 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) | |||
| 75 | if (!fpl) | 75 | if (!fpl) |
| 76 | return -ENOMEM; | 76 | return -ENOMEM; |
| 77 | *fplp = fpl; | 77 | *fplp = fpl; |
| 78 | INIT_LIST_HEAD(&fpl->list); | ||
| 79 | fpl->count = 0; | 78 | fpl->count = 0; |
| 80 | } | 79 | } |
| 81 | fpp = &fpl->fp[fpl->count]; | 80 | fpp = &fpl->fp[fpl->count]; |
| @@ -301,7 +300,6 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl) | |||
| 301 | 300 | ||
| 302 | new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL); | 301 | new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL); |
| 303 | if (new_fpl) { | 302 | if (new_fpl) { |
| 304 | INIT_LIST_HEAD(&new_fpl->list); | ||
| 305 | for (i=fpl->count-1; i>=0; i--) | 303 | for (i=fpl->count-1; i>=0; i--) |
| 306 | get_file(fpl->fp[i]); | 304 | get_file(fpl->fp[i]); |
| 307 | memcpy(new_fpl, fpl, sizeof(*fpl)); | 305 | memcpy(new_fpl, fpl, sizeof(*fpl)); |
diff --git a/net/core/sock.c b/net/core/sock.c index 5e2a3132a8c9..341e39456952 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -136,7 +136,6 @@ | |||
| 136 | static struct lock_class_key af_family_keys[AF_MAX]; | 136 | static struct lock_class_key af_family_keys[AF_MAX]; |
| 137 | static struct lock_class_key af_family_slock_keys[AF_MAX]; | 137 | static struct lock_class_key af_family_slock_keys[AF_MAX]; |
| 138 | 138 | ||
| 139 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 140 | /* | 139 | /* |
| 141 | * Make lock validator output more readable. (we pre-construct these | 140 | * Make lock validator output more readable. (we pre-construct these |
| 142 | * strings build-time, so that runtime initialization of socket | 141 | * strings build-time, so that runtime initialization of socket |
| @@ -187,7 +186,6 @@ static const char *af_family_clock_key_strings[AF_MAX+1] = { | |||
| 187 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , | 186 | "clock-AF_RXRPC" , "clock-AF_ISDN" , "clock-AF_PHONET" , |
| 188 | "clock-AF_MAX" | 187 | "clock-AF_MAX" |
| 189 | }; | 188 | }; |
| 190 | #endif | ||
| 191 | 189 | ||
| 192 | /* | 190 | /* |
| 193 | * sk_callback_lock locking rules are per-address-family, | 191 | * sk_callback_lock locking rules are per-address-family, |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 861978a4f1a8..cfb38ac9d698 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
| @@ -209,9 +209,17 @@ static int ip_local_deliver_finish(struct sk_buff *skb) | |||
| 209 | 209 | ||
| 210 | hash = protocol & (MAX_INET_PROTOS - 1); | 210 | hash = protocol & (MAX_INET_PROTOS - 1); |
| 211 | ipprot = rcu_dereference(inet_protos[hash]); | 211 | ipprot = rcu_dereference(inet_protos[hash]); |
| 212 | if (ipprot != NULL && (net == &init_net || ipprot->netns_ok)) { | 212 | if (ipprot != NULL) { |
| 213 | int ret; | 213 | int ret; |
| 214 | 214 | ||
| 215 | if (!net_eq(net, &init_net) && !ipprot->netns_ok) { | ||
| 216 | if (net_ratelimit()) | ||
| 217 | printk("%s: proto %d isn't netns-ready\n", | ||
| 218 | __func__, protocol); | ||
| 219 | kfree_skb(skb); | ||
| 220 | goto out; | ||
| 221 | } | ||
| 222 | |||
| 215 | if (!ipprot->no_policy) { | 223 | if (!ipprot->no_policy) { |
| 216 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 224 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
| 217 | kfree_skb(skb); | 225 | kfree_skb(skb); |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 410046a8cc91..e44deb8d4df2 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
| @@ -661,6 +661,11 @@ int datagram_send_ctl(struct net *net, | |||
| 661 | switch (rthdr->type) { | 661 | switch (rthdr->type) { |
| 662 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 662 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
| 663 | case IPV6_SRCRT_TYPE_2: | 663 | case IPV6_SRCRT_TYPE_2: |
| 664 | if (rthdr->hdrlen != 2 || | ||
| 665 | rthdr->segments_left != 1) { | ||
| 666 | err = -EINVAL; | ||
| 667 | goto exit_f; | ||
| 668 | } | ||
| 664 | break; | 669 | break; |
| 665 | #endif | 670 | #endif |
| 666 | default: | 671 | default: |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 4e5eac301f91..2aa294be0c79 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
| @@ -366,11 +366,16 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 366 | } | 366 | } |
| 367 | 367 | ||
| 368 | /* routing header option needs extra check */ | 368 | /* routing header option needs extra check */ |
| 369 | retv = -EINVAL; | ||
| 369 | if (optname == IPV6_RTHDR && opt && opt->srcrt) { | 370 | if (optname == IPV6_RTHDR && opt && opt->srcrt) { |
| 370 | struct ipv6_rt_hdr *rthdr = opt->srcrt; | 371 | struct ipv6_rt_hdr *rthdr = opt->srcrt; |
| 371 | switch (rthdr->type) { | 372 | switch (rthdr->type) { |
| 372 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 373 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
| 373 | case IPV6_SRCRT_TYPE_2: | 374 | case IPV6_SRCRT_TYPE_2: |
| 375 | if (rthdr->hdrlen != 2 || | ||
| 376 | rthdr->segments_left != 1) | ||
| 377 | goto sticky_done; | ||
| 378 | |||
| 374 | break; | 379 | break; |
| 375 | #endif | 380 | #endif |
| 376 | default: | 381 | default: |
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index defeb7a0d502..7ab30f668b5a 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c | |||
| @@ -144,8 +144,8 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev, | |||
| 144 | struct phonethdr *ph; | 144 | struct phonethdr *ph; |
| 145 | int err; | 145 | int err; |
| 146 | 146 | ||
| 147 | if (skb->len + 2 > 0xffff) { | 147 | if (skb->len + 2 > 0xffff /* Phonet length field limit */ || |
| 148 | /* Phonet length field would overflow */ | 148 | skb->len + sizeof(struct phonethdr) > dev->mtu) { |
| 149 | err = -EMSGSIZE; | 149 | err = -EMSGSIZE; |
| 150 | goto drop; | 150 | goto drop; |
| 151 | } | 151 | } |
