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 | } |