diff options
author | Markus Lidel <Markus.Lidel@shadowconnect.com> | 2005-06-24 01:02:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 03:05:28 -0400 |
commit | 61fbfa8129c1771061a0e9f47747854293081c5b (patch) | |
tree | 03fe14c41e2a49d3841ae6820a2dd43a91fddee9 /drivers/message/i2o | |
parent | 34d6e07570ef74b965131452a862b13dfa779188 (diff) |
[PATCH] I2O: bugfixes and compability enhancements
Changes:
- Fixed sysfs bug where user and parent links where added to the I2O
device itself
- Fixed bug when calculating TID for the event handler and cleaned up the
workflow of i2o_driver_dispatch()
- Fixed oops when no I2O device could be found for an event delivered to
Exec-OSM
- Fixed initialization of spinlock in Exec-OSM
- Fixed memory leak in i2o_cfg_passthru() and i2o_cfg_passthru()
- Removed MTRR support
- Added PCI ID of Promise SX6000 with firmware >= 1.20.x.x
- Turn of caching for ioremapped memory of in_queue
- Added initialization sequence for Promise controllers
- Moved definition of u8 / u16 / u32 for raidutils before first use
Signed-off-by: Markus Lidel <Markus.Lidel@shadowconnect.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/message/i2o')
-rw-r--r-- | drivers/message/i2o/device.c | 10 | ||||
-rw-r--r-- | drivers/message/i2o/driver.c | 89 | ||||
-rw-r--r-- | drivers/message/i2o/exec-osm.c | 9 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_config.c | 48 | ||||
-rw-r--r-- | drivers/message/i2o/i2o_scsi.c | 3 | ||||
-rw-r--r-- | drivers/message/i2o/pci.c | 93 |
6 files changed, 116 insertions, 136 deletions
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index eb907e87bc7b..280627ae6cf7 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c | |||
@@ -401,25 +401,27 @@ static int i2o_device_class_add(struct class_device *cd) | |||
401 | 401 | ||
402 | /* create user entries for this device */ | 402 | /* create user entries for this device */ |
403 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); | 403 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid); |
404 | if (tmp) | 404 | if (tmp && (tmp != i2o_dev)) |
405 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, | 405 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, |
406 | "user"); | 406 | "user"); |
407 | 407 | ||
408 | /* create user entries refering to this device */ | 408 | /* create user entries refering to this device */ |
409 | list_for_each_entry(tmp, &c->devices, list) | 409 | list_for_each_entry(tmp, &c->devices, list) |
410 | if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid) | 410 | if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid) |
411 | && (tmp != i2o_dev)) | ||
411 | sysfs_create_link(&tmp->device.kobj, | 412 | sysfs_create_link(&tmp->device.kobj, |
412 | &i2o_dev->device.kobj, "user"); | 413 | &i2o_dev->device.kobj, "user"); |
413 | 414 | ||
414 | /* create parent entries for this device */ | 415 | /* create parent entries for this device */ |
415 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); | 416 | tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid); |
416 | if (tmp) | 417 | if (tmp && (tmp != i2o_dev)) |
417 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, | 418 | sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj, |
418 | "parent"); | 419 | "parent"); |
419 | 420 | ||
420 | /* create parent entries refering to this device */ | 421 | /* create parent entries refering to this device */ |
421 | list_for_each_entry(tmp, &c->devices, list) | 422 | list_for_each_entry(tmp, &c->devices, list) |
422 | if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) | 423 | if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid) |
424 | && (tmp != i2o_dev)) | ||
423 | sysfs_create_link(&tmp->device.kobj, | 425 | sysfs_create_link(&tmp->device.kobj, |
424 | &i2o_dev->device.kobj, "parent"); | 426 | &i2o_dev->device.kobj, "parent"); |
425 | 427 | ||
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c index 91f4edbb2a27..c71e68f70e7d 100644 --- a/drivers/message/i2o/driver.c +++ b/drivers/message/i2o/driver.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/rwsem.h> | 18 | #include <linux/rwsem.h> |
19 | #include <linux/i2o.h> | 19 | #include <linux/i2o.h> |
20 | 20 | ||
21 | #define OSM_NAME "core" | ||
22 | |||
21 | /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ | 23 | /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */ |
22 | unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; | 24 | unsigned int i2o_max_drivers = I2O_MAX_DRIVERS; |
23 | module_param_named(max_drivers, i2o_max_drivers, uint, 0); | 25 | module_param_named(max_drivers, i2o_max_drivers, uint, 0); |
@@ -182,62 +184,59 @@ int i2o_driver_dispatch(struct i2o_controller *c, u32 m, | |||
182 | struct i2o_driver *drv; | 184 | struct i2o_driver *drv; |
183 | u32 context = readl(&msg->u.s.icntxt); | 185 | u32 context = readl(&msg->u.s.icntxt); |
184 | 186 | ||
185 | if (likely(context < i2o_max_drivers)) { | 187 | if (unlikely(context >= i2o_max_drivers)) { |
186 | spin_lock(&i2o_drivers_lock); | 188 | printk(KERN_WARNING "%s: Spurious reply to unknown driver " |
187 | drv = i2o_drivers[context]; | 189 | "%d\n", c->name, readl(&msg->u.s.icntxt)); |
188 | spin_unlock(&i2o_drivers_lock); | 190 | return -EIO; |
189 | 191 | } | |
190 | if (unlikely(!drv)) { | ||
191 | printk(KERN_WARNING "%s: Spurious reply to unknown " | ||
192 | "driver %d\n", c->name, context); | ||
193 | return -EIO; | ||
194 | } | ||
195 | 192 | ||
196 | if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { | 193 | spin_lock(&i2o_drivers_lock); |
197 | struct i2o_device *dev, *tmp; | 194 | drv = i2o_drivers[context]; |
198 | struct i2o_event *evt; | 195 | spin_unlock(&i2o_drivers_lock); |
199 | u16 size; | ||
200 | u16 tid; | ||
201 | 196 | ||
202 | tid = readl(&msg->u.head[1]) & 0x1fff; | 197 | if (unlikely(!drv)) { |
198 | osm_warn("Spurious reply to unknown driver %d\n", context); | ||
199 | return -EIO; | ||
200 | } | ||
203 | 201 | ||
204 | pr_debug("%s: event received from device %d\n", c->name, | 202 | if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) { |
205 | tid); | 203 | struct i2o_device *dev, *tmp; |
204 | struct i2o_event *evt; | ||
205 | u16 size; | ||
206 | u16 tid = readl(&msg->u.head[1]) & 0xfff; | ||
206 | 207 | ||
207 | /* cut of header from message size (in 32-bit words) */ | 208 | osm_debug("event received from device %d\n", tid); |
208 | size = (readl(&msg->u.head[0]) >> 16) - 5; | ||
209 | 209 | ||
210 | evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC); | 210 | /* cut of header from message size (in 32-bit words) */ |
211 | if (!evt) | 211 | size = (readl(&msg->u.head[0]) >> 16) - 5; |
212 | return -ENOMEM; | ||
213 | memset(evt, 0, size * 4 + sizeof(*evt)); | ||
214 | 212 | ||
215 | evt->size = size; | 213 | evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO); |
216 | memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, | 214 | if (!evt) |
217 | (size + 2) * 4); | 215 | return -ENOMEM; |
218 | 216 | ||
219 | list_for_each_entry_safe(dev, tmp, &c->devices, list) | 217 | evt->size = size; |
220 | if (dev->lct_data.tid == tid) { | 218 | evt->tcntxt = readl(&msg->u.s.tcntxt); |
221 | evt->i2o_dev = dev; | 219 | evt->event_indicator = readl(&msg->body[0]); |
222 | break; | 220 | memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt, size * 4); |
223 | } | ||
224 | 221 | ||
225 | INIT_WORK(&evt->work, (void (*)(void *))drv->event, | 222 | list_for_each_entry_safe(dev, tmp, &c->devices, list) |
226 | evt); | 223 | if (dev->lct_data.tid == tid) { |
227 | queue_work(drv->event_queue, &evt->work); | 224 | evt->i2o_dev = dev; |
228 | return 1; | 225 | break; |
229 | } | 226 | } |
230 | 227 | ||
231 | if (likely(drv->reply)) | 228 | INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt); |
232 | return drv->reply(c, m, msg); | 229 | queue_work(drv->event_queue, &evt->work); |
233 | else | 230 | return 1; |
234 | pr_debug("%s: Reply to driver %s, but no reply function" | 231 | } |
235 | " defined!\n", c->name, drv->name); | 232 | |
233 | if (unlikely(!drv->reply)) { | ||
234 | pr_debug("%s: Reply to driver %s, but no reply function" | ||
235 | " defined!\n", c->name, drv->name); | ||
236 | return -EIO; | 236 | return -EIO; |
237 | } else | 237 | } |
238 | printk(KERN_WARNING "%s: Spurious reply to unknown driver " | 238 | |
239 | "%d\n", c->name, readl(&msg->u.s.icntxt)); | 239 | return drv->reply(c, m, msg); |
240 | return -EIO; | ||
241 | } | 240 | } |
242 | 241 | ||
243 | /** | 242 | /** |
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 79c1cbfb8f44..1e28e886f1ca 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c | |||
@@ -204,12 +204,10 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m, | |||
204 | struct i2o_message __iomem *msg) | 204 | struct i2o_message __iomem *msg) |
205 | { | 205 | { |
206 | struct i2o_exec_wait *wait, *tmp; | 206 | struct i2o_exec_wait *wait, *tmp; |
207 | static spinlock_t lock; | 207 | static spinlock_t lock = SPIN_LOCK_UNLOCKED; |
208 | int rc = 1; | 208 | int rc = 1; |
209 | u32 context; | 209 | u32 context; |
210 | 210 | ||
211 | spin_lock_init(&lock); | ||
212 | |||
213 | context = readl(&msg->u.s.tcntxt); | 211 | context = readl(&msg->u.s.tcntxt); |
214 | 212 | ||
215 | /* | 213 | /* |
@@ -381,8 +379,9 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m, | |||
381 | */ | 379 | */ |
382 | static void i2o_exec_event(struct i2o_event *evt) | 380 | static void i2o_exec_event(struct i2o_event *evt) |
383 | { | 381 | { |
384 | osm_info("Event received from device: %d\n", | 382 | if(likely(evt->i2o_dev)) |
385 | evt->i2o_dev->lct_data.tid); | 383 | osm_info("Event received from device: %d\n", |
384 | evt->i2o_dev->lct_data.tid); | ||
386 | kfree(evt); | 385 | kfree(evt); |
387 | }; | 386 | }; |
388 | 387 | ||
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 1fb5cdf67f8f..46d373287a30 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c | |||
@@ -555,6 +555,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
555 | u32 sg_offset = 0; | 555 | u32 sg_offset = 0; |
556 | u32 sg_count = 0; | 556 | u32 sg_count = 0; |
557 | u32 i = 0; | 557 | u32 i = 0; |
558 | u32 sg_index = 0; | ||
558 | i2o_status_block *sb; | 559 | i2o_status_block *sb; |
559 | struct i2o_message *msg; | 560 | struct i2o_message *msg; |
560 | u32 m; | 561 | u32 m; |
@@ -634,8 +635,8 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
634 | if (sg_count > SG_TABLESIZE) { | 635 | if (sg_count > SG_TABLESIZE) { |
635 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", | 636 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", |
636 | c->name, sg_count); | 637 | c->name, sg_count); |
637 | kfree(reply); | 638 | rcode = -EINVAL; |
638 | return -EINVAL; | 639 | goto cleanup; |
639 | } | 640 | } |
640 | 641 | ||
641 | for (i = 0; i < sg_count; i++) { | 642 | for (i = 0; i < sg_count; i++) { |
@@ -651,7 +652,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
651 | goto cleanup; | 652 | goto cleanup; |
652 | } | 653 | } |
653 | sg_size = sg[i].flag_count & 0xffffff; | 654 | sg_size = sg[i].flag_count & 0xffffff; |
654 | p = &(sg_list[i]); | 655 | p = &(sg_list[sg_index++]); |
655 | /* Allocate memory for the transfer */ | 656 | /* Allocate memory for the transfer */ |
656 | if (i2o_dma_alloc | 657 | if (i2o_dma_alloc |
657 | (&c->pdev->dev, p, sg_size, | 658 | (&c->pdev->dev, p, sg_size, |
@@ -660,7 +661,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
660 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", | 661 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
661 | c->name, sg_size, i, sg_count); | 662 | c->name, sg_size, i, sg_count); |
662 | rcode = -ENOMEM; | 663 | rcode = -ENOMEM; |
663 | goto cleanup; | 664 | goto sg_list_cleanup; |
664 | } | 665 | } |
665 | /* Copy in the user's SG buffer if necessary */ | 666 | /* Copy in the user's SG buffer if necessary */ |
666 | if (sg[i]. | 667 | if (sg[i]. |
@@ -673,7 +674,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
673 | "%s: Could not copy SG buf %d FROM user\n", | 674 | "%s: Could not copy SG buf %d FROM user\n", |
674 | c->name, i); | 675 | c->name, i); |
675 | rcode = -EFAULT; | 676 | rcode = -EFAULT; |
676 | goto cleanup; | 677 | goto sg_list_cleanup; |
677 | } | 678 | } |
678 | } | 679 | } |
679 | //TODO 64bit fix | 680 | //TODO 64bit fix |
@@ -683,10 +684,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
683 | 684 | ||
684 | rcode = i2o_msg_post_wait(c, m, 60); | 685 | rcode = i2o_msg_post_wait(c, m, 60); |
685 | if (rcode) | 686 | if (rcode) |
686 | goto cleanup; | 687 | goto sg_list_cleanup; |
687 | 688 | ||
688 | if (sg_offset) { | 689 | if (sg_offset) { |
689 | u32 msg[128]; | 690 | u32 msg[MSG_FRAME_SIZE]; |
690 | /* Copy back the Scatter Gather buffers back to user space */ | 691 | /* Copy back the Scatter Gather buffers back to user space */ |
691 | u32 j; | 692 | u32 j; |
692 | // TODO 64bit fix | 693 | // TODO 64bit fix |
@@ -698,14 +699,14 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
698 | // get user msg size in u32s | 699 | // get user msg size in u32s |
699 | if (get_user(size, &user_msg[0])) { | 700 | if (get_user(size, &user_msg[0])) { |
700 | rcode = -EFAULT; | 701 | rcode = -EFAULT; |
701 | goto cleanup; | 702 | goto sg_list_cleanup; |
702 | } | 703 | } |
703 | size = size >> 16; | 704 | size = size >> 16; |
704 | size *= 4; | 705 | size *= 4; |
705 | /* Copy in the user's I2O command */ | 706 | /* Copy in the user's I2O command */ |
706 | if (copy_from_user(msg, user_msg, size)) { | 707 | if (copy_from_user(msg, user_msg, size)) { |
707 | rcode = -EFAULT; | 708 | rcode = -EFAULT; |
708 | goto cleanup; | 709 | goto sg_list_cleanup; |
709 | } | 710 | } |
710 | sg_count = | 711 | sg_count = |
711 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); | 712 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); |
@@ -727,7 +728,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
727 | c->name, sg_list[j].virt, | 728 | c->name, sg_list[j].virt, |
728 | sg[j].addr_bus); | 729 | sg[j].addr_bus); |
729 | rcode = -EFAULT; | 730 | rcode = -EFAULT; |
730 | goto cleanup; | 731 | goto sg_list_cleanup; |
731 | } | 732 | } |
732 | } | 733 | } |
733 | } | 734 | } |
@@ -741,6 +742,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
741 | "%s: Could not copy message context FROM user\n", | 742 | "%s: Could not copy message context FROM user\n", |
742 | c->name); | 743 | c->name); |
743 | rcode = -EFAULT; | 744 | rcode = -EFAULT; |
745 | goto sg_list_cleanup; | ||
744 | } | 746 | } |
745 | if (copy_to_user(user_reply, reply, reply_size)) { | 747 | if (copy_to_user(user_reply, reply, reply_size)) { |
746 | printk(KERN_WARNING | 748 | printk(KERN_WARNING |
@@ -749,6 +751,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar | |||
749 | } | 751 | } |
750 | } | 752 | } |
751 | 753 | ||
754 | sg_list_cleanup: | ||
755 | for (i = 0; i < sg_index; i++) | ||
756 | i2o_dma_free(&c->pdev->dev, &sg_list[i]); | ||
757 | |||
752 | cleanup: | 758 | cleanup: |
753 | kfree(reply); | 759 | kfree(reply); |
754 | return rcode; | 760 | return rcode; |
@@ -862,8 +868,8 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
862 | if (sg_count > SG_TABLESIZE) { | 868 | if (sg_count > SG_TABLESIZE) { |
863 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", | 869 | printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n", |
864 | c->name, sg_count); | 870 | c->name, sg_count); |
865 | kfree(reply); | 871 | rcode = -EINVAL; |
866 | return -EINVAL; | 872 | goto cleanup; |
867 | } | 873 | } |
868 | 874 | ||
869 | for (i = 0; i < sg_count; i++) { | 875 | for (i = 0; i < sg_count; i++) { |
@@ -875,7 +881,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
875 | "%s:Bad SG element %d - not simple (%x)\n", | 881 | "%s:Bad SG element %d - not simple (%x)\n", |
876 | c->name, i, sg[i].flag_count); | 882 | c->name, i, sg[i].flag_count); |
877 | rcode = -EINVAL; | 883 | rcode = -EINVAL; |
878 | goto cleanup; | 884 | goto sg_list_cleanup; |
879 | } | 885 | } |
880 | sg_size = sg[i].flag_count & 0xffffff; | 886 | sg_size = sg[i].flag_count & 0xffffff; |
881 | /* Allocate memory for the transfer */ | 887 | /* Allocate memory for the transfer */ |
@@ -885,7 +891,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
885 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", | 891 | "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
886 | c->name, sg_size, i, sg_count); | 892 | c->name, sg_size, i, sg_count); |
887 | rcode = -ENOMEM; | 893 | rcode = -ENOMEM; |
888 | goto cleanup; | 894 | goto sg_list_cleanup; |
889 | } | 895 | } |
890 | sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. | 896 | sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. |
891 | /* Copy in the user's SG buffer if necessary */ | 897 | /* Copy in the user's SG buffer if necessary */ |
@@ -899,7 +905,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
899 | "%s: Could not copy SG buf %d FROM user\n", | 905 | "%s: Could not copy SG buf %d FROM user\n", |
900 | c->name, i); | 906 | c->name, i); |
901 | rcode = -EFAULT; | 907 | rcode = -EFAULT; |
902 | goto cleanup; | 908 | goto sg_list_cleanup; |
903 | } | 909 | } |
904 | } | 910 | } |
905 | //TODO 64bit fix | 911 | //TODO 64bit fix |
@@ -909,7 +915,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
909 | 915 | ||
910 | rcode = i2o_msg_post_wait(c, m, 60); | 916 | rcode = i2o_msg_post_wait(c, m, 60); |
911 | if (rcode) | 917 | if (rcode) |
912 | goto cleanup; | 918 | goto sg_list_cleanup; |
913 | 919 | ||
914 | if (sg_offset) { | 920 | if (sg_offset) { |
915 | u32 msg[128]; | 921 | u32 msg[128]; |
@@ -924,14 +930,14 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
924 | // get user msg size in u32s | 930 | // get user msg size in u32s |
925 | if (get_user(size, &user_msg[0])) { | 931 | if (get_user(size, &user_msg[0])) { |
926 | rcode = -EFAULT; | 932 | rcode = -EFAULT; |
927 | goto cleanup; | 933 | goto sg_list_cleanup; |
928 | } | 934 | } |
929 | size = size >> 16; | 935 | size = size >> 16; |
930 | size *= 4; | 936 | size *= 4; |
931 | /* Copy in the user's I2O command */ | 937 | /* Copy in the user's I2O command */ |
932 | if (copy_from_user(msg, user_msg, size)) { | 938 | if (copy_from_user(msg, user_msg, size)) { |
933 | rcode = -EFAULT; | 939 | rcode = -EFAULT; |
934 | goto cleanup; | 940 | goto sg_list_cleanup; |
935 | } | 941 | } |
936 | sg_count = | 942 | sg_count = |
937 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); | 943 | (size - sg_offset * 4) / sizeof(struct sg_simple_element); |
@@ -953,7 +959,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
953 | c->name, sg_list[j], | 959 | c->name, sg_list[j], |
954 | sg[j].addr_bus); | 960 | sg[j].addr_bus); |
955 | rcode = -EFAULT; | 961 | rcode = -EFAULT; |
956 | goto cleanup; | 962 | goto sg_list_cleanup; |
957 | } | 963 | } |
958 | } | 964 | } |
959 | } | 965 | } |
@@ -975,6 +981,10 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
975 | } | 981 | } |
976 | } | 982 | } |
977 | 983 | ||
984 | sg_list_cleanup: | ||
985 | for (i = 0; i < sg_index; i++) | ||
986 | kfree(sg_list[i]); | ||
987 | |||
978 | cleanup: | 988 | cleanup: |
979 | kfree(reply); | 989 | kfree(reply); |
980 | return rcode; | 990 | return rcode; |
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index 43f5875e0be5..af40f1c1ec77 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c | |||
@@ -103,7 +103,8 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) | |||
103 | 103 | ||
104 | list_for_each_entry(i2o_dev, &c->devices, list) | 104 | list_for_each_entry(i2o_dev, &c->devices, list) |
105 | if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) { | 105 | if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) { |
106 | if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* SCSI bus */ | 106 | if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) |
107 | && (type == 0x01)) /* SCSI bus */ | ||
107 | max_channel++; | 108 | max_channel++; |
108 | } | 109 | } |
109 | 110 | ||
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index e772752f056d..579a8b7a2120 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c | |||
@@ -31,10 +31,6 @@ | |||
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/i2o.h> | 32 | #include <linux/i2o.h> |
33 | 33 | ||
34 | #ifdef CONFIG_MTRR | ||
35 | #include <asm/mtrr.h> | ||
36 | #endif // CONFIG_MTRR | ||
37 | |||
38 | /* Module internal functions from other sources */ | 34 | /* Module internal functions from other sources */ |
39 | extern struct i2o_controller *i2o_iop_alloc(void); | 35 | extern struct i2o_controller *i2o_iop_alloc(void); |
40 | extern void i2o_iop_free(struct i2o_controller *); | 36 | extern void i2o_iop_free(struct i2o_controller *); |
@@ -49,6 +45,8 @@ extern int i2o_driver_dispatch(struct i2o_controller *, u32, | |||
49 | static struct pci_device_id __devinitdata i2o_pci_ids[] = { | 45 | static struct pci_device_id __devinitdata i2o_pci_ids[] = { |
50 | {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, | 46 | {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)}, |
51 | {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)}, | 47 | {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)}, |
48 | {.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962, | ||
49 | .subvendor = PCI_VENDOR_ID_PROMISE,.subdevice = PCI_ANY_ID}, | ||
52 | {0} | 50 | {0} |
53 | }; | 51 | }; |
54 | 52 | ||
@@ -97,13 +95,6 @@ static void i2o_pci_free(struct i2o_controller *c) | |||
97 | i2o_dma_free(dev, &c->hrt); | 95 | i2o_dma_free(dev, &c->hrt); |
98 | i2o_dma_free(dev, &c->status); | 96 | i2o_dma_free(dev, &c->status); |
99 | 97 | ||
100 | #ifdef CONFIG_MTRR | ||
101 | if (c->mtrr_reg0 >= 0) | ||
102 | mtrr_del(c->mtrr_reg0, 0, 0); | ||
103 | if (c->mtrr_reg1 >= 0) | ||
104 | mtrr_del(c->mtrr_reg1, 0, 0); | ||
105 | #endif | ||
106 | |||
107 | if (c->raptor && c->in_queue.virt) | 98 | if (c->raptor && c->in_queue.virt) |
108 | iounmap(c->in_queue.virt); | 99 | iounmap(c->in_queue.virt); |
109 | 100 | ||
@@ -178,14 +169,15 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
178 | c->name, (unsigned long)c->base.phys, | 169 | c->name, (unsigned long)c->base.phys, |
179 | (unsigned long)c->base.len); | 170 | (unsigned long)c->base.len); |
180 | 171 | ||
181 | c->base.virt = ioremap(c->base.phys, c->base.len); | 172 | c->base.virt = ioremap_nocache(c->base.phys, c->base.len); |
182 | if (!c->base.virt) { | 173 | if (!c->base.virt) { |
183 | printk(KERN_ERR "%s: Unable to map controller.\n", c->name); | 174 | printk(KERN_ERR "%s: Unable to map controller.\n", c->name); |
184 | return -ENOMEM; | 175 | return -ENOMEM; |
185 | } | 176 | } |
186 | 177 | ||
187 | if (c->raptor) { | 178 | if (c->raptor) { |
188 | c->in_queue.virt = ioremap(c->in_queue.phys, c->in_queue.len); | 179 | c->in_queue.virt = |
180 | ioremap_nocache(c->in_queue.phys, c->in_queue.len); | ||
189 | if (!c->in_queue.virt) { | 181 | if (!c->in_queue.virt) { |
190 | printk(KERN_ERR "%s: Unable to map controller.\n", | 182 | printk(KERN_ERR "%s: Unable to map controller.\n", |
191 | c->name); | 183 | c->name); |
@@ -199,40 +191,6 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c) | |||
199 | c->post_port = c->base.virt + 0x40; | 191 | c->post_port = c->base.virt + 0x40; |
200 | c->reply_port = c->base.virt + 0x44; | 192 | c->reply_port = c->base.virt + 0x44; |
201 | 193 | ||
202 | #ifdef CONFIG_MTRR | ||
203 | /* Enable Write Combining MTRR for IOP's memory region */ | ||
204 | c->mtrr_reg0 = mtrr_add(c->in_queue.phys, c->in_queue.len, | ||
205 | MTRR_TYPE_WRCOMB, 1); | ||
206 | c->mtrr_reg1 = -1; | ||
207 | |||
208 | if (c->mtrr_reg0 < 0) | ||
209 | printk(KERN_WARNING "%s: could not enable write combining " | ||
210 | "MTRR\n", c->name); | ||
211 | else | ||
212 | printk(KERN_INFO "%s: using write combining MTRR\n", c->name); | ||
213 | |||
214 | /* | ||
215 | * If it is an INTEL i960 I/O processor then set the first 64K to | ||
216 | * Uncacheable since the region contains the messaging unit which | ||
217 | * shouldn't be cached. | ||
218 | */ | ||
219 | if ((pdev->vendor == PCI_VENDOR_ID_INTEL || | ||
220 | pdev->vendor == PCI_VENDOR_ID_DPT) && !c->raptor) { | ||
221 | printk(KERN_INFO "%s: MTRR workaround for Intel i960 processor" | ||
222 | "\n", c->name); | ||
223 | c->mtrr_reg1 = mtrr_add(c->base.phys, 0x10000, | ||
224 | MTRR_TYPE_UNCACHABLE, 1); | ||
225 | |||
226 | if (c->mtrr_reg1 < 0) { | ||
227 | printk(KERN_WARNING "%s: Error in setting " | ||
228 | "MTRR_TYPE_UNCACHABLE\n", c->name); | ||
229 | mtrr_del(c->mtrr_reg0, c->in_queue.phys, | ||
230 | c->in_queue.len); | ||
231 | c->mtrr_reg0 = -1; | ||
232 | } | ||
233 | } | ||
234 | #endif | ||
235 | |||
236 | if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { | 194 | if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) { |
237 | i2o_pci_free(c); | 195 | i2o_pci_free(c); |
238 | return -ENOMEM; | 196 | return -ENOMEM; |
@@ -385,28 +343,25 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
385 | { | 343 | { |
386 | struct i2o_controller *c; | 344 | struct i2o_controller *c; |
387 | int rc; | 345 | int rc; |
346 | struct pci_dev *i960 = NULL; | ||
388 | 347 | ||
389 | printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); | 348 | printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); |
390 | 349 | ||
391 | if ((pdev->class & 0xff) > 1) { | 350 | if ((pdev->class & 0xff) > 1) { |
392 | printk(KERN_WARNING "i2o: I2O controller found but does not " | 351 | printk(KERN_WARNING "i2o: %s does not support I2O 1.5 " |
393 | "support I2O 1.5 (skipping).\n"); | 352 | "(skipping).\n", pci_name(pdev)); |
394 | return -ENODEV; | 353 | return -ENODEV; |
395 | } | 354 | } |
396 | 355 | ||
397 | if ((rc = pci_enable_device(pdev))) { | 356 | if ((rc = pci_enable_device(pdev))) { |
398 | printk(KERN_WARNING "i2o: I2O controller found but could not be" | 357 | printk(KERN_WARNING "i2o: couldn't enable device %s\n", |
399 | " enabled.\n"); | 358 | pci_name(pdev)); |
400 | return rc; | 359 | return rc; |
401 | } | 360 | } |
402 | 361 | ||
403 | printk(KERN_INFO "i2o: I2O controller found on bus %d at %d.\n", | ||
404 | pdev->bus->number, pdev->devfn); | ||
405 | |||
406 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { | 362 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { |
407 | printk(KERN_WARNING "i2o: I2O controller on bus %d at %d: No " | 363 | printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", |
408 | "suitable DMA available!\n", pdev->bus->number, | 364 | pci_name(pdev)); |
409 | pdev->devfn); | ||
410 | rc = -ENODEV; | 365 | rc = -ENODEV; |
411 | goto disable; | 366 | goto disable; |
412 | } | 367 | } |
@@ -415,11 +370,13 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
415 | 370 | ||
416 | c = i2o_iop_alloc(); | 371 | c = i2o_iop_alloc(); |
417 | if (IS_ERR(c)) { | 372 | if (IS_ERR(c)) { |
418 | printk(KERN_ERR "i2o: memory for I2O controller could not be " | 373 | printk(KERN_ERR "i2o: couldn't allocate memory for %s\n", |
419 | "allocated\n"); | 374 | pci_name(pdev)); |
420 | rc = PTR_ERR(c); | 375 | rc = PTR_ERR(c); |
421 | goto disable; | 376 | goto disable; |
422 | } | 377 | } else |
378 | printk(KERN_INFO "%s: controller found (%s)\n", c->name, | ||
379 | pci_name(pdev)); | ||
423 | 380 | ||
424 | c->pdev = pdev; | 381 | c->pdev = pdev; |
425 | c->device = pdev->dev; | 382 | c->device = pdev->dev; |
@@ -432,9 +389,18 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
432 | } | 389 | } |
433 | 390 | ||
434 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) { | 391 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) { |
392 | /* | ||
393 | * Expose the ship behind i960 for initialization, or it will | ||
394 | * failed | ||
395 | */ | ||
396 | i960 = | ||
397 | pci_find_slot(c->pdev->bus->number, | ||
398 | PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0)); | ||
399 | |||
400 | if (i960) | ||
401 | pci_write_config_word(i960, 0x42, 0); | ||
402 | |||
435 | c->promise = 1; | 403 | c->promise = 1; |
436 | printk(KERN_INFO "%s: Promise workarounds activated.\n", | ||
437 | c->name); | ||
438 | } | 404 | } |
439 | 405 | ||
440 | /* Cards that go bananas if you quiesce them before you reset them. */ | 406 | /* Cards that go bananas if you quiesce them before you reset them. */ |
@@ -459,6 +425,9 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
459 | if ((rc = i2o_iop_add(c))) | 425 | if ((rc = i2o_iop_add(c))) |
460 | goto uninstall; | 426 | goto uninstall; |
461 | 427 | ||
428 | if (i960) | ||
429 | pci_write_config_word(i960, 0x42, 0x03ff); | ||
430 | |||
462 | return 0; | 431 | return 0; |
463 | 432 | ||
464 | uninstall: | 433 | uninstall: |