diff options
135 files changed, 5142 insertions, 2060 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 15e4fed127f6..2e1898e4e8fd 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1416,6 +1416,11 @@ and is between 256 and 4096 characters. It is defined in the file | |||
1416 | 1416 | ||
1417 | scsi_logging= [SCSI] | 1417 | scsi_logging= [SCSI] |
1418 | 1418 | ||
1419 | scsi_mod.scan= [SCSI] sync (default) scans SCSI busses as they are | ||
1420 | discovered. async scans them in kernel threads, | ||
1421 | allowing boot to proceed. none ignores them, expecting | ||
1422 | user space to do the scan. | ||
1423 | |||
1419 | selinux [SELINUX] Disable or enable SELinux at boot time. | 1424 | selinux [SELINUX] Disable or enable SELinux at boot time. |
1420 | Format: { "0" | "1" } | 1425 | Format: { "0" | "1" } |
1421 | See security/selinux/Kconfig help text. | 1426 | See security/selinux/Kconfig help text. |
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt index 75a535a975c3..6f70f2b9327e 100644 --- a/Documentation/scsi/scsi_mid_low_api.txt +++ b/Documentation/scsi/scsi_mid_low_api.txt | |||
@@ -375,7 +375,6 @@ Summary: | |||
375 | scsi_add_device - creates new scsi device (lu) instance | 375 | scsi_add_device - creates new scsi device (lu) instance |
376 | scsi_add_host - perform sysfs registration and set up transport class | 376 | scsi_add_host - perform sysfs registration and set up transport class |
377 | scsi_adjust_queue_depth - change the queue depth on a SCSI device | 377 | scsi_adjust_queue_depth - change the queue depth on a SCSI device |
378 | scsi_assign_lock - replace default host_lock with given lock | ||
379 | scsi_bios_ptable - return copy of block device's partition table | 378 | scsi_bios_ptable - return copy of block device's partition table |
380 | scsi_block_requests - prevent further commands being queued to given host | 379 | scsi_block_requests - prevent further commands being queued to given host |
381 | scsi_deactivate_tcq - turn off tag command queueing | 380 | scsi_deactivate_tcq - turn off tag command queueing |
@@ -489,20 +488,6 @@ void scsi_adjust_queue_depth(struct scsi_device * sdev, int tagged, | |||
489 | 488 | ||
490 | 489 | ||
491 | /** | 490 | /** |
492 | * scsi_assign_lock - replace default host_lock with given lock | ||
493 | * @shost: a pointer to a scsi host instance | ||
494 | * @lock: pointer to lock to replace host_lock for this host | ||
495 | * | ||
496 | * Returns nothing | ||
497 | * | ||
498 | * Might block: no | ||
499 | * | ||
500 | * Defined in: include/scsi/scsi_host.h . | ||
501 | **/ | ||
502 | void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock) | ||
503 | |||
504 | |||
505 | /** | ||
506 | * scsi_bios_ptable - return copy of block device's partition table | 491 | * scsi_bios_ptable - return copy of block device's partition table |
507 | * @dev: pointer to block device | 492 | * @dev: pointer to block device |
508 | * | 493 | * |
@@ -1366,17 +1351,11 @@ Locks | |||
1366 | Each struct Scsi_Host instance has a spin_lock called struct | 1351 | Each struct Scsi_Host instance has a spin_lock called struct |
1367 | Scsi_Host::default_lock which is initialized in scsi_host_alloc() [found in | 1352 | Scsi_Host::default_lock which is initialized in scsi_host_alloc() [found in |
1368 | hosts.c]. Within the same function the struct Scsi_Host::host_lock pointer | 1353 | hosts.c]. Within the same function the struct Scsi_Host::host_lock pointer |
1369 | is initialized to point at default_lock with the scsi_assign_lock() function. | 1354 | is initialized to point at default_lock. Thereafter lock and unlock |
1370 | Thereafter lock and unlock operations performed by the mid level use the | 1355 | operations performed by the mid level use the struct Scsi_Host::host_lock |
1371 | struct Scsi_Host::host_lock pointer. | 1356 | pointer. Previously drivers could override the host_lock pointer but |
1372 | 1357 | this is not allowed anymore. | |
1373 | LLDs can override the use of struct Scsi_Host::default_lock by | 1358 | |
1374 | using scsi_assign_lock(). The earliest opportunity to do this would | ||
1375 | be in the detect() function after it has invoked scsi_register(). It | ||
1376 | could be replaced by a coarser grain lock (e.g. per driver) or a | ||
1377 | lock of equal granularity (i.e. per host). Using finer grain locks | ||
1378 | (e.g. per SCSI device) may be possible by juggling locks in | ||
1379 | queuecommand(). | ||
1380 | 1359 | ||
1381 | Autosense | 1360 | Autosense |
1382 | ========= | 1361 | ========= |
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 5493c2fbbab1..b3e210723a71 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
@@ -277,7 +277,7 @@ static int sg_io(struct file *file, request_queue_t *q, | |||
277 | if (rq->bio) | 277 | if (rq->bio) |
278 | blk_queue_bounce(q, &rq->bio); | 278 | blk_queue_bounce(q, &rq->bio); |
279 | 279 | ||
280 | rq->timeout = (hdr->timeout * HZ) / 1000; | 280 | rq->timeout = jiffies_to_msecs(hdr->timeout); |
281 | if (!rq->timeout) | 281 | if (!rq->timeout) |
282 | rq->timeout = q->sg_timeout; | 282 | rq->timeout = q->sg_timeout; |
283 | if (!rq->timeout) | 283 | if (!rq->timeout) |
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 4ca6fa5dcb42..9ed7f58424a3 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c | |||
@@ -154,19 +154,12 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) | |||
154 | tuple.TupleOffset = 0; | 154 | tuple.TupleOffset = 0; |
155 | tuple.TupleDataMax = 255; | 155 | tuple.TupleDataMax = 255; |
156 | tuple.Attributes = 0; | 156 | tuple.Attributes = 0; |
157 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
158 | |||
159 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple)); | ||
160 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple)); | ||
161 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, &stk->parse)); | ||
162 | pdev->conf.ConfigBase = stk->parse.config.base; | ||
163 | pdev->conf.Present = stk->parse.config.rmask[0]; | ||
164 | 157 | ||
165 | /* See if we have a manufacturer identifier. Use it to set is_kme for | 158 | /* See if we have a manufacturer identifier. Use it to set is_kme for |
166 | vendor quirks */ | 159 | vendor quirks */ |
167 | tuple.DesiredTuple = CISTPL_MANFID; | 160 | is_kme = ((pdev->manf_id == MANFID_KME) && |
168 | if (!pcmcia_get_first_tuple(pdev, &tuple) && !pcmcia_get_tuple_data(pdev, &tuple) && !pcmcia_parse_tuple(pdev, &tuple, &stk->parse)) | 161 | ((pdev->card_id == PRODID_KME_KXLC005_A) || |
169 | is_kme = ((stk->parse.manfid.manf == MANFID_KME) && ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); | 162 | (pdev->card_id == PRODID_KME_KXLC005_B))); |
170 | 163 | ||
171 | /* Not sure if this is right... look up the current Vcc */ | 164 | /* Not sure if this is right... look up the current Vcc */ |
172 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(pdev, &stk->conf)); | 165 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(pdev, &stk->conf)); |
@@ -356,8 +349,10 @@ static struct pcmcia_device_id pcmcia_devices[] = { | |||
356 | PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6), | 349 | PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6), |
357 | PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), | 350 | PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), |
358 | PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443), | 351 | PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443), |
352 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), | ||
359 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), | 353 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), |
360 | PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), | 354 | PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), |
355 | PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), | ||
361 | PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), | 356 | PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), |
362 | PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), | 357 | PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), |
363 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), | 358 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), |
diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index cbc07250b898..acfb6a430dcc 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c | |||
@@ -892,43 +892,10 @@ static void bluecard_detach(struct pcmcia_device *link) | |||
892 | } | 892 | } |
893 | 893 | ||
894 | 894 | ||
895 | static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) | ||
896 | { | ||
897 | int i; | ||
898 | |||
899 | i = pcmcia_get_first_tuple(handle, tuple); | ||
900 | if (i != CS_SUCCESS) | ||
901 | return CS_NO_MORE_ITEMS; | ||
902 | |||
903 | i = pcmcia_get_tuple_data(handle, tuple); | ||
904 | if (i != CS_SUCCESS) | ||
905 | return i; | ||
906 | |||
907 | return pcmcia_parse_tuple(handle, tuple, parse); | ||
908 | } | ||
909 | |||
910 | static int bluecard_config(struct pcmcia_device *link) | 895 | static int bluecard_config(struct pcmcia_device *link) |
911 | { | 896 | { |
912 | bluecard_info_t *info = link->priv; | 897 | bluecard_info_t *info = link->priv; |
913 | tuple_t tuple; | 898 | int i, n; |
914 | u_short buf[256]; | ||
915 | cisparse_t parse; | ||
916 | int i, n, last_ret, last_fn; | ||
917 | |||
918 | tuple.TupleData = (cisdata_t *)buf; | ||
919 | tuple.TupleOffset = 0; | ||
920 | tuple.TupleDataMax = 255; | ||
921 | tuple.Attributes = 0; | ||
922 | |||
923 | /* Get configuration register information */ | ||
924 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
925 | last_ret = first_tuple(link, &tuple, &parse); | ||
926 | if (last_ret != CS_SUCCESS) { | ||
927 | last_fn = ParseTuple; | ||
928 | goto cs_failed; | ||
929 | } | ||
930 | link->conf.ConfigBase = parse.config.base; | ||
931 | link->conf.Present = parse.config.rmask[0]; | ||
932 | 899 | ||
933 | link->conf.ConfigIndex = 0x20; | 900 | link->conf.ConfigIndex = 0x20; |
934 | link->io.NumPorts1 = 64; | 901 | link->io.NumPorts1 = 64; |
@@ -966,9 +933,6 @@ static int bluecard_config(struct pcmcia_device *link) | |||
966 | 933 | ||
967 | return 0; | 934 | return 0; |
968 | 935 | ||
969 | cs_failed: | ||
970 | cs_error(link, last_fn, last_ret); | ||
971 | |||
972 | failed: | 936 | failed: |
973 | bluecard_release(link); | 937 | bluecard_release(link); |
974 | return -ENODEV; | 938 | return -ENODEV; |
diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 3a96a0babc6a..aae3abace586 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c | |||
@@ -713,22 +713,7 @@ static int bt3c_config(struct pcmcia_device *link) | |||
713 | u_short buf[256]; | 713 | u_short buf[256]; |
714 | cisparse_t parse; | 714 | cisparse_t parse; |
715 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | 715 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; |
716 | int i, j, try, last_ret, last_fn; | 716 | int i, j, try; |
717 | |||
718 | tuple.TupleData = (cisdata_t *)buf; | ||
719 | tuple.TupleOffset = 0; | ||
720 | tuple.TupleDataMax = 255; | ||
721 | tuple.Attributes = 0; | ||
722 | |||
723 | /* Get configuration register information */ | ||
724 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
725 | last_ret = first_tuple(link, &tuple, &parse); | ||
726 | if (last_ret != CS_SUCCESS) { | ||
727 | last_fn = ParseTuple; | ||
728 | goto cs_failed; | ||
729 | } | ||
730 | link->conf.ConfigBase = parse.config.base; | ||
731 | link->conf.Present = parse.config.rmask[0]; | ||
732 | 717 | ||
733 | /* First pass: look for a config entry that looks normal. */ | 718 | /* First pass: look for a config entry that looks normal. */ |
734 | tuple.TupleData = (cisdata_t *)buf; | 719 | tuple.TupleData = (cisdata_t *)buf; |
@@ -802,9 +787,6 @@ found_port: | |||
802 | 787 | ||
803 | return 0; | 788 | return 0; |
804 | 789 | ||
805 | cs_failed: | ||
806 | cs_error(link, last_fn, last_ret); | ||
807 | |||
808 | failed: | 790 | failed: |
809 | bt3c_release(link); | 791 | bt3c_release(link); |
810 | return -ENODEV; | 792 | return -ENODEV; |
diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 3b29086b7c3f..92648ef2f5d0 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c | |||
@@ -644,22 +644,7 @@ static int btuart_config(struct pcmcia_device *link) | |||
644 | u_short buf[256]; | 644 | u_short buf[256]; |
645 | cisparse_t parse; | 645 | cisparse_t parse; |
646 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | 646 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; |
647 | int i, j, try, last_ret, last_fn; | 647 | int i, j, try; |
648 | |||
649 | tuple.TupleData = (cisdata_t *)buf; | ||
650 | tuple.TupleOffset = 0; | ||
651 | tuple.TupleDataMax = 255; | ||
652 | tuple.Attributes = 0; | ||
653 | |||
654 | /* Get configuration register information */ | ||
655 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
656 | last_ret = first_tuple(link, &tuple, &parse); | ||
657 | if (last_ret != CS_SUCCESS) { | ||
658 | last_fn = ParseTuple; | ||
659 | goto cs_failed; | ||
660 | } | ||
661 | link->conf.ConfigBase = parse.config.base; | ||
662 | link->conf.Present = parse.config.rmask[0]; | ||
663 | 648 | ||
664 | /* First pass: look for a config entry that looks normal. */ | 649 | /* First pass: look for a config entry that looks normal. */ |
665 | tuple.TupleData = (cisdata_t *) buf; | 650 | tuple.TupleData = (cisdata_t *) buf; |
@@ -734,9 +719,6 @@ found_port: | |||
734 | 719 | ||
735 | return 0; | 720 | return 0; |
736 | 721 | ||
737 | cs_failed: | ||
738 | cs_error(link, last_fn, last_ret); | ||
739 | |||
740 | failed: | 722 | failed: |
741 | btuart_release(link); | 723 | btuart_release(link); |
742 | return -ENODEV; | 724 | return -ENODEV; |
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 07eafbc5dc3a..77b99eecbc49 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c | |||
@@ -626,22 +626,7 @@ static int dtl1_config(struct pcmcia_device *link) | |||
626 | u_short buf[256]; | 626 | u_short buf[256]; |
627 | cisparse_t parse; | 627 | cisparse_t parse; |
628 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; | 628 | cistpl_cftable_entry_t *cf = &parse.cftable_entry; |
629 | int i, last_ret, last_fn; | 629 | int i; |
630 | |||
631 | tuple.TupleData = (cisdata_t *)buf; | ||
632 | tuple.TupleOffset = 0; | ||
633 | tuple.TupleDataMax = 255; | ||
634 | tuple.Attributes = 0; | ||
635 | |||
636 | /* Get configuration register information */ | ||
637 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
638 | last_ret = first_tuple(link, &tuple, &parse); | ||
639 | if (last_ret != CS_SUCCESS) { | ||
640 | last_fn = ParseTuple; | ||
641 | goto cs_failed; | ||
642 | } | ||
643 | link->conf.ConfigBase = parse.config.base; | ||
644 | link->conf.Present = parse.config.rmask[0]; | ||
645 | 630 | ||
646 | tuple.TupleData = (cisdata_t *)buf; | 631 | tuple.TupleData = (cisdata_t *)buf; |
647 | tuple.TupleOffset = 0; | 632 | tuple.TupleOffset = 0; |
@@ -690,9 +675,6 @@ static int dtl1_config(struct pcmcia_device *link) | |||
690 | 675 | ||
691 | return 0; | 676 | return 0; |
692 | 677 | ||
693 | cs_failed: | ||
694 | cs_error(link, last_fn, last_ret); | ||
695 | |||
696 | failed: | 678 | failed: |
697 | dtl1_release(link); | 679 | dtl1_release(link); |
698 | return -ENODEV; | 680 | return -ENODEV; |
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 50d20aafeb18..211c93fda6fc 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c | |||
@@ -1764,29 +1764,11 @@ static int cm4000_config(struct pcmcia_device * link, int devno) | |||
1764 | int rc; | 1764 | int rc; |
1765 | 1765 | ||
1766 | /* read the config-tuples */ | 1766 | /* read the config-tuples */ |
1767 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
1768 | tuple.Attributes = 0; | 1767 | tuple.Attributes = 0; |
1769 | tuple.TupleData = buf; | 1768 | tuple.TupleData = buf; |
1770 | tuple.TupleDataMax = sizeof(buf); | 1769 | tuple.TupleDataMax = sizeof(buf); |
1771 | tuple.TupleOffset = 0; | 1770 | tuple.TupleOffset = 0; |
1772 | 1771 | ||
1773 | if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) { | ||
1774 | fail_fn = GetFirstTuple; | ||
1775 | goto cs_failed; | ||
1776 | } | ||
1777 | if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) { | ||
1778 | fail_fn = GetTupleData; | ||
1779 | goto cs_failed; | ||
1780 | } | ||
1781 | if ((fail_rc = | ||
1782 | pcmcia_parse_tuple(link, &tuple, &parse)) != CS_SUCCESS) { | ||
1783 | fail_fn = ParseTuple; | ||
1784 | goto cs_failed; | ||
1785 | } | ||
1786 | |||
1787 | link->conf.ConfigBase = parse.config.base; | ||
1788 | link->conf.Present = parse.config.rmask[0]; | ||
1789 | |||
1790 | link->io.BasePort2 = 0; | 1772 | link->io.BasePort2 = 0; |
1791 | link->io.NumPorts2 = 0; | 1773 | link->io.NumPorts2 = 0; |
1792 | link->io.Attributes2 = 0; | 1774 | link->io.Attributes2 = 0; |
@@ -1841,8 +1823,6 @@ static int cm4000_config(struct pcmcia_device * link, int devno) | |||
1841 | 1823 | ||
1842 | return 0; | 1824 | return 0; |
1843 | 1825 | ||
1844 | cs_failed: | ||
1845 | cs_error(link, fail_fn, fail_rc); | ||
1846 | cs_release: | 1826 | cs_release: |
1847 | cm4000_release(link); | 1827 | cm4000_release(link); |
1848 | return -ENODEV; | 1828 | return -ENODEV; |
@@ -1973,14 +1953,14 @@ static int __init cmm_init(void) | |||
1973 | printk(KERN_INFO "%s\n", version); | 1953 | printk(KERN_INFO "%s\n", version); |
1974 | 1954 | ||
1975 | cmm_class = class_create(THIS_MODULE, "cardman_4000"); | 1955 | cmm_class = class_create(THIS_MODULE, "cardman_4000"); |
1976 | if (!cmm_class) | 1956 | if (IS_ERR(cmm_class)) |
1977 | return -1; | 1957 | return PTR_ERR(cmm_class); |
1978 | 1958 | ||
1979 | major = register_chrdev(0, DEVICE_NAME, &cm4000_fops); | 1959 | major = register_chrdev(0, DEVICE_NAME, &cm4000_fops); |
1980 | if (major < 0) { | 1960 | if (major < 0) { |
1981 | printk(KERN_WARNING MODULE_NAME | 1961 | printk(KERN_WARNING MODULE_NAME |
1982 | ": could not get major number\n"); | 1962 | ": could not get major number\n"); |
1983 | return -1; | 1963 | return major; |
1984 | } | 1964 | } |
1985 | 1965 | ||
1986 | rc = pcmcia_register_driver(&cm4000_driver); | 1966 | rc = pcmcia_register_driver(&cm4000_driver); |
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 55cf4be42976..9b1ff7e8f896 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c | |||
@@ -523,29 +523,11 @@ static int reader_config(struct pcmcia_device *link, int devno) | |||
523 | int fail_fn, fail_rc; | 523 | int fail_fn, fail_rc; |
524 | int rc; | 524 | int rc; |
525 | 525 | ||
526 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
527 | tuple.Attributes = 0; | 526 | tuple.Attributes = 0; |
528 | tuple.TupleData = buf; | 527 | tuple.TupleData = buf; |
529 | tuple.TupleDataMax = sizeof(buf); | 528 | tuple.TupleDataMax = sizeof(buf); |
530 | tuple.TupleOffset = 0; | 529 | tuple.TupleOffset = 0; |
531 | 530 | ||
532 | if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) { | ||
533 | fail_fn = GetFirstTuple; | ||
534 | goto cs_failed; | ||
535 | } | ||
536 | if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) { | ||
537 | fail_fn = GetTupleData; | ||
538 | goto cs_failed; | ||
539 | } | ||
540 | if ((fail_rc = pcmcia_parse_tuple(link, &tuple, &parse)) | ||
541 | != CS_SUCCESS) { | ||
542 | fail_fn = ParseTuple; | ||
543 | goto cs_failed; | ||
544 | } | ||
545 | |||
546 | link->conf.ConfigBase = parse.config.base; | ||
547 | link->conf.Present = parse.config.rmask[0]; | ||
548 | |||
549 | link->io.BasePort2 = 0; | 531 | link->io.BasePort2 = 0; |
550 | link->io.NumPorts2 = 0; | 532 | link->io.NumPorts2 = 0; |
551 | link->io.Attributes2 = 0; | 533 | link->io.Attributes2 = 0; |
@@ -609,8 +591,6 @@ static int reader_config(struct pcmcia_device *link, int devno) | |||
609 | 591 | ||
610 | return 0; | 592 | return 0; |
611 | 593 | ||
612 | cs_failed: | ||
613 | cs_error(link, fail_fn, fail_rc); | ||
614 | cs_release: | 594 | cs_release: |
615 | reader_release(link); | 595 | reader_release(link); |
616 | return -ENODEV; | 596 | return -ENODEV; |
@@ -721,14 +701,14 @@ static int __init cm4040_init(void) | |||
721 | 701 | ||
722 | printk(KERN_INFO "%s\n", version); | 702 | printk(KERN_INFO "%s\n", version); |
723 | cmx_class = class_create(THIS_MODULE, "cardman_4040"); | 703 | cmx_class = class_create(THIS_MODULE, "cardman_4040"); |
724 | if (!cmx_class) | 704 | if (IS_ERR(cmx_class)) |
725 | return -1; | 705 | return PTR_ERR(cmx_class); |
726 | 706 | ||
727 | major = register_chrdev(0, DEVICE_NAME, &reader_fops); | 707 | major = register_chrdev(0, DEVICE_NAME, &reader_fops); |
728 | if (major < 0) { | 708 | if (major < 0) { |
729 | printk(KERN_WARNING MODULE_NAME | 709 | printk(KERN_WARNING MODULE_NAME |
730 | ": could not get major number\n"); | 710 | ": could not get major number\n"); |
731 | return -1; | 711 | return major; |
732 | } | 712 | } |
733 | 713 | ||
734 | rc = pcmcia_register_driver(&reader_driver); | 714 | rc = pcmcia_register_driver(&reader_driver); |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index e4d950072b5a..1bd12296dca5 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -604,17 +604,10 @@ static int mgslpc_config(struct pcmcia_device *link) | |||
604 | if (debug_level >= DEBUG_LEVEL_INFO) | 604 | if (debug_level >= DEBUG_LEVEL_INFO) |
605 | printk("mgslpc_config(0x%p)\n", link); | 605 | printk("mgslpc_config(0x%p)\n", link); |
606 | 606 | ||
607 | /* read CONFIG tuple to find its configuration registers */ | ||
608 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
609 | tuple.Attributes = 0; | 607 | tuple.Attributes = 0; |
610 | tuple.TupleData = buf; | 608 | tuple.TupleData = buf; |
611 | tuple.TupleDataMax = sizeof(buf); | 609 | tuple.TupleDataMax = sizeof(buf); |
612 | tuple.TupleOffset = 0; | 610 | tuple.TupleOffset = 0; |
613 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
614 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
615 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
616 | link->conf.ConfigBase = parse.config.base; | ||
617 | link->conf.Present = parse.config.rmask[0]; | ||
618 | 611 | ||
619 | /* get CIS configuration entry */ | 612 | /* get CIS configuration entry */ |
620 | 613 | ||
diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index bef4759f70e5..7efd28ac21ed 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c | |||
@@ -192,20 +192,10 @@ static int ide_config(struct pcmcia_device *link) | |||
192 | tuple.TupleOffset = 0; | 192 | tuple.TupleOffset = 0; |
193 | tuple.TupleDataMax = 255; | 193 | tuple.TupleDataMax = 255; |
194 | tuple.Attributes = 0; | 194 | tuple.Attributes = 0; |
195 | tuple.DesiredTuple = CISTPL_CONFIG; | 195 | |
196 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 196 | is_kme = ((link->manf_id == MANFID_KME) && |
197 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | 197 | ((link->card_id == PRODID_KME_KXLC005_A) || |
198 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &stk->parse)); | 198 | (link->card_id == PRODID_KME_KXLC005_B))); |
199 | link->conf.ConfigBase = stk->parse.config.base; | ||
200 | link->conf.Present = stk->parse.config.rmask[0]; | ||
201 | |||
202 | tuple.DesiredTuple = CISTPL_MANFID; | ||
203 | if (!pcmcia_get_first_tuple(link, &tuple) && | ||
204 | !pcmcia_get_tuple_data(link, &tuple) && | ||
205 | !pcmcia_parse_tuple(link, &tuple, &stk->parse)) | ||
206 | is_kme = ((stk->parse.manfid.manf == MANFID_KME) && | ||
207 | ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || | ||
208 | (stk->parse.manfid.card == PRODID_KME_KXLC005_B))); | ||
209 | 199 | ||
210 | /* Not sure if this is right... look up the current Vcc */ | 200 | /* Not sure if this is right... look up the current Vcc */ |
211 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf)); | 201 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf)); |
@@ -408,8 +398,10 @@ static struct pcmcia_device_id ide_ids[] = { | |||
408 | PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6), | 398 | PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6), |
409 | PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), | 399 | PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003), |
410 | PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443), | 400 | PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443), |
401 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), | ||
411 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), | 402 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), |
412 | PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), | 403 | PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), |
404 | PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), | ||
413 | PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), | 405 | PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), |
414 | PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), | 406 | PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), |
415 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), | 407 | PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), |
diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index 7bbfd85ab793..fd5d7364a487 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c | |||
@@ -194,41 +194,11 @@ static int avmcs_config(struct pcmcia_device *link) | |||
194 | 194 | ||
195 | dev = link->priv; | 195 | dev = link->priv; |
196 | 196 | ||
197 | /* | ||
198 | This reads the card's CONFIG tuple to find its configuration | ||
199 | registers. | ||
200 | */ | ||
201 | do { | 197 | do { |
202 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
203 | i = pcmcia_get_first_tuple(link, &tuple); | ||
204 | if (i != CS_SUCCESS) break; | ||
205 | tuple.TupleData = buf; | ||
206 | tuple.TupleDataMax = 64; | ||
207 | tuple.TupleOffset = 0; | ||
208 | i = pcmcia_get_tuple_data(link, &tuple); | ||
209 | if (i != CS_SUCCESS) break; | ||
210 | i = pcmcia_parse_tuple(link, &tuple, &parse); | ||
211 | if (i != CS_SUCCESS) break; | ||
212 | link->conf.ConfigBase = parse.config.base; | ||
213 | } while (0); | ||
214 | if (i != CS_SUCCESS) { | ||
215 | cs_error(link, ParseTuple, i); | ||
216 | return -ENODEV; | ||
217 | } | ||
218 | |||
219 | do { | ||
220 | |||
221 | tuple.Attributes = 0; | ||
222 | tuple.TupleData = buf; | ||
223 | tuple.TupleDataMax = 254; | ||
224 | tuple.TupleOffset = 0; | ||
225 | tuple.DesiredTuple = CISTPL_VERS_1; | ||
226 | |||
227 | devname[0] = 0; | 198 | devname[0] = 0; |
228 | if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) { | 199 | if (link->prod_id[1]) |
229 | strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], | 200 | strlcpy(devname, link->prod_id[1], sizeof(devname)); |
230 | sizeof(devname)); | 201 | |
231 | } | ||
232 | /* | 202 | /* |
233 | * find IO port | 203 | * find IO port |
234 | */ | 204 | */ |
diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index ac28e3278ad9..876fec6c6be8 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c | |||
@@ -216,41 +216,11 @@ static int avma1cs_config(struct pcmcia_device *link) | |||
216 | 216 | ||
217 | DEBUG(0, "avma1cs_config(0x%p)\n", link); | 217 | DEBUG(0, "avma1cs_config(0x%p)\n", link); |
218 | 218 | ||
219 | /* | ||
220 | This reads the card's CONFIG tuple to find its configuration | ||
221 | registers. | ||
222 | */ | ||
223 | do { | 219 | do { |
224 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
225 | i = pcmcia_get_first_tuple(link, &tuple); | ||
226 | if (i != CS_SUCCESS) break; | ||
227 | tuple.TupleData = buf; | ||
228 | tuple.TupleDataMax = 64; | ||
229 | tuple.TupleOffset = 0; | ||
230 | i = pcmcia_get_tuple_data(link, &tuple); | ||
231 | if (i != CS_SUCCESS) break; | ||
232 | i = pcmcia_parse_tuple(link, &tuple, &parse); | ||
233 | if (i != CS_SUCCESS) break; | ||
234 | link->conf.ConfigBase = parse.config.base; | ||
235 | } while (0); | ||
236 | if (i != CS_SUCCESS) { | ||
237 | cs_error(link, ParseTuple, i); | ||
238 | return -ENODEV; | ||
239 | } | ||
240 | |||
241 | do { | ||
242 | |||
243 | tuple.Attributes = 0; | ||
244 | tuple.TupleData = buf; | ||
245 | tuple.TupleDataMax = 254; | ||
246 | tuple.TupleOffset = 0; | ||
247 | tuple.DesiredTuple = CISTPL_VERS_1; | ||
248 | |||
249 | devname[0] = 0; | 220 | devname[0] = 0; |
250 | if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) { | 221 | if (link->prod_id[1]) |
251 | strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], | 222 | strlcpy(devname, link->prod_id[1], sizeof(devname)); |
252 | sizeof(devname)); | 223 | |
253 | } | ||
254 | /* | 224 | /* |
255 | * find IO port | 225 | * find IO port |
256 | */ | 226 | */ |
diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index e18e75be8ed3..4e180d210faa 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c | |||
@@ -242,23 +242,6 @@ static int elsa_cs_config(struct pcmcia_device *link) | |||
242 | DEBUG(0, "elsa_config(0x%p)\n", link); | 242 | DEBUG(0, "elsa_config(0x%p)\n", link); |
243 | dev = link->priv; | 243 | dev = link->priv; |
244 | 244 | ||
245 | /* | ||
246 | This reads the card's CONFIG tuple to find its configuration | ||
247 | registers. | ||
248 | */ | ||
249 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
250 | tuple.TupleData = (cisdata_t *)buf; | ||
251 | tuple.TupleDataMax = 255; | ||
252 | tuple.TupleOffset = 0; | ||
253 | tuple.Attributes = 0; | ||
254 | i = first_tuple(link, &tuple, &parse); | ||
255 | if (i != CS_SUCCESS) { | ||
256 | last_fn = ParseTuple; | ||
257 | goto cs_failed; | ||
258 | } | ||
259 | link->conf.ConfigBase = parse.config.base; | ||
260 | link->conf.Present = parse.config.rmask[0]; | ||
261 | |||
262 | tuple.TupleData = (cisdata_t *)buf; | 245 | tuple.TupleData = (cisdata_t *)buf; |
263 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; | 246 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; |
264 | tuple.Attributes = 0; | 247 | tuple.Attributes = 0; |
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index f9c14a2970bc..46ed65334c51 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c | |||
@@ -233,20 +233,10 @@ static int sedlbauer_config(struct pcmcia_device *link) | |||
233 | 233 | ||
234 | DEBUG(0, "sedlbauer_config(0x%p)\n", link); | 234 | DEBUG(0, "sedlbauer_config(0x%p)\n", link); |
235 | 235 | ||
236 | /* | ||
237 | This reads the card's CONFIG tuple to find its configuration | ||
238 | registers. | ||
239 | */ | ||
240 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
241 | tuple.Attributes = 0; | 236 | tuple.Attributes = 0; |
242 | tuple.TupleData = buf; | 237 | tuple.TupleData = buf; |
243 | tuple.TupleDataMax = sizeof(buf); | 238 | tuple.TupleDataMax = sizeof(buf); |
244 | tuple.TupleOffset = 0; | 239 | tuple.TupleOffset = 0; |
245 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
246 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
247 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
248 | link->conf.ConfigBase = parse.config.base; | ||
249 | link->conf.Present = parse.config.rmask[0]; | ||
250 | 240 | ||
251 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); | 241 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); |
252 | 242 | ||
diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index afcc2aeadb34..6b754f183796 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c | |||
@@ -232,23 +232,6 @@ static int teles_cs_config(struct pcmcia_device *link) | |||
232 | DEBUG(0, "teles_config(0x%p)\n", link); | 232 | DEBUG(0, "teles_config(0x%p)\n", link); |
233 | dev = link->priv; | 233 | dev = link->priv; |
234 | 234 | ||
235 | /* | ||
236 | This reads the card's CONFIG tuple to find its configuration | ||
237 | registers. | ||
238 | */ | ||
239 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
240 | tuple.TupleData = (cisdata_t *)buf; | ||
241 | tuple.TupleDataMax = 255; | ||
242 | tuple.TupleOffset = 0; | ||
243 | tuple.Attributes = 0; | ||
244 | i = first_tuple(link, &tuple, &parse); | ||
245 | if (i != CS_SUCCESS) { | ||
246 | last_fn = ParseTuple; | ||
247 | goto cs_failed; | ||
248 | } | ||
249 | link->conf.ConfigBase = parse.config.base; | ||
250 | link->conf.Present = parse.config.rmask[0]; | ||
251 | |||
252 | tuple.TupleData = (cisdata_t *)buf; | 235 | tuple.TupleData = (cisdata_t *)buf; |
253 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; | 236 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; |
254 | tuple.Attributes = 0; | 237 | tuple.Attributes = 0; |
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index 046009928526..794cc61819dd 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c | |||
@@ -338,7 +338,6 @@ static int tc574_config(struct pcmcia_device *link) | |||
338 | struct net_device *dev = link->priv; | 338 | struct net_device *dev = link->priv; |
339 | struct el3_private *lp = netdev_priv(dev); | 339 | struct el3_private *lp = netdev_priv(dev); |
340 | tuple_t tuple; | 340 | tuple_t tuple; |
341 | cisparse_t parse; | ||
342 | unsigned short buf[32]; | 341 | unsigned short buf[32]; |
343 | int last_fn, last_ret, i, j; | 342 | int last_fn, last_ret, i, j; |
344 | kio_addr_t ioaddr; | 343 | kio_addr_t ioaddr; |
@@ -350,17 +349,6 @@ static int tc574_config(struct pcmcia_device *link) | |||
350 | 349 | ||
351 | DEBUG(0, "3c574_config(0x%p)\n", link); | 350 | DEBUG(0, "3c574_config(0x%p)\n", link); |
352 | 351 | ||
353 | tuple.Attributes = 0; | ||
354 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
355 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
356 | tuple.TupleData = (cisdata_t *)buf; | ||
357 | tuple.TupleDataMax = 64; | ||
358 | tuple.TupleOffset = 0; | ||
359 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
360 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
361 | link->conf.ConfigBase = parse.config.base; | ||
362 | link->conf.Present = parse.config.rmask[0]; | ||
363 | |||
364 | link->io.IOAddrLines = 16; | 352 | link->io.IOAddrLines = 16; |
365 | for (i = j = 0; j < 0x400; j += 0x20) { | 353 | for (i = j = 0; j < 0x400; j += 0x20) { |
366 | link->io.BasePort1 = j ^ 0x300; | 354 | link->io.BasePort1 = j ^ 0x300; |
@@ -382,6 +370,10 @@ static int tc574_config(struct pcmcia_device *link) | |||
382 | /* The 3c574 normally uses an EEPROM for configuration info, including | 370 | /* The 3c574 normally uses an EEPROM for configuration info, including |
383 | the hardware address. The future products may include a modem chip | 371 | the hardware address. The future products may include a modem chip |
384 | and put the address in the CIS. */ | 372 | and put the address in the CIS. */ |
373 | tuple.Attributes = 0; | ||
374 | tuple.TupleData = (cisdata_t *)buf; | ||
375 | tuple.TupleDataMax = 64; | ||
376 | tuple.TupleOffset = 0; | ||
385 | tuple.DesiredTuple = 0x88; | 377 | tuple.DesiredTuple = 0x88; |
386 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { | 378 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { |
387 | pcmcia_get_tuple_data(link, &tuple); | 379 | pcmcia_get_tuple_data(link, &tuple); |
@@ -397,12 +389,9 @@ static int tc574_config(struct pcmcia_device *link) | |||
397 | goto failed; | 389 | goto failed; |
398 | } | 390 | } |
399 | } | 391 | } |
400 | tuple.DesiredTuple = CISTPL_VERS_1; | 392 | if (link->prod_id[1]) |
401 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS && | 393 | cardname = link->prod_id[1]; |
402 | pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS && | 394 | else |
403 | pcmcia_parse_tuple(link, &tuple, &parse) == CS_SUCCESS) { | ||
404 | cardname = parse.version_1.str + parse.version_1.ofs[1]; | ||
405 | } else | ||
406 | cardname = "3Com 3c574"; | 395 | cardname = "3Com 3c574"; |
407 | 396 | ||
408 | { | 397 | { |
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 231fa2c9ec6c..1e73ff7d5d8e 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c | |||
@@ -253,7 +253,6 @@ static int tc589_config(struct pcmcia_device *link) | |||
253 | struct net_device *dev = link->priv; | 253 | struct net_device *dev = link->priv; |
254 | struct el3_private *lp = netdev_priv(dev); | 254 | struct el3_private *lp = netdev_priv(dev); |
255 | tuple_t tuple; | 255 | tuple_t tuple; |
256 | cisparse_t parse; | ||
257 | u16 buf[32], *phys_addr; | 256 | u16 buf[32], *phys_addr; |
258 | int last_fn, last_ret, i, j, multi = 0, fifo; | 257 | int last_fn, last_ret, i, j, multi = 0, fifo; |
259 | kio_addr_t ioaddr; | 258 | kio_addr_t ioaddr; |
@@ -263,26 +262,16 @@ static int tc589_config(struct pcmcia_device *link) | |||
263 | 262 | ||
264 | phys_addr = (u16 *)dev->dev_addr; | 263 | phys_addr = (u16 *)dev->dev_addr; |
265 | tuple.Attributes = 0; | 264 | tuple.Attributes = 0; |
266 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
267 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
268 | tuple.TupleData = (cisdata_t *)buf; | 265 | tuple.TupleData = (cisdata_t *)buf; |
269 | tuple.TupleDataMax = sizeof(buf); | 266 | tuple.TupleDataMax = sizeof(buf); |
270 | tuple.TupleOffset = 0; | 267 | tuple.TupleOffset = 0; |
271 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
272 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
273 | link->conf.ConfigBase = parse.config.base; | ||
274 | link->conf.Present = parse.config.rmask[0]; | ||
275 | |||
276 | /* Is this a 3c562? */ | ||
277 | tuple.DesiredTuple = CISTPL_MANFID; | ||
278 | tuple.Attributes = TUPLE_RETURN_COMMON; | 268 | tuple.Attributes = TUPLE_RETURN_COMMON; |
279 | if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && | 269 | |
280 | (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) { | 270 | /* Is this a 3c562? */ |
281 | if (le16_to_cpu(buf[0]) != MANFID_3COM) | 271 | if (link->manf_id != MANFID_3COM) |
282 | printk(KERN_INFO "3c589_cs: hmmm, is this really a " | 272 | printk(KERN_INFO "3c589_cs: hmmm, is this really a " |
283 | "3Com card??\n"); | 273 | "3Com card??\n"); |
284 | multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562); | 274 | multi = (link->card_id == PRODID_3COM_3C562); |
285 | } | ||
286 | 275 | ||
287 | /* For the 3c562, the base address must be xx00-xx7f */ | 276 | /* For the 3c562, the base address must be xx00-xx7f */ |
288 | link->io.IOAddrLines = 16; | 277 | link->io.IOAddrLines = 16; |
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 5ddd5742f779..6139048f8117 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c | |||
@@ -299,11 +299,7 @@ static int axnet_config(struct pcmcia_device *link) | |||
299 | tuple.TupleData = (cisdata_t *)buf; | 299 | tuple.TupleData = (cisdata_t *)buf; |
300 | tuple.TupleDataMax = sizeof(buf); | 300 | tuple.TupleDataMax = sizeof(buf); |
301 | tuple.TupleOffset = 0; | 301 | tuple.TupleOffset = 0; |
302 | tuple.DesiredTuple = CISTPL_CONFIG; | 302 | |
303 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
304 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
305 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
306 | link->conf.ConfigBase = parse.config.base; | ||
307 | /* don't trust the CIS on this; Linksys got it wrong */ | 303 | /* don't trust the CIS on this; Linksys got it wrong */ |
308 | link->conf.Present = 0x63; | 304 | link->conf.Present = 0x63; |
309 | 305 | ||
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 48434d7924eb..91f65e91cd5f 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c | |||
@@ -249,12 +249,9 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
249 | static int com20020_config(struct pcmcia_device *link) | 249 | static int com20020_config(struct pcmcia_device *link) |
250 | { | 250 | { |
251 | struct arcnet_local *lp; | 251 | struct arcnet_local *lp; |
252 | tuple_t tuple; | ||
253 | cisparse_t parse; | ||
254 | com20020_dev_t *info; | 252 | com20020_dev_t *info; |
255 | struct net_device *dev; | 253 | struct net_device *dev; |
256 | int i, last_ret, last_fn; | 254 | int i, last_ret, last_fn; |
257 | u_char buf[64]; | ||
258 | int ioaddr; | 255 | int ioaddr; |
259 | 256 | ||
260 | info = link->priv; | 257 | info = link->priv; |
@@ -264,16 +261,6 @@ static int com20020_config(struct pcmcia_device *link) | |||
264 | 261 | ||
265 | DEBUG(0, "com20020_config(0x%p)\n", link); | 262 | DEBUG(0, "com20020_config(0x%p)\n", link); |
266 | 263 | ||
267 | tuple.Attributes = 0; | ||
268 | tuple.TupleData = buf; | ||
269 | tuple.TupleDataMax = 64; | ||
270 | tuple.TupleOffset = 0; | ||
271 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
272 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
273 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
274 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
275 | link->conf.ConfigBase = parse.config.base; | ||
276 | |||
277 | DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1); | 264 | DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1); |
278 | i = !CS_SUCCESS; | 265 | i = !CS_SUCCESS; |
279 | if (!link->io.BasePort1) | 266 | if (!link->io.BasePort1) |
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 65f6fdf43725..0d7de617e535 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c | |||
@@ -342,7 +342,7 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
342 | tuple_t tuple; | 342 | tuple_t tuple; |
343 | cisparse_t parse; | 343 | cisparse_t parse; |
344 | u_short buf[32]; | 344 | u_short buf[32]; |
345 | int i, last_fn, last_ret, ret; | 345 | int i, last_fn = 0, last_ret = 0, ret; |
346 | kio_addr_t ioaddr; | 346 | kio_addr_t ioaddr; |
347 | cardtype_t cardtype; | 347 | cardtype_t cardtype; |
348 | char *card_name = "unknown"; | 348 | char *card_name = "unknown"; |
@@ -350,21 +350,9 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
350 | 350 | ||
351 | DEBUG(0, "fmvj18x_config(0x%p)\n", link); | 351 | DEBUG(0, "fmvj18x_config(0x%p)\n", link); |
352 | 352 | ||
353 | /* | ||
354 | This reads the card's CONFIG tuple to find its configuration | ||
355 | registers. | ||
356 | */ | ||
357 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
358 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
359 | tuple.TupleData = (u_char *)buf; | 353 | tuple.TupleData = (u_char *)buf; |
360 | tuple.TupleDataMax = 64; | 354 | tuple.TupleDataMax = 64; |
361 | tuple.TupleOffset = 0; | 355 | tuple.TupleOffset = 0; |
362 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
363 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
364 | |||
365 | link->conf.ConfigBase = parse.config.base; | ||
366 | link->conf.Present = parse.config.rmask[0]; | ||
367 | |||
368 | tuple.DesiredTuple = CISTPL_FUNCE; | 356 | tuple.DesiredTuple = CISTPL_FUNCE; |
369 | tuple.TupleOffset = 0; | 357 | tuple.TupleOffset = 0; |
370 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { | 358 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { |
@@ -374,17 +362,12 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
374 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | 362 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
375 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | 363 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
376 | link->conf.ConfigIndex = parse.cftable_entry.index; | 364 | link->conf.ConfigIndex = parse.cftable_entry.index; |
377 | tuple.DesiredTuple = CISTPL_MANFID; | 365 | switch (link->manf_id) { |
378 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) | ||
379 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
380 | else | ||
381 | buf[0] = 0xffff; | ||
382 | switch (le16_to_cpu(buf[0])) { | ||
383 | case MANFID_TDK: | 366 | case MANFID_TDK: |
384 | cardtype = TDK; | 367 | cardtype = TDK; |
385 | if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410 | 368 | if (link->card_id == PRODID_TDK_GN3410 |
386 | || le16_to_cpu(buf[1]) == PRODID_TDK_NP9610 | 369 | || link->card_id == PRODID_TDK_NP9610 |
387 | || le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) { | 370 | || link->card_id == PRODID_TDK_MN3200) { |
388 | /* MultiFunction Card */ | 371 | /* MultiFunction Card */ |
389 | link->conf.ConfigBase = 0x800; | 372 | link->conf.ConfigBase = 0x800; |
390 | link->conf.ConfigIndex = 0x47; | 373 | link->conf.ConfigIndex = 0x47; |
@@ -395,11 +378,11 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
395 | cardtype = CONTEC; | 378 | cardtype = CONTEC; |
396 | break; | 379 | break; |
397 | case MANFID_FUJITSU: | 380 | case MANFID_FUJITSU: |
398 | if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10302) | 381 | if (link->card_id == PRODID_FUJITSU_MBH10302) |
399 | /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302), | 382 | /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302), |
400 | but these are MBH10304 based card. */ | 383 | but these are MBH10304 based card. */ |
401 | cardtype = MBH10304; | 384 | cardtype = MBH10304; |
402 | else if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304) | 385 | else if (link->card_id == PRODID_FUJITSU_MBH10304) |
403 | cardtype = MBH10304; | 386 | cardtype = MBH10304; |
404 | else | 387 | else |
405 | cardtype = LA501; | 388 | cardtype = LA501; |
@@ -409,14 +392,9 @@ static int fmvj18x_config(struct pcmcia_device *link) | |||
409 | } | 392 | } |
410 | } else { | 393 | } else { |
411 | /* old type card */ | 394 | /* old type card */ |
412 | tuple.DesiredTuple = CISTPL_MANFID; | 395 | switch (link->manf_id) { |
413 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) | ||
414 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
415 | else | ||
416 | buf[0] = 0xffff; | ||
417 | switch (le16_to_cpu(buf[0])) { | ||
418 | case MANFID_FUJITSU: | 396 | case MANFID_FUJITSU: |
419 | if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304) { | 397 | if (link->card_id == PRODID_FUJITSU_MBH10304) { |
420 | cardtype = XXX10304; /* MBH10304 with buggy CIS */ | 398 | cardtype = XXX10304; /* MBH10304 with buggy CIS */ |
421 | link->conf.ConfigIndex = 0x20; | 399 | link->conf.ConfigIndex = 0x20; |
422 | } else { | 400 | } else { |
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index bc0ca41a0542..a956a51d284f 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c | |||
@@ -222,24 +222,12 @@ static int ibmtr_config(struct pcmcia_device *link) | |||
222 | ibmtr_dev_t *info = link->priv; | 222 | ibmtr_dev_t *info = link->priv; |
223 | struct net_device *dev = info->dev; | 223 | struct net_device *dev = info->dev; |
224 | struct tok_info *ti = netdev_priv(dev); | 224 | struct tok_info *ti = netdev_priv(dev); |
225 | tuple_t tuple; | ||
226 | cisparse_t parse; | ||
227 | win_req_t req; | 225 | win_req_t req; |
228 | memreq_t mem; | 226 | memreq_t mem; |
229 | int i, last_ret, last_fn; | 227 | int i, last_ret, last_fn; |
230 | u_char buf[64]; | ||
231 | 228 | ||
232 | DEBUG(0, "ibmtr_config(0x%p)\n", link); | 229 | DEBUG(0, "ibmtr_config(0x%p)\n", link); |
233 | 230 | ||
234 | tuple.Attributes = 0; | ||
235 | tuple.TupleData = buf; | ||
236 | tuple.TupleDataMax = 64; | ||
237 | tuple.TupleOffset = 0; | ||
238 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
239 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
240 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
241 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
242 | link->conf.ConfigBase = parse.config.base; | ||
243 | link->conf.ConfigIndex = 0x61; | 231 | link->conf.ConfigIndex = 0x61; |
244 | 232 | ||
245 | /* Determine if this is PRIMARY or ALTERNATE. */ | 233 | /* Determine if this is PRIMARY or ALTERNATE. */ |
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index e77110e4c288..3b707747a811 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c | |||
@@ -656,23 +656,12 @@ static int nmclan_config(struct pcmcia_device *link) | |||
656 | struct net_device *dev = link->priv; | 656 | struct net_device *dev = link->priv; |
657 | mace_private *lp = netdev_priv(dev); | 657 | mace_private *lp = netdev_priv(dev); |
658 | tuple_t tuple; | 658 | tuple_t tuple; |
659 | cisparse_t parse; | ||
660 | u_char buf[64]; | 659 | u_char buf[64]; |
661 | int i, last_ret, last_fn; | 660 | int i, last_ret, last_fn; |
662 | kio_addr_t ioaddr; | 661 | kio_addr_t ioaddr; |
663 | 662 | ||
664 | DEBUG(0, "nmclan_config(0x%p)\n", link); | 663 | DEBUG(0, "nmclan_config(0x%p)\n", link); |
665 | 664 | ||
666 | tuple.Attributes = 0; | ||
667 | tuple.TupleData = buf; | ||
668 | tuple.TupleDataMax = 64; | ||
669 | tuple.TupleOffset = 0; | ||
670 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
671 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
672 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
673 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
674 | link->conf.ConfigBase = parse.config.base; | ||
675 | |||
676 | CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); | 665 | CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); |
677 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); | 666 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
678 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); | 667 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
@@ -686,6 +675,7 @@ static int nmclan_config(struct pcmcia_device *link) | |||
686 | tuple.TupleData = buf; | 675 | tuple.TupleData = buf; |
687 | tuple.TupleDataMax = 64; | 676 | tuple.TupleDataMax = 64; |
688 | tuple.TupleOffset = 0; | 677 | tuple.TupleOffset = 0; |
678 | tuple.Attributes = 0; | ||
689 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 679 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
690 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | 680 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
691 | memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN); | 681 | memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN); |
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index c51cc5d8789a..2b1238e2dbdb 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
@@ -519,31 +519,15 @@ static int pcnet_config(struct pcmcia_device *link) | |||
519 | tuple_t tuple; | 519 | tuple_t tuple; |
520 | cisparse_t parse; | 520 | cisparse_t parse; |
521 | int i, last_ret, last_fn, start_pg, stop_pg, cm_offset; | 521 | int i, last_ret, last_fn, start_pg, stop_pg, cm_offset; |
522 | int manfid = 0, prodid = 0, has_shmem = 0; | 522 | int has_shmem = 0; |
523 | u_short buf[64]; | 523 | u_short buf[64]; |
524 | hw_info_t *hw_info; | 524 | hw_info_t *hw_info; |
525 | 525 | ||
526 | DEBUG(0, "pcnet_config(0x%p)\n", link); | 526 | DEBUG(0, "pcnet_config(0x%p)\n", link); |
527 | 527 | ||
528 | tuple.Attributes = 0; | ||
529 | tuple.TupleData = (cisdata_t *)buf; | 528 | tuple.TupleData = (cisdata_t *)buf; |
530 | tuple.TupleDataMax = sizeof(buf); | 529 | tuple.TupleDataMax = sizeof(buf); |
531 | tuple.TupleOffset = 0; | 530 | tuple.TupleOffset = 0; |
532 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
533 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
534 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
535 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
536 | link->conf.ConfigBase = parse.config.base; | ||
537 | link->conf.Present = parse.config.rmask[0]; | ||
538 | |||
539 | tuple.DesiredTuple = CISTPL_MANFID; | ||
540 | tuple.Attributes = TUPLE_RETURN_COMMON; | ||
541 | if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && | ||
542 | (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) { | ||
543 | manfid = le16_to_cpu(buf[0]); | ||
544 | prodid = le16_to_cpu(buf[1]); | ||
545 | } | ||
546 | |||
547 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 531 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
548 | tuple.Attributes = 0; | 532 | tuple.Attributes = 0; |
549 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 533 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
@@ -589,8 +573,8 @@ static int pcnet_config(struct pcmcia_device *link) | |||
589 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 573 | link->conf.Attributes |= CONF_ENABLE_SPKR; |
590 | link->conf.Status = CCSR_AUDIO_ENA; | 574 | link->conf.Status = CCSR_AUDIO_ENA; |
591 | } | 575 | } |
592 | if ((manfid == MANFID_IBM) && | 576 | if ((link->manf_id == MANFID_IBM) && |
593 | (prodid == PRODID_IBM_HOME_AND_AWAY)) | 577 | (link->card_id == PRODID_IBM_HOME_AND_AWAY)) |
594 | link->conf.ConfigIndex |= 0x10; | 578 | link->conf.ConfigIndex |= 0x10; |
595 | 579 | ||
596 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); | 580 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
@@ -624,10 +608,10 @@ static int pcnet_config(struct pcmcia_device *link) | |||
624 | info->flags = hw_info->flags; | 608 | info->flags = hw_info->flags; |
625 | /* Check for user overrides */ | 609 | /* Check for user overrides */ |
626 | info->flags |= (delay_output) ? DELAY_OUTPUT : 0; | 610 | info->flags |= (delay_output) ? DELAY_OUTPUT : 0; |
627 | if ((manfid == MANFID_SOCKET) && | 611 | if ((link->manf_id == MANFID_SOCKET) && |
628 | ((prodid == PRODID_SOCKET_LPE) || | 612 | ((link->card_id == PRODID_SOCKET_LPE) || |
629 | (prodid == PRODID_SOCKET_LPE_CF) || | 613 | (link->card_id == PRODID_SOCKET_LPE_CF) || |
630 | (prodid == PRODID_SOCKET_EIO))) | 614 | (link->card_id == PRODID_SOCKET_EIO))) |
631 | info->flags &= ~USE_BIG_BUF; | 615 | info->flags &= ~USE_BIG_BUF; |
632 | if (!use_big_buf) | 616 | if (!use_big_buf) |
633 | info->flags &= ~USE_BIG_BUF; | 617 | info->flags &= ~USE_BIG_BUF; |
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 20fcc3576202..530df8883fe5 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
@@ -560,16 +560,8 @@ static int mhz_setup(struct pcmcia_device *link) | |||
560 | 560 | ||
561 | /* Read the station address from the CIS. It is stored as the last | 561 | /* Read the station address from the CIS. It is stored as the last |
562 | (fourth) string in the Version 1 Version/ID tuple. */ | 562 | (fourth) string in the Version 1 Version/ID tuple. */ |
563 | tuple->DesiredTuple = CISTPL_VERS_1; | 563 | if (link->prod_id[3]) { |
564 | if (first_tuple(link, tuple, parse) != CS_SUCCESS) { | 564 | station_addr = link->prod_id[3]; |
565 | rc = -1; | ||
566 | goto free_cfg_mem; | ||
567 | } | ||
568 | /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ | ||
569 | if (next_tuple(link, tuple, parse) != CS_SUCCESS) | ||
570 | first_tuple(link, tuple, parse); | ||
571 | if (parse->version_1.ns > 3) { | ||
572 | station_addr = parse->version_1.str + parse->version_1.ofs[3]; | ||
573 | if (cvt_ascii_address(dev, station_addr) == 0) { | 565 | if (cvt_ascii_address(dev, station_addr) == 0) { |
574 | rc = 0; | 566 | rc = 0; |
575 | goto free_cfg_mem; | 567 | goto free_cfg_mem; |
@@ -744,15 +736,12 @@ static int smc_setup(struct pcmcia_device *link) | |||
744 | } | 736 | } |
745 | } | 737 | } |
746 | /* Try the third string in the Version 1 Version/ID tuple. */ | 738 | /* Try the third string in the Version 1 Version/ID tuple. */ |
747 | tuple->DesiredTuple = CISTPL_VERS_1; | 739 | if (link->prod_id[2]) { |
748 | if (first_tuple(link, tuple, parse) != CS_SUCCESS) { | 740 | station_addr = link->prod_id[2]; |
749 | rc = -1; | 741 | if (cvt_ascii_address(dev, station_addr) == 0) { |
750 | goto free_cfg_mem; | 742 | rc = 0; |
751 | } | 743 | goto free_cfg_mem; |
752 | station_addr = parse->version_1.str + parse->version_1.ofs[2]; | 744 | } |
753 | if (cvt_ascii_address(dev, station_addr) == 0) { | ||
754 | rc = 0; | ||
755 | goto free_cfg_mem; | ||
756 | } | 745 | } |
757 | 746 | ||
758 | rc = -1; | 747 | rc = -1; |
@@ -970,10 +959,6 @@ static int smc91c92_config(struct pcmcia_device *link) | |||
970 | { | 959 | { |
971 | struct net_device *dev = link->priv; | 960 | struct net_device *dev = link->priv; |
972 | struct smc_private *smc = netdev_priv(dev); | 961 | struct smc_private *smc = netdev_priv(dev); |
973 | struct smc_cfg_mem *cfg_mem; | ||
974 | tuple_t *tuple; | ||
975 | cisparse_t *parse; | ||
976 | u_char *buf; | ||
977 | char *name; | 962 | char *name; |
978 | int i, j, rev; | 963 | int i, j, rev; |
979 | kio_addr_t ioaddr; | 964 | kio_addr_t ioaddr; |
@@ -981,30 +966,8 @@ static int smc91c92_config(struct pcmcia_device *link) | |||
981 | 966 | ||
982 | DEBUG(0, "smc91c92_config(0x%p)\n", link); | 967 | DEBUG(0, "smc91c92_config(0x%p)\n", link); |
983 | 968 | ||
984 | cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); | 969 | smc->manfid = link->manf_id; |
985 | if (!cfg_mem) | 970 | smc->cardid = link->card_id; |
986 | goto config_failed; | ||
987 | |||
988 | tuple = &cfg_mem->tuple; | ||
989 | parse = &cfg_mem->parse; | ||
990 | buf = cfg_mem->buf; | ||
991 | |||
992 | tuple->Attributes = tuple->TupleOffset = 0; | ||
993 | tuple->TupleData = (cisdata_t *)buf; | ||
994 | tuple->TupleDataMax = 64; | ||
995 | |||
996 | tuple->DesiredTuple = CISTPL_CONFIG; | ||
997 | i = first_tuple(link, tuple, parse); | ||
998 | CS_EXIT_TEST(i, ParseTuple, config_failed); | ||
999 | link->conf.ConfigBase = parse->config.base; | ||
1000 | link->conf.Present = parse->config.rmask[0]; | ||
1001 | |||
1002 | tuple->DesiredTuple = CISTPL_MANFID; | ||
1003 | tuple->Attributes = TUPLE_RETURN_COMMON; | ||
1004 | if (first_tuple(link, tuple, parse) == CS_SUCCESS) { | ||
1005 | smc->manfid = parse->manfid.manf; | ||
1006 | smc->cardid = parse->manfid.card; | ||
1007 | } | ||
1008 | 971 | ||
1009 | if ((smc->manfid == MANFID_OSITECH) && | 972 | if ((smc->manfid == MANFID_OSITECH) && |
1010 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | 973 | (smc->cardid != PRODID_OSITECH_SEVEN)) { |
@@ -1134,14 +1097,12 @@ static int smc91c92_config(struct pcmcia_device *link) | |||
1134 | printk(KERN_NOTICE " No MII transceivers found!\n"); | 1097 | printk(KERN_NOTICE " No MII transceivers found!\n"); |
1135 | } | 1098 | } |
1136 | } | 1099 | } |
1137 | kfree(cfg_mem); | ||
1138 | return 0; | 1100 | return 0; |
1139 | 1101 | ||
1140 | config_undo: | 1102 | config_undo: |
1141 | unregister_netdev(dev); | 1103 | unregister_netdev(dev); |
1142 | config_failed: /* CS_EXIT_TEST() calls jump to here... */ | 1104 | config_failed: /* CS_EXIT_TEST() calls jump to here... */ |
1143 | smc91c92_release(link); | 1105 | smc91c92_release(link); |
1144 | kfree(cfg_mem); | ||
1145 | return -ENODEV; | 1106 | return -ENODEV; |
1146 | } /* smc91c92_config */ | 1107 | } /* smc91c92_config */ |
1147 | 1108 | ||
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 5de8850f2323..8478dca3d8d1 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c | |||
@@ -709,22 +709,11 @@ set_card_type(struct pcmcia_device *link, const void *s) | |||
709 | * Returns: true if this is a CE2 | 709 | * Returns: true if this is a CE2 |
710 | */ | 710 | */ |
711 | static int | 711 | static int |
712 | has_ce2_string(struct pcmcia_device * link) | 712 | has_ce2_string(struct pcmcia_device * p_dev) |
713 | { | 713 | { |
714 | tuple_t tuple; | 714 | if (p_dev->prod_id[2] && strstr(p_dev->prod_id[2], "CE2")) |
715 | cisparse_t parse; | 715 | return 1; |
716 | u_char buf[256]; | 716 | return 0; |
717 | |||
718 | tuple.Attributes = 0; | ||
719 | tuple.TupleData = buf; | ||
720 | tuple.TupleDataMax = 254; | ||
721 | tuple.TupleOffset = 0; | ||
722 | tuple.DesiredTuple = CISTPL_VERS_1; | ||
723 | if (!first_tuple(link, &tuple, &parse) && parse.version_1.ns > 2) { | ||
724 | if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2")) | ||
725 | return 1; | ||
726 | } | ||
727 | return 0; | ||
728 | } | 717 | } |
729 | 718 | ||
730 | /**************** | 719 | /**************** |
@@ -794,13 +783,6 @@ xirc2ps_config(struct pcmcia_device * link) | |||
794 | goto failure; | 783 | goto failure; |
795 | } | 784 | } |
796 | 785 | ||
797 | /* get configuration stuff */ | ||
798 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
799 | if ((err=first_tuple(link, &tuple, &parse))) | ||
800 | goto cis_error; | ||
801 | link->conf.ConfigBase = parse.config.base; | ||
802 | link->conf.Present = parse.config.rmask[0]; | ||
803 | |||
804 | /* get the ethernet address from the CIS */ | 786 | /* get the ethernet address from the CIS */ |
805 | tuple.DesiredTuple = CISTPL_FUNCE; | 787 | tuple.DesiredTuple = CISTPL_FUNCE; |
806 | for (err = first_tuple(link, &tuple, &parse); !err; | 788 | for (err = first_tuple(link, &tuple, &parse); !err; |
@@ -1064,8 +1046,6 @@ xirc2ps_config(struct pcmcia_device * link) | |||
1064 | xirc2ps_release(link); | 1046 | xirc2ps_release(link); |
1065 | return -ENODEV; | 1047 | return -ENODEV; |
1066 | 1048 | ||
1067 | cis_error: | ||
1068 | printk(KNOT_XIRC "unable to parse CIS\n"); | ||
1069 | failure: | 1049 | failure: |
1070 | return -ENODEV; | 1050 | return -ENODEV; |
1071 | } /* xirc2ps_config */ | 1051 | } /* xirc2ps_config */ |
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index ac9437d497f0..f12355398fe7 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c | |||
@@ -219,21 +219,6 @@ static int airo_config(struct pcmcia_device *link) | |||
219 | dev = link->priv; | 219 | dev = link->priv; |
220 | 220 | ||
221 | DEBUG(0, "airo_config(0x%p)\n", link); | 221 | DEBUG(0, "airo_config(0x%p)\n", link); |
222 | |||
223 | /* | ||
224 | This reads the card's CONFIG tuple to find its configuration | ||
225 | registers. | ||
226 | */ | ||
227 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
228 | tuple.Attributes = 0; | ||
229 | tuple.TupleData = buf; | ||
230 | tuple.TupleDataMax = sizeof(buf); | ||
231 | tuple.TupleOffset = 0; | ||
232 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
233 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
234 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
235 | link->conf.ConfigBase = parse.config.base; | ||
236 | link->conf.Present = parse.config.rmask[0]; | ||
237 | 222 | ||
238 | /* | 223 | /* |
239 | In this loop, we scan the CIS for configuration table entries, | 224 | In this loop, we scan the CIS for configuration table entries, |
@@ -247,6 +232,10 @@ static int airo_config(struct pcmcia_device *link) | |||
247 | these things without consulting the CIS, and most client drivers | 232 | these things without consulting the CIS, and most client drivers |
248 | will only use the CIS to fill in implementation-defined details. | 233 | will only use the CIS to fill in implementation-defined details. |
249 | */ | 234 | */ |
235 | tuple.Attributes = 0; | ||
236 | tuple.TupleData = buf; | ||
237 | tuple.TupleDataMax = sizeof(buf); | ||
238 | tuple.TupleOffset = 0; | ||
250 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 239 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
251 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 240 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
252 | while (1) { | 241 | while (1) { |
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 5c410989c4d7..12617cd0b78e 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c | |||
@@ -244,17 +244,6 @@ static int atmel_config(struct pcmcia_device *link) | |||
244 | tuple.TupleOffset = 0; | 244 | tuple.TupleOffset = 0; |
245 | 245 | ||
246 | /* | 246 | /* |
247 | This reads the card's CONFIG tuple to find its configuration | ||
248 | registers. | ||
249 | */ | ||
250 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
251 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
252 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
253 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
254 | link->conf.ConfigBase = parse.config.base; | ||
255 | link->conf.Present = parse.config.rmask[0]; | ||
256 | |||
257 | /* | ||
258 | In this loop, we scan the CIS for configuration table entries, | 247 | In this loop, we scan the CIS for configuration table entries, |
259 | each of which describes a valid card configuration, including | 248 | each of which describes a valid card configuration, including |
260 | voltage, IO window, memory window, and interrupt settings. | 249 | voltage, IO window, memory window, and interrupt settings. |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index f63909e4bc32..ee542ec6d6a8 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -293,15 +293,12 @@ static int sandisk_enable_wireless(struct net_device *dev) | |||
293 | goto done; | 293 | goto done; |
294 | } | 294 | } |
295 | 295 | ||
296 | tuple.DesiredTuple = CISTPL_MANFID; | ||
297 | tuple.Attributes = TUPLE_RETURN_COMMON; | 296 | tuple.Attributes = TUPLE_RETURN_COMMON; |
298 | tuple.TupleData = buf; | 297 | tuple.TupleData = buf; |
299 | tuple.TupleDataMax = sizeof(buf); | 298 | tuple.TupleDataMax = sizeof(buf); |
300 | tuple.TupleOffset = 0; | 299 | tuple.TupleOffset = 0; |
301 | if (pcmcia_get_first_tuple(hw_priv->link, &tuple) || | 300 | |
302 | pcmcia_get_tuple_data(hw_priv->link, &tuple) || | 301 | if (hw_priv->link->manf_id != 0xd601 || hw_priv->link->card_id != 0x0101) { |
303 | pcmcia_parse_tuple(hw_priv->link, &tuple, parse) || | ||
304 | parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) { | ||
305 | /* No SanDisk manfid found */ | 302 | /* No SanDisk manfid found */ |
306 | ret = -ENODEV; | 303 | ret = -ENODEV; |
307 | goto done; | 304 | goto done; |
@@ -573,16 +570,10 @@ static int prism2_config(struct pcmcia_device *link) | |||
573 | } | 570 | } |
574 | memset(hw_priv, 0, sizeof(*hw_priv)); | 571 | memset(hw_priv, 0, sizeof(*hw_priv)); |
575 | 572 | ||
576 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
577 | tuple.Attributes = 0; | 573 | tuple.Attributes = 0; |
578 | tuple.TupleData = buf; | 574 | tuple.TupleData = buf; |
579 | tuple.TupleDataMax = sizeof(buf); | 575 | tuple.TupleDataMax = sizeof(buf); |
580 | tuple.TupleOffset = 0; | 576 | tuple.TupleOffset = 0; |
581 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
582 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
583 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse)); | ||
584 | link->conf.ConfigBase = parse->config.base; | ||
585 | link->conf.Present = parse->config.rmask[0]; | ||
586 | 577 | ||
587 | CS_CHECK(GetConfigurationInfo, | 578 | CS_CHECK(GetConfigurationInfo, |
588 | pcmcia_get_configuration_info(link, &conf)); | 579 | pcmcia_get_configuration_info(link, &conf)); |
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 6714e0dfa8d6..644b4741ef74 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c | |||
@@ -735,10 +735,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
735 | static int netwave_pcmcia_config(struct pcmcia_device *link) { | 735 | static int netwave_pcmcia_config(struct pcmcia_device *link) { |
736 | struct net_device *dev = link->priv; | 736 | struct net_device *dev = link->priv; |
737 | netwave_private *priv = netdev_priv(dev); | 737 | netwave_private *priv = netdev_priv(dev); |
738 | tuple_t tuple; | ||
739 | cisparse_t parse; | ||
740 | int i, j, last_ret, last_fn; | 738 | int i, j, last_ret, last_fn; |
741 | u_char buf[64]; | ||
742 | win_req_t req; | 739 | win_req_t req; |
743 | memreq_t mem; | 740 | memreq_t mem; |
744 | u_char __iomem *ramBase = NULL; | 741 | u_char __iomem *ramBase = NULL; |
@@ -746,21 +743,6 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) { | |||
746 | DEBUG(0, "netwave_pcmcia_config(0x%p)\n", link); | 743 | DEBUG(0, "netwave_pcmcia_config(0x%p)\n", link); |
747 | 744 | ||
748 | /* | 745 | /* |
749 | This reads the card's CONFIG tuple to find its configuration | ||
750 | registers. | ||
751 | */ | ||
752 | tuple.Attributes = 0; | ||
753 | tuple.TupleData = (cisdata_t *) buf; | ||
754 | tuple.TupleDataMax = 64; | ||
755 | tuple.TupleOffset = 0; | ||
756 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
757 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
758 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
759 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
760 | link->conf.ConfigBase = parse.config.base; | ||
761 | link->conf.Present = parse.config.rmask[0]; | ||
762 | |||
763 | /* | ||
764 | * Try allocating IO ports. This tries a few fixed addresses. | 746 | * Try allocating IO ports. This tries a few fixed addresses. |
765 | * If you want, you can also read the card's config table to | 747 | * If you want, you can also read the card's config table to |
766 | * pick addresses -- see the serial driver for an example. | 748 | * pick addresses -- see the serial driver for an example. |
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index bc14689cbf24..d08ae8d2726c 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
@@ -178,21 +178,6 @@ orinoco_cs_config(struct pcmcia_device *link) | |||
178 | cisparse_t parse; | 178 | cisparse_t parse; |
179 | void __iomem *mem; | 179 | void __iomem *mem; |
180 | 180 | ||
181 | /* | ||
182 | * This reads the card's CONFIG tuple to find its | ||
183 | * configuration registers. | ||
184 | */ | ||
185 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
186 | tuple.Attributes = 0; | ||
187 | tuple.TupleData = buf; | ||
188 | tuple.TupleDataMax = sizeof(buf); | ||
189 | tuple.TupleOffset = 0; | ||
190 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
191 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
192 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
193 | link->conf.ConfigBase = parse.config.base; | ||
194 | link->conf.Present = parse.config.rmask[0]; | ||
195 | |||
196 | /* Look up the current Vcc */ | 181 | /* Look up the current Vcc */ |
197 | CS_CHECK(GetConfigurationInfo, | 182 | CS_CHECK(GetConfigurationInfo, |
198 | pcmcia_get_configuration_info(link, &conf)); | 183 | pcmcia_get_configuration_info(link, &conf)); |
@@ -211,6 +196,10 @@ orinoco_cs_config(struct pcmcia_device *link) | |||
211 | * and most client drivers will only use the CIS to fill in | 196 | * and most client drivers will only use the CIS to fill in |
212 | * implementation-defined details. | 197 | * implementation-defined details. |
213 | */ | 198 | */ |
199 | tuple.Attributes = 0; | ||
200 | tuple.TupleData = buf; | ||
201 | tuple.TupleDataMax = sizeof(buf); | ||
202 | tuple.TupleOffset = 0; | ||
214 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 203 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
215 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 204 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
216 | while (1) { | 205 | while (1) { |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 7fbfc9e41d07..88e10c9bc4ac 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -408,11 +408,8 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
408 | #define MAX_TUPLE_SIZE 128 | 408 | #define MAX_TUPLE_SIZE 128 |
409 | static int ray_config(struct pcmcia_device *link) | 409 | static int ray_config(struct pcmcia_device *link) |
410 | { | 410 | { |
411 | tuple_t tuple; | ||
412 | cisparse_t parse; | ||
413 | int last_fn = 0, last_ret = 0; | 411 | int last_fn = 0, last_ret = 0; |
414 | int i; | 412 | int i; |
415 | u_char buf[MAX_TUPLE_SIZE]; | ||
416 | win_req_t req; | 413 | win_req_t req; |
417 | memreq_t mem; | 414 | memreq_t mem; |
418 | struct net_device *dev = (struct net_device *)link->priv; | 415 | struct net_device *dev = (struct net_device *)link->priv; |
@@ -420,29 +417,12 @@ static int ray_config(struct pcmcia_device *link) | |||
420 | 417 | ||
421 | DEBUG(1, "ray_config(0x%p)\n", link); | 418 | DEBUG(1, "ray_config(0x%p)\n", link); |
422 | 419 | ||
423 | /* This reads the card's CONFIG tuple to find its configuration regs */ | ||
424 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
425 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
426 | tuple.TupleData = buf; | ||
427 | tuple.TupleDataMax = MAX_TUPLE_SIZE; | ||
428 | tuple.TupleOffset = 0; | ||
429 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
430 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
431 | link->conf.ConfigBase = parse.config.base; | ||
432 | link->conf.Present = parse.config.rmask[0]; | ||
433 | |||
434 | /* Determine card type and firmware version */ | 420 | /* Determine card type and firmware version */ |
435 | buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0; | 421 | printk(KERN_INFO "ray_cs Detected: %s%s%s%s\n", |
436 | tuple.DesiredTuple = CISTPL_VERS_1; | 422 | link->prod_id[0] ? link->prod_id[0] : " ", |
437 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 423 | link->prod_id[1] ? link->prod_id[1] : " ", |
438 | tuple.TupleData = buf; | 424 | link->prod_id[2] ? link->prod_id[2] : " ", |
439 | tuple.TupleDataMax = MAX_TUPLE_SIZE; | 425 | link->prod_id[3] ? link->prod_id[3] : " "); |
440 | tuple.TupleOffset = 2; | ||
441 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
442 | |||
443 | for (i=0; i<tuple.TupleDataLen - 4; i++) | ||
444 | if (buf[i] == 0) buf[i] = ' '; | ||
445 | printk(KERN_INFO "ray_cs Detected: %s\n",buf); | ||
446 | 426 | ||
447 | /* Now allocate an interrupt line. Note that this does not | 427 | /* Now allocate an interrupt line. Note that this does not |
448 | actually assign a handler to the interrupt. | 428 | actually assign a handler to the interrupt. |
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index bcc7038130f6..cf2d1486b01d 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
@@ -647,21 +647,6 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
647 | cisparse_t parse; | 647 | cisparse_t parse; |
648 | void __iomem *mem; | 648 | void __iomem *mem; |
649 | 649 | ||
650 | /* | ||
651 | * This reads the card's CONFIG tuple to find its | ||
652 | * configuration registers. | ||
653 | */ | ||
654 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
655 | tuple.Attributes = 0; | ||
656 | tuple.TupleData = buf; | ||
657 | tuple.TupleDataMax = sizeof(buf); | ||
658 | tuple.TupleOffset = 0; | ||
659 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
660 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
661 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
662 | link->conf.ConfigBase = parse.config.base; | ||
663 | link->conf.Present = parse.config.rmask[0]; | ||
664 | |||
665 | /* Look up the current Vcc */ | 650 | /* Look up the current Vcc */ |
666 | CS_CHECK(GetConfigurationInfo, | 651 | CS_CHECK(GetConfigurationInfo, |
667 | pcmcia_get_configuration_info(link, &conf)); | 652 | pcmcia_get_configuration_info(link, &conf)); |
@@ -681,6 +666,10 @@ spectrum_cs_config(struct pcmcia_device *link) | |||
681 | * implementation-defined details. | 666 | * implementation-defined details. |
682 | */ | 667 | */ |
683 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 668 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
669 | tuple.Attributes = 0; | ||
670 | tuple.TupleData = buf; | ||
671 | tuple.TupleDataMax = sizeof(buf); | ||
672 | tuple.TupleOffset = 0; | ||
684 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 673 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
685 | while (1) { | 674 | while (1) { |
686 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 675 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index aafb301041b1..233d906c08f0 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c | |||
@@ -3939,11 +3939,8 @@ wv_hw_reset(struct net_device * dev) | |||
3939 | static inline int | 3939 | static inline int |
3940 | wv_pcmcia_config(struct pcmcia_device * link) | 3940 | wv_pcmcia_config(struct pcmcia_device * link) |
3941 | { | 3941 | { |
3942 | tuple_t tuple; | ||
3943 | cisparse_t parse; | ||
3944 | struct net_device * dev = (struct net_device *) link->priv; | 3942 | struct net_device * dev = (struct net_device *) link->priv; |
3945 | int i; | 3943 | int i; |
3946 | u_char buf[64]; | ||
3947 | win_req_t req; | 3944 | win_req_t req; |
3948 | memreq_t mem; | 3945 | memreq_t mem; |
3949 | net_local * lp = netdev_priv(dev); | 3946 | net_local * lp = netdev_priv(dev); |
@@ -3953,36 +3950,6 @@ wv_pcmcia_config(struct pcmcia_device * link) | |||
3953 | printk(KERN_DEBUG "->wv_pcmcia_config(0x%p)\n", link); | 3950 | printk(KERN_DEBUG "->wv_pcmcia_config(0x%p)\n", link); |
3954 | #endif | 3951 | #endif |
3955 | 3952 | ||
3956 | /* | ||
3957 | * This reads the card's CONFIG tuple to find its configuration | ||
3958 | * registers. | ||
3959 | */ | ||
3960 | do | ||
3961 | { | ||
3962 | tuple.Attributes = 0; | ||
3963 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
3964 | i = pcmcia_get_first_tuple(link, &tuple); | ||
3965 | if(i != CS_SUCCESS) | ||
3966 | break; | ||
3967 | tuple.TupleData = (cisdata_t *)buf; | ||
3968 | tuple.TupleDataMax = 64; | ||
3969 | tuple.TupleOffset = 0; | ||
3970 | i = pcmcia_get_tuple_data(link, &tuple); | ||
3971 | if(i != CS_SUCCESS) | ||
3972 | break; | ||
3973 | i = pcmcia_parse_tuple(link, &tuple, &parse); | ||
3974 | if(i != CS_SUCCESS) | ||
3975 | break; | ||
3976 | link->conf.ConfigBase = parse.config.base; | ||
3977 | link->conf.Present = parse.config.rmask[0]; | ||
3978 | } | ||
3979 | while(0); | ||
3980 | if(i != CS_SUCCESS) | ||
3981 | { | ||
3982 | cs_error(link, ParseTuple, i); | ||
3983 | return FALSE; | ||
3984 | } | ||
3985 | |||
3986 | do | 3953 | do |
3987 | { | 3954 | { |
3988 | i = pcmcia_request_io(link, &link->io); | 3955 | i = pcmcia_request_io(link, &link->io); |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 5b98a7876982..583e0d655a98 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -1966,25 +1966,10 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
1966 | */ | 1966 | */ |
1967 | static int wl3501_config(struct pcmcia_device *link) | 1967 | static int wl3501_config(struct pcmcia_device *link) |
1968 | { | 1968 | { |
1969 | tuple_t tuple; | ||
1970 | cisparse_t parse; | ||
1971 | struct net_device *dev = link->priv; | 1969 | struct net_device *dev = link->priv; |
1972 | int i = 0, j, last_fn, last_ret; | 1970 | int i = 0, j, last_fn, last_ret; |
1973 | unsigned char bf[64]; | ||
1974 | struct wl3501_card *this; | 1971 | struct wl3501_card *this; |
1975 | 1972 | ||
1976 | /* This reads the card's CONFIG tuple to find its config registers. */ | ||
1977 | tuple.Attributes = 0; | ||
1978 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
1979 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
1980 | tuple.TupleData = bf; | ||
1981 | tuple.TupleDataMax = sizeof(bf); | ||
1982 | tuple.TupleOffset = 0; | ||
1983 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
1984 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
1985 | link->conf.ConfigBase = parse.config.base; | ||
1986 | link->conf.Present = parse.config.rmask[0]; | ||
1987 | |||
1988 | /* Try allocating IO ports. This tries a few fixed addresses. If you | 1973 | /* Try allocating IO ports. This tries a few fixed addresses. If you |
1989 | * want, you can also read the card's config table to pick addresses -- | 1974 | * want, you can also read the card's config table to pick addresses -- |
1990 | * see the serial driver for an example. */ | 1975 | * see the serial driver for an example. */ |
diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index b953d5907c05..e60b4bf6bae8 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c | |||
@@ -166,14 +166,6 @@ static int parport_config(struct pcmcia_device *link) | |||
166 | 166 | ||
167 | tuple.TupleData = (cisdata_t *)buf; | 167 | tuple.TupleData = (cisdata_t *)buf; |
168 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; | 168 | tuple.TupleOffset = 0; tuple.TupleDataMax = 255; |
169 | tuple.Attributes = 0; | ||
170 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
171 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
172 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
173 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
174 | link->conf.ConfigBase = parse.config.base; | ||
175 | link->conf.Present = parse.config.rmask[0]; | ||
176 | |||
177 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 169 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
178 | tuple.Attributes = 0; | 170 | tuple.Attributes = 0; |
179 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 171 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
@@ -263,6 +255,7 @@ void parport_cs_release(struct pcmcia_device *link) | |||
263 | 255 | ||
264 | static struct pcmcia_device_id parport_ids[] = { | 256 | static struct pcmcia_device_id parport_ids[] = { |
265 | PCMCIA_DEVICE_FUNC_ID(3), | 257 | PCMCIA_DEVICE_FUNC_ID(3), |
258 | PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc), | ||
266 | PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003), | 259 | PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003), |
267 | PCMCIA_DEVICE_NULL | 260 | PCMCIA_DEVICE_NULL |
268 | }; | 261 | }; |
diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index 3bcb7dc32995..b6746301d9a9 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c | |||
@@ -32,10 +32,11 @@ | |||
32 | * A0..A10 work in each range; A23 indicates I/O space; A25 is CFRNW; | 32 | * A0..A10 work in each range; A23 indicates I/O space; A25 is CFRNW; |
33 | * some other bit in {A24,A22..A11} is nREG to flag memory access | 33 | * some other bit in {A24,A22..A11} is nREG to flag memory access |
34 | * (vs attributes). So more than 2KB/region would just be waste. | 34 | * (vs attributes). So more than 2KB/region would just be waste. |
35 | * Note: These are offsets from the physical base address. | ||
35 | */ | 36 | */ |
36 | #define CF_ATTR_PHYS (AT91_CF_BASE) | 37 | #define CF_ATTR_PHYS (0) |
37 | #define CF_IO_PHYS (AT91_CF_BASE + (1 << 23)) | 38 | #define CF_IO_PHYS (1 << 23) |
38 | #define CF_MEM_PHYS (AT91_CF_BASE + 0x017ff800) | 39 | #define CF_MEM_PHYS (0x017ff800) |
39 | 40 | ||
40 | /*--------------------------------------------------------------------------*/ | 41 | /*--------------------------------------------------------------------------*/ |
41 | 42 | ||
@@ -48,6 +49,8 @@ struct at91_cf_socket { | |||
48 | 49 | ||
49 | struct platform_device *pdev; | 50 | struct platform_device *pdev; |
50 | struct at91_cf_data *board; | 51 | struct at91_cf_data *board; |
52 | |||
53 | unsigned long phys_baseaddr; | ||
51 | }; | 54 | }; |
52 | 55 | ||
53 | #define SZ_2K (2 * SZ_1K) | 56 | #define SZ_2K (2 * SZ_1K) |
@@ -154,9 +157,8 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) | |||
154 | 157 | ||
155 | /* | 158 | /* |
156 | * Use 16 bit accesses unless/until we need 8-bit i/o space. | 159 | * Use 16 bit accesses unless/until we need 8-bit i/o space. |
157 | * Always set CSR4 ... PCMCIA won't always unmap things. | ||
158 | */ | 160 | */ |
159 | csr = at91_sys_read(AT91_SMC_CSR(4)) & ~AT91_SMC_DBW; | 161 | csr = at91_sys_read(AT91_SMC_CSR(cf->board->chipselect)) & ~AT91_SMC_DBW; |
160 | 162 | ||
161 | /* | 163 | /* |
162 | * NOTE: this CF controller ignores IOIS16, so we can't really do | 164 | * NOTE: this CF controller ignores IOIS16, so we can't really do |
@@ -168,14 +170,14 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io) | |||
168 | * some cards only like that way to get at the odd byte, despite | 170 | * some cards only like that way to get at the odd byte, despite |
169 | * CF 3.0 spec table 35 also giving the D8-D15 option. | 171 | * CF 3.0 spec table 35 also giving the D8-D15 option. |
170 | */ | 172 | */ |
171 | if (!(io->flags & (MAP_16BIT|MAP_AUTOSZ))) { | 173 | if (!(io->flags & (MAP_16BIT | MAP_AUTOSZ))) { |
172 | csr |= AT91_SMC_DBW_8; | 174 | csr |= AT91_SMC_DBW_8; |
173 | pr_debug("%s: 8bit i/o bus\n", driver_name); | 175 | pr_debug("%s: 8bit i/o bus\n", driver_name); |
174 | } else { | 176 | } else { |
175 | csr |= AT91_SMC_DBW_16; | 177 | csr |= AT91_SMC_DBW_16; |
176 | pr_debug("%s: 16bit i/o bus\n", driver_name); | 178 | pr_debug("%s: 16bit i/o bus\n", driver_name); |
177 | } | 179 | } |
178 | at91_sys_write(AT91_SMC_CSR(4), csr); | 180 | at91_sys_write(AT91_SMC_CSR(cf->board->chipselect), csr); |
179 | 181 | ||
180 | io->start = cf->socket.io_offset; | 182 | io->start = cf->socket.io_offset; |
181 | io->stop = io->start + SZ_2K - 1; | 183 | io->stop = io->start + SZ_2K - 1; |
@@ -194,11 +196,11 @@ at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map) | |||
194 | 196 | ||
195 | cf = container_of(s, struct at91_cf_socket, socket); | 197 | cf = container_of(s, struct at91_cf_socket, socket); |
196 | 198 | ||
197 | map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT; | 199 | map->flags &= (MAP_ACTIVE | MAP_ATTRIB | MAP_16BIT); |
198 | if (map->flags & MAP_ATTRIB) | 200 | if (map->flags & MAP_ATTRIB) |
199 | map->static_start = CF_ATTR_PHYS; | 201 | map->static_start = cf->phys_baseaddr + CF_ATTR_PHYS; |
200 | else | 202 | else |
201 | map->static_start = CF_MEM_PHYS; | 203 | map->static_start = cf->phys_baseaddr + CF_MEM_PHYS; |
202 | 204 | ||
203 | return 0; | 205 | return 0; |
204 | } | 206 | } |
@@ -219,7 +221,6 @@ static int __init at91_cf_probe(struct platform_device *pdev) | |||
219 | struct at91_cf_socket *cf; | 221 | struct at91_cf_socket *cf; |
220 | struct at91_cf_data *board = pdev->dev.platform_data; | 222 | struct at91_cf_data *board = pdev->dev.platform_data; |
221 | struct resource *io; | 223 | struct resource *io; |
222 | unsigned int csa; | ||
223 | int status; | 224 | int status; |
224 | 225 | ||
225 | if (!board || !board->det_pin || !board->rst_pin) | 226 | if (!board || !board->det_pin || !board->rst_pin) |
@@ -235,33 +236,11 @@ static int __init at91_cf_probe(struct platform_device *pdev) | |||
235 | 236 | ||
236 | cf->board = board; | 237 | cf->board = board; |
237 | cf->pdev = pdev; | 238 | cf->pdev = pdev; |
239 | cf->phys_baseaddr = io->start; | ||
238 | platform_set_drvdata(pdev, cf); | 240 | platform_set_drvdata(pdev, cf); |
239 | 241 | ||
240 | /* CF takes over CS4, CS5, CS6 */ | ||
241 | csa = at91_sys_read(AT91_EBI_CSA); | ||
242 | at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH); | ||
243 | |||
244 | /* nWAIT is _not_ a default setting */ | ||
245 | (void) at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */ | ||
246 | |||
247 | /* | ||
248 | * Static memory controller timing adjustments. | ||
249 | * REVISIT: these timings are in terms of MCK cycles, so | ||
250 | * when MCK changes (cpufreq etc) so must these values... | ||
251 | */ | ||
252 | at91_sys_write(AT91_SMC_CSR(4), | ||
253 | AT91_SMC_ACSS_STD | ||
254 | | AT91_SMC_DBW_16 | ||
255 | | AT91_SMC_BAT | ||
256 | | AT91_SMC_WSEN | ||
257 | | AT91_SMC_NWS_(32) /* wait states */ | ||
258 | | AT91_SMC_RWSETUP_(6) /* setup time */ | ||
259 | | AT91_SMC_RWHOLD_(4) /* hold time */ | ||
260 | ); | ||
261 | |||
262 | /* must be a GPIO; ergo must trigger on both edges */ | 242 | /* must be a GPIO; ergo must trigger on both edges */ |
263 | status = request_irq(board->det_pin, at91_cf_irq, | 243 | status = request_irq(board->det_pin, at91_cf_irq, 0, driver_name, cf); |
264 | IRQF_SAMPLE_RANDOM, driver_name, cf); | ||
265 | if (status < 0) | 244 | if (status < 0) |
266 | goto fail0; | 245 | goto fail0; |
267 | device_init_wakeup(&pdev->dev, 1); | 246 | device_init_wakeup(&pdev->dev, 1); |
@@ -282,14 +261,18 @@ static int __init at91_cf_probe(struct platform_device *pdev) | |||
282 | cf->socket.pci_irq = NR_IRQS + 1; | 261 | cf->socket.pci_irq = NR_IRQS + 1; |
283 | 262 | ||
284 | /* pcmcia layer only remaps "real" memory not iospace */ | 263 | /* pcmcia layer only remaps "real" memory not iospace */ |
285 | cf->socket.io_offset = (unsigned long) ioremap(CF_IO_PHYS, SZ_2K); | 264 | cf->socket.io_offset = (unsigned long) ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K); |
286 | if (!cf->socket.io_offset) | 265 | if (!cf->socket.io_offset) { |
266 | status = -ENXIO; | ||
287 | goto fail1; | 267 | goto fail1; |
268 | } | ||
288 | 269 | ||
289 | /* reserve CS4, CS5, and CS6 regions; but use just CS4 */ | 270 | /* reserve chip-select regions */ |
290 | if (!request_mem_region(io->start, io->end + 1 - io->start, | 271 | if (!request_mem_region(io->start, io->end + 1 - io->start, |
291 | driver_name)) | 272 | driver_name)) { |
273 | status = -ENXIO; | ||
292 | goto fail1; | 274 | goto fail1; |
275 | } | ||
293 | 276 | ||
294 | pr_info("%s: irqs det #%d, io #%d\n", driver_name, | 277 | pr_info("%s: irqs det #%d, io #%d\n", driver_name, |
295 | board->det_pin, board->irq_pin); | 278 | board->det_pin, board->irq_pin); |
@@ -319,9 +302,7 @@ fail1: | |||
319 | fail0a: | 302 | fail0a: |
320 | device_init_wakeup(&pdev->dev, 0); | 303 | device_init_wakeup(&pdev->dev, 0); |
321 | free_irq(board->det_pin, cf); | 304 | free_irq(board->det_pin, cf); |
322 | device_init_wakeup(&pdev->dev, 0); | ||
323 | fail0: | 305 | fail0: |
324 | at91_sys_write(AT91_EBI_CSA, csa); | ||
325 | kfree(cf); | 306 | kfree(cf); |
326 | return status; | 307 | return status; |
327 | } | 308 | } |
@@ -331,19 +312,15 @@ static int __exit at91_cf_remove(struct platform_device *pdev) | |||
331 | struct at91_cf_socket *cf = platform_get_drvdata(pdev); | 312 | struct at91_cf_socket *cf = platform_get_drvdata(pdev); |
332 | struct at91_cf_data *board = cf->board; | 313 | struct at91_cf_data *board = cf->board; |
333 | struct resource *io = cf->socket.io[0].res; | 314 | struct resource *io = cf->socket.io[0].res; |
334 | unsigned int csa; | ||
335 | 315 | ||
336 | pcmcia_unregister_socket(&cf->socket); | 316 | pcmcia_unregister_socket(&cf->socket); |
337 | if (board->irq_pin) | 317 | if (board->irq_pin) |
338 | free_irq(board->irq_pin, cf); | 318 | free_irq(board->irq_pin, cf); |
339 | free_irq(board->det_pin, cf); | ||
340 | device_init_wakeup(&pdev->dev, 0); | 319 | device_init_wakeup(&pdev->dev, 0); |
320 | free_irq(board->det_pin, cf); | ||
341 | iounmap((void __iomem *) cf->socket.io_offset); | 321 | iounmap((void __iomem *) cf->socket.io_offset); |
342 | release_mem_region(io->start, io->end + 1 - io->start); | 322 | release_mem_region(io->start, io->end + 1 - io->start); |
343 | 323 | ||
344 | csa = at91_sys_read(AT91_EBI_CSA); | ||
345 | at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A); | ||
346 | |||
347 | kfree(cf); | 324 | kfree(cf); |
348 | return 0; | 325 | return 0; |
349 | } | 326 | } |
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index d6164cd583fd..f573ea04db6f 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h | |||
@@ -135,7 +135,7 @@ int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_s | |||
135 | struct pcmcia_callback{ | 135 | struct pcmcia_callback{ |
136 | struct module *owner; | 136 | struct module *owner; |
137 | int (*event) (struct pcmcia_socket *s, event_t event, int priority); | 137 | int (*event) (struct pcmcia_socket *s, event_t event, int priority); |
138 | void (*requery) (struct pcmcia_socket *s); | 138 | void (*requery) (struct pcmcia_socket *s, int new_cis); |
139 | int (*suspend) (struct pcmcia_socket *s); | 139 | int (*suspend) (struct pcmcia_socket *s); |
140 | int (*resume) (struct pcmcia_socket *s); | 140 | int (*resume) (struct pcmcia_socket *s); |
141 | }; | 141 | }; |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index ff14fd8f0cd1..7355eb455a88 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -231,65 +231,6 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv) | |||
231 | } | 231 | } |
232 | 232 | ||
233 | 233 | ||
234 | #ifdef CONFIG_PCMCIA_LOAD_CIS | ||
235 | |||
236 | /** | ||
237 | * pcmcia_load_firmware - load CIS from userspace if device-provided is broken | ||
238 | * @dev - the pcmcia device which needs a CIS override | ||
239 | * @filename - requested filename in /lib/firmware/ | ||
240 | * | ||
241 | * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if | ||
242 | * the one provided by the card is broken. The firmware files reside in | ||
243 | * /lib/firmware/ in userspace. | ||
244 | */ | ||
245 | static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) | ||
246 | { | ||
247 | struct pcmcia_socket *s = dev->socket; | ||
248 | const struct firmware *fw; | ||
249 | char path[20]; | ||
250 | int ret=-ENOMEM; | ||
251 | cisdump_t *cis; | ||
252 | |||
253 | if (!filename) | ||
254 | return -EINVAL; | ||
255 | |||
256 | ds_dbg(1, "trying to load firmware %s\n", filename); | ||
257 | |||
258 | if (strlen(filename) > 14) | ||
259 | return -EINVAL; | ||
260 | |||
261 | snprintf(path, 20, "%s", filename); | ||
262 | |||
263 | if (request_firmware(&fw, path, &dev->dev) == 0) { | ||
264 | if (fw->size >= CISTPL_MAX_CIS_SIZE) | ||
265 | goto release; | ||
266 | |||
267 | cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); | ||
268 | if (!cis) | ||
269 | goto release; | ||
270 | |||
271 | cis->Length = fw->size + 1; | ||
272 | memcpy(cis->Data, fw->data, fw->size); | ||
273 | |||
274 | if (!pcmcia_replace_cis(s, cis)) | ||
275 | ret = 0; | ||
276 | } | ||
277 | release: | ||
278 | release_firmware(fw); | ||
279 | |||
280 | return (ret); | ||
281 | } | ||
282 | |||
283 | #else /* !CONFIG_PCMCIA_LOAD_CIS */ | ||
284 | |||
285 | static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) | ||
286 | { | ||
287 | return -ENODEV; | ||
288 | } | ||
289 | |||
290 | #endif | ||
291 | |||
292 | |||
293 | /*======================================================================*/ | 234 | /*======================================================================*/ |
294 | 235 | ||
295 | 236 | ||
@@ -309,6 +250,8 @@ int pcmcia_register_driver(struct pcmcia_driver *driver) | |||
309 | driver->drv.bus = &pcmcia_bus_type; | 250 | driver->drv.bus = &pcmcia_bus_type; |
310 | driver->drv.owner = driver->owner; | 251 | driver->drv.owner = driver->owner; |
311 | 252 | ||
253 | ds_dbg(3, "registering driver %s\n", driver->drv.name); | ||
254 | |||
312 | return driver_register(&driver->drv); | 255 | return driver_register(&driver->drv); |
313 | } | 256 | } |
314 | EXPORT_SYMBOL(pcmcia_register_driver); | 257 | EXPORT_SYMBOL(pcmcia_register_driver); |
@@ -318,6 +261,7 @@ EXPORT_SYMBOL(pcmcia_register_driver); | |||
318 | */ | 261 | */ |
319 | void pcmcia_unregister_driver(struct pcmcia_driver *driver) | 262 | void pcmcia_unregister_driver(struct pcmcia_driver *driver) |
320 | { | 263 | { |
264 | ds_dbg(3, "unregistering driver %s\n", driver->drv.name); | ||
321 | driver_unregister(&driver->drv); | 265 | driver_unregister(&driver->drv); |
322 | } | 266 | } |
323 | EXPORT_SYMBOL(pcmcia_unregister_driver); | 267 | EXPORT_SYMBOL(pcmcia_unregister_driver); |
@@ -343,23 +287,27 @@ void pcmcia_put_dev(struct pcmcia_device *p_dev) | |||
343 | static void pcmcia_release_function(struct kref *ref) | 287 | static void pcmcia_release_function(struct kref *ref) |
344 | { | 288 | { |
345 | struct config_t *c = container_of(ref, struct config_t, ref); | 289 | struct config_t *c = container_of(ref, struct config_t, ref); |
290 | ds_dbg(1, "releasing config_t\n"); | ||
346 | kfree(c); | 291 | kfree(c); |
347 | } | 292 | } |
348 | 293 | ||
349 | static void pcmcia_release_dev(struct device *dev) | 294 | static void pcmcia_release_dev(struct device *dev) |
350 | { | 295 | { |
351 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 296 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
352 | ds_dbg(1, "releasing dev %p\n", p_dev); | 297 | ds_dbg(1, "releasing device %s\n", p_dev->dev.bus_id); |
353 | pcmcia_put_socket(p_dev->socket); | 298 | pcmcia_put_socket(p_dev->socket); |
354 | kfree(p_dev->devname); | 299 | kfree(p_dev->devname); |
355 | kref_put(&p_dev->function_config->ref, pcmcia_release_function); | 300 | kref_put(&p_dev->function_config->ref, pcmcia_release_function); |
356 | kfree(p_dev); | 301 | kfree(p_dev); |
357 | } | 302 | } |
358 | 303 | ||
359 | static void pcmcia_add_pseudo_device(struct pcmcia_socket *s) | 304 | static void pcmcia_add_device_later(struct pcmcia_socket *s, int mfc) |
360 | { | 305 | { |
361 | if (!s->pcmcia_state.device_add_pending) { | 306 | if (!s->pcmcia_state.device_add_pending) { |
307 | ds_dbg(1, "scheduling to add %s secondary" | ||
308 | " device to %d\n", mfc ? "mfc" : "pfc", s->sock); | ||
362 | s->pcmcia_state.device_add_pending = 1; | 309 | s->pcmcia_state.device_add_pending = 1; |
310 | s->pcmcia_state.mfc_pfc = mfc; | ||
363 | schedule_work(&s->device_add); | 311 | schedule_work(&s->device_add); |
364 | } | 312 | } |
365 | return; | 313 | return; |
@@ -371,6 +319,7 @@ static int pcmcia_device_probe(struct device * dev) | |||
371 | struct pcmcia_driver *p_drv; | 319 | struct pcmcia_driver *p_drv; |
372 | struct pcmcia_device_id *did; | 320 | struct pcmcia_device_id *did; |
373 | struct pcmcia_socket *s; | 321 | struct pcmcia_socket *s; |
322 | cistpl_config_t cis_config; | ||
374 | int ret = 0; | 323 | int ret = 0; |
375 | 324 | ||
376 | dev = get_device(dev); | 325 | dev = get_device(dev); |
@@ -381,15 +330,33 @@ static int pcmcia_device_probe(struct device * dev) | |||
381 | p_drv = to_pcmcia_drv(dev->driver); | 330 | p_drv = to_pcmcia_drv(dev->driver); |
382 | s = p_dev->socket; | 331 | s = p_dev->socket; |
383 | 332 | ||
333 | ds_dbg(1, "trying to bind %s to %s\n", p_dev->dev.bus_id, | ||
334 | p_drv->drv.name); | ||
335 | |||
384 | if ((!p_drv->probe) || (!p_dev->function_config) || | 336 | if ((!p_drv->probe) || (!p_dev->function_config) || |
385 | (!try_module_get(p_drv->owner))) { | 337 | (!try_module_get(p_drv->owner))) { |
386 | ret = -EINVAL; | 338 | ret = -EINVAL; |
387 | goto put_dev; | 339 | goto put_dev; |
388 | } | 340 | } |
389 | 341 | ||
342 | /* set up some more device information */ | ||
343 | ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG, | ||
344 | &cis_config); | ||
345 | if (!ret) { | ||
346 | p_dev->conf.ConfigBase = cis_config.base; | ||
347 | p_dev->conf.Present = cis_config.rmask[0]; | ||
348 | } else { | ||
349 | printk(KERN_INFO "pcmcia: could not parse base and rmask0 of CIS\n"); | ||
350 | p_dev->conf.ConfigBase = 0; | ||
351 | p_dev->conf.Present = 0; | ||
352 | } | ||
353 | |||
390 | ret = p_drv->probe(p_dev); | 354 | ret = p_drv->probe(p_dev); |
391 | if (ret) | 355 | if (ret) { |
356 | ds_dbg(1, "binding %s to %s failed with %d\n", | ||
357 | p_dev->dev.bus_id, p_drv->drv.name, ret); | ||
392 | goto put_module; | 358 | goto put_module; |
359 | } | ||
393 | 360 | ||
394 | /* handle pseudo multifunction devices: | 361 | /* handle pseudo multifunction devices: |
395 | * there are at most two pseudo multifunction devices. | 362 | * there are at most two pseudo multifunction devices. |
@@ -400,7 +367,7 @@ static int pcmcia_device_probe(struct device * dev) | |||
400 | did = p_dev->dev.driver_data; | 367 | did = p_dev->dev.driver_data; |
401 | if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && | 368 | if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && |
402 | (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) | 369 | (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) |
403 | pcmcia_add_pseudo_device(p_dev->socket); | 370 | pcmcia_add_device_later(p_dev->socket, 0); |
404 | 371 | ||
405 | put_module: | 372 | put_module: |
406 | if (ret) | 373 | if (ret) |
@@ -421,8 +388,8 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le | |||
421 | struct pcmcia_device *tmp; | 388 | struct pcmcia_device *tmp; |
422 | unsigned long flags; | 389 | unsigned long flags; |
423 | 390 | ||
424 | ds_dbg(2, "unbind_request(%d)\n", s->sock); | 391 | ds_dbg(2, "pcmcia_card_remove(%d) %s\n", s->sock, |
425 | 392 | leftover ? leftover->devname : ""); | |
426 | 393 | ||
427 | if (!leftover) | 394 | if (!leftover) |
428 | s->device_count = 0; | 395 | s->device_count = 0; |
@@ -439,6 +406,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le | |||
439 | p_dev->_removed=1; | 406 | p_dev->_removed=1; |
440 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 407 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
441 | 408 | ||
409 | ds_dbg(2, "unregistering device %s\n", p_dev->dev.bus_id); | ||
442 | device_unregister(&p_dev->dev); | 410 | device_unregister(&p_dev->dev); |
443 | } | 411 | } |
444 | 412 | ||
@@ -455,6 +423,8 @@ static int pcmcia_device_remove(struct device * dev) | |||
455 | p_dev = to_pcmcia_dev(dev); | 423 | p_dev = to_pcmcia_dev(dev); |
456 | p_drv = to_pcmcia_drv(dev->driver); | 424 | p_drv = to_pcmcia_drv(dev->driver); |
457 | 425 | ||
426 | ds_dbg(1, "removing device %s\n", p_dev->dev.bus_id); | ||
427 | |||
458 | /* If we're removing the primary module driving a | 428 | /* If we're removing the primary module driving a |
459 | * pseudo multi-function card, we need to unbind | 429 | * pseudo multi-function card, we need to unbind |
460 | * all devices | 430 | * all devices |
@@ -587,8 +557,10 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
587 | 557 | ||
588 | mutex_lock(&device_add_lock); | 558 | mutex_lock(&device_add_lock); |
589 | 559 | ||
590 | /* max of 2 devices per card */ | 560 | ds_dbg(3, "adding device to %d, function %d\n", s->sock, function); |
591 | if (s->device_count == 2) | 561 | |
562 | /* max of 4 devices per card */ | ||
563 | if (s->device_count == 4) | ||
592 | goto err_put; | 564 | goto err_put; |
593 | 565 | ||
594 | p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL); | 566 | p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL); |
@@ -598,8 +570,6 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
598 | p_dev->socket = s; | 570 | p_dev->socket = s; |
599 | p_dev->device_no = (s->device_count++); | 571 | p_dev->device_no = (s->device_count++); |
600 | p_dev->func = function; | 572 | p_dev->func = function; |
601 | if (s->functions <= function) | ||
602 | s->functions = function + 1; | ||
603 | 573 | ||
604 | p_dev->dev.bus = &pcmcia_bus_type; | 574 | p_dev->dev.bus = &pcmcia_bus_type; |
605 | p_dev->dev.parent = s->dev.dev; | 575 | p_dev->dev.parent = s->dev.dev; |
@@ -610,8 +580,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
610 | if (!p_dev->devname) | 580 | if (!p_dev->devname) |
611 | goto err_free; | 581 | goto err_free; |
612 | sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id); | 582 | sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id); |
583 | ds_dbg(3, "devname is %s\n", p_dev->devname); | ||
613 | 584 | ||
614 | /* compat */ | ||
615 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 585 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
616 | 586 | ||
617 | /* | 587 | /* |
@@ -631,6 +601,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f | |||
631 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 601 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
632 | 602 | ||
633 | if (!p_dev->function_config) { | 603 | if (!p_dev->function_config) { |
604 | ds_dbg(3, "creating config_t for %s\n", p_dev->dev.bus_id); | ||
634 | p_dev->function_config = kzalloc(sizeof(struct config_t), | 605 | p_dev->function_config = kzalloc(sizeof(struct config_t), |
635 | GFP_KERNEL); | 606 | GFP_KERNEL); |
636 | if (!p_dev->function_config) | 607 | if (!p_dev->function_config) |
@@ -674,11 +645,16 @@ static int pcmcia_card_add(struct pcmcia_socket *s) | |||
674 | unsigned int no_funcs, i; | 645 | unsigned int no_funcs, i; |
675 | int ret = 0; | 646 | int ret = 0; |
676 | 647 | ||
677 | if (!(s->resource_setup_done)) | 648 | if (!(s->resource_setup_done)) { |
649 | ds_dbg(3, "no resources available, delaying card_add\n"); | ||
678 | return -EAGAIN; /* try again, but later... */ | 650 | return -EAGAIN; /* try again, but later... */ |
651 | } | ||
679 | 652 | ||
680 | if (pcmcia_validate_mem(s)) | 653 | if (pcmcia_validate_mem(s)) { |
654 | ds_dbg(3, "validating mem resources failed, " | ||
655 | "delaying card_add\n"); | ||
681 | return -EAGAIN; /* try again, but later... */ | 656 | return -EAGAIN; /* try again, but later... */ |
657 | } | ||
682 | 658 | ||
683 | ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo); | 659 | ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo); |
684 | if (ret || !cisinfo.Chains) { | 660 | if (ret || !cisinfo.Chains) { |
@@ -690,6 +666,7 @@ static int pcmcia_card_add(struct pcmcia_socket *s) | |||
690 | no_funcs = mfc.nfn; | 666 | no_funcs = mfc.nfn; |
691 | else | 667 | else |
692 | no_funcs = 1; | 668 | no_funcs = 1; |
669 | s->functions = no_funcs; | ||
693 | 670 | ||
694 | for (i=0; i < no_funcs; i++) | 671 | for (i=0; i < no_funcs; i++) |
695 | pcmcia_device_add(s, i); | 672 | pcmcia_device_add(s, i); |
@@ -698,39 +675,50 @@ static int pcmcia_card_add(struct pcmcia_socket *s) | |||
698 | } | 675 | } |
699 | 676 | ||
700 | 677 | ||
701 | static void pcmcia_delayed_add_pseudo_device(struct work_struct *work) | 678 | static void pcmcia_delayed_add_device(struct work_struct *work) |
702 | { | 679 | { |
703 | struct pcmcia_socket *s = | 680 | struct pcmcia_socket *s = |
704 | container_of(work, struct pcmcia_socket, device_add); | 681 | container_of(work, struct pcmcia_socket, device_add); |
705 | pcmcia_device_add(s, 0); | 682 | ds_dbg(1, "adding additional device to %d\n", s->sock); |
683 | pcmcia_device_add(s, s->pcmcia_state.mfc_pfc); | ||
706 | s->pcmcia_state.device_add_pending = 0; | 684 | s->pcmcia_state.device_add_pending = 0; |
685 | s->pcmcia_state.mfc_pfc = 0; | ||
707 | } | 686 | } |
708 | 687 | ||
709 | static int pcmcia_requery(struct device *dev, void * _data) | 688 | static int pcmcia_requery(struct device *dev, void * _data) |
710 | { | 689 | { |
711 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 690 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
712 | if (!p_dev->dev.driver) | 691 | if (!p_dev->dev.driver) { |
692 | ds_dbg(1, "update device information for %s\n", | ||
693 | p_dev->dev.bus_id); | ||
713 | pcmcia_device_query(p_dev); | 694 | pcmcia_device_query(p_dev); |
695 | } | ||
714 | 696 | ||
715 | return 0; | 697 | return 0; |
716 | } | 698 | } |
717 | 699 | ||
718 | static void pcmcia_bus_rescan(struct pcmcia_socket *skt) | 700 | static void pcmcia_bus_rescan(struct pcmcia_socket *skt, int new_cis) |
719 | { | 701 | { |
720 | int no_devices=0; | 702 | int no_devices = 0; |
721 | int ret = 0; | 703 | int ret = 0; |
722 | unsigned long flags; | 704 | unsigned long flags; |
723 | 705 | ||
724 | /* must be called with skt_mutex held */ | 706 | /* must be called with skt_mutex held */ |
707 | ds_dbg(0, "re-scanning socket %d\n", skt->sock); | ||
708 | |||
725 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); | 709 | spin_lock_irqsave(&pcmcia_dev_list_lock, flags); |
726 | if (list_empty(&skt->devices_list)) | 710 | if (list_empty(&skt->devices_list)) |
727 | no_devices=1; | 711 | no_devices = 1; |
728 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); | 712 | spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); |
729 | 713 | ||
714 | /* If this is because of a CIS override, start over */ | ||
715 | if (new_cis && !no_devices) | ||
716 | pcmcia_card_remove(skt, NULL); | ||
717 | |||
730 | /* if no devices were added for this socket yet because of | 718 | /* if no devices were added for this socket yet because of |
731 | * missing resource information or other trouble, we need to | 719 | * missing resource information or other trouble, we need to |
732 | * do this now. */ | 720 | * do this now. */ |
733 | if (no_devices) { | 721 | if (no_devices || new_cis) { |
734 | ret = pcmcia_card_add(skt); | 722 | ret = pcmcia_card_add(skt); |
735 | if (ret) | 723 | if (ret) |
736 | return; | 724 | return; |
@@ -748,6 +736,97 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt) | |||
748 | printk(KERN_INFO "pcmcia: bus_rescan_devices failed\n"); | 736 | printk(KERN_INFO "pcmcia: bus_rescan_devices failed\n"); |
749 | } | 737 | } |
750 | 738 | ||
739 | #ifdef CONFIG_PCMCIA_LOAD_CIS | ||
740 | |||
741 | /** | ||
742 | * pcmcia_load_firmware - load CIS from userspace if device-provided is broken | ||
743 | * @dev - the pcmcia device which needs a CIS override | ||
744 | * @filename - requested filename in /lib/firmware/ | ||
745 | * | ||
746 | * This uses the in-kernel firmware loading mechanism to use a "fake CIS" if | ||
747 | * the one provided by the card is broken. The firmware files reside in | ||
748 | * /lib/firmware/ in userspace. | ||
749 | */ | ||
750 | static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) | ||
751 | { | ||
752 | struct pcmcia_socket *s = dev->socket; | ||
753 | const struct firmware *fw; | ||
754 | char path[20]; | ||
755 | int ret = -ENOMEM; | ||
756 | int no_funcs; | ||
757 | int old_funcs; | ||
758 | cisdump_t *cis; | ||
759 | cistpl_longlink_mfc_t mfc; | ||
760 | |||
761 | if (!filename) | ||
762 | return -EINVAL; | ||
763 | |||
764 | ds_dbg(1, "trying to load CIS file %s\n", filename); | ||
765 | |||
766 | if (strlen(filename) > 14) { | ||
767 | printk(KERN_WARNING "pcmcia: CIS filename is too long\n"); | ||
768 | return -EINVAL; | ||
769 | } | ||
770 | |||
771 | snprintf(path, 20, "%s", filename); | ||
772 | |||
773 | if (request_firmware(&fw, path, &dev->dev) == 0) { | ||
774 | if (fw->size >= CISTPL_MAX_CIS_SIZE) { | ||
775 | ret = -EINVAL; | ||
776 | printk(KERN_ERR "pcmcia: CIS override is too big\n"); | ||
777 | goto release; | ||
778 | } | ||
779 | |||
780 | cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL); | ||
781 | if (!cis) { | ||
782 | ret = -ENOMEM; | ||
783 | goto release; | ||
784 | } | ||
785 | |||
786 | cis->Length = fw->size + 1; | ||
787 | memcpy(cis->Data, fw->data, fw->size); | ||
788 | |||
789 | if (!pcmcia_replace_cis(s, cis)) | ||
790 | ret = 0; | ||
791 | else { | ||
792 | printk(KERN_ERR "pcmcia: CIS override failed\n"); | ||
793 | goto release; | ||
794 | } | ||
795 | |||
796 | |||
797 | /* update information */ | ||
798 | pcmcia_device_query(dev); | ||
799 | |||
800 | /* does this cis override add or remove functions? */ | ||
801 | old_funcs = s->functions; | ||
802 | |||
803 | if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC, &mfc)) | ||
804 | no_funcs = mfc.nfn; | ||
805 | else | ||
806 | no_funcs = 1; | ||
807 | s->functions = no_funcs; | ||
808 | |||
809 | if (old_funcs > no_funcs) | ||
810 | pcmcia_card_remove(s, dev); | ||
811 | else if (no_funcs > old_funcs) | ||
812 | pcmcia_add_device_later(s, 1); | ||
813 | } | ||
814 | release: | ||
815 | release_firmware(fw); | ||
816 | |||
817 | return (ret); | ||
818 | } | ||
819 | |||
820 | #else /* !CONFIG_PCMCIA_LOAD_CIS */ | ||
821 | |||
822 | static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename) | ||
823 | { | ||
824 | return -ENODEV; | ||
825 | } | ||
826 | |||
827 | #endif | ||
828 | |||
829 | |||
751 | static inline int pcmcia_devmatch(struct pcmcia_device *dev, | 830 | static inline int pcmcia_devmatch(struct pcmcia_device *dev, |
752 | struct pcmcia_device_id *did) | 831 | struct pcmcia_device_id *did) |
753 | { | 832 | { |
@@ -814,11 +893,14 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev, | |||
814 | * after it has re-checked that there is no possible module | 893 | * after it has re-checked that there is no possible module |
815 | * with a prod_id/manf_id/card_id match. | 894 | * with a prod_id/manf_id/card_id match. |
816 | */ | 895 | */ |
896 | ds_dbg(0, "skipping FUNC_ID match for %s until userspace " | ||
897 | "interaction\n", dev->dev.bus_id); | ||
817 | if (!dev->allow_func_id_match) | 898 | if (!dev->allow_func_id_match) |
818 | return 0; | 899 | return 0; |
819 | } | 900 | } |
820 | 901 | ||
821 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { | 902 | if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { |
903 | ds_dbg(0, "device %s needs a fake CIS\n", dev->dev.bus_id); | ||
822 | if (!dev->socket->fake_cis) | 904 | if (!dev->socket->fake_cis) |
823 | pcmcia_load_firmware(dev, did->cisfile); | 905 | pcmcia_load_firmware(dev, did->cisfile); |
824 | 906 | ||
@@ -848,13 +930,21 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { | |||
848 | 930 | ||
849 | #ifdef CONFIG_PCMCIA_IOCTL | 931 | #ifdef CONFIG_PCMCIA_IOCTL |
850 | /* matching by cardmgr */ | 932 | /* matching by cardmgr */ |
851 | if (p_dev->cardmgr == p_drv) | 933 | if (p_dev->cardmgr == p_drv) { |
934 | ds_dbg(0, "cardmgr matched %s to %s\n", dev->bus_id, | ||
935 | drv->name); | ||
852 | return 1; | 936 | return 1; |
937 | } | ||
853 | #endif | 938 | #endif |
854 | 939 | ||
855 | while (did && did->match_flags) { | 940 | while (did && did->match_flags) { |
856 | if (pcmcia_devmatch(p_dev, did)) | 941 | ds_dbg(3, "trying to match %s to %s\n", dev->bus_id, |
942 | drv->name); | ||
943 | if (pcmcia_devmatch(p_dev, did)) { | ||
944 | ds_dbg(0, "matched %s to %s\n", dev->bus_id, | ||
945 | drv->name); | ||
857 | return 1; | 946 | return 1; |
947 | } | ||
858 | did++; | 948 | did++; |
859 | } | 949 | } |
860 | 950 | ||
@@ -1045,6 +1135,8 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) | |||
1045 | struct pcmcia_driver *p_drv = NULL; | 1135 | struct pcmcia_driver *p_drv = NULL; |
1046 | int ret = 0; | 1136 | int ret = 0; |
1047 | 1137 | ||
1138 | ds_dbg(2, "suspending %s\n", dev->bus_id); | ||
1139 | |||
1048 | if (dev->driver) | 1140 | if (dev->driver) |
1049 | p_drv = to_pcmcia_drv(dev->driver); | 1141 | p_drv = to_pcmcia_drv(dev->driver); |
1050 | 1142 | ||
@@ -1053,12 +1145,18 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) | |||
1053 | 1145 | ||
1054 | if (p_drv->suspend) { | 1146 | if (p_drv->suspend) { |
1055 | ret = p_drv->suspend(p_dev); | 1147 | ret = p_drv->suspend(p_dev); |
1056 | if (ret) | 1148 | if (ret) { |
1149 | printk(KERN_ERR "pcmcia: device %s (driver %s) did " | ||
1150 | "not want to go to sleep (%d)\n", | ||
1151 | p_dev->devname, p_drv->drv.name, ret); | ||
1057 | goto out; | 1152 | goto out; |
1153 | } | ||
1058 | } | 1154 | } |
1059 | 1155 | ||
1060 | if (p_dev->device_no == p_dev->func) | 1156 | if (p_dev->device_no == p_dev->func) { |
1157 | ds_dbg(2, "releasing configuration for %s\n", dev->bus_id); | ||
1061 | pcmcia_release_configuration(p_dev); | 1158 | pcmcia_release_configuration(p_dev); |
1159 | } | ||
1062 | 1160 | ||
1063 | out: | 1161 | out: |
1064 | if (!ret) | 1162 | if (!ret) |
@@ -1073,6 +1171,8 @@ static int pcmcia_dev_resume(struct device * dev) | |||
1073 | struct pcmcia_driver *p_drv = NULL; | 1171 | struct pcmcia_driver *p_drv = NULL; |
1074 | int ret = 0; | 1172 | int ret = 0; |
1075 | 1173 | ||
1174 | ds_dbg(2, "resuming %s\n", dev->bus_id); | ||
1175 | |||
1076 | if (dev->driver) | 1176 | if (dev->driver) |
1077 | p_drv = to_pcmcia_drv(dev->driver); | 1177 | p_drv = to_pcmcia_drv(dev->driver); |
1078 | 1178 | ||
@@ -1080,6 +1180,7 @@ static int pcmcia_dev_resume(struct device * dev) | |||
1080 | goto out; | 1180 | goto out; |
1081 | 1181 | ||
1082 | if (p_dev->device_no == p_dev->func) { | 1182 | if (p_dev->device_no == p_dev->func) { |
1183 | ds_dbg(2, "requesting configuration for %s\n", dev->bus_id); | ||
1083 | ret = pcmcia_request_configuration(p_dev, &p_dev->conf); | 1184 | ret = pcmcia_request_configuration(p_dev, &p_dev->conf); |
1084 | if (ret) | 1185 | if (ret) |
1085 | goto out; | 1186 | goto out; |
@@ -1121,12 +1222,14 @@ static int pcmcia_bus_resume_callback(struct device *dev, void * _data) | |||
1121 | 1222 | ||
1122 | static int pcmcia_bus_resume(struct pcmcia_socket *skt) | 1223 | static int pcmcia_bus_resume(struct pcmcia_socket *skt) |
1123 | { | 1224 | { |
1225 | ds_dbg(2, "resuming socket %d\n", skt->sock); | ||
1124 | bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback); | 1226 | bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback); |
1125 | return 0; | 1227 | return 0; |
1126 | } | 1228 | } |
1127 | 1229 | ||
1128 | static int pcmcia_bus_suspend(struct pcmcia_socket *skt) | 1230 | static int pcmcia_bus_suspend(struct pcmcia_socket *skt) |
1129 | { | 1231 | { |
1232 | ds_dbg(2, "suspending socket %d\n", skt->sock); | ||
1130 | if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt, | 1233 | if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt, |
1131 | pcmcia_bus_suspend_callback)) { | 1234 | pcmcia_bus_suspend_callback)) { |
1132 | pcmcia_bus_resume(skt); | 1235 | pcmcia_bus_resume(skt); |
@@ -1247,7 +1350,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev, | |||
1247 | init_waitqueue_head(&socket->queue); | 1350 | init_waitqueue_head(&socket->queue); |
1248 | #endif | 1351 | #endif |
1249 | INIT_LIST_HEAD(&socket->devices_list); | 1352 | INIT_LIST_HEAD(&socket->devices_list); |
1250 | INIT_WORK(&socket->device_add, pcmcia_delayed_add_pseudo_device); | 1353 | INIT_WORK(&socket->device_add, pcmcia_delayed_add_device); |
1251 | memset(&socket->pcmcia_state, 0, sizeof(u8)); | 1354 | memset(&socket->pcmcia_state, 0, sizeof(u8)); |
1252 | socket->device_count = 0; | 1355 | socket->device_count = 0; |
1253 | 1356 | ||
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c index 36fdaa58458c..3c22ac4625c2 100644 --- a/drivers/pcmcia/m32r_cfc.c +++ b/drivers/pcmcia/m32r_cfc.c | |||
@@ -398,7 +398,7 @@ static irqreturn_t pcc_interrupt(int irq, void *dev) | |||
398 | static void pcc_interrupt_wrapper(u_long data) | 398 | static void pcc_interrupt_wrapper(u_long data) |
399 | { | 399 | { |
400 | debug(3, "m32r_cfc: pcc_interrupt_wrapper:\n"); | 400 | debug(3, "m32r_cfc: pcc_interrupt_wrapper:\n"); |
401 | pcc_interrupt(0, NULL, NULL); | 401 | pcc_interrupt(0, NULL); |
402 | init_timer(&poll_timer); | 402 | init_timer(&poll_timer); |
403 | poll_timer.expires = jiffies + poll_interval; | 403 | poll_timer.expires = jiffies + poll_interval; |
404 | add_timer(&poll_timer); | 404 | add_timer(&poll_timer); |
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 310ede575caa..d077870c6731 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c | |||
@@ -594,7 +594,12 @@ static int ds_ioctl(struct inode * inode, struct file * file, | |||
594 | 594 | ||
595 | err = ret = 0; | 595 | err = ret = 0; |
596 | 596 | ||
597 | if (cmd & IOC_IN) __copy_from_user((char *)buf, uarg, size); | 597 | if (cmd & IOC_IN) { |
598 | if (__copy_from_user((char *)buf, uarg, size)) { | ||
599 | err = -EFAULT; | ||
600 | goto free_out; | ||
601 | } | ||
602 | } | ||
598 | 603 | ||
599 | switch (cmd) { | 604 | switch (cmd) { |
600 | case DS_ADJUST_RESOURCE_INFO: | 605 | case DS_ADJUST_RESOURCE_INFO: |
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index a70f97fdbbdd..360c24896548 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c | |||
@@ -581,10 +581,10 @@ static irqreturn_t pd6729_test(int irq, void *dev) | |||
581 | return IRQ_HANDLED; | 581 | return IRQ_HANDLED; |
582 | } | 582 | } |
583 | 583 | ||
584 | static int pd6729_check_irq(int irq, int flags) | 584 | static int pd6729_check_irq(int irq) |
585 | { | 585 | { |
586 | if (request_irq(irq, pd6729_test, flags, "x", pd6729_test) != 0) | 586 | if (request_irq(irq, pd6729_test, IRQF_PROBE_SHARED, "x", pd6729_test) |
587 | return -1; | 587 | != 0) return -1; |
588 | free_irq(irq, pd6729_test); | 588 | free_irq(irq, pd6729_test); |
589 | return 0; | 589 | return 0; |
590 | } | 590 | } |
@@ -610,7 +610,7 @@ static u_int __devinit pd6729_isa_scan(void) | |||
610 | 610 | ||
611 | /* just find interrupts that aren't in use */ | 611 | /* just find interrupts that aren't in use */ |
612 | for (i = 0; i < 16; i++) | 612 | for (i = 0; i < 16; i++) |
613 | if ((mask0 & (1 << i)) && (pd6729_check_irq(i, 0) == 0)) | 613 | if ((mask0 & (1 << i)) && (pd6729_check_irq(i) == 0)) |
614 | mask |= (1 << i); | 614 | mask |= (1 << i); |
615 | 615 | ||
616 | printk(KERN_INFO "pd6729: ISA irqs = "); | 616 | printk(KERN_INFO "pd6729: ISA irqs = "); |
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 933cd864a5c9..b005602d6b53 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c | |||
@@ -188,7 +188,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf, | |||
188 | (s->state & SOCKET_PRESENT) && | 188 | (s->state & SOCKET_PRESENT) && |
189 | !(s->state & SOCKET_CARDBUS)) { | 189 | !(s->state & SOCKET_CARDBUS)) { |
190 | if (try_module_get(s->callback->owner)) { | 190 | if (try_module_get(s->callback->owner)) { |
191 | s->callback->requery(s); | 191 | s->callback->requery(s, 0); |
192 | module_put(s->callback->owner); | 192 | module_put(s->callback->owner); |
193 | } | 193 | } |
194 | } | 194 | } |
@@ -325,7 +325,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz | |||
325 | if ((s->callback) && (s->state & SOCKET_PRESENT) && | 325 | if ((s->callback) && (s->state & SOCKET_PRESENT) && |
326 | !(s->state & SOCKET_CARDBUS)) { | 326 | !(s->state & SOCKET_CARDBUS)) { |
327 | if (try_module_get(s->callback->owner)) { | 327 | if (try_module_get(s->callback->owner)) { |
328 | s->callback->requery(s); | 328 | s->callback->requery(s, 1); |
329 | module_put(s->callback->owner); | 329 | module_put(s->callback->owner); |
330 | } | 330 | } |
331 | } | 331 | } |
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 562432d017b0..335a25540c08 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c | |||
@@ -622,8 +622,10 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata, | |||
622 | dma_unmap_single(hostdata->dev, slot->dma_handle, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); | 622 | dma_unmap_single(hostdata->dev, slot->dma_handle, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); |
623 | /* restore the old result if the request sense was | 623 | /* restore the old result if the request sense was |
624 | * successful */ | 624 | * successful */ |
625 | if(result == 0) | 625 | if (result == 0) |
626 | result = cmnd[7]; | 626 | result = cmnd[7]; |
627 | /* restore the original length */ | ||
628 | SCp->cmd_len = cmnd[8]; | ||
627 | } else | 629 | } else |
628 | NCR_700_unmap(hostdata, SCp, slot); | 630 | NCR_700_unmap(hostdata, SCp, slot); |
629 | 631 | ||
@@ -1007,6 +1009,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, | |||
1007 | * of the command */ | 1009 | * of the command */ |
1008 | cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; | 1010 | cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC; |
1009 | cmnd[7] = hostdata->status[0]; | 1011 | cmnd[7] = hostdata->status[0]; |
1012 | cmnd[8] = SCp->cmd_len; | ||
1013 | SCp->cmd_len = 6; /* command length for | ||
1014 | * REQUEST_SENSE */ | ||
1010 | slot->pCmd = dma_map_single(hostdata->dev, cmnd, MAX_COMMAND_SIZE, DMA_TO_DEVICE); | 1015 | slot->pCmd = dma_map_single(hostdata->dev, cmnd, MAX_COMMAND_SIZE, DMA_TO_DEVICE); |
1011 | slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); | 1016 | slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE); |
1012 | slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); | 1017 | slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer)); |
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index cdd033724786..3075204915c8 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c | |||
@@ -2186,21 +2186,21 @@ static int __init BusLogic_init(void) | |||
2186 | 2186 | ||
2187 | if (BusLogic_ProbeOptions.NoProbe) | 2187 | if (BusLogic_ProbeOptions.NoProbe) |
2188 | return -ENODEV; | 2188 | return -ENODEV; |
2189 | BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *) | 2189 | BusLogic_ProbeInfoList = |
2190 | kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_ATOMIC); | 2190 | kzalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_KERNEL); |
2191 | if (BusLogic_ProbeInfoList == NULL) { | 2191 | if (BusLogic_ProbeInfoList == NULL) { |
2192 | BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL); | 2192 | BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL); |
2193 | return -ENOMEM; | 2193 | return -ENOMEM; |
2194 | } | 2194 | } |
2195 | memset(BusLogic_ProbeInfoList, 0, BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo)); | 2195 | |
2196 | PrototypeHostAdapter = (struct BusLogic_HostAdapter *) | 2196 | PrototypeHostAdapter = |
2197 | kmalloc(sizeof(struct BusLogic_HostAdapter), GFP_ATOMIC); | 2197 | kzalloc(sizeof(struct BusLogic_HostAdapter), GFP_KERNEL); |
2198 | if (PrototypeHostAdapter == NULL) { | 2198 | if (PrototypeHostAdapter == NULL) { |
2199 | kfree(BusLogic_ProbeInfoList); | 2199 | kfree(BusLogic_ProbeInfoList); |
2200 | BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL); | 2200 | BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL); |
2201 | return -ENOMEM; | 2201 | return -ENOMEM; |
2202 | } | 2202 | } |
2203 | memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter)); | 2203 | |
2204 | #ifdef MODULE | 2204 | #ifdef MODULE |
2205 | if (BusLogic != NULL) | 2205 | if (BusLogic != NULL) |
2206 | BusLogic_Setup(BusLogic); | 2206 | BusLogic_Setup(BusLogic); |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 9540eb8efdcb..69569096dae5 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -29,6 +29,13 @@ config SCSI | |||
29 | However, do not compile this as a module if your root file system | 29 | However, do not compile this as a module if your root file system |
30 | (the one containing the directory /) is located on a SCSI device. | 30 | (the one containing the directory /) is located on a SCSI device. |
31 | 31 | ||
32 | config SCSI_TGT | ||
33 | tristate "SCSI target support" | ||
34 | depends on SCSI && EXPERIMENTAL | ||
35 | ---help--- | ||
36 | If you want to use SCSI target mode drivers enable this option. | ||
37 | If you choose M, the module will be called scsi_tgt. | ||
38 | |||
32 | config SCSI_NETLINK | 39 | config SCSI_NETLINK |
33 | bool | 40 | bool |
34 | default n | 41 | default n |
@@ -216,6 +223,23 @@ config SCSI_LOGGING | |||
216 | there should be no noticeable performance impact as long as you have | 223 | there should be no noticeable performance impact as long as you have |
217 | logging turned off. | 224 | logging turned off. |
218 | 225 | ||
226 | config SCSI_SCAN_ASYNC | ||
227 | bool "Asynchronous SCSI scanning" | ||
228 | depends on SCSI | ||
229 | help | ||
230 | The SCSI subsystem can probe for devices while the rest of the | ||
231 | system continues booting, and even probe devices on different | ||
232 | busses in parallel, leading to a significant speed-up. | ||
233 | If you have built SCSI as modules, enabling this option can | ||
234 | be a problem as the devices may not have been found by the | ||
235 | time your system expects them to have been. You can load the | ||
236 | scsi_wait_scan module to ensure that all scans have completed. | ||
237 | If you build your SCSI drivers into the kernel, then everything | ||
238 | will work fine if you say Y here. | ||
239 | |||
240 | You can override this choice by specifying scsi_mod.scan="sync" | ||
241 | or "async" on the kernel's command line. | ||
242 | |||
219 | menu "SCSI Transports" | 243 | menu "SCSI Transports" |
220 | depends on SCSI | 244 | depends on SCSI |
221 | 245 | ||
@@ -797,6 +821,20 @@ config SCSI_IBMVSCSI | |||
797 | To compile this driver as a module, choose M here: the | 821 | To compile this driver as a module, choose M here: the |
798 | module will be called ibmvscsic. | 822 | module will be called ibmvscsic. |
799 | 823 | ||
824 | config SCSI_IBMVSCSIS | ||
825 | tristate "IBM Virtual SCSI Server support" | ||
826 | depends on PPC_PSERIES && SCSI_TGT && SCSI_SRP | ||
827 | help | ||
828 | This is the SRP target driver for IBM pSeries virtual environments. | ||
829 | |||
830 | The userspace component needed to initialize the driver and | ||
831 | documentation can be found: | ||
832 | |||
833 | http://stgt.berlios.de/ | ||
834 | |||
835 | To compile this driver as a module, choose M here: the | ||
836 | module will be called ibmvstgt. | ||
837 | |||
800 | config SCSI_INITIO | 838 | config SCSI_INITIO |
801 | tristate "Initio 9100U(W) support" | 839 | tristate "Initio 9100U(W) support" |
802 | depends on PCI && SCSI | 840 | depends on PCI && SCSI |
@@ -944,8 +982,13 @@ config SCSI_STEX | |||
944 | tristate "Promise SuperTrak EX Series support" | 982 | tristate "Promise SuperTrak EX Series support" |
945 | depends on PCI && SCSI | 983 | depends on PCI && SCSI |
946 | ---help--- | 984 | ---help--- |
947 | This driver supports Promise SuperTrak EX8350/8300/16350/16300 | 985 | This driver supports Promise SuperTrak EX series storage controllers. |
948 | Storage controllers. | 986 | |
987 | Promise provides Linux RAID configuration utility for these | ||
988 | controllers. Please visit <http://www.promise.com> to download. | ||
989 | |||
990 | To compile this driver as a module, choose M here: the | ||
991 | module will be called stex. | ||
949 | 992 | ||
950 | config SCSI_SYM53C8XX_2 | 993 | config SCSI_SYM53C8XX_2 |
951 | tristate "SYM53C8XX Version 2 SCSI support" | 994 | tristate "SYM53C8XX Version 2 SCSI support" |
@@ -1026,6 +1069,7 @@ config SCSI_IPR | |||
1026 | config SCSI_IPR_TRACE | 1069 | config SCSI_IPR_TRACE |
1027 | bool "enable driver internal trace" | 1070 | bool "enable driver internal trace" |
1028 | depends on SCSI_IPR | 1071 | depends on SCSI_IPR |
1072 | default y | ||
1029 | help | 1073 | help |
1030 | If you say Y here, the driver will trace all commands issued | 1074 | If you say Y here, the driver will trace all commands issued |
1031 | to the adapter. Performance impact is minimal. Trace can be | 1075 | to the adapter. Performance impact is minimal. Trace can be |
@@ -1034,6 +1078,7 @@ config SCSI_IPR_TRACE | |||
1034 | config SCSI_IPR_DUMP | 1078 | config SCSI_IPR_DUMP |
1035 | bool "enable adapter dump support" | 1079 | bool "enable adapter dump support" |
1036 | depends on SCSI_IPR | 1080 | depends on SCSI_IPR |
1081 | default y | ||
1037 | help | 1082 | help |
1038 | If you say Y here, the driver will support adapter crash dump. | 1083 | If you say Y here, the driver will support adapter crash dump. |
1039 | If you enable this support, the iprdump daemon can be used | 1084 | If you enable this support, the iprdump daemon can be used |
@@ -1734,6 +1779,16 @@ config ZFCP | |||
1734 | called zfcp. If you want to compile it as a module, say M here | 1779 | called zfcp. If you want to compile it as a module, say M here |
1735 | and read <file:Documentation/modules.txt>. | 1780 | and read <file:Documentation/modules.txt>. |
1736 | 1781 | ||
1782 | config SCSI_SRP | ||
1783 | tristate "SCSI RDMA Protocol helper library" | ||
1784 | depends on SCSI && PCI | ||
1785 | select SCSI_TGT | ||
1786 | help | ||
1787 | If you wish to use SRP target drivers, say Y. | ||
1788 | |||
1789 | To compile this driver as a module, choose M here: the | ||
1790 | module will be called libsrp. | ||
1791 | |||
1737 | endmenu | 1792 | endmenu |
1738 | 1793 | ||
1739 | source "drivers/scsi/pcmcia/Kconfig" | 1794 | source "drivers/scsi/pcmcia/Kconfig" |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index bcca39c3bcbf..bd7c9888f7f4 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -21,6 +21,7 @@ CFLAGS_seagate.o = -DARBITRATE -DPARITY -DSEAGATE_USE_ASM | |||
21 | subdir-$(CONFIG_PCMCIA) += pcmcia | 21 | subdir-$(CONFIG_PCMCIA) += pcmcia |
22 | 22 | ||
23 | obj-$(CONFIG_SCSI) += scsi_mod.o | 23 | obj-$(CONFIG_SCSI) += scsi_mod.o |
24 | obj-$(CONFIG_SCSI_TGT) += scsi_tgt.o | ||
24 | 25 | ||
25 | obj-$(CONFIG_RAID_ATTRS) += raid_class.o | 26 | obj-$(CONFIG_RAID_ATTRS) += raid_class.o |
26 | 27 | ||
@@ -125,7 +126,9 @@ obj-$(CONFIG_SCSI_FCAL) += fcal.o | |||
125 | obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o | 126 | obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o |
126 | obj-$(CONFIG_SCSI_NSP32) += nsp32.o | 127 | obj-$(CONFIG_SCSI_NSP32) += nsp32.o |
127 | obj-$(CONFIG_SCSI_IPR) += ipr.o | 128 | obj-$(CONFIG_SCSI_IPR) += ipr.o |
129 | obj-$(CONFIG_SCSI_SRP) += libsrp.o | ||
128 | obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/ | 130 | obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/ |
131 | obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi/ | ||
129 | obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o | 132 | obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o |
130 | obj-$(CONFIG_SCSI_STEX) += stex.o | 133 | obj-$(CONFIG_SCSI_STEX) += stex.o |
131 | 134 | ||
@@ -141,6 +144,8 @@ obj-$(CONFIG_CHR_DEV_SCH) += ch.o | |||
141 | # This goes last, so that "real" scsi devices probe earlier | 144 | # This goes last, so that "real" scsi devices probe earlier |
142 | obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o | 145 | obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o |
143 | 146 | ||
147 | obj-$(CONFIG_SCSI) += scsi_wait_scan.o | ||
148 | |||
144 | scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ | 149 | scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ |
145 | scsicam.o scsi_error.o scsi_lib.o \ | 150 | scsicam.o scsi_error.o scsi_lib.o \ |
146 | scsi_scan.o scsi_sysfs.o \ | 151 | scsi_scan.o scsi_sysfs.o \ |
@@ -149,6 +154,8 @@ scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o | |||
149 | scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o | 154 | scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o |
150 | scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o | 155 | scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o |
151 | 156 | ||
157 | scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o | ||
158 | |||
152 | sd_mod-objs := sd.o | 159 | sd_mod-objs := sd.o |
153 | sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o | 160 | sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o |
154 | ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ | 161 | ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ |
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index d4613815f685..8578555d58fd 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c | |||
@@ -220,9 +220,11 @@ static void *addresses[] = { | |||
220 | static unsigned short ports[] = { 0x230, 0x330, 0x280, 0x290, 0x330, 0x340, 0x300, 0x310, 0x348, 0x350 }; | 220 | static unsigned short ports[] = { 0x230, 0x330, 0x280, 0x290, 0x330, 0x340, 0x300, 0x310, 0x348, 0x350 }; |
221 | #define PORT_COUNT ARRAY_SIZE(ports) | 221 | #define PORT_COUNT ARRAY_SIZE(ports) |
222 | 222 | ||
223 | #ifndef MODULE | ||
223 | /* possible interrupt channels */ | 224 | /* possible interrupt channels */ |
224 | static unsigned short intrs[] = { 10, 11, 12, 15 }; | 225 | static unsigned short intrs[] = { 10, 11, 12, 15 }; |
225 | #define INTR_COUNT ARRAY_SIZE(intrs) | 226 | #define INTR_COUNT ARRAY_SIZE(intrs) |
227 | #endif /* !MODULE */ | ||
226 | 228 | ||
227 | /* signatures for NCR 53c406a based controllers */ | 229 | /* signatures for NCR 53c406a based controllers */ |
228 | #if USE_BIOS | 230 | #if USE_BIOS |
@@ -605,6 +607,7 @@ static int NCR53c406a_release(struct Scsi_Host *shost) | |||
605 | return 0; | 607 | return 0; |
606 | } | 608 | } |
607 | 609 | ||
610 | #ifndef MODULE | ||
608 | /* called from init/main.c */ | 611 | /* called from init/main.c */ |
609 | static int __init NCR53c406a_setup(char *str) | 612 | static int __init NCR53c406a_setup(char *str) |
610 | { | 613 | { |
@@ -661,6 +664,8 @@ static int __init NCR53c406a_setup(char *str) | |||
661 | 664 | ||
662 | __setup("ncr53c406a=", NCR53c406a_setup); | 665 | __setup("ncr53c406a=", NCR53c406a_setup); |
663 | 666 | ||
667 | #endif /* !MODULE */ | ||
668 | |||
664 | static const char *NCR53c406a_info(struct Scsi_Host *SChost) | 669 | static const char *NCR53c406a_info(struct Scsi_Host *SChost) |
665 | { | 670 | { |
666 | DEB(printk("NCR53c406a_info called\n")); | 671 | DEB(printk("NCR53c406a_info called\n")); |
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index eb3ed91bac79..4f8b4c53d435 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h | |||
@@ -11,8 +11,8 @@ | |||
11 | *----------------------------------------------------------------------------*/ | 11 | *----------------------------------------------------------------------------*/ |
12 | 12 | ||
13 | #ifndef AAC_DRIVER_BUILD | 13 | #ifndef AAC_DRIVER_BUILD |
14 | # define AAC_DRIVER_BUILD 2409 | 14 | # define AAC_DRIVER_BUILD 2423 |
15 | # define AAC_DRIVER_BRANCH "-mh2" | 15 | # define AAC_DRIVER_BRANCH "-mh3" |
16 | #endif | 16 | #endif |
17 | #define MAXIMUM_NUM_CONTAINERS 32 | 17 | #define MAXIMUM_NUM_CONTAINERS 32 |
18 | 18 | ||
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 19e42ac07cb2..4893a6d06a33 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -518,6 +518,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
518 | */ | 518 | */ |
519 | unsigned long count = 36000000L; /* 3 minutes */ | 519 | unsigned long count = 36000000L; /* 3 minutes */ |
520 | while (down_trylock(&fibptr->event_wait)) { | 520 | while (down_trylock(&fibptr->event_wait)) { |
521 | int blink; | ||
521 | if (--count == 0) { | 522 | if (--count == 0) { |
522 | spin_lock_irqsave(q->lock, qflags); | 523 | spin_lock_irqsave(q->lock, qflags); |
523 | q->numpending--; | 524 | q->numpending--; |
@@ -530,6 +531,14 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
530 | } | 531 | } |
531 | return -ETIMEDOUT; | 532 | return -ETIMEDOUT; |
532 | } | 533 | } |
534 | if ((blink = aac_adapter_check_health(dev)) > 0) { | ||
535 | if (wait == -1) { | ||
536 | printk(KERN_ERR "aacraid: aac_fib_send: adapter blinkLED 0x%x.\n" | ||
537 | "Usually a result of a serious unrecoverable hardware problem\n", | ||
538 | blink); | ||
539 | } | ||
540 | return -EFAULT; | ||
541 | } | ||
533 | udelay(5); | 542 | udelay(5); |
534 | } | 543 | } |
535 | } else if (down_interruptible(&fibptr->event_wait)) { | 544 | } else if (down_interruptible(&fibptr->event_wait)) { |
@@ -1093,6 +1102,20 @@ static int _aac_reset_adapter(struct aac_dev *aac) | |||
1093 | goto out; | 1102 | goto out; |
1094 | } | 1103 | } |
1095 | 1104 | ||
1105 | /* | ||
1106 | * Loop through the fibs, close the synchronous FIBS | ||
1107 | */ | ||
1108 | for (index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) { | ||
1109 | struct fib *fib = &aac->fibs[index]; | ||
1110 | if (!(fib->hw_fib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) && | ||
1111 | (fib->hw_fib->header.XferState & cpu_to_le32(ResponseExpected))) { | ||
1112 | unsigned long flagv; | ||
1113 | spin_lock_irqsave(&fib->event_lock, flagv); | ||
1114 | up(&fib->event_wait); | ||
1115 | spin_unlock_irqrestore(&fib->event_lock, flagv); | ||
1116 | schedule(); | ||
1117 | } | ||
1118 | } | ||
1096 | index = aac->cardtype; | 1119 | index = aac->cardtype; |
1097 | 1120 | ||
1098 | /* | 1121 | /* |
diff --git a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c index c3c38a7e8d32..d7af9c63a04d 100644 --- a/drivers/scsi/aha1740.c +++ b/drivers/scsi/aha1740.c | |||
@@ -586,7 +586,7 @@ static struct scsi_host_template aha1740_template = { | |||
586 | 586 | ||
587 | static int aha1740_probe (struct device *dev) | 587 | static int aha1740_probe (struct device *dev) |
588 | { | 588 | { |
589 | int slotbase; | 589 | int slotbase, rc; |
590 | unsigned int irq_level, irq_type, translation; | 590 | unsigned int irq_level, irq_type, translation; |
591 | struct Scsi_Host *shpnt; | 591 | struct Scsi_Host *shpnt; |
592 | struct aha1740_hostdata *host; | 592 | struct aha1740_hostdata *host; |
@@ -641,10 +641,16 @@ static int aha1740_probe (struct device *dev) | |||
641 | } | 641 | } |
642 | 642 | ||
643 | eisa_set_drvdata (edev, shpnt); | 643 | eisa_set_drvdata (edev, shpnt); |
644 | scsi_add_host (shpnt, dev); /* XXX handle failure */ | 644 | |
645 | rc = scsi_add_host (shpnt, dev); | ||
646 | if (rc) | ||
647 | goto err_irq; | ||
648 | |||
645 | scsi_scan_host (shpnt); | 649 | scsi_scan_host (shpnt); |
646 | return 0; | 650 | return 0; |
647 | 651 | ||
652 | err_irq: | ||
653 | free_irq(irq_level, shpnt); | ||
648 | err_unmap: | 654 | err_unmap: |
649 | dma_unmap_single (&edev->dev, host->ecb_dma_addr, | 655 | dma_unmap_single (&edev->dev, host->ecb_dma_addr, |
650 | sizeof (host->ecb), DMA_BIDIRECTIONAL); | 656 | sizeof (host->ecb), DMA_BIDIRECTIONAL); |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 2001fe890e71..1a3ab6aa856b 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c | |||
@@ -62,6 +62,7 @@ static struct pci_device_id ahd_linux_pci_id_table[] = { | |||
62 | /* aic7901 based controllers */ | 62 | /* aic7901 based controllers */ |
63 | ID(ID_AHA_29320A), | 63 | ID(ID_AHA_29320A), |
64 | ID(ID_AHA_29320ALP), | 64 | ID(ID_AHA_29320ALP), |
65 | ID(ID_AHA_29320LPE), | ||
65 | /* aic7902 based controllers */ | 66 | /* aic7902 based controllers */ |
66 | ID(ID_AHA_29320), | 67 | ID(ID_AHA_29320), |
67 | ID(ID_AHA_29320B), | 68 | ID(ID_AHA_29320B), |
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index c07735819cd1..2cf7bb3123f0 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c | |||
@@ -109,7 +109,13 @@ static struct ahd_pci_identity ahd_pci_ident_table [] = | |||
109 | { | 109 | { |
110 | ID_AHA_29320ALP, | 110 | ID_AHA_29320ALP, |
111 | ID_ALL_MASK, | 111 | ID_ALL_MASK, |
112 | "Adaptec 29320ALP Ultra320 SCSI adapter", | 112 | "Adaptec 29320ALP PCIx Ultra320 SCSI adapter", |
113 | ahd_aic7901_setup | ||
114 | }, | ||
115 | { | ||
116 | ID_AHA_29320LPE, | ||
117 | ID_ALL_MASK, | ||
118 | "Adaptec 29320LPE PCIe Ultra320 SCSI adapter", | ||
113 | ahd_aic7901_setup | 119 | ahd_aic7901_setup |
114 | }, | 120 | }, |
115 | /* aic7901A based controllers */ | 121 | /* aic7901A based controllers */ |
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.h b/drivers/scsi/aic7xxx/aic79xx_pci.h index da45153668c7..16b7c70a673c 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.h +++ b/drivers/scsi/aic7xxx/aic79xx_pci.h | |||
@@ -51,6 +51,7 @@ | |||
51 | #define ID_AIC7901 0x800F9005FFFF9005ull | 51 | #define ID_AIC7901 0x800F9005FFFF9005ull |
52 | #define ID_AHA_29320A 0x8000900500609005ull | 52 | #define ID_AHA_29320A 0x8000900500609005ull |
53 | #define ID_AHA_29320ALP 0x8017900500449005ull | 53 | #define ID_AHA_29320ALP 0x8017900500449005ull |
54 | #define ID_AHA_29320LPE 0x8017900500459005ull | ||
54 | 55 | ||
55 | #define ID_AIC7901A 0x801E9005FFFF9005ull | 56 | #define ID_AIC7901A 0x801E9005FFFF9005ull |
56 | #define ID_AHA_29320LP 0x8014900500449005ull | 57 | #define ID_AHA_29320LP 0x8014900500449005ull |
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 57c5ba4043f2..42302ef05ee5 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c | |||
@@ -724,6 +724,15 @@ static void asd_free_queues(struct asd_ha_struct *asd_ha) | |||
724 | 724 | ||
725 | list_for_each_safe(pos, n, &pending) { | 725 | list_for_each_safe(pos, n, &pending) { |
726 | struct asd_ascb *ascb = list_entry(pos, struct asd_ascb, list); | 726 | struct asd_ascb *ascb = list_entry(pos, struct asd_ascb, list); |
727 | /* | ||
728 | * Delete unexpired ascb timers. This may happen if we issue | ||
729 | * a CONTROL PHY scb to an adapter and rmmod before the scb | ||
730 | * times out. Apparently we don't wait for the CONTROL PHY | ||
731 | * to complete, so it doesn't matter if we kill the timer. | ||
732 | */ | ||
733 | del_timer_sync(&ascb->timer); | ||
734 | WARN_ON(ascb->scb->header.opcode != CONTROL_PHY); | ||
735 | |||
727 | list_del_init(pos); | 736 | list_del_init(pos); |
728 | ASD_DPRINTK("freeing from pending\n"); | 737 | ASD_DPRINTK("freeing from pending\n"); |
729 | asd_ascb_free(ascb); | 738 | asd_ascb_free(ascb); |
diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index b15caf1c8fa2..14d5d8c2ee13 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c | |||
@@ -25,6 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <scsi/scsi_host.h> | ||
28 | 29 | ||
29 | #include "aic94xx.h" | 30 | #include "aic94xx.h" |
30 | #include "aic94xx_reg.h" | 31 | #include "aic94xx_reg.h" |
@@ -412,6 +413,39 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id) | |||
412 | } | 413 | } |
413 | } | 414 | } |
414 | 415 | ||
416 | /* hard reset a phy later */ | ||
417 | static void do_phy_reset_later(void *data) | ||
418 | { | ||
419 | struct sas_phy *sas_phy = data; | ||
420 | int error; | ||
421 | |||
422 | ASD_DPRINTK("%s: About to hard reset phy %d\n", __FUNCTION__, | ||
423 | sas_phy->identify.phy_identifier); | ||
424 | /* Reset device port */ | ||
425 | error = sas_phy_reset(sas_phy, 1); | ||
426 | if (error) | ||
427 | ASD_DPRINTK("%s: Hard reset of phy %d failed (%d).\n", | ||
428 | __FUNCTION__, sas_phy->identify.phy_identifier, error); | ||
429 | } | ||
430 | |||
431 | static void phy_reset_later(struct sas_phy *sas_phy, struct Scsi_Host *shost) | ||
432 | { | ||
433 | INIT_WORK(&sas_phy->reset_work, do_phy_reset_later, sas_phy); | ||
434 | queue_work(shost->work_q, &sas_phy->reset_work); | ||
435 | } | ||
436 | |||
437 | /* start up the ABORT TASK tmf... */ | ||
438 | static void task_kill_later(struct asd_ascb *ascb) | ||
439 | { | ||
440 | struct asd_ha_struct *asd_ha = ascb->ha; | ||
441 | struct sas_ha_struct *sas_ha = &asd_ha->sas_ha; | ||
442 | struct Scsi_Host *shost = sas_ha->core.shost; | ||
443 | struct sas_task *task = ascb->uldd_task; | ||
444 | |||
445 | INIT_WORK(&task->abort_work, (void (*)(void *))sas_task_abort, task); | ||
446 | queue_work(shost->work_q, &task->abort_work); | ||
447 | } | ||
448 | |||
415 | static void escb_tasklet_complete(struct asd_ascb *ascb, | 449 | static void escb_tasklet_complete(struct asd_ascb *ascb, |
416 | struct done_list_struct *dl) | 450 | struct done_list_struct *dl) |
417 | { | 451 | { |
@@ -439,6 +473,74 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, | |||
439 | ascb->scb->header.opcode); | 473 | ascb->scb->header.opcode); |
440 | } | 474 | } |
441 | 475 | ||
476 | /* Catch these before we mask off the sb_opcode bits */ | ||
477 | switch (sb_opcode) { | ||
478 | case REQ_TASK_ABORT: { | ||
479 | struct asd_ascb *a, *b; | ||
480 | u16 tc_abort; | ||
481 | |||
482 | tc_abort = *((u16*)(&dl->status_block[1])); | ||
483 | tc_abort = le16_to_cpu(tc_abort); | ||
484 | |||
485 | ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n", | ||
486 | __FUNCTION__, dl->status_block[3]); | ||
487 | |||
488 | /* Find the pending task and abort it. */ | ||
489 | list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list) | ||
490 | if (a->tc_index == tc_abort) { | ||
491 | task_kill_later(a); | ||
492 | break; | ||
493 | } | ||
494 | goto out; | ||
495 | } | ||
496 | case REQ_DEVICE_RESET: { | ||
497 | struct Scsi_Host *shost = sas_ha->core.shost; | ||
498 | struct sas_phy *dev_phy; | ||
499 | struct asd_ascb *a; | ||
500 | u16 conn_handle; | ||
501 | |||
502 | conn_handle = *((u16*)(&dl->status_block[1])); | ||
503 | conn_handle = le16_to_cpu(conn_handle); | ||
504 | |||
505 | ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__, | ||
506 | dl->status_block[3]); | ||
507 | |||
508 | /* Kill all pending tasks and reset the device */ | ||
509 | dev_phy = NULL; | ||
510 | list_for_each_entry(a, &asd_ha->seq.pend_q, list) { | ||
511 | struct sas_task *task; | ||
512 | struct domain_device *dev; | ||
513 | u16 x; | ||
514 | |||
515 | task = a->uldd_task; | ||
516 | if (!task) | ||
517 | continue; | ||
518 | dev = task->dev; | ||
519 | |||
520 | x = (unsigned long)dev->lldd_dev; | ||
521 | if (x == conn_handle) { | ||
522 | dev_phy = dev->port->phy; | ||
523 | task_kill_later(a); | ||
524 | } | ||
525 | } | ||
526 | |||
527 | /* Reset device port */ | ||
528 | if (!dev_phy) { | ||
529 | ASD_DPRINTK("%s: No pending commands; can't reset.\n", | ||
530 | __FUNCTION__); | ||
531 | goto out; | ||
532 | } | ||
533 | phy_reset_later(dev_phy, shost); | ||
534 | goto out; | ||
535 | } | ||
536 | case SIGNAL_NCQ_ERROR: | ||
537 | ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __FUNCTION__); | ||
538 | goto out; | ||
539 | case CLEAR_NCQ_ERROR: | ||
540 | ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __FUNCTION__); | ||
541 | goto out; | ||
542 | } | ||
543 | |||
442 | sb_opcode &= ~DL_PHY_MASK; | 544 | sb_opcode &= ~DL_PHY_MASK; |
443 | 545 | ||
444 | switch (sb_opcode) { | 546 | switch (sb_opcode) { |
@@ -469,22 +571,6 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, | |||
469 | asd_deform_port(asd_ha, phy); | 571 | asd_deform_port(asd_ha, phy); |
470 | sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT); | 572 | sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT); |
471 | break; | 573 | break; |
472 | case REQ_TASK_ABORT: | ||
473 | ASD_DPRINTK("%s: phy%d: REQ_TASK_ABORT\n", __FUNCTION__, | ||
474 | phy_id); | ||
475 | break; | ||
476 | case REQ_DEVICE_RESET: | ||
477 | ASD_DPRINTK("%s: phy%d: REQ_DEVICE_RESET\n", __FUNCTION__, | ||
478 | phy_id); | ||
479 | break; | ||
480 | case SIGNAL_NCQ_ERROR: | ||
481 | ASD_DPRINTK("%s: phy%d: SIGNAL_NCQ_ERROR\n", __FUNCTION__, | ||
482 | phy_id); | ||
483 | break; | ||
484 | case CLEAR_NCQ_ERROR: | ||
485 | ASD_DPRINTK("%s: phy%d: CLEAR_NCQ_ERROR\n", __FUNCTION__, | ||
486 | phy_id); | ||
487 | break; | ||
488 | default: | 574 | default: |
489 | ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __FUNCTION__, | 575 | ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __FUNCTION__, |
490 | phy_id, sb_opcode); | 576 | phy_id, sb_opcode); |
@@ -504,7 +590,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, | |||
504 | 590 | ||
505 | break; | 591 | break; |
506 | } | 592 | } |
507 | 593 | out: | |
508 | asd_invalidate_edb(ascb, edb); | 594 | asd_invalidate_edb(ascb, edb); |
509 | } | 595 | } |
510 | 596 | ||
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c index ef8285c326e4..668569e8856b 100644 --- a/drivers/scsi/fd_mcs.c +++ b/drivers/scsi/fd_mcs.c | |||
@@ -294,6 +294,7 @@ static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL }; | |||
294 | static int user_fifo_count = 0; | 294 | static int user_fifo_count = 0; |
295 | static int user_fifo_size = 0; | 295 | static int user_fifo_size = 0; |
296 | 296 | ||
297 | #ifndef MODULE | ||
297 | static int __init fd_mcs_setup(char *str) | 298 | static int __init fd_mcs_setup(char *str) |
298 | { | 299 | { |
299 | static int done_setup = 0; | 300 | static int done_setup = 0; |
@@ -311,6 +312,7 @@ static int __init fd_mcs_setup(char *str) | |||
311 | } | 312 | } |
312 | 313 | ||
313 | __setup("fd_mcs=", fd_mcs_setup); | 314 | __setup("fd_mcs=", fd_mcs_setup); |
315 | #endif /* !MODULE */ | ||
314 | 316 | ||
315 | static void print_banner(struct Scsi_Host *shpnt) | 317 | static void print_banner(struct Scsi_Host *shpnt) |
316 | { | 318 | { |
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 68ef1636678d..38c3a291efac 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -263,6 +263,10 @@ static void scsi_host_dev_release(struct device *dev) | |||
263 | kthread_stop(shost->ehandler); | 263 | kthread_stop(shost->ehandler); |
264 | if (shost->work_q) | 264 | if (shost->work_q) |
265 | destroy_workqueue(shost->work_q); | 265 | destroy_workqueue(shost->work_q); |
266 | if (shost->uspace_req_q) { | ||
267 | kfree(shost->uspace_req_q->queuedata); | ||
268 | scsi_free_queue(shost->uspace_req_q); | ||
269 | } | ||
266 | 270 | ||
267 | scsi_destroy_command_freelist(shost); | 271 | scsi_destroy_command_freelist(shost); |
268 | if (shost->bqt) | 272 | if (shost->bqt) |
@@ -301,8 +305,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) | |||
301 | if (!shost) | 305 | if (!shost) |
302 | return NULL; | 306 | return NULL; |
303 | 307 | ||
304 | spin_lock_init(&shost->default_lock); | 308 | shost->host_lock = &shost->default_lock; |
305 | scsi_assign_lock(shost, &shost->default_lock); | 309 | spin_lock_init(shost->host_lock); |
306 | shost->shost_state = SHOST_CREATED; | 310 | shost->shost_state = SHOST_CREATED; |
307 | INIT_LIST_HEAD(&shost->__devices); | 311 | INIT_LIST_HEAD(&shost->__devices); |
308 | INIT_LIST_HEAD(&shost->__targets); | 312 | INIT_LIST_HEAD(&shost->__targets); |
diff --git a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile index 4e247b6b8700..6ac0633d5452 100644 --- a/drivers/scsi/ibmvscsi/Makefile +++ b/drivers/scsi/ibmvscsi/Makefile | |||
@@ -3,3 +3,5 @@ obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsic.o | |||
3 | ibmvscsic-y += ibmvscsi.o | 3 | ibmvscsic-y += ibmvscsi.o |
4 | ibmvscsic-$(CONFIG_PPC_ISERIES) += iseries_vscsi.o | 4 | ibmvscsic-$(CONFIG_PPC_ISERIES) += iseries_vscsi.o |
5 | ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o | 5 | ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o |
6 | |||
7 | obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvstgt.o | ||
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c new file mode 100644 index 000000000000..0e74174a1b37 --- /dev/null +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c | |||
@@ -0,0 +1,958 @@ | |||
1 | /* | ||
2 | * IBM eServer i/pSeries Virtual SCSI Target Driver | ||
3 | * Copyright (C) 2003-2005 Dave Boutcher (boutcher@us.ibm.com) IBM Corp. | ||
4 | * Santiago Leon (santil@us.ibm.com) IBM Corp. | ||
5 | * Linda Xie (lxie@us.ibm.com) IBM Corp. | ||
6 | * | ||
7 | * Copyright (C) 2005-2006 FUJITA Tomonori <tomof@acm.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
22 | * USA | ||
23 | */ | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <scsi/scsi.h> | ||
27 | #include <scsi/scsi_host.h> | ||
28 | #include <scsi/scsi_tgt.h> | ||
29 | #include <scsi/libsrp.h> | ||
30 | #include <asm/hvcall.h> | ||
31 | #include <asm/iommu.h> | ||
32 | #include <asm/prom.h> | ||
33 | #include <asm/vio.h> | ||
34 | |||
35 | #include "ibmvscsi.h" | ||
36 | |||
37 | #define INITIAL_SRP_LIMIT 16 | ||
38 | #define DEFAULT_MAX_SECTORS 512 | ||
39 | |||
40 | #define TGT_NAME "ibmvstgt" | ||
41 | |||
42 | /* | ||
43 | * Hypervisor calls. | ||
44 | */ | ||
45 | #define h_copy_rdma(l, sa, sb, da, db) \ | ||
46 | plpar_hcall_norets(H_COPY_RDMA, l, sa, sb, da, db) | ||
47 | #define h_send_crq(ua, l, h) \ | ||
48 | plpar_hcall_norets(H_SEND_CRQ, ua, l, h) | ||
49 | #define h_reg_crq(ua, tok, sz)\ | ||
50 | plpar_hcall_norets(H_REG_CRQ, ua, tok, sz); | ||
51 | #define h_free_crq(ua) \ | ||
52 | plpar_hcall_norets(H_FREE_CRQ, ua); | ||
53 | |||
54 | /* tmp - will replace with SCSI logging stuff */ | ||
55 | #define eprintk(fmt, args...) \ | ||
56 | do { \ | ||
57 | printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \ | ||
58 | } while (0) | ||
59 | /* #define dprintk eprintk */ | ||
60 | #define dprintk(fmt, args...) | ||
61 | |||
62 | struct vio_port { | ||
63 | struct vio_dev *dma_dev; | ||
64 | |||
65 | struct crq_queue crq_queue; | ||
66 | struct work_struct crq_work; | ||
67 | |||
68 | unsigned long liobn; | ||
69 | unsigned long riobn; | ||
70 | }; | ||
71 | |||
72 | static struct workqueue_struct *vtgtd; | ||
73 | |||
74 | /* | ||
75 | * These are fixed for the system and come from the Open Firmware device tree. | ||
76 | * We just store them here to save getting them every time. | ||
77 | */ | ||
78 | static char system_id[64] = ""; | ||
79 | static char partition_name[97] = "UNKNOWN"; | ||
80 | static unsigned int partition_number = -1; | ||
81 | |||
82 | static struct vio_port *target_to_port(struct srp_target *target) | ||
83 | { | ||
84 | return (struct vio_port *) target->ldata; | ||
85 | } | ||
86 | |||
87 | static inline union viosrp_iu *vio_iu(struct iu_entry *iue) | ||
88 | { | ||
89 | return (union viosrp_iu *) (iue->sbuf->buf); | ||
90 | } | ||
91 | |||
92 | static int send_iu(struct iu_entry *iue, uint64_t length, uint8_t format) | ||
93 | { | ||
94 | struct srp_target *target = iue->target; | ||
95 | struct vio_port *vport = target_to_port(target); | ||
96 | long rc, rc1; | ||
97 | union { | ||
98 | struct viosrp_crq cooked; | ||
99 | uint64_t raw[2]; | ||
100 | } crq; | ||
101 | |||
102 | /* First copy the SRP */ | ||
103 | rc = h_copy_rdma(length, vport->liobn, iue->sbuf->dma, | ||
104 | vport->riobn, iue->remote_token); | ||
105 | |||
106 | if (rc) | ||
107 | eprintk("Error %ld transferring data\n", rc); | ||
108 | |||
109 | crq.cooked.valid = 0x80; | ||
110 | crq.cooked.format = format; | ||
111 | crq.cooked.reserved = 0x00; | ||
112 | crq.cooked.timeout = 0x00; | ||
113 | crq.cooked.IU_length = length; | ||
114 | crq.cooked.IU_data_ptr = vio_iu(iue)->srp.rsp.tag; | ||
115 | |||
116 | if (rc == 0) | ||
117 | crq.cooked.status = 0x99; /* Just needs to be non-zero */ | ||
118 | else | ||
119 | crq.cooked.status = 0x00; | ||
120 | |||
121 | rc1 = h_send_crq(vport->dma_dev->unit_address, crq.raw[0], crq.raw[1]); | ||
122 | |||
123 | if (rc1) { | ||
124 | eprintk("%ld sending response\n", rc1); | ||
125 | return rc1; | ||
126 | } | ||
127 | |||
128 | return rc; | ||
129 | } | ||
130 | |||
131 | #define SRP_RSP_SENSE_DATA_LEN 18 | ||
132 | |||
133 | static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc, | ||
134 | unsigned char status, unsigned char asc) | ||
135 | { | ||
136 | union viosrp_iu *iu = vio_iu(iue); | ||
137 | uint64_t tag = iu->srp.rsp.tag; | ||
138 | |||
139 | /* If the linked bit is on and status is good */ | ||
140 | if (test_bit(V_LINKED, &iue->flags) && (status == NO_SENSE)) | ||
141 | status = 0x10; | ||
142 | |||
143 | memset(iu, 0, sizeof(struct srp_rsp)); | ||
144 | iu->srp.rsp.opcode = SRP_RSP; | ||
145 | iu->srp.rsp.req_lim_delta = 1; | ||
146 | iu->srp.rsp.tag = tag; | ||
147 | |||
148 | if (test_bit(V_DIOVER, &iue->flags)) | ||
149 | iu->srp.rsp.flags |= SRP_RSP_FLAG_DIOVER; | ||
150 | |||
151 | iu->srp.rsp.data_in_res_cnt = 0; | ||
152 | iu->srp.rsp.data_out_res_cnt = 0; | ||
153 | |||
154 | iu->srp.rsp.flags &= ~SRP_RSP_FLAG_RSPVALID; | ||
155 | |||
156 | iu->srp.rsp.resp_data_len = 0; | ||
157 | iu->srp.rsp.status = status; | ||
158 | if (status) { | ||
159 | uint8_t *sense = iu->srp.rsp.data; | ||
160 | |||
161 | if (sc) { | ||
162 | iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; | ||
163 | iu->srp.rsp.sense_data_len = SCSI_SENSE_BUFFERSIZE; | ||
164 | memcpy(sense, sc->sense_buffer, SCSI_SENSE_BUFFERSIZE); | ||
165 | } else { | ||
166 | iu->srp.rsp.status = SAM_STAT_CHECK_CONDITION; | ||
167 | iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; | ||
168 | iu->srp.rsp.sense_data_len = SRP_RSP_SENSE_DATA_LEN; | ||
169 | |||
170 | /* Valid bit and 'current errors' */ | ||
171 | sense[0] = (0x1 << 7 | 0x70); | ||
172 | /* Sense key */ | ||
173 | sense[2] = status; | ||
174 | /* Additional sense length */ | ||
175 | sense[7] = 0xa; /* 10 bytes */ | ||
176 | /* Additional sense code */ | ||
177 | sense[12] = asc; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | send_iu(iue, sizeof(iu->srp.rsp) + SRP_RSP_SENSE_DATA_LEN, | ||
182 | VIOSRP_SRP_FORMAT); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static void handle_cmd_queue(struct srp_target *target) | ||
188 | { | ||
189 | struct Scsi_Host *shost = target->shost; | ||
190 | struct iu_entry *iue; | ||
191 | struct srp_cmd *cmd; | ||
192 | unsigned long flags; | ||
193 | int err; | ||
194 | |||
195 | retry: | ||
196 | spin_lock_irqsave(&target->lock, flags); | ||
197 | |||
198 | list_for_each_entry(iue, &target->cmd_queue, ilist) { | ||
199 | if (!test_and_set_bit(V_FLYING, &iue->flags)) { | ||
200 | spin_unlock_irqrestore(&target->lock, flags); | ||
201 | cmd = iue->sbuf->buf; | ||
202 | err = srp_cmd_queue(shost, cmd, iue, 0); | ||
203 | if (err) { | ||
204 | eprintk("cannot queue cmd %p %d\n", cmd, err); | ||
205 | srp_iu_put(iue); | ||
206 | } | ||
207 | goto retry; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | spin_unlock_irqrestore(&target->lock, flags); | ||
212 | } | ||
213 | |||
214 | static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg, | ||
215 | struct srp_direct_buf *md, int nmd, | ||
216 | enum dma_data_direction dir, unsigned int rest) | ||
217 | { | ||
218 | struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; | ||
219 | struct srp_target *target = iue->target; | ||
220 | struct vio_port *vport = target_to_port(target); | ||
221 | dma_addr_t token; | ||
222 | long err; | ||
223 | unsigned int done = 0; | ||
224 | int i, sidx, soff; | ||
225 | |||
226 | sidx = soff = 0; | ||
227 | token = sg_dma_address(sg + sidx); | ||
228 | |||
229 | for (i = 0; i < nmd && rest; i++) { | ||
230 | unsigned int mdone, mlen; | ||
231 | |||
232 | mlen = min(rest, md[i].len); | ||
233 | for (mdone = 0; mlen;) { | ||
234 | int slen = min(sg_dma_len(sg + sidx) - soff, mlen); | ||
235 | |||
236 | if (dir == DMA_TO_DEVICE) | ||
237 | err = h_copy_rdma(slen, | ||
238 | vport->riobn, | ||
239 | md[i].va + mdone, | ||
240 | vport->liobn, | ||
241 | token + soff); | ||
242 | else | ||
243 | err = h_copy_rdma(slen, | ||
244 | vport->liobn, | ||
245 | token + soff, | ||
246 | vport->riobn, | ||
247 | md[i].va + mdone); | ||
248 | |||
249 | if (err != H_SUCCESS) { | ||
250 | eprintk("rdma error %d %d\n", dir, slen); | ||
251 | goto out; | ||
252 | } | ||
253 | |||
254 | mlen -= slen; | ||
255 | mdone += slen; | ||
256 | soff += slen; | ||
257 | done += slen; | ||
258 | |||
259 | if (soff == sg_dma_len(sg + sidx)) { | ||
260 | sidx++; | ||
261 | soff = 0; | ||
262 | token = sg_dma_address(sg + sidx); | ||
263 | |||
264 | if (sidx > nsg) { | ||
265 | eprintk("out of sg %p %d %d\n", | ||
266 | iue, sidx, nsg); | ||
267 | goto out; | ||
268 | } | ||
269 | } | ||
270 | }; | ||
271 | |||
272 | rest -= mlen; | ||
273 | } | ||
274 | out: | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int ibmvstgt_transfer_data(struct scsi_cmnd *sc, | ||
280 | void (*done)(struct scsi_cmnd *)) | ||
281 | { | ||
282 | struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; | ||
283 | int err; | ||
284 | |||
285 | err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); | ||
286 | |||
287 | done(sc); | ||
288 | |||
289 | return err; | ||
290 | } | ||
291 | |||
292 | static int ibmvstgt_cmd_done(struct scsi_cmnd *sc, | ||
293 | void (*done)(struct scsi_cmnd *)) | ||
294 | { | ||
295 | unsigned long flags; | ||
296 | struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; | ||
297 | struct srp_target *target = iue->target; | ||
298 | |||
299 | dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]); | ||
300 | |||
301 | spin_lock_irqsave(&target->lock, flags); | ||
302 | list_del(&iue->ilist); | ||
303 | spin_unlock_irqrestore(&target->lock, flags); | ||
304 | |||
305 | if (sc->result != SAM_STAT_GOOD) { | ||
306 | eprintk("operation failed %p %d %x\n", | ||
307 | iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]); | ||
308 | send_rsp(iue, sc, HARDWARE_ERROR, 0x00); | ||
309 | } else | ||
310 | send_rsp(iue, sc, NO_SENSE, 0x00); | ||
311 | |||
312 | done(sc); | ||
313 | srp_iu_put(iue); | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | int send_adapter_info(struct iu_entry *iue, | ||
318 | dma_addr_t remote_buffer, uint16_t length) | ||
319 | { | ||
320 | struct srp_target *target = iue->target; | ||
321 | struct vio_port *vport = target_to_port(target); | ||
322 | struct Scsi_Host *shost = target->shost; | ||
323 | dma_addr_t data_token; | ||
324 | struct mad_adapter_info_data *info; | ||
325 | int err; | ||
326 | |||
327 | info = dma_alloc_coherent(target->dev, sizeof(*info), &data_token, | ||
328 | GFP_KERNEL); | ||
329 | if (!info) { | ||
330 | eprintk("bad dma_alloc_coherent %p\n", target); | ||
331 | return 1; | ||
332 | } | ||
333 | |||
334 | /* Get remote info */ | ||
335 | err = h_copy_rdma(sizeof(*info), vport->riobn, remote_buffer, | ||
336 | vport->liobn, data_token); | ||
337 | if (err == H_SUCCESS) { | ||
338 | dprintk("Client connect: %s (%d)\n", | ||
339 | info->partition_name, info->partition_number); | ||
340 | } | ||
341 | |||
342 | memset(info, 0, sizeof(*info)); | ||
343 | |||
344 | strcpy(info->srp_version, "16.a"); | ||
345 | strncpy(info->partition_name, partition_name, | ||
346 | sizeof(info->partition_name)); | ||
347 | info->partition_number = partition_number; | ||
348 | info->mad_version = 1; | ||
349 | info->os_type = 2; | ||
350 | info->port_max_txu[0] = shost->hostt->max_sectors << 9; | ||
351 | |||
352 | /* Send our info to remote */ | ||
353 | err = h_copy_rdma(sizeof(*info), vport->liobn, data_token, | ||
354 | vport->riobn, remote_buffer); | ||
355 | |||
356 | dma_free_coherent(target->dev, sizeof(*info), info, data_token); | ||
357 | |||
358 | if (err != H_SUCCESS) { | ||
359 | eprintk("Error sending adapter info %d\n", err); | ||
360 | return 1; | ||
361 | } | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static void process_login(struct iu_entry *iue) | ||
367 | { | ||
368 | union viosrp_iu *iu = vio_iu(iue); | ||
369 | struct srp_login_rsp *rsp = &iu->srp.login_rsp; | ||
370 | uint64_t tag = iu->srp.rsp.tag; | ||
371 | |||
372 | /* TODO handle case that requested size is wrong and | ||
373 | * buffer format is wrong | ||
374 | */ | ||
375 | memset(iu, 0, sizeof(struct srp_login_rsp)); | ||
376 | rsp->opcode = SRP_LOGIN_RSP; | ||
377 | rsp->req_lim_delta = INITIAL_SRP_LIMIT; | ||
378 | rsp->tag = tag; | ||
379 | rsp->max_it_iu_len = sizeof(union srp_iu); | ||
380 | rsp->max_ti_iu_len = sizeof(union srp_iu); | ||
381 | /* direct and indirect */ | ||
382 | rsp->buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; | ||
383 | |||
384 | send_iu(iue, sizeof(*rsp), VIOSRP_SRP_FORMAT); | ||
385 | } | ||
386 | |||
387 | static inline void queue_cmd(struct iu_entry *iue) | ||
388 | { | ||
389 | struct srp_target *target = iue->target; | ||
390 | unsigned long flags; | ||
391 | |||
392 | spin_lock_irqsave(&target->lock, flags); | ||
393 | list_add_tail(&iue->ilist, &target->cmd_queue); | ||
394 | spin_unlock_irqrestore(&target->lock, flags); | ||
395 | } | ||
396 | |||
397 | static int process_tsk_mgmt(struct iu_entry *iue) | ||
398 | { | ||
399 | union viosrp_iu *iu = vio_iu(iue); | ||
400 | int fn; | ||
401 | |||
402 | dprintk("%p %u\n", iue, iu->srp.tsk_mgmt.tsk_mgmt_func); | ||
403 | |||
404 | switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { | ||
405 | case SRP_TSK_ABORT_TASK: | ||
406 | fn = ABORT_TASK; | ||
407 | break; | ||
408 | case SRP_TSK_ABORT_TASK_SET: | ||
409 | fn = ABORT_TASK_SET; | ||
410 | break; | ||
411 | case SRP_TSK_CLEAR_TASK_SET: | ||
412 | fn = CLEAR_TASK_SET; | ||
413 | break; | ||
414 | case SRP_TSK_LUN_RESET: | ||
415 | fn = LOGICAL_UNIT_RESET; | ||
416 | break; | ||
417 | case SRP_TSK_CLEAR_ACA: | ||
418 | fn = CLEAR_ACA; | ||
419 | break; | ||
420 | default: | ||
421 | fn = 0; | ||
422 | } | ||
423 | if (fn) | ||
424 | scsi_tgt_tsk_mgmt_request(iue->target->shost, fn, | ||
425 | iu->srp.tsk_mgmt.task_tag, | ||
426 | (struct scsi_lun *) &iu->srp.tsk_mgmt.lun, | ||
427 | iue); | ||
428 | else | ||
429 | send_rsp(iue, NULL, ILLEGAL_REQUEST, 0x20); | ||
430 | |||
431 | return !fn; | ||
432 | } | ||
433 | |||
434 | static int process_mad_iu(struct iu_entry *iue) | ||
435 | { | ||
436 | union viosrp_iu *iu = vio_iu(iue); | ||
437 | struct viosrp_adapter_info *info; | ||
438 | struct viosrp_host_config *conf; | ||
439 | |||
440 | switch (iu->mad.empty_iu.common.type) { | ||
441 | case VIOSRP_EMPTY_IU_TYPE: | ||
442 | eprintk("%s\n", "Unsupported EMPTY MAD IU"); | ||
443 | break; | ||
444 | case VIOSRP_ERROR_LOG_TYPE: | ||
445 | eprintk("%s\n", "Unsupported ERROR LOG MAD IU"); | ||
446 | iu->mad.error_log.common.status = 1; | ||
447 | send_iu(iue, sizeof(iu->mad.error_log), VIOSRP_MAD_FORMAT); | ||
448 | break; | ||
449 | case VIOSRP_ADAPTER_INFO_TYPE: | ||
450 | info = &iu->mad.adapter_info; | ||
451 | info->common.status = send_adapter_info(iue, info->buffer, | ||
452 | info->common.length); | ||
453 | send_iu(iue, sizeof(*info), VIOSRP_MAD_FORMAT); | ||
454 | break; | ||
455 | case VIOSRP_HOST_CONFIG_TYPE: | ||
456 | conf = &iu->mad.host_config; | ||
457 | conf->common.status = 1; | ||
458 | send_iu(iue, sizeof(*conf), VIOSRP_MAD_FORMAT); | ||
459 | break; | ||
460 | default: | ||
461 | eprintk("Unknown type %u\n", iu->srp.rsp.opcode); | ||
462 | } | ||
463 | |||
464 | return 1; | ||
465 | } | ||
466 | |||
467 | static int process_srp_iu(struct iu_entry *iue) | ||
468 | { | ||
469 | union viosrp_iu *iu = vio_iu(iue); | ||
470 | int done = 1; | ||
471 | u8 opcode = iu->srp.rsp.opcode; | ||
472 | |||
473 | switch (opcode) { | ||
474 | case SRP_LOGIN_REQ: | ||
475 | process_login(iue); | ||
476 | break; | ||
477 | case SRP_TSK_MGMT: | ||
478 | done = process_tsk_mgmt(iue); | ||
479 | break; | ||
480 | case SRP_CMD: | ||
481 | queue_cmd(iue); | ||
482 | done = 0; | ||
483 | break; | ||
484 | case SRP_LOGIN_RSP: | ||
485 | case SRP_I_LOGOUT: | ||
486 | case SRP_T_LOGOUT: | ||
487 | case SRP_RSP: | ||
488 | case SRP_CRED_REQ: | ||
489 | case SRP_CRED_RSP: | ||
490 | case SRP_AER_REQ: | ||
491 | case SRP_AER_RSP: | ||
492 | eprintk("Unsupported type %u\n", opcode); | ||
493 | break; | ||
494 | default: | ||
495 | eprintk("Unknown type %u\n", opcode); | ||
496 | } | ||
497 | |||
498 | return done; | ||
499 | } | ||
500 | |||
501 | static void process_iu(struct viosrp_crq *crq, struct srp_target *target) | ||
502 | { | ||
503 | struct vio_port *vport = target_to_port(target); | ||
504 | struct iu_entry *iue; | ||
505 | long err, done; | ||
506 | |||
507 | iue = srp_iu_get(target); | ||
508 | if (!iue) { | ||
509 | eprintk("Error getting IU from pool, %p\n", target); | ||
510 | return; | ||
511 | } | ||
512 | |||
513 | iue->remote_token = crq->IU_data_ptr; | ||
514 | |||
515 | err = h_copy_rdma(crq->IU_length, vport->riobn, | ||
516 | iue->remote_token, vport->liobn, iue->sbuf->dma); | ||
517 | |||
518 | if (err != H_SUCCESS) { | ||
519 | eprintk("%ld transferring data error %p\n", err, iue); | ||
520 | done = 1; | ||
521 | goto out; | ||
522 | } | ||
523 | |||
524 | if (crq->format == VIOSRP_MAD_FORMAT) | ||
525 | done = process_mad_iu(iue); | ||
526 | else | ||
527 | done = process_srp_iu(iue); | ||
528 | out: | ||
529 | if (done) | ||
530 | srp_iu_put(iue); | ||
531 | } | ||
532 | |||
533 | static irqreturn_t ibmvstgt_interrupt(int irq, void *data) | ||
534 | { | ||
535 | struct srp_target *target = (struct srp_target *) data; | ||
536 | struct vio_port *vport = target_to_port(target); | ||
537 | |||
538 | vio_disable_interrupts(vport->dma_dev); | ||
539 | queue_work(vtgtd, &vport->crq_work); | ||
540 | |||
541 | return IRQ_HANDLED; | ||
542 | } | ||
543 | |||
544 | static int crq_queue_create(struct crq_queue *queue, struct srp_target *target) | ||
545 | { | ||
546 | int err; | ||
547 | struct vio_port *vport = target_to_port(target); | ||
548 | |||
549 | queue->msgs = (struct viosrp_crq *) get_zeroed_page(GFP_KERNEL); | ||
550 | if (!queue->msgs) | ||
551 | goto malloc_failed; | ||
552 | queue->size = PAGE_SIZE / sizeof(*queue->msgs); | ||
553 | |||
554 | queue->msg_token = dma_map_single(target->dev, queue->msgs, | ||
555 | queue->size * sizeof(*queue->msgs), | ||
556 | DMA_BIDIRECTIONAL); | ||
557 | |||
558 | if (dma_mapping_error(queue->msg_token)) | ||
559 | goto map_failed; | ||
560 | |||
561 | err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token, | ||
562 | PAGE_SIZE); | ||
563 | |||
564 | /* If the adapter was left active for some reason (like kexec) | ||
565 | * try freeing and re-registering | ||
566 | */ | ||
567 | if (err == H_RESOURCE) { | ||
568 | do { | ||
569 | err = h_free_crq(vport->dma_dev->unit_address); | ||
570 | } while (err == H_BUSY || H_IS_LONG_BUSY(err)); | ||
571 | |||
572 | err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token, | ||
573 | PAGE_SIZE); | ||
574 | } | ||
575 | |||
576 | if (err != H_SUCCESS && err != 2) { | ||
577 | eprintk("Error 0x%x opening virtual adapter\n", err); | ||
578 | goto reg_crq_failed; | ||
579 | } | ||
580 | |||
581 | err = request_irq(vport->dma_dev->irq, &ibmvstgt_interrupt, | ||
582 | SA_INTERRUPT, "ibmvstgt", target); | ||
583 | if (err) | ||
584 | goto req_irq_failed; | ||
585 | |||
586 | vio_enable_interrupts(vport->dma_dev); | ||
587 | |||
588 | h_send_crq(vport->dma_dev->unit_address, 0xC001000000000000, 0); | ||
589 | |||
590 | queue->cur = 0; | ||
591 | spin_lock_init(&queue->lock); | ||
592 | |||
593 | return 0; | ||
594 | |||
595 | req_irq_failed: | ||
596 | do { | ||
597 | err = h_free_crq(vport->dma_dev->unit_address); | ||
598 | } while (err == H_BUSY || H_IS_LONG_BUSY(err)); | ||
599 | |||
600 | reg_crq_failed: | ||
601 | dma_unmap_single(target->dev, queue->msg_token, | ||
602 | queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL); | ||
603 | map_failed: | ||
604 | free_page((unsigned long) queue->msgs); | ||
605 | |||
606 | malloc_failed: | ||
607 | return -ENOMEM; | ||
608 | } | ||
609 | |||
610 | static void crq_queue_destroy(struct srp_target *target) | ||
611 | { | ||
612 | struct vio_port *vport = target_to_port(target); | ||
613 | struct crq_queue *queue = &vport->crq_queue; | ||
614 | int err; | ||
615 | |||
616 | free_irq(vport->dma_dev->irq, target); | ||
617 | do { | ||
618 | err = h_free_crq(vport->dma_dev->unit_address); | ||
619 | } while (err == H_BUSY || H_IS_LONG_BUSY(err)); | ||
620 | |||
621 | dma_unmap_single(target->dev, queue->msg_token, | ||
622 | queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL); | ||
623 | |||
624 | free_page((unsigned long) queue->msgs); | ||
625 | } | ||
626 | |||
627 | static void process_crq(struct viosrp_crq *crq, struct srp_target *target) | ||
628 | { | ||
629 | struct vio_port *vport = target_to_port(target); | ||
630 | dprintk("%x %x\n", crq->valid, crq->format); | ||
631 | |||
632 | switch (crq->valid) { | ||
633 | case 0xC0: | ||
634 | /* initialization */ | ||
635 | switch (crq->format) { | ||
636 | case 0x01: | ||
637 | h_send_crq(vport->dma_dev->unit_address, | ||
638 | 0xC002000000000000, 0); | ||
639 | break; | ||
640 | case 0x02: | ||
641 | break; | ||
642 | default: | ||
643 | eprintk("Unknown format %u\n", crq->format); | ||
644 | } | ||
645 | break; | ||
646 | case 0xFF: | ||
647 | /* transport event */ | ||
648 | break; | ||
649 | case 0x80: | ||
650 | /* real payload */ | ||
651 | switch (crq->format) { | ||
652 | case VIOSRP_SRP_FORMAT: | ||
653 | case VIOSRP_MAD_FORMAT: | ||
654 | process_iu(crq, target); | ||
655 | break; | ||
656 | case VIOSRP_OS400_FORMAT: | ||
657 | case VIOSRP_AIX_FORMAT: | ||
658 | case VIOSRP_LINUX_FORMAT: | ||
659 | case VIOSRP_INLINE_FORMAT: | ||
660 | eprintk("Unsupported format %u\n", crq->format); | ||
661 | break; | ||
662 | default: | ||
663 | eprintk("Unknown format %u\n", crq->format); | ||
664 | } | ||
665 | break; | ||
666 | default: | ||
667 | eprintk("unknown message type 0x%02x!?\n", crq->valid); | ||
668 | } | ||
669 | } | ||
670 | |||
671 | static inline struct viosrp_crq *next_crq(struct crq_queue *queue) | ||
672 | { | ||
673 | struct viosrp_crq *crq; | ||
674 | unsigned long flags; | ||
675 | |||
676 | spin_lock_irqsave(&queue->lock, flags); | ||
677 | crq = &queue->msgs[queue->cur]; | ||
678 | if (crq->valid & 0x80) { | ||
679 | if (++queue->cur == queue->size) | ||
680 | queue->cur = 0; | ||
681 | } else | ||
682 | crq = NULL; | ||
683 | spin_unlock_irqrestore(&queue->lock, flags); | ||
684 | |||
685 | return crq; | ||
686 | } | ||
687 | |||
688 | static void handle_crq(void *data) | ||
689 | { | ||
690 | struct srp_target *target = (struct srp_target *) data; | ||
691 | struct vio_port *vport = target_to_port(target); | ||
692 | struct viosrp_crq *crq; | ||
693 | int done = 0; | ||
694 | |||
695 | while (!done) { | ||
696 | while ((crq = next_crq(&vport->crq_queue)) != NULL) { | ||
697 | process_crq(crq, target); | ||
698 | crq->valid = 0x00; | ||
699 | } | ||
700 | |||
701 | vio_enable_interrupts(vport->dma_dev); | ||
702 | |||
703 | crq = next_crq(&vport->crq_queue); | ||
704 | if (crq) { | ||
705 | vio_disable_interrupts(vport->dma_dev); | ||
706 | process_crq(crq, target); | ||
707 | crq->valid = 0x00; | ||
708 | } else | ||
709 | done = 1; | ||
710 | } | ||
711 | |||
712 | handle_cmd_queue(target); | ||
713 | } | ||
714 | |||
715 | |||
716 | static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc) | ||
717 | { | ||
718 | unsigned long flags; | ||
719 | struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; | ||
720 | struct srp_target *target = iue->target; | ||
721 | |||
722 | dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]); | ||
723 | |||
724 | spin_lock_irqsave(&target->lock, flags); | ||
725 | list_del(&iue->ilist); | ||
726 | spin_unlock_irqrestore(&target->lock, flags); | ||
727 | |||
728 | srp_iu_put(iue); | ||
729 | |||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | static int ibmvstgt_tsk_mgmt_response(u64 mid, int result) | ||
734 | { | ||
735 | struct iu_entry *iue = (struct iu_entry *) ((void *) mid); | ||
736 | union viosrp_iu *iu = vio_iu(iue); | ||
737 | unsigned char status, asc; | ||
738 | |||
739 | eprintk("%p %d\n", iue, result); | ||
740 | status = NO_SENSE; | ||
741 | asc = 0; | ||
742 | |||
743 | switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { | ||
744 | case SRP_TSK_ABORT_TASK: | ||
745 | asc = 0x14; | ||
746 | if (result) | ||
747 | status = ABORTED_COMMAND; | ||
748 | break; | ||
749 | default: | ||
750 | break; | ||
751 | } | ||
752 | |||
753 | send_rsp(iue, NULL, status, asc); | ||
754 | srp_iu_put(iue); | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | static ssize_t system_id_show(struct class_device *cdev, char *buf) | ||
760 | { | ||
761 | return snprintf(buf, PAGE_SIZE, "%s\n", system_id); | ||
762 | } | ||
763 | |||
764 | static ssize_t partition_number_show(struct class_device *cdev, char *buf) | ||
765 | { | ||
766 | return snprintf(buf, PAGE_SIZE, "%x\n", partition_number); | ||
767 | } | ||
768 | |||
769 | static ssize_t unit_address_show(struct class_device *cdev, char *buf) | ||
770 | { | ||
771 | struct Scsi_Host *shost = class_to_shost(cdev); | ||
772 | struct srp_target *target = host_to_srp_target(shost); | ||
773 | struct vio_port *vport = target_to_port(target); | ||
774 | return snprintf(buf, PAGE_SIZE, "%x\n", vport->dma_dev->unit_address); | ||
775 | } | ||
776 | |||
777 | static CLASS_DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL); | ||
778 | static CLASS_DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL); | ||
779 | static CLASS_DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL); | ||
780 | |||
781 | static struct class_device_attribute *ibmvstgt_attrs[] = { | ||
782 | &class_device_attr_system_id, | ||
783 | &class_device_attr_partition_number, | ||
784 | &class_device_attr_unit_address, | ||
785 | NULL, | ||
786 | }; | ||
787 | |||
788 | static struct scsi_host_template ibmvstgt_sht = { | ||
789 | .name = TGT_NAME, | ||
790 | .module = THIS_MODULE, | ||
791 | .can_queue = INITIAL_SRP_LIMIT, | ||
792 | .sg_tablesize = SG_ALL, | ||
793 | .use_clustering = DISABLE_CLUSTERING, | ||
794 | .max_sectors = DEFAULT_MAX_SECTORS, | ||
795 | .transfer_response = ibmvstgt_cmd_done, | ||
796 | .transfer_data = ibmvstgt_transfer_data, | ||
797 | .eh_abort_handler = ibmvstgt_eh_abort_handler, | ||
798 | .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response, | ||
799 | .shost_attrs = ibmvstgt_attrs, | ||
800 | .proc_name = TGT_NAME, | ||
801 | }; | ||
802 | |||
803 | static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) | ||
804 | { | ||
805 | struct Scsi_Host *shost; | ||
806 | struct srp_target *target; | ||
807 | struct vio_port *vport; | ||
808 | unsigned int *dma, dma_size; | ||
809 | int err = -ENOMEM; | ||
810 | |||
811 | vport = kzalloc(sizeof(struct vio_port), GFP_KERNEL); | ||
812 | if (!vport) | ||
813 | return err; | ||
814 | shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target)); | ||
815 | if (!shost) | ||
816 | goto free_vport; | ||
817 | err = scsi_tgt_alloc_queue(shost); | ||
818 | if (err) | ||
819 | goto put_host; | ||
820 | |||
821 | target = host_to_srp_target(shost); | ||
822 | target->shost = shost; | ||
823 | vport->dma_dev = dev; | ||
824 | target->ldata = vport; | ||
825 | err = srp_target_alloc(target, &dev->dev, INITIAL_SRP_LIMIT, | ||
826 | SRP_MAX_IU_LEN); | ||
827 | if (err) | ||
828 | goto put_host; | ||
829 | |||
830 | dma = (unsigned int *) vio_get_attribute(dev, "ibm,my-dma-window", | ||
831 | &dma_size); | ||
832 | if (!dma || dma_size != 40) { | ||
833 | eprintk("Couldn't get window property %d\n", dma_size); | ||
834 | err = -EIO; | ||
835 | goto free_srp_target; | ||
836 | } | ||
837 | vport->liobn = dma[0]; | ||
838 | vport->riobn = dma[5]; | ||
839 | |||
840 | INIT_WORK(&vport->crq_work, handle_crq, target); | ||
841 | |||
842 | err = crq_queue_create(&vport->crq_queue, target); | ||
843 | if (err) | ||
844 | goto free_srp_target; | ||
845 | |||
846 | err = scsi_add_host(shost, target->dev); | ||
847 | if (err) | ||
848 | goto destroy_queue; | ||
849 | return 0; | ||
850 | |||
851 | destroy_queue: | ||
852 | crq_queue_destroy(target); | ||
853 | free_srp_target: | ||
854 | srp_target_free(target); | ||
855 | put_host: | ||
856 | scsi_host_put(shost); | ||
857 | free_vport: | ||
858 | kfree(vport); | ||
859 | return err; | ||
860 | } | ||
861 | |||
862 | static int ibmvstgt_remove(struct vio_dev *dev) | ||
863 | { | ||
864 | struct srp_target *target = (struct srp_target *) dev->dev.driver_data; | ||
865 | struct Scsi_Host *shost = target->shost; | ||
866 | struct vio_port *vport = target->ldata; | ||
867 | |||
868 | crq_queue_destroy(target); | ||
869 | scsi_remove_host(shost); | ||
870 | scsi_tgt_free_queue(shost); | ||
871 | srp_target_free(target); | ||
872 | kfree(vport); | ||
873 | scsi_host_put(shost); | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | static struct vio_device_id ibmvstgt_device_table[] __devinitdata = { | ||
878 | {"v-scsi-host", "IBM,v-scsi-host"}, | ||
879 | {"",""} | ||
880 | }; | ||
881 | |||
882 | MODULE_DEVICE_TABLE(vio, ibmvstgt_device_table); | ||
883 | |||
884 | static struct vio_driver ibmvstgt_driver = { | ||
885 | .id_table = ibmvstgt_device_table, | ||
886 | .probe = ibmvstgt_probe, | ||
887 | .remove = ibmvstgt_remove, | ||
888 | .driver = { | ||
889 | .name = "ibmvscsis", | ||
890 | .owner = THIS_MODULE, | ||
891 | } | ||
892 | }; | ||
893 | |||
894 | static int get_system_info(void) | ||
895 | { | ||
896 | struct device_node *rootdn; | ||
897 | const char *id, *model, *name; | ||
898 | unsigned int *num; | ||
899 | |||
900 | rootdn = find_path_device("/"); | ||
901 | if (!rootdn) | ||
902 | return -ENOENT; | ||
903 | |||
904 | model = get_property(rootdn, "model", NULL); | ||
905 | id = get_property(rootdn, "system-id", NULL); | ||
906 | if (model && id) | ||
907 | snprintf(system_id, sizeof(system_id), "%s-%s", model, id); | ||
908 | |||
909 | name = get_property(rootdn, "ibm,partition-name", NULL); | ||
910 | if (name) | ||
911 | strncpy(partition_name, name, sizeof(partition_name)); | ||
912 | |||
913 | num = (unsigned int *) get_property(rootdn, "ibm,partition-no", NULL); | ||
914 | if (num) | ||
915 | partition_number = *num; | ||
916 | |||
917 | return 0; | ||
918 | } | ||
919 | |||
920 | static int ibmvstgt_init(void) | ||
921 | { | ||
922 | int err = -ENOMEM; | ||
923 | |||
924 | printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n"); | ||
925 | |||
926 | vtgtd = create_workqueue("ibmvtgtd"); | ||
927 | if (!vtgtd) | ||
928 | return err; | ||
929 | |||
930 | err = get_system_info(); | ||
931 | if (err) | ||
932 | goto destroy_wq; | ||
933 | |||
934 | err = vio_register_driver(&ibmvstgt_driver); | ||
935 | if (err) | ||
936 | goto destroy_wq; | ||
937 | |||
938 | return 0; | ||
939 | |||
940 | destroy_wq: | ||
941 | destroy_workqueue(vtgtd); | ||
942 | return err; | ||
943 | } | ||
944 | |||
945 | static void ibmvstgt_exit(void) | ||
946 | { | ||
947 | printk("Unregister IBM virtual SCSI driver\n"); | ||
948 | |||
949 | destroy_workqueue(vtgtd); | ||
950 | vio_unregister_driver(&ibmvstgt_driver); | ||
951 | } | ||
952 | |||
953 | MODULE_DESCRIPTION("IBM Virtual SCSI Target"); | ||
954 | MODULE_AUTHOR("Santiago Leon"); | ||
955 | MODULE_LICENSE("GPL"); | ||
956 | |||
957 | module_init(ibmvstgt_init); | ||
958 | module_exit(ibmvstgt_exit); | ||
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index afed293dd7b9..f160357e37a6 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c | |||
@@ -170,7 +170,7 @@ static int setup_debug = 0; | |||
170 | static void i91uSCBPost(BYTE * pHcb, BYTE * pScb); | 170 | static void i91uSCBPost(BYTE * pHcb, BYTE * pScb); |
171 | 171 | ||
172 | /* PCI Devices supported by this driver */ | 172 | /* PCI Devices supported by this driver */ |
173 | static struct pci_device_id i91u_pci_devices[] __devinitdata = { | 173 | static struct pci_device_id i91u_pci_devices[] = { |
174 | { PCI_VENDOR_ID_INIT, I950_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 174 | { PCI_VENDOR_ID_INIT, I950_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
175 | { PCI_VENDOR_ID_INIT, I940_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 175 | { PCI_VENDOR_ID_INIT, I940_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
176 | { PCI_VENDOR_ID_INIT, I935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | 176 | { PCI_VENDOR_ID_INIT, I935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, |
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index d51c3e764bb0..ccd4dafce8e2 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -79,7 +79,6 @@ | |||
79 | #include <scsi/scsi_tcq.h> | 79 | #include <scsi/scsi_tcq.h> |
80 | #include <scsi/scsi_eh.h> | 80 | #include <scsi/scsi_eh.h> |
81 | #include <scsi/scsi_cmnd.h> | 81 | #include <scsi/scsi_cmnd.h> |
82 | #include <scsi/scsi_transport.h> | ||
83 | #include "ipr.h" | 82 | #include "ipr.h" |
84 | 83 | ||
85 | /* | 84 | /* |
@@ -98,7 +97,7 @@ static DEFINE_SPINLOCK(ipr_driver_lock); | |||
98 | 97 | ||
99 | /* This table describes the differences between DMA controller chips */ | 98 | /* This table describes the differences between DMA controller chips */ |
100 | static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { | 99 | static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { |
101 | { /* Gemstone, Citrine, and Obsidian */ | 100 | { /* Gemstone, Citrine, Obsidian, and Obsidian-E */ |
102 | .mailbox = 0x0042C, | 101 | .mailbox = 0x0042C, |
103 | .cache_line_size = 0x20, | 102 | .cache_line_size = 0x20, |
104 | { | 103 | { |
@@ -135,6 +134,7 @@ static const struct ipr_chip_t ipr_chip[] = { | |||
135 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, &ipr_chip_cfg[0] }, | 134 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, &ipr_chip_cfg[0] }, |
136 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, &ipr_chip_cfg[0] }, | 135 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, &ipr_chip_cfg[0] }, |
137 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, &ipr_chip_cfg[0] }, | 136 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, &ipr_chip_cfg[0] }, |
137 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, &ipr_chip_cfg[0] }, | ||
138 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, &ipr_chip_cfg[1] }, | 138 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, &ipr_chip_cfg[1] }, |
139 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, &ipr_chip_cfg[1] } | 139 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, &ipr_chip_cfg[1] } |
140 | }; | 140 | }; |
@@ -1249,19 +1249,23 @@ static void ipr_log_array_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1249 | 1249 | ||
1250 | /** | 1250 | /** |
1251 | * ipr_log_hex_data - Log additional hex IOA error data. | 1251 | * ipr_log_hex_data - Log additional hex IOA error data. |
1252 | * @ioa_cfg: ioa config struct | ||
1252 | * @data: IOA error data | 1253 | * @data: IOA error data |
1253 | * @len: data length | 1254 | * @len: data length |
1254 | * | 1255 | * |
1255 | * Return value: | 1256 | * Return value: |
1256 | * none | 1257 | * none |
1257 | **/ | 1258 | **/ |
1258 | static void ipr_log_hex_data(u32 *data, int len) | 1259 | static void ipr_log_hex_data(struct ipr_ioa_cfg *ioa_cfg, u32 *data, int len) |
1259 | { | 1260 | { |
1260 | int i; | 1261 | int i; |
1261 | 1262 | ||
1262 | if (len == 0) | 1263 | if (len == 0) |
1263 | return; | 1264 | return; |
1264 | 1265 | ||
1266 | if (ioa_cfg->log_level <= IPR_DEFAULT_LOG_LEVEL) | ||
1267 | len = min_t(int, len, IPR_DEFAULT_MAX_ERROR_DUMP); | ||
1268 | |||
1265 | for (i = 0; i < len / 4; i += 4) { | 1269 | for (i = 0; i < len / 4; i += 4) { |
1266 | ipr_err("%08X: %08X %08X %08X %08X\n", i*4, | 1270 | ipr_err("%08X: %08X %08X %08X %08X\n", i*4, |
1267 | be32_to_cpu(data[i]), | 1271 | be32_to_cpu(data[i]), |
@@ -1290,7 +1294,7 @@ static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1290 | ipr_err("%s\n", error->failure_reason); | 1294 | ipr_err("%s\n", error->failure_reason); |
1291 | ipr_err("Remote Adapter VPD:\n"); | 1295 | ipr_err("Remote Adapter VPD:\n"); |
1292 | ipr_log_ext_vpd(&error->vpd); | 1296 | ipr_log_ext_vpd(&error->vpd); |
1293 | ipr_log_hex_data(error->data, | 1297 | ipr_log_hex_data(ioa_cfg, error->data, |
1294 | be32_to_cpu(hostrcb->hcam.length) - | 1298 | be32_to_cpu(hostrcb->hcam.length) - |
1295 | (offsetof(struct ipr_hostrcb_error, u) + | 1299 | (offsetof(struct ipr_hostrcb_error, u) + |
1296 | offsetof(struct ipr_hostrcb_type_17_error, data))); | 1300 | offsetof(struct ipr_hostrcb_type_17_error, data))); |
@@ -1315,12 +1319,225 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1315 | ipr_err("%s\n", error->failure_reason); | 1319 | ipr_err("%s\n", error->failure_reason); |
1316 | ipr_err("Remote Adapter VPD:\n"); | 1320 | ipr_err("Remote Adapter VPD:\n"); |
1317 | ipr_log_vpd(&error->vpd); | 1321 | ipr_log_vpd(&error->vpd); |
1318 | ipr_log_hex_data(error->data, | 1322 | ipr_log_hex_data(ioa_cfg, error->data, |
1319 | be32_to_cpu(hostrcb->hcam.length) - | 1323 | be32_to_cpu(hostrcb->hcam.length) - |
1320 | (offsetof(struct ipr_hostrcb_error, u) + | 1324 | (offsetof(struct ipr_hostrcb_error, u) + |
1321 | offsetof(struct ipr_hostrcb_type_07_error, data))); | 1325 | offsetof(struct ipr_hostrcb_type_07_error, data))); |
1322 | } | 1326 | } |
1323 | 1327 | ||
1328 | static const struct { | ||
1329 | u8 active; | ||
1330 | char *desc; | ||
1331 | } path_active_desc[] = { | ||
1332 | { IPR_PATH_NO_INFO, "Path" }, | ||
1333 | { IPR_PATH_ACTIVE, "Active path" }, | ||
1334 | { IPR_PATH_NOT_ACTIVE, "Inactive path" } | ||
1335 | }; | ||
1336 | |||
1337 | static const struct { | ||
1338 | u8 state; | ||
1339 | char *desc; | ||
1340 | } path_state_desc[] = { | ||
1341 | { IPR_PATH_STATE_NO_INFO, "has no path state information available" }, | ||
1342 | { IPR_PATH_HEALTHY, "is healthy" }, | ||
1343 | { IPR_PATH_DEGRADED, "is degraded" }, | ||
1344 | { IPR_PATH_FAILED, "is failed" } | ||
1345 | }; | ||
1346 | |||
1347 | /** | ||
1348 | * ipr_log_fabric_path - Log a fabric path error | ||
1349 | * @hostrcb: hostrcb struct | ||
1350 | * @fabric: fabric descriptor | ||
1351 | * | ||
1352 | * Return value: | ||
1353 | * none | ||
1354 | **/ | ||
1355 | static void ipr_log_fabric_path(struct ipr_hostrcb *hostrcb, | ||
1356 | struct ipr_hostrcb_fabric_desc *fabric) | ||
1357 | { | ||
1358 | int i, j; | ||
1359 | u8 path_state = fabric->path_state; | ||
1360 | u8 active = path_state & IPR_PATH_ACTIVE_MASK; | ||
1361 | u8 state = path_state & IPR_PATH_STATE_MASK; | ||
1362 | |||
1363 | for (i = 0; i < ARRAY_SIZE(path_active_desc); i++) { | ||
1364 | if (path_active_desc[i].active != active) | ||
1365 | continue; | ||
1366 | |||
1367 | for (j = 0; j < ARRAY_SIZE(path_state_desc); j++) { | ||
1368 | if (path_state_desc[j].state != state) | ||
1369 | continue; | ||
1370 | |||
1371 | if (fabric->cascaded_expander == 0xff && fabric->phy == 0xff) { | ||
1372 | ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d\n", | ||
1373 | path_active_desc[i].desc, path_state_desc[j].desc, | ||
1374 | fabric->ioa_port); | ||
1375 | } else if (fabric->cascaded_expander == 0xff) { | ||
1376 | ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Phy=%d\n", | ||
1377 | path_active_desc[i].desc, path_state_desc[j].desc, | ||
1378 | fabric->ioa_port, fabric->phy); | ||
1379 | } else if (fabric->phy == 0xff) { | ||
1380 | ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d\n", | ||
1381 | path_active_desc[i].desc, path_state_desc[j].desc, | ||
1382 | fabric->ioa_port, fabric->cascaded_expander); | ||
1383 | } else { | ||
1384 | ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d, Phy=%d\n", | ||
1385 | path_active_desc[i].desc, path_state_desc[j].desc, | ||
1386 | fabric->ioa_port, fabric->cascaded_expander, fabric->phy); | ||
1387 | } | ||
1388 | return; | ||
1389 | } | ||
1390 | } | ||
1391 | |||
1392 | ipr_err("Path state=%02X IOA Port=%d Cascade=%d Phy=%d\n", path_state, | ||
1393 | fabric->ioa_port, fabric->cascaded_expander, fabric->phy); | ||
1394 | } | ||
1395 | |||
1396 | static const struct { | ||
1397 | u8 type; | ||
1398 | char *desc; | ||
1399 | } path_type_desc[] = { | ||
1400 | { IPR_PATH_CFG_IOA_PORT, "IOA port" }, | ||
1401 | { IPR_PATH_CFG_EXP_PORT, "Expander port" }, | ||
1402 | { IPR_PATH_CFG_DEVICE_PORT, "Device port" }, | ||
1403 | { IPR_PATH_CFG_DEVICE_LUN, "Device LUN" } | ||
1404 | }; | ||
1405 | |||
1406 | static const struct { | ||
1407 | u8 status; | ||
1408 | char *desc; | ||
1409 | } path_status_desc[] = { | ||
1410 | { IPR_PATH_CFG_NO_PROB, "Functional" }, | ||
1411 | { IPR_PATH_CFG_DEGRADED, "Degraded" }, | ||
1412 | { IPR_PATH_CFG_FAILED, "Failed" }, | ||
1413 | { IPR_PATH_CFG_SUSPECT, "Suspect" }, | ||
1414 | { IPR_PATH_NOT_DETECTED, "Missing" }, | ||
1415 | { IPR_PATH_INCORRECT_CONN, "Incorrectly connected" } | ||
1416 | }; | ||
1417 | |||
1418 | static const char *link_rate[] = { | ||
1419 | "unknown", | ||
1420 | "disabled", | ||
1421 | "phy reset problem", | ||
1422 | "spinup hold", | ||
1423 | "port selector", | ||
1424 | "unknown", | ||
1425 | "unknown", | ||
1426 | "unknown", | ||
1427 | "1.5Gbps", | ||
1428 | "3.0Gbps", | ||
1429 | "unknown", | ||
1430 | "unknown", | ||
1431 | "unknown", | ||
1432 | "unknown", | ||
1433 | "unknown", | ||
1434 | "unknown" | ||
1435 | }; | ||
1436 | |||
1437 | /** | ||
1438 | * ipr_log_path_elem - Log a fabric path element. | ||
1439 | * @hostrcb: hostrcb struct | ||
1440 | * @cfg: fabric path element struct | ||
1441 | * | ||
1442 | * Return value: | ||
1443 | * none | ||
1444 | **/ | ||
1445 | static void ipr_log_path_elem(struct ipr_hostrcb *hostrcb, | ||
1446 | struct ipr_hostrcb_config_element *cfg) | ||
1447 | { | ||
1448 | int i, j; | ||
1449 | u8 type = cfg->type_status & IPR_PATH_CFG_TYPE_MASK; | ||
1450 | u8 status = cfg->type_status & IPR_PATH_CFG_STATUS_MASK; | ||
1451 | |||
1452 | if (type == IPR_PATH_CFG_NOT_EXIST) | ||
1453 | return; | ||
1454 | |||
1455 | for (i = 0; i < ARRAY_SIZE(path_type_desc); i++) { | ||
1456 | if (path_type_desc[i].type != type) | ||
1457 | continue; | ||
1458 | |||
1459 | for (j = 0; j < ARRAY_SIZE(path_status_desc); j++) { | ||
1460 | if (path_status_desc[j].status != status) | ||
1461 | continue; | ||
1462 | |||
1463 | if (type == IPR_PATH_CFG_IOA_PORT) { | ||
1464 | ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, WWN=%08X%08X\n", | ||
1465 | path_status_desc[j].desc, path_type_desc[i].desc, | ||
1466 | cfg->phy, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1467 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1468 | } else { | ||
1469 | if (cfg->cascaded_expander == 0xff && cfg->phy == 0xff) { | ||
1470 | ipr_hcam_err(hostrcb, "%s %s: Link rate=%s, WWN=%08X%08X\n", | ||
1471 | path_status_desc[j].desc, path_type_desc[i].desc, | ||
1472 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1473 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1474 | } else if (cfg->cascaded_expander == 0xff) { | ||
1475 | ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, " | ||
1476 | "WWN=%08X%08X\n", path_status_desc[j].desc, | ||
1477 | path_type_desc[i].desc, cfg->phy, | ||
1478 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1479 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1480 | } else if (cfg->phy == 0xff) { | ||
1481 | ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Link rate=%s, " | ||
1482 | "WWN=%08X%08X\n", path_status_desc[j].desc, | ||
1483 | path_type_desc[i].desc, cfg->cascaded_expander, | ||
1484 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1485 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1486 | } else { | ||
1487 | ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Phy=%d, Link rate=%s " | ||
1488 | "WWN=%08X%08X\n", path_status_desc[j].desc, | ||
1489 | path_type_desc[i].desc, cfg->cascaded_expander, cfg->phy, | ||
1490 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1491 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1492 | } | ||
1493 | } | ||
1494 | return; | ||
1495 | } | ||
1496 | } | ||
1497 | |||
1498 | ipr_hcam_err(hostrcb, "Path element=%02X: Cascade=%d Phy=%d Link rate=%s " | ||
1499 | "WWN=%08X%08X\n", cfg->type_status, cfg->cascaded_expander, cfg->phy, | ||
1500 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
1501 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
1502 | } | ||
1503 | |||
1504 | /** | ||
1505 | * ipr_log_fabric_error - Log a fabric error. | ||
1506 | * @ioa_cfg: ioa config struct | ||
1507 | * @hostrcb: hostrcb struct | ||
1508 | * | ||
1509 | * Return value: | ||
1510 | * none | ||
1511 | **/ | ||
1512 | static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg, | ||
1513 | struct ipr_hostrcb *hostrcb) | ||
1514 | { | ||
1515 | struct ipr_hostrcb_type_20_error *error; | ||
1516 | struct ipr_hostrcb_fabric_desc *fabric; | ||
1517 | struct ipr_hostrcb_config_element *cfg; | ||
1518 | int i, add_len; | ||
1519 | |||
1520 | error = &hostrcb->hcam.u.error.u.type_20_error; | ||
1521 | error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; | ||
1522 | ipr_hcam_err(hostrcb, "%s\n", error->failure_reason); | ||
1523 | |||
1524 | add_len = be32_to_cpu(hostrcb->hcam.length) - | ||
1525 | (offsetof(struct ipr_hostrcb_error, u) + | ||
1526 | offsetof(struct ipr_hostrcb_type_20_error, desc)); | ||
1527 | |||
1528 | for (i = 0, fabric = error->desc; i < error->num_entries; i++) { | ||
1529 | ipr_log_fabric_path(hostrcb, fabric); | ||
1530 | for_each_fabric_cfg(fabric, cfg) | ||
1531 | ipr_log_path_elem(hostrcb, cfg); | ||
1532 | |||
1533 | add_len -= be16_to_cpu(fabric->length); | ||
1534 | fabric = (struct ipr_hostrcb_fabric_desc *) | ||
1535 | ((unsigned long)fabric + be16_to_cpu(fabric->length)); | ||
1536 | } | ||
1537 | |||
1538 | ipr_log_hex_data(ioa_cfg, (u32 *)fabric, add_len); | ||
1539 | } | ||
1540 | |||
1324 | /** | 1541 | /** |
1325 | * ipr_log_generic_error - Log an adapter error. | 1542 | * ipr_log_generic_error - Log an adapter error. |
1326 | * @ioa_cfg: ioa config struct | 1543 | * @ioa_cfg: ioa config struct |
@@ -1332,7 +1549,7 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1332 | static void ipr_log_generic_error(struct ipr_ioa_cfg *ioa_cfg, | 1549 | static void ipr_log_generic_error(struct ipr_ioa_cfg *ioa_cfg, |
1333 | struct ipr_hostrcb *hostrcb) | 1550 | struct ipr_hostrcb *hostrcb) |
1334 | { | 1551 | { |
1335 | ipr_log_hex_data(hostrcb->hcam.u.raw.data, | 1552 | ipr_log_hex_data(ioa_cfg, hostrcb->hcam.u.raw.data, |
1336 | be32_to_cpu(hostrcb->hcam.length)); | 1553 | be32_to_cpu(hostrcb->hcam.length)); |
1337 | } | 1554 | } |
1338 | 1555 | ||
@@ -1394,13 +1611,7 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, | |||
1394 | if (!ipr_error_table[error_index].log_hcam) | 1611 | if (!ipr_error_table[error_index].log_hcam) |
1395 | return; | 1612 | return; |
1396 | 1613 | ||
1397 | if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) { | 1614 | ipr_hcam_err(hostrcb, "%s\n", ipr_error_table[error_index].error); |
1398 | ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr, | ||
1399 | "%s\n", ipr_error_table[error_index].error); | ||
1400 | } else { | ||
1401 | dev_err(&ioa_cfg->pdev->dev, "%s\n", | ||
1402 | ipr_error_table[error_index].error); | ||
1403 | } | ||
1404 | 1615 | ||
1405 | /* Set indication we have logged an error */ | 1616 | /* Set indication we have logged an error */ |
1406 | ioa_cfg->errors_logged++; | 1617 | ioa_cfg->errors_logged++; |
@@ -1437,6 +1648,9 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, | |||
1437 | case IPR_HOST_RCB_OVERLAY_ID_17: | 1648 | case IPR_HOST_RCB_OVERLAY_ID_17: |
1438 | ipr_log_enhanced_dual_ioa_error(ioa_cfg, hostrcb); | 1649 | ipr_log_enhanced_dual_ioa_error(ioa_cfg, hostrcb); |
1439 | break; | 1650 | break; |
1651 | case IPR_HOST_RCB_OVERLAY_ID_20: | ||
1652 | ipr_log_fabric_error(ioa_cfg, hostrcb); | ||
1653 | break; | ||
1440 | case IPR_HOST_RCB_OVERLAY_ID_1: | 1654 | case IPR_HOST_RCB_OVERLAY_ID_1: |
1441 | case IPR_HOST_RCB_OVERLAY_ID_DEFAULT: | 1655 | case IPR_HOST_RCB_OVERLAY_ID_DEFAULT: |
1442 | default: | 1656 | default: |
@@ -2970,7 +3184,6 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg) | |||
2970 | struct ipr_dump *dump; | 3184 | struct ipr_dump *dump; |
2971 | unsigned long lock_flags = 0; | 3185 | unsigned long lock_flags = 0; |
2972 | 3186 | ||
2973 | ENTER; | ||
2974 | dump = kzalloc(sizeof(struct ipr_dump), GFP_KERNEL); | 3187 | dump = kzalloc(sizeof(struct ipr_dump), GFP_KERNEL); |
2975 | 3188 | ||
2976 | if (!dump) { | 3189 | if (!dump) { |
@@ -2997,7 +3210,6 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg) | |||
2997 | } | 3210 | } |
2998 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 3211 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
2999 | 3212 | ||
3000 | LEAVE; | ||
3001 | return 0; | 3213 | return 0; |
3002 | } | 3214 | } |
3003 | 3215 | ||
@@ -3574,6 +3786,12 @@ static int ipr_sata_reset(struct ata_port *ap, unsigned int *classes) | |||
3574 | 3786 | ||
3575 | ENTER; | 3787 | ENTER; |
3576 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | 3788 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); |
3789 | while(ioa_cfg->in_reset_reload) { | ||
3790 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
3791 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); | ||
3792 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
3793 | } | ||
3794 | |||
3577 | res = sata_port->res; | 3795 | res = sata_port->res; |
3578 | if (res) { | 3796 | if (res) { |
3579 | rc = ipr_device_reset(ioa_cfg, res); | 3797 | rc = ipr_device_reset(ioa_cfg, res); |
@@ -3637,6 +3855,10 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd) | |||
3637 | if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) { | 3855 | if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) { |
3638 | if (ipr_cmd->scsi_cmd) | 3856 | if (ipr_cmd->scsi_cmd) |
3639 | ipr_cmd->done = ipr_scsi_eh_done; | 3857 | ipr_cmd->done = ipr_scsi_eh_done; |
3858 | if (ipr_cmd->qc && !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) { | ||
3859 | ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT; | ||
3860 | ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED; | ||
3861 | } | ||
3640 | } | 3862 | } |
3641 | } | 3863 | } |
3642 | 3864 | ||
@@ -3771,7 +3993,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) | |||
3771 | */ | 3993 | */ |
3772 | if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead) | 3994 | if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead) |
3773 | return FAILED; | 3995 | return FAILED; |
3774 | if (!res || (!ipr_is_gscsi(res) && !ipr_is_vset_device(res))) | 3996 | if (!res || !ipr_is_gscsi(res)) |
3775 | return FAILED; | 3997 | return FAILED; |
3776 | 3998 | ||
3777 | list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { | 3999 | list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { |
@@ -4616,7 +4838,7 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd, | |||
4616 | * Return value: | 4838 | * Return value: |
4617 | * 0 on success / other on failure | 4839 | * 0 on success / other on failure |
4618 | **/ | 4840 | **/ |
4619 | int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) | 4841 | static int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) |
4620 | { | 4842 | { |
4621 | struct ipr_resource_entry *res; | 4843 | struct ipr_resource_entry *res; |
4622 | 4844 | ||
@@ -4649,40 +4871,6 @@ static const char * ipr_ioa_info(struct Scsi_Host *host) | |||
4649 | return buffer; | 4871 | return buffer; |
4650 | } | 4872 | } |
4651 | 4873 | ||
4652 | /** | ||
4653 | * ipr_scsi_timed_out - Handle scsi command timeout | ||
4654 | * @scsi_cmd: scsi command struct | ||
4655 | * | ||
4656 | * Return value: | ||
4657 | * EH_NOT_HANDLED | ||
4658 | **/ | ||
4659 | enum scsi_eh_timer_return ipr_scsi_timed_out(struct scsi_cmnd *scsi_cmd) | ||
4660 | { | ||
4661 | struct ipr_ioa_cfg *ioa_cfg; | ||
4662 | struct ipr_cmnd *ipr_cmd; | ||
4663 | unsigned long flags; | ||
4664 | |||
4665 | ENTER; | ||
4666 | spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags); | ||
4667 | ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata; | ||
4668 | |||
4669 | list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { | ||
4670 | if (ipr_cmd->qc && ipr_cmd->qc->scsicmd == scsi_cmd) { | ||
4671 | ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT; | ||
4672 | ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED; | ||
4673 | break; | ||
4674 | } | ||
4675 | } | ||
4676 | |||
4677 | spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags); | ||
4678 | LEAVE; | ||
4679 | return EH_NOT_HANDLED; | ||
4680 | } | ||
4681 | |||
4682 | static struct scsi_transport_template ipr_transport_template = { | ||
4683 | .eh_timed_out = ipr_scsi_timed_out | ||
4684 | }; | ||
4685 | |||
4686 | static struct scsi_host_template driver_template = { | 4874 | static struct scsi_host_template driver_template = { |
4687 | .module = THIS_MODULE, | 4875 | .module = THIS_MODULE, |
4688 | .name = "IPR", | 4876 | .name = "IPR", |
@@ -4777,6 +4965,12 @@ static void ipr_ata_post_internal(struct ata_queued_cmd *qc) | |||
4777 | unsigned long flags; | 4965 | unsigned long flags; |
4778 | 4966 | ||
4779 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); | 4967 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); |
4968 | while(ioa_cfg->in_reset_reload) { | ||
4969 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); | ||
4970 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); | ||
4971 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); | ||
4972 | } | ||
4973 | |||
4780 | list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { | 4974 | list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { |
4781 | if (ipr_cmd->qc == qc) { | 4975 | if (ipr_cmd->qc == qc) { |
4782 | ipr_device_reset(ioa_cfg, sata_port->res); | 4976 | ipr_device_reset(ioa_cfg, sata_port->res); |
@@ -6833,6 +7027,7 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) | |||
6833 | 7027 | ||
6834 | ioa_cfg->hostrcb[i]->hostrcb_dma = | 7028 | ioa_cfg->hostrcb[i]->hostrcb_dma = |
6835 | ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam); | 7029 | ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam); |
7030 | ioa_cfg->hostrcb[i]->ioa_cfg = ioa_cfg; | ||
6836 | list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q); | 7031 | list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q); |
6837 | } | 7032 | } |
6838 | 7033 | ||
@@ -7018,7 +7213,6 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, | |||
7018 | 7213 | ||
7019 | ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata; | 7214 | ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata; |
7020 | memset(ioa_cfg, 0, sizeof(struct ipr_ioa_cfg)); | 7215 | memset(ioa_cfg, 0, sizeof(struct ipr_ioa_cfg)); |
7021 | host->transportt = &ipr_transport_template; | ||
7022 | ata_host_init(&ioa_cfg->ata_host, &pdev->dev, | 7216 | ata_host_init(&ioa_cfg->ata_host, &pdev->dev, |
7023 | sata_port_info.flags, &ipr_sata_ops); | 7217 | sata_port_info.flags, &ipr_sata_ops); |
7024 | 7218 | ||
@@ -7352,12 +7546,24 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { | |||
7352 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, | 7546 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, |
7353 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, | 7547 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, |
7354 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | 7548 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, |
7549 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, | ||
7550 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, | ||
7551 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | ||
7355 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, | 7552 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, |
7356 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, | 7553 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, |
7357 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | 7554 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, |
7358 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, | 7555 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, |
7359 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, | 7556 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, |
7360 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | 7557 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, |
7558 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, | ||
7559 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, | ||
7560 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | ||
7561 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, | ||
7562 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B8, | ||
7563 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | ||
7564 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, | ||
7565 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, | ||
7566 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] }, | ||
7361 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, | 7567 | { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, |
7362 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, | 7568 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, |
7363 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, | 7569 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, |
@@ -7367,6 +7573,9 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { | |||
7367 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, | 7573 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, |
7368 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, | 7574 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F, |
7369 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, | 7575 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, |
7576 | { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, | ||
7577 | PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F, | ||
7578 | 0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] }, | ||
7370 | { } | 7579 | { } |
7371 | }; | 7580 | }; |
7372 | MODULE_DEVICE_TABLE(pci, ipr_pci_table); | 7581 | MODULE_DEVICE_TABLE(pci, ipr_pci_table); |
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 6d035283af08..9f62a1d4d511 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
@@ -37,8 +37,8 @@ | |||
37 | /* | 37 | /* |
38 | * Literals | 38 | * Literals |
39 | */ | 39 | */ |
40 | #define IPR_DRIVER_VERSION "2.2.0" | 40 | #define IPR_DRIVER_VERSION "2.3.0" |
41 | #define IPR_DRIVER_DATE "(September 25, 2006)" | 41 | #define IPR_DRIVER_DATE "(November 8, 2006)" |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding | 44 | * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding |
@@ -54,6 +54,8 @@ | |||
54 | */ | 54 | */ |
55 | #define IPR_NUM_BASE_CMD_BLKS 100 | 55 | #define IPR_NUM_BASE_CMD_BLKS 100 |
56 | 56 | ||
57 | #define PCI_DEVICE_ID_IBM_OBSIDIAN_E 0x0339 | ||
58 | |||
57 | #define IPR_SUBS_DEV_ID_2780 0x0264 | 59 | #define IPR_SUBS_DEV_ID_2780 0x0264 |
58 | #define IPR_SUBS_DEV_ID_5702 0x0266 | 60 | #define IPR_SUBS_DEV_ID_5702 0x0266 |
59 | #define IPR_SUBS_DEV_ID_5703 0x0278 | 61 | #define IPR_SUBS_DEV_ID_5703 0x0278 |
@@ -66,7 +68,11 @@ | |||
66 | #define IPR_SUBS_DEV_ID_571F 0x02D5 | 68 | #define IPR_SUBS_DEV_ID_571F 0x02D5 |
67 | #define IPR_SUBS_DEV_ID_572A 0x02C1 | 69 | #define IPR_SUBS_DEV_ID_572A 0x02C1 |
68 | #define IPR_SUBS_DEV_ID_572B 0x02C2 | 70 | #define IPR_SUBS_DEV_ID_572B 0x02C2 |
71 | #define IPR_SUBS_DEV_ID_572F 0x02C3 | ||
69 | #define IPR_SUBS_DEV_ID_575B 0x030D | 72 | #define IPR_SUBS_DEV_ID_575B 0x030D |
73 | #define IPR_SUBS_DEV_ID_575C 0x0338 | ||
74 | #define IPR_SUBS_DEV_ID_57B7 0x0360 | ||
75 | #define IPR_SUBS_DEV_ID_57B8 0x02C2 | ||
70 | 76 | ||
71 | #define IPR_NAME "ipr" | 77 | #define IPR_NAME "ipr" |
72 | 78 | ||
@@ -98,6 +104,7 @@ | |||
98 | #define IPR_IOASC_IOA_WAS_RESET 0x10000001 | 104 | #define IPR_IOASC_IOA_WAS_RESET 0x10000001 |
99 | #define IPR_IOASC_PCI_ACCESS_ERROR 0x10000002 | 105 | #define IPR_IOASC_PCI_ACCESS_ERROR 0x10000002 |
100 | 106 | ||
107 | #define IPR_DEFAULT_MAX_ERROR_DUMP 984 | ||
101 | #define IPR_NUM_LOG_HCAMS 2 | 108 | #define IPR_NUM_LOG_HCAMS 2 |
102 | #define IPR_NUM_CFG_CHG_HCAMS 2 | 109 | #define IPR_NUM_CFG_CHG_HCAMS 2 |
103 | #define IPR_NUM_HCAMS (IPR_NUM_LOG_HCAMS + IPR_NUM_CFG_CHG_HCAMS) | 110 | #define IPR_NUM_HCAMS (IPR_NUM_LOG_HCAMS + IPR_NUM_CFG_CHG_HCAMS) |
@@ -731,6 +738,64 @@ struct ipr_hostrcb_type_17_error { | |||
731 | u32 data[476]; | 738 | u32 data[476]; |
732 | }__attribute__((packed, aligned (4))); | 739 | }__attribute__((packed, aligned (4))); |
733 | 740 | ||
741 | struct ipr_hostrcb_config_element { | ||
742 | u8 type_status; | ||
743 | #define IPR_PATH_CFG_TYPE_MASK 0xF0 | ||
744 | #define IPR_PATH_CFG_NOT_EXIST 0x00 | ||
745 | #define IPR_PATH_CFG_IOA_PORT 0x10 | ||
746 | #define IPR_PATH_CFG_EXP_PORT 0x20 | ||
747 | #define IPR_PATH_CFG_DEVICE_PORT 0x30 | ||
748 | #define IPR_PATH_CFG_DEVICE_LUN 0x40 | ||
749 | |||
750 | #define IPR_PATH_CFG_STATUS_MASK 0x0F | ||
751 | #define IPR_PATH_CFG_NO_PROB 0x00 | ||
752 | #define IPR_PATH_CFG_DEGRADED 0x01 | ||
753 | #define IPR_PATH_CFG_FAILED 0x02 | ||
754 | #define IPR_PATH_CFG_SUSPECT 0x03 | ||
755 | #define IPR_PATH_NOT_DETECTED 0x04 | ||
756 | #define IPR_PATH_INCORRECT_CONN 0x05 | ||
757 | |||
758 | u8 cascaded_expander; | ||
759 | u8 phy; | ||
760 | u8 link_rate; | ||
761 | #define IPR_PHY_LINK_RATE_MASK 0x0F | ||
762 | |||
763 | __be32 wwid[2]; | ||
764 | }__attribute__((packed, aligned (4))); | ||
765 | |||
766 | struct ipr_hostrcb_fabric_desc { | ||
767 | __be16 length; | ||
768 | u8 ioa_port; | ||
769 | u8 cascaded_expander; | ||
770 | u8 phy; | ||
771 | u8 path_state; | ||
772 | #define IPR_PATH_ACTIVE_MASK 0xC0 | ||
773 | #define IPR_PATH_NO_INFO 0x00 | ||
774 | #define IPR_PATH_ACTIVE 0x40 | ||
775 | #define IPR_PATH_NOT_ACTIVE 0x80 | ||
776 | |||
777 | #define IPR_PATH_STATE_MASK 0x0F | ||
778 | #define IPR_PATH_STATE_NO_INFO 0x00 | ||
779 | #define IPR_PATH_HEALTHY 0x01 | ||
780 | #define IPR_PATH_DEGRADED 0x02 | ||
781 | #define IPR_PATH_FAILED 0x03 | ||
782 | |||
783 | __be16 num_entries; | ||
784 | struct ipr_hostrcb_config_element elem[1]; | ||
785 | }__attribute__((packed, aligned (4))); | ||
786 | |||
787 | #define for_each_fabric_cfg(fabric, cfg) \ | ||
788 | for (cfg = (fabric)->elem; \ | ||
789 | cfg < ((fabric)->elem + be16_to_cpu((fabric)->num_entries)); \ | ||
790 | cfg++) | ||
791 | |||
792 | struct ipr_hostrcb_type_20_error { | ||
793 | u8 failure_reason[64]; | ||
794 | u8 reserved[3]; | ||
795 | u8 num_entries; | ||
796 | struct ipr_hostrcb_fabric_desc desc[1]; | ||
797 | }__attribute__((packed, aligned (4))); | ||
798 | |||
734 | struct ipr_hostrcb_error { | 799 | struct ipr_hostrcb_error { |
735 | __be32 failing_dev_ioasc; | 800 | __be32 failing_dev_ioasc; |
736 | struct ipr_res_addr failing_dev_res_addr; | 801 | struct ipr_res_addr failing_dev_res_addr; |
@@ -747,6 +812,7 @@ struct ipr_hostrcb_error { | |||
747 | struct ipr_hostrcb_type_13_error type_13_error; | 812 | struct ipr_hostrcb_type_13_error type_13_error; |
748 | struct ipr_hostrcb_type_14_error type_14_error; | 813 | struct ipr_hostrcb_type_14_error type_14_error; |
749 | struct ipr_hostrcb_type_17_error type_17_error; | 814 | struct ipr_hostrcb_type_17_error type_17_error; |
815 | struct ipr_hostrcb_type_20_error type_20_error; | ||
750 | } u; | 816 | } u; |
751 | }__attribute__((packed, aligned (4))); | 817 | }__attribute__((packed, aligned (4))); |
752 | 818 | ||
@@ -786,6 +852,7 @@ struct ipr_hcam { | |||
786 | #define IPR_HOST_RCB_OVERLAY_ID_14 0x14 | 852 | #define IPR_HOST_RCB_OVERLAY_ID_14 0x14 |
787 | #define IPR_HOST_RCB_OVERLAY_ID_16 0x16 | 853 | #define IPR_HOST_RCB_OVERLAY_ID_16 0x16 |
788 | #define IPR_HOST_RCB_OVERLAY_ID_17 0x17 | 854 | #define IPR_HOST_RCB_OVERLAY_ID_17 0x17 |
855 | #define IPR_HOST_RCB_OVERLAY_ID_20 0x20 | ||
789 | #define IPR_HOST_RCB_OVERLAY_ID_DEFAULT 0xFF | 856 | #define IPR_HOST_RCB_OVERLAY_ID_DEFAULT 0xFF |
790 | 857 | ||
791 | u8 reserved1[3]; | 858 | u8 reserved1[3]; |
@@ -805,6 +872,7 @@ struct ipr_hostrcb { | |||
805 | struct ipr_hcam hcam; | 872 | struct ipr_hcam hcam; |
806 | dma_addr_t hostrcb_dma; | 873 | dma_addr_t hostrcb_dma; |
807 | struct list_head queue; | 874 | struct list_head queue; |
875 | struct ipr_ioa_cfg *ioa_cfg; | ||
808 | }; | 876 | }; |
809 | 877 | ||
810 | /* IPR smart dump table structures */ | 878 | /* IPR smart dump table structures */ |
@@ -1283,6 +1351,17 @@ struct ipr_ucode_image_header { | |||
1283 | } \ | 1351 | } \ |
1284 | } | 1352 | } |
1285 | 1353 | ||
1354 | #define ipr_hcam_err(hostrcb, fmt, ...) \ | ||
1355 | { \ | ||
1356 | if (ipr_is_device(&(hostrcb)->hcam.u.error.failing_dev_res_addr)) { \ | ||
1357 | ipr_ra_err((hostrcb)->ioa_cfg, \ | ||
1358 | (hostrcb)->hcam.u.error.failing_dev_res_addr, \ | ||
1359 | fmt, ##__VA_ARGS__); \ | ||
1360 | } else { \ | ||
1361 | dev_err(&(hostrcb)->ioa_cfg->pdev->dev, fmt, ##__VA_ARGS__); \ | ||
1362 | } \ | ||
1363 | } | ||
1364 | |||
1286 | #define ipr_trace ipr_dbg("%s: %s: Line: %d\n",\ | 1365 | #define ipr_trace ipr_dbg("%s: %s: Line: %d\n",\ |
1287 | __FILE__, __FUNCTION__, __LINE__) | 1366 | __FILE__, __FUNCTION__, __LINE__) |
1288 | 1367 | ||
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index f06a06ae6092..8b704f73055a 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c | |||
@@ -5001,7 +5001,7 @@ ips_init_copperhead(ips_ha_t * ha) | |||
5001 | break; | 5001 | break; |
5002 | 5002 | ||
5003 | /* Delay for 1 Second */ | 5003 | /* Delay for 1 Second */ |
5004 | msleep(IPS_ONE_SEC); | 5004 | MDELAY(IPS_ONE_SEC); |
5005 | } | 5005 | } |
5006 | 5006 | ||
5007 | if (j >= 45) | 5007 | if (j >= 45) |
@@ -5027,7 +5027,7 @@ ips_init_copperhead(ips_ha_t * ha) | |||
5027 | break; | 5027 | break; |
5028 | 5028 | ||
5029 | /* Delay for 1 Second */ | 5029 | /* Delay for 1 Second */ |
5030 | msleep(IPS_ONE_SEC); | 5030 | MDELAY(IPS_ONE_SEC); |
5031 | } | 5031 | } |
5032 | 5032 | ||
5033 | if (j >= 240) | 5033 | if (j >= 240) |
@@ -5045,7 +5045,7 @@ ips_init_copperhead(ips_ha_t * ha) | |||
5045 | break; | 5045 | break; |
5046 | 5046 | ||
5047 | /* Delay for 1 Second */ | 5047 | /* Delay for 1 Second */ |
5048 | msleep(IPS_ONE_SEC); | 5048 | MDELAY(IPS_ONE_SEC); |
5049 | } | 5049 | } |
5050 | 5050 | ||
5051 | if (i >= 240) | 5051 | if (i >= 240) |
@@ -5095,7 +5095,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) | |||
5095 | break; | 5095 | break; |
5096 | 5096 | ||
5097 | /* Delay for 1 Second */ | 5097 | /* Delay for 1 Second */ |
5098 | msleep(IPS_ONE_SEC); | 5098 | MDELAY(IPS_ONE_SEC); |
5099 | } | 5099 | } |
5100 | 5100 | ||
5101 | if (j >= 45) | 5101 | if (j >= 45) |
@@ -5121,7 +5121,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) | |||
5121 | break; | 5121 | break; |
5122 | 5122 | ||
5123 | /* Delay for 1 Second */ | 5123 | /* Delay for 1 Second */ |
5124 | msleep(IPS_ONE_SEC); | 5124 | MDELAY(IPS_ONE_SEC); |
5125 | } | 5125 | } |
5126 | 5126 | ||
5127 | if (j >= 240) | 5127 | if (j >= 240) |
@@ -5139,7 +5139,7 @@ ips_init_copperhead_memio(ips_ha_t * ha) | |||
5139 | break; | 5139 | break; |
5140 | 5140 | ||
5141 | /* Delay for 1 Second */ | 5141 | /* Delay for 1 Second */ |
5142 | msleep(IPS_ONE_SEC); | 5142 | MDELAY(IPS_ONE_SEC); |
5143 | } | 5143 | } |
5144 | 5144 | ||
5145 | if (i >= 240) | 5145 | if (i >= 240) |
@@ -5191,7 +5191,7 @@ ips_init_morpheus(ips_ha_t * ha) | |||
5191 | break; | 5191 | break; |
5192 | 5192 | ||
5193 | /* Delay for 1 Second */ | 5193 | /* Delay for 1 Second */ |
5194 | msleep(IPS_ONE_SEC); | 5194 | MDELAY(IPS_ONE_SEC); |
5195 | } | 5195 | } |
5196 | 5196 | ||
5197 | if (i >= 45) { | 5197 | if (i >= 45) { |
@@ -5217,7 +5217,7 @@ ips_init_morpheus(ips_ha_t * ha) | |||
5217 | if (Post != 0x4F00) | 5217 | if (Post != 0x4F00) |
5218 | break; | 5218 | break; |
5219 | /* Delay for 1 Second */ | 5219 | /* Delay for 1 Second */ |
5220 | msleep(IPS_ONE_SEC); | 5220 | MDELAY(IPS_ONE_SEC); |
5221 | } | 5221 | } |
5222 | 5222 | ||
5223 | if (i >= 120) { | 5223 | if (i >= 120) { |
@@ -5247,7 +5247,7 @@ ips_init_morpheus(ips_ha_t * ha) | |||
5247 | break; | 5247 | break; |
5248 | 5248 | ||
5249 | /* Delay for 1 Second */ | 5249 | /* Delay for 1 Second */ |
5250 | msleep(IPS_ONE_SEC); | 5250 | MDELAY(IPS_ONE_SEC); |
5251 | } | 5251 | } |
5252 | 5252 | ||
5253 | if (i >= 240) { | 5253 | if (i >= 240) { |
@@ -5307,12 +5307,12 @@ ips_reset_copperhead(ips_ha_t * ha) | |||
5307 | outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR); | 5307 | outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR); |
5308 | 5308 | ||
5309 | /* Delay for 1 Second */ | 5309 | /* Delay for 1 Second */ |
5310 | msleep(IPS_ONE_SEC); | 5310 | MDELAY(IPS_ONE_SEC); |
5311 | 5311 | ||
5312 | outb(0, ha->io_addr + IPS_REG_SCPR); | 5312 | outb(0, ha->io_addr + IPS_REG_SCPR); |
5313 | 5313 | ||
5314 | /* Delay for 1 Second */ | 5314 | /* Delay for 1 Second */ |
5315 | msleep(IPS_ONE_SEC); | 5315 | MDELAY(IPS_ONE_SEC); |
5316 | 5316 | ||
5317 | if ((*ha->func.init) (ha)) | 5317 | if ((*ha->func.init) (ha)) |
5318 | break; | 5318 | break; |
@@ -5352,12 +5352,12 @@ ips_reset_copperhead_memio(ips_ha_t * ha) | |||
5352 | writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR); | 5352 | writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR); |
5353 | 5353 | ||
5354 | /* Delay for 1 Second */ | 5354 | /* Delay for 1 Second */ |
5355 | msleep(IPS_ONE_SEC); | 5355 | MDELAY(IPS_ONE_SEC); |
5356 | 5356 | ||
5357 | writeb(0, ha->mem_ptr + IPS_REG_SCPR); | 5357 | writeb(0, ha->mem_ptr + IPS_REG_SCPR); |
5358 | 5358 | ||
5359 | /* Delay for 1 Second */ | 5359 | /* Delay for 1 Second */ |
5360 | msleep(IPS_ONE_SEC); | 5360 | MDELAY(IPS_ONE_SEC); |
5361 | 5361 | ||
5362 | if ((*ha->func.init) (ha)) | 5362 | if ((*ha->func.init) (ha)) |
5363 | break; | 5363 | break; |
@@ -5398,7 +5398,7 @@ ips_reset_morpheus(ips_ha_t * ha) | |||
5398 | writel(0x80000000, ha->mem_ptr + IPS_REG_I960_IDR); | 5398 | writel(0x80000000, ha->mem_ptr + IPS_REG_I960_IDR); |
5399 | 5399 | ||
5400 | /* Delay for 5 Seconds */ | 5400 | /* Delay for 5 Seconds */ |
5401 | msleep(5 * IPS_ONE_SEC); | 5401 | MDELAY(5 * IPS_ONE_SEC); |
5402 | 5402 | ||
5403 | /* Do a PCI config read to wait for adapter */ | 5403 | /* Do a PCI config read to wait for adapter */ |
5404 | pci_read_config_byte(ha->pcidev, 4, &junk); | 5404 | pci_read_config_byte(ha->pcidev, 4, &junk); |
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 34680f3dd452..b726dcc424b1 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h | |||
@@ -51,6 +51,7 @@ | |||
51 | #define _IPS_H_ | 51 | #define _IPS_H_ |
52 | 52 | ||
53 | #include <linux/version.h> | 53 | #include <linux/version.h> |
54 | #include <linux/nmi.h> | ||
54 | #include <asm/uaccess.h> | 55 | #include <asm/uaccess.h> |
55 | #include <asm/io.h> | 56 | #include <asm/io.h> |
56 | 57 | ||
@@ -116,9 +117,11 @@ | |||
116 | dev_printk(level , &((pcidev)->dev) , format , ## arg) | 117 | dev_printk(level , &((pcidev)->dev) , format , ## arg) |
117 | #endif | 118 | #endif |
118 | 119 | ||
119 | #ifndef MDELAY | 120 | #define MDELAY(n) \ |
120 | #define MDELAY mdelay | 121 | do { \ |
121 | #endif | 122 | mdelay(n); \ |
123 | touch_nmi_watchdog(); \ | ||
124 | } while (0) | ||
122 | 125 | ||
123 | #ifndef min | 126 | #ifndef min |
124 | #define min(x,y) ((x) < (y) ? x : y) | 127 | #define min(x,y) ((x) < (y) ? x : y) |
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index e34a93435497..d31e6fa466f7 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
@@ -597,10 +597,15 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
597 | child->iproto = phy->attached_iproto; | 597 | child->iproto = phy->attached_iproto; |
598 | memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); | 598 | memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); |
599 | sas_hash_addr(child->hashed_sas_addr, child->sas_addr); | 599 | sas_hash_addr(child->hashed_sas_addr, child->sas_addr); |
600 | phy->port = sas_port_alloc(&parent->rphy->dev, phy_id); | 600 | if (!phy->port) { |
601 | BUG_ON(!phy->port); | 601 | phy->port = sas_port_alloc(&parent->rphy->dev, phy_id); |
602 | /* FIXME: better error handling*/ | 602 | if (unlikely(!phy->port)) |
603 | BUG_ON(sas_port_add(phy->port) != 0); | 603 | goto out_err; |
604 | if (unlikely(sas_port_add(phy->port) != 0)) { | ||
605 | sas_port_free(phy->port); | ||
606 | goto out_err; | ||
607 | } | ||
608 | } | ||
604 | sas_ex_get_linkrate(parent, child, phy); | 609 | sas_ex_get_linkrate(parent, child, phy); |
605 | 610 | ||
606 | if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { | 611 | if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) { |
@@ -615,8 +620,7 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
615 | SAS_DPRINTK("report phy sata to %016llx:0x%x returned " | 620 | SAS_DPRINTK("report phy sata to %016llx:0x%x returned " |
616 | "0x%x\n", SAS_ADDR(parent->sas_addr), | 621 | "0x%x\n", SAS_ADDR(parent->sas_addr), |
617 | phy_id, res); | 622 | phy_id, res); |
618 | kfree(child); | 623 | goto out_free; |
619 | return NULL; | ||
620 | } | 624 | } |
621 | memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis, | 625 | memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis, |
622 | sizeof(struct dev_to_host_fis)); | 626 | sizeof(struct dev_to_host_fis)); |
@@ -627,14 +631,14 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
627 | "%016llx:0x%x returned 0x%x\n", | 631 | "%016llx:0x%x returned 0x%x\n", |
628 | SAS_ADDR(child->sas_addr), | 632 | SAS_ADDR(child->sas_addr), |
629 | SAS_ADDR(parent->sas_addr), phy_id, res); | 633 | SAS_ADDR(parent->sas_addr), phy_id, res); |
630 | kfree(child); | 634 | goto out_free; |
631 | return NULL; | ||
632 | } | 635 | } |
633 | } else if (phy->attached_tproto & SAS_PROTO_SSP) { | 636 | } else if (phy->attached_tproto & SAS_PROTO_SSP) { |
634 | child->dev_type = SAS_END_DEV; | 637 | child->dev_type = SAS_END_DEV; |
635 | rphy = sas_end_device_alloc(phy->port); | 638 | rphy = sas_end_device_alloc(phy->port); |
636 | /* FIXME: error handling */ | 639 | /* FIXME: error handling */ |
637 | BUG_ON(!rphy); | 640 | if (unlikely(!rphy)) |
641 | goto out_free; | ||
638 | child->tproto = phy->attached_tproto; | 642 | child->tproto = phy->attached_tproto; |
639 | sas_init_dev(child); | 643 | sas_init_dev(child); |
640 | 644 | ||
@@ -651,9 +655,7 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
651 | "at %016llx:0x%x returned 0x%x\n", | 655 | "at %016llx:0x%x returned 0x%x\n", |
652 | SAS_ADDR(child->sas_addr), | 656 | SAS_ADDR(child->sas_addr), |
653 | SAS_ADDR(parent->sas_addr), phy_id, res); | 657 | SAS_ADDR(parent->sas_addr), phy_id, res); |
654 | /* FIXME: this kfrees list elements without removing them */ | 658 | goto out_list_del; |
655 | //kfree(child); | ||
656 | return NULL; | ||
657 | } | 659 | } |
658 | } else { | 660 | } else { |
659 | SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", | 661 | SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n", |
@@ -663,6 +665,16 @@ static struct domain_device *sas_ex_discover_end_dev( | |||
663 | 665 | ||
664 | list_add_tail(&child->siblings, &parent_ex->children); | 666 | list_add_tail(&child->siblings, &parent_ex->children); |
665 | return child; | 667 | return child; |
668 | |||
669 | out_list_del: | ||
670 | list_del(&child->dev_list_node); | ||
671 | sas_rphy_free(rphy); | ||
672 | out_free: | ||
673 | sas_port_delete(phy->port); | ||
674 | out_err: | ||
675 | phy->port = NULL; | ||
676 | kfree(child); | ||
677 | return NULL; | ||
666 | } | 678 | } |
667 | 679 | ||
668 | static struct domain_device *sas_ex_discover_expander( | 680 | static struct domain_device *sas_ex_discover_expander( |
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index 7b4e9169f44d..d65bc4e0f214 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c | |||
@@ -114,6 +114,8 @@ int sas_register_ha(struct sas_ha_struct *sas_ha) | |||
114 | } | 114 | } |
115 | } | 115 | } |
116 | 116 | ||
117 | INIT_LIST_HEAD(&sas_ha->eh_done_q); | ||
118 | |||
117 | return 0; | 119 | return 0; |
118 | 120 | ||
119 | Undo_ports: | 121 | Undo_ports: |
@@ -144,7 +146,7 @@ static int sas_get_linkerrors(struct sas_phy *phy) | |||
144 | return sas_smp_get_phy_events(phy); | 146 | return sas_smp_get_phy_events(phy); |
145 | } | 147 | } |
146 | 148 | ||
147 | static int sas_phy_reset(struct sas_phy *phy, int hard_reset) | 149 | int sas_phy_reset(struct sas_phy *phy, int hard_reset) |
148 | { | 150 | { |
149 | int ret; | 151 | int ret; |
150 | enum phy_func reset_type; | 152 | enum phy_func reset_type; |
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index e46e79355b77..e064aac06b90 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -29,9 +29,11 @@ | |||
29 | #include <scsi/scsi_device.h> | 29 | #include <scsi/scsi_device.h> |
30 | #include <scsi/scsi_tcq.h> | 30 | #include <scsi/scsi_tcq.h> |
31 | #include <scsi/scsi.h> | 31 | #include <scsi/scsi.h> |
32 | #include <scsi/scsi_eh.h> | ||
32 | #include <scsi/scsi_transport.h> | 33 | #include <scsi/scsi_transport.h> |
33 | #include <scsi/scsi_transport_sas.h> | 34 | #include <scsi/scsi_transport_sas.h> |
34 | #include "../scsi_sas_internal.h" | 35 | #include "../scsi_sas_internal.h" |
36 | #include "../scsi_transport_api.h" | ||
35 | 37 | ||
36 | #include <linux/err.h> | 38 | #include <linux/err.h> |
37 | #include <linux/blkdev.h> | 39 | #include <linux/blkdev.h> |
@@ -46,6 +48,7 @@ static void sas_scsi_task_done(struct sas_task *task) | |||
46 | { | 48 | { |
47 | struct task_status_struct *ts = &task->task_status; | 49 | struct task_status_struct *ts = &task->task_status; |
48 | struct scsi_cmnd *sc = task->uldd_task; | 50 | struct scsi_cmnd *sc = task->uldd_task; |
51 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(sc->device->host); | ||
49 | unsigned ts_flags = task->task_state_flags; | 52 | unsigned ts_flags = task->task_state_flags; |
50 | int hs = 0, stat = 0; | 53 | int hs = 0, stat = 0; |
51 | 54 | ||
@@ -116,7 +119,7 @@ static void sas_scsi_task_done(struct sas_task *task) | |||
116 | sas_free_task(task); | 119 | sas_free_task(task); |
117 | /* This is very ugly but this is how SCSI Core works. */ | 120 | /* This is very ugly but this is how SCSI Core works. */ |
118 | if (ts_flags & SAS_TASK_STATE_ABORTED) | 121 | if (ts_flags & SAS_TASK_STATE_ABORTED) |
119 | scsi_finish_command(sc); | 122 | scsi_eh_finish_cmd(sc, &sas_ha->eh_done_q); |
120 | else | 123 | else |
121 | sc->scsi_done(sc); | 124 | sc->scsi_done(sc); |
122 | } | 125 | } |
@@ -307,6 +310,15 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task) | |||
307 | spin_unlock_irqrestore(&core->task_queue_lock, flags); | 310 | spin_unlock_irqrestore(&core->task_queue_lock, flags); |
308 | } | 311 | } |
309 | 312 | ||
313 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
314 | if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { | ||
315 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
316 | SAS_DPRINTK("%s: task 0x%p already aborted\n", | ||
317 | __FUNCTION__, task); | ||
318 | return TASK_IS_ABORTED; | ||
319 | } | ||
320 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
321 | |||
310 | for (i = 0; i < 5; i++) { | 322 | for (i = 0; i < 5; i++) { |
311 | SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task); | 323 | SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task); |
312 | res = si->dft->lldd_abort_task(task); | 324 | res = si->dft->lldd_abort_task(task); |
@@ -409,13 +421,16 @@ Again: | |||
409 | SAS_DPRINTK("going over list...\n"); | 421 | SAS_DPRINTK("going over list...\n"); |
410 | list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { | 422 | list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { |
411 | struct sas_task *task = TO_SAS_TASK(cmd); | 423 | struct sas_task *task = TO_SAS_TASK(cmd); |
424 | list_del_init(&cmd->eh_entry); | ||
412 | 425 | ||
426 | if (!task) { | ||
427 | SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__); | ||
428 | continue; | ||
429 | } | ||
413 | SAS_DPRINTK("trying to find task 0x%p\n", task); | 430 | SAS_DPRINTK("trying to find task 0x%p\n", task); |
414 | list_del_init(&cmd->eh_entry); | ||
415 | res = sas_scsi_find_task(task); | 431 | res = sas_scsi_find_task(task); |
416 | 432 | ||
417 | cmd->eh_eflags = 0; | 433 | cmd->eh_eflags = 0; |
418 | shost->host_failed--; | ||
419 | 434 | ||
420 | switch (res) { | 435 | switch (res) { |
421 | case TASK_IS_DONE: | 436 | case TASK_IS_DONE: |
@@ -491,6 +506,7 @@ Again: | |||
491 | } | 506 | } |
492 | } | 507 | } |
493 | out: | 508 | out: |
509 | scsi_eh_flush_done_q(&ha->eh_done_q); | ||
494 | SAS_DPRINTK("--- Exit %s\n", __FUNCTION__); | 510 | SAS_DPRINTK("--- Exit %s\n", __FUNCTION__); |
495 | return; | 511 | return; |
496 | clear_q: | 512 | clear_q: |
@@ -508,12 +524,18 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) | |||
508 | unsigned long flags; | 524 | unsigned long flags; |
509 | 525 | ||
510 | if (!task) { | 526 | if (!task) { |
511 | SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", | 527 | SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n", |
512 | cmd, task); | 528 | cmd, task); |
513 | return EH_HANDLED; | 529 | return EH_HANDLED; |
514 | } | 530 | } |
515 | 531 | ||
516 | spin_lock_irqsave(&task->task_state_lock, flags); | 532 | spin_lock_irqsave(&task->task_state_lock, flags); |
533 | if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { | ||
534 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
535 | SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: " | ||
536 | "EH_NOT_HANDLED\n", cmd, task); | ||
537 | return EH_NOT_HANDLED; | ||
538 | } | ||
517 | if (task->task_state_flags & SAS_TASK_STATE_DONE) { | 539 | if (task->task_state_flags & SAS_TASK_STATE_DONE) { |
518 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 540 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
519 | SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", | 541 | SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", |
@@ -777,6 +799,64 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha) | |||
777 | spin_unlock_irqrestore(&core->task_queue_lock, flags); | 799 | spin_unlock_irqrestore(&core->task_queue_lock, flags); |
778 | } | 800 | } |
779 | 801 | ||
802 | static int do_sas_task_abort(struct sas_task *task) | ||
803 | { | ||
804 | struct scsi_cmnd *sc = task->uldd_task; | ||
805 | struct sas_internal *si = | ||
806 | to_sas_internal(task->dev->port->ha->core.shost->transportt); | ||
807 | unsigned long flags; | ||
808 | int res; | ||
809 | |||
810 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
811 | if (task->task_state_flags & SAS_TASK_STATE_ABORTED) { | ||
812 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
813 | SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__, | ||
814 | task); | ||
815 | return 0; | ||
816 | } | ||
817 | |||
818 | task->task_state_flags |= SAS_TASK_INITIATOR_ABORTED; | ||
819 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) | ||
820 | task->task_state_flags |= SAS_TASK_STATE_ABORTED; | ||
821 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
822 | |||
823 | if (!si->dft->lldd_abort_task) | ||
824 | return -ENODEV; | ||
825 | |||
826 | res = si->dft->lldd_abort_task(task); | ||
827 | if ((task->task_state_flags & SAS_TASK_STATE_DONE) || | ||
828 | (res == TMF_RESP_FUNC_COMPLETE)) | ||
829 | { | ||
830 | /* SMP commands don't have scsi_cmds(?) */ | ||
831 | if (!sc) { | ||
832 | task->task_done(task); | ||
833 | return 0; | ||
834 | } | ||
835 | scsi_req_abort_cmd(sc); | ||
836 | scsi_schedule_eh(sc->device->host); | ||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
841 | task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED; | ||
842 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) | ||
843 | task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; | ||
844 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
845 | |||
846 | return -EAGAIN; | ||
847 | } | ||
848 | |||
849 | void sas_task_abort(struct sas_task *task) | ||
850 | { | ||
851 | int i; | ||
852 | |||
853 | for (i = 0; i < 5; i++) | ||
854 | if (!do_sas_task_abort(task)) | ||
855 | return; | ||
856 | |||
857 | SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__); | ||
858 | } | ||
859 | |||
780 | EXPORT_SYMBOL_GPL(sas_queuecommand); | 860 | EXPORT_SYMBOL_GPL(sas_queuecommand); |
781 | EXPORT_SYMBOL_GPL(sas_target_alloc); | 861 | EXPORT_SYMBOL_GPL(sas_target_alloc); |
782 | EXPORT_SYMBOL_GPL(sas_slave_configure); | 862 | EXPORT_SYMBOL_GPL(sas_slave_configure); |
@@ -784,3 +864,5 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy); | |||
784 | EXPORT_SYMBOL_GPL(sas_change_queue_depth); | 864 | EXPORT_SYMBOL_GPL(sas_change_queue_depth); |
785 | EXPORT_SYMBOL_GPL(sas_change_queue_type); | 865 | EXPORT_SYMBOL_GPL(sas_change_queue_type); |
786 | EXPORT_SYMBOL_GPL(sas_bios_param); | 866 | EXPORT_SYMBOL_GPL(sas_bios_param); |
867 | EXPORT_SYMBOL_GPL(sas_task_abort); | ||
868 | EXPORT_SYMBOL_GPL(sas_phy_reset); | ||
diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c new file mode 100644 index 000000000000..89403b00e042 --- /dev/null +++ b/drivers/scsi/libsrp.c | |||
@@ -0,0 +1,441 @@ | |||
1 | /* | ||
2 | * SCSI RDAM Protocol lib functions | ||
3 | * | ||
4 | * Copyright (C) 2006 FUJITA Tomonori <tomof@acm.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
19 | * 02110-1301 USA | ||
20 | */ | ||
21 | #include <linux/err.h> | ||
22 | #include <linux/kfifo.h> | ||
23 | #include <linux/scatterlist.h> | ||
24 | #include <linux/dma-mapping.h> | ||
25 | #include <linux/pci.h> | ||
26 | #include <scsi/scsi.h> | ||
27 | #include <scsi/scsi_cmnd.h> | ||
28 | #include <scsi/scsi_tcq.h> | ||
29 | #include <scsi/scsi_tgt.h> | ||
30 | #include <scsi/srp.h> | ||
31 | #include <scsi/libsrp.h> | ||
32 | |||
33 | enum srp_task_attributes { | ||
34 | SRP_SIMPLE_TASK = 0, | ||
35 | SRP_HEAD_TASK = 1, | ||
36 | SRP_ORDERED_TASK = 2, | ||
37 | SRP_ACA_TASK = 4 | ||
38 | }; | ||
39 | |||
40 | /* tmp - will replace with SCSI logging stuff */ | ||
41 | #define eprintk(fmt, args...) \ | ||
42 | do { \ | ||
43 | printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \ | ||
44 | } while (0) | ||
45 | /* #define dprintk eprintk */ | ||
46 | #define dprintk(fmt, args...) | ||
47 | |||
48 | static int srp_iu_pool_alloc(struct srp_queue *q, size_t max, | ||
49 | struct srp_buf **ring) | ||
50 | { | ||
51 | int i; | ||
52 | struct iu_entry *iue; | ||
53 | |||
54 | q->pool = kcalloc(max, sizeof(struct iu_entry *), GFP_KERNEL); | ||
55 | if (!q->pool) | ||
56 | return -ENOMEM; | ||
57 | q->items = kcalloc(max, sizeof(struct iu_entry), GFP_KERNEL); | ||
58 | if (!q->items) | ||
59 | goto free_pool; | ||
60 | |||
61 | spin_lock_init(&q->lock); | ||
62 | q->queue = kfifo_init((void *) q->pool, max * sizeof(void *), | ||
63 | GFP_KERNEL, &q->lock); | ||
64 | if (IS_ERR(q->queue)) | ||
65 | goto free_item; | ||
66 | |||
67 | for (i = 0, iue = q->items; i < max; i++) { | ||
68 | __kfifo_put(q->queue, (void *) &iue, sizeof(void *)); | ||
69 | iue->sbuf = ring[i]; | ||
70 | iue++; | ||
71 | } | ||
72 | return 0; | ||
73 | |||
74 | free_item: | ||
75 | kfree(q->items); | ||
76 | free_pool: | ||
77 | kfree(q->pool); | ||
78 | return -ENOMEM; | ||
79 | } | ||
80 | |||
81 | static void srp_iu_pool_free(struct srp_queue *q) | ||
82 | { | ||
83 | kfree(q->items); | ||
84 | kfree(q->pool); | ||
85 | } | ||
86 | |||
87 | static struct srp_buf **srp_ring_alloc(struct device *dev, | ||
88 | size_t max, size_t size) | ||
89 | { | ||
90 | int i; | ||
91 | struct srp_buf **ring; | ||
92 | |||
93 | ring = kcalloc(max, sizeof(struct srp_buf *), GFP_KERNEL); | ||
94 | if (!ring) | ||
95 | return NULL; | ||
96 | |||
97 | for (i = 0; i < max; i++) { | ||
98 | ring[i] = kzalloc(sizeof(struct srp_buf), GFP_KERNEL); | ||
99 | if (!ring[i]) | ||
100 | goto out; | ||
101 | ring[i]->buf = dma_alloc_coherent(dev, size, &ring[i]->dma, | ||
102 | GFP_KERNEL); | ||
103 | if (!ring[i]->buf) | ||
104 | goto out; | ||
105 | } | ||
106 | return ring; | ||
107 | |||
108 | out: | ||
109 | for (i = 0; i < max && ring[i]; i++) { | ||
110 | if (ring[i]->buf) | ||
111 | dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma); | ||
112 | kfree(ring[i]); | ||
113 | } | ||
114 | kfree(ring); | ||
115 | |||
116 | return NULL; | ||
117 | } | ||
118 | |||
119 | static void srp_ring_free(struct device *dev, struct srp_buf **ring, size_t max, | ||
120 | size_t size) | ||
121 | { | ||
122 | int i; | ||
123 | |||
124 | for (i = 0; i < max; i++) { | ||
125 | dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma); | ||
126 | kfree(ring[i]); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | int srp_target_alloc(struct srp_target *target, struct device *dev, | ||
131 | size_t nr, size_t iu_size) | ||
132 | { | ||
133 | int err; | ||
134 | |||
135 | spin_lock_init(&target->lock); | ||
136 | INIT_LIST_HEAD(&target->cmd_queue); | ||
137 | |||
138 | target->dev = dev; | ||
139 | target->dev->driver_data = target; | ||
140 | |||
141 | target->srp_iu_size = iu_size; | ||
142 | target->rx_ring_size = nr; | ||
143 | target->rx_ring = srp_ring_alloc(target->dev, nr, iu_size); | ||
144 | if (!target->rx_ring) | ||
145 | return -ENOMEM; | ||
146 | err = srp_iu_pool_alloc(&target->iu_queue, nr, target->rx_ring); | ||
147 | if (err) | ||
148 | goto free_ring; | ||
149 | |||
150 | return 0; | ||
151 | |||
152 | free_ring: | ||
153 | srp_ring_free(target->dev, target->rx_ring, nr, iu_size); | ||
154 | return -ENOMEM; | ||
155 | } | ||
156 | EXPORT_SYMBOL_GPL(srp_target_alloc); | ||
157 | |||
158 | void srp_target_free(struct srp_target *target) | ||
159 | { | ||
160 | srp_ring_free(target->dev, target->rx_ring, target->rx_ring_size, | ||
161 | target->srp_iu_size); | ||
162 | srp_iu_pool_free(&target->iu_queue); | ||
163 | } | ||
164 | EXPORT_SYMBOL_GPL(srp_target_free); | ||
165 | |||
166 | struct iu_entry *srp_iu_get(struct srp_target *target) | ||
167 | { | ||
168 | struct iu_entry *iue = NULL; | ||
169 | |||
170 | kfifo_get(target->iu_queue.queue, (void *) &iue, sizeof(void *)); | ||
171 | if (!iue) | ||
172 | return iue; | ||
173 | iue->target = target; | ||
174 | INIT_LIST_HEAD(&iue->ilist); | ||
175 | iue->flags = 0; | ||
176 | return iue; | ||
177 | } | ||
178 | EXPORT_SYMBOL_GPL(srp_iu_get); | ||
179 | |||
180 | void srp_iu_put(struct iu_entry *iue) | ||
181 | { | ||
182 | kfifo_put(iue->target->iu_queue.queue, (void *) &iue, sizeof(void *)); | ||
183 | } | ||
184 | EXPORT_SYMBOL_GPL(srp_iu_put); | ||
185 | |||
186 | static int srp_direct_data(struct scsi_cmnd *sc, struct srp_direct_buf *md, | ||
187 | enum dma_data_direction dir, srp_rdma_t rdma_io, | ||
188 | int dma_map, int ext_desc) | ||
189 | { | ||
190 | struct iu_entry *iue = NULL; | ||
191 | struct scatterlist *sg = NULL; | ||
192 | int err, nsg = 0, len; | ||
193 | |||
194 | if (dma_map) { | ||
195 | iue = (struct iu_entry *) sc->SCp.ptr; | ||
196 | sg = sc->request_buffer; | ||
197 | |||
198 | dprintk("%p %u %u %d\n", iue, sc->request_bufflen, | ||
199 | md->len, sc->use_sg); | ||
200 | |||
201 | nsg = dma_map_sg(iue->target->dev, sg, sc->use_sg, | ||
202 | DMA_BIDIRECTIONAL); | ||
203 | if (!nsg) { | ||
204 | printk("fail to map %p %d\n", iue, sc->use_sg); | ||
205 | return 0; | ||
206 | } | ||
207 | len = min(sc->request_bufflen, md->len); | ||
208 | } else | ||
209 | len = md->len; | ||
210 | |||
211 | err = rdma_io(sc, sg, nsg, md, 1, dir, len); | ||
212 | |||
213 | if (dma_map) | ||
214 | dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL); | ||
215 | |||
216 | return err; | ||
217 | } | ||
218 | |||
219 | static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, | ||
220 | struct srp_indirect_buf *id, | ||
221 | enum dma_data_direction dir, srp_rdma_t rdma_io, | ||
222 | int dma_map, int ext_desc) | ||
223 | { | ||
224 | struct iu_entry *iue = NULL; | ||
225 | struct srp_direct_buf *md = NULL; | ||
226 | struct scatterlist dummy, *sg = NULL; | ||
227 | dma_addr_t token = 0; | ||
228 | long err; | ||
229 | unsigned int done = 0; | ||
230 | int nmd, nsg = 0, len; | ||
231 | |||
232 | if (dma_map || ext_desc) { | ||
233 | iue = (struct iu_entry *) sc->SCp.ptr; | ||
234 | sg = sc->request_buffer; | ||
235 | |||
236 | dprintk("%p %u %u %d %d\n", | ||
237 | iue, sc->request_bufflen, id->len, | ||
238 | cmd->data_in_desc_cnt, cmd->data_out_desc_cnt); | ||
239 | } | ||
240 | |||
241 | nmd = id->table_desc.len / sizeof(struct srp_direct_buf); | ||
242 | |||
243 | if ((dir == DMA_FROM_DEVICE && nmd == cmd->data_in_desc_cnt) || | ||
244 | (dir == DMA_TO_DEVICE && nmd == cmd->data_out_desc_cnt)) { | ||
245 | md = &id->desc_list[0]; | ||
246 | goto rdma; | ||
247 | } | ||
248 | |||
249 | if (ext_desc && dma_map) { | ||
250 | md = dma_alloc_coherent(iue->target->dev, id->table_desc.len, | ||
251 | &token, GFP_KERNEL); | ||
252 | if (!md) { | ||
253 | eprintk("Can't get dma memory %u\n", id->table_desc.len); | ||
254 | return -ENOMEM; | ||
255 | } | ||
256 | |||
257 | sg_init_one(&dummy, md, id->table_desc.len); | ||
258 | sg_dma_address(&dummy) = token; | ||
259 | err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE, | ||
260 | id->table_desc.len); | ||
261 | if (err < 0) { | ||
262 | eprintk("Error copying indirect table %ld\n", err); | ||
263 | goto free_mem; | ||
264 | } | ||
265 | } else { | ||
266 | eprintk("This command uses external indirect buffer\n"); | ||
267 | return -EINVAL; | ||
268 | } | ||
269 | |||
270 | rdma: | ||
271 | if (dma_map) { | ||
272 | nsg = dma_map_sg(iue->target->dev, sg, sc->use_sg, DMA_BIDIRECTIONAL); | ||
273 | if (!nsg) { | ||
274 | eprintk("fail to map %p %d\n", iue, sc->use_sg); | ||
275 | goto free_mem; | ||
276 | } | ||
277 | len = min(sc->request_bufflen, id->len); | ||
278 | } else | ||
279 | len = id->len; | ||
280 | |||
281 | err = rdma_io(sc, sg, nsg, md, nmd, dir, len); | ||
282 | |||
283 | if (dma_map) | ||
284 | dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL); | ||
285 | |||
286 | free_mem: | ||
287 | if (token && dma_map) | ||
288 | dma_free_coherent(iue->target->dev, id->table_desc.len, md, token); | ||
289 | |||
290 | return done; | ||
291 | } | ||
292 | |||
293 | static int data_out_desc_size(struct srp_cmd *cmd) | ||
294 | { | ||
295 | int size = 0; | ||
296 | u8 fmt = cmd->buf_fmt >> 4; | ||
297 | |||
298 | switch (fmt) { | ||
299 | case SRP_NO_DATA_DESC: | ||
300 | break; | ||
301 | case SRP_DATA_DESC_DIRECT: | ||
302 | size = sizeof(struct srp_direct_buf); | ||
303 | break; | ||
304 | case SRP_DATA_DESC_INDIRECT: | ||
305 | size = sizeof(struct srp_indirect_buf) + | ||
306 | sizeof(struct srp_direct_buf) * cmd->data_out_desc_cnt; | ||
307 | break; | ||
308 | default: | ||
309 | eprintk("client error. Invalid data_out_format %x\n", fmt); | ||
310 | break; | ||
311 | } | ||
312 | return size; | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * TODO: this can be called multiple times for a single command if it | ||
317 | * has very long data. | ||
318 | */ | ||
319 | int srp_transfer_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, | ||
320 | srp_rdma_t rdma_io, int dma_map, int ext_desc) | ||
321 | { | ||
322 | struct srp_direct_buf *md; | ||
323 | struct srp_indirect_buf *id; | ||
324 | enum dma_data_direction dir; | ||
325 | int offset, err = 0; | ||
326 | u8 format; | ||
327 | |||
328 | offset = cmd->add_cdb_len * 4; | ||
329 | |||
330 | dir = srp_cmd_direction(cmd); | ||
331 | if (dir == DMA_FROM_DEVICE) | ||
332 | offset += data_out_desc_size(cmd); | ||
333 | |||
334 | if (dir == DMA_TO_DEVICE) | ||
335 | format = cmd->buf_fmt >> 4; | ||
336 | else | ||
337 | format = cmd->buf_fmt & ((1U << 4) - 1); | ||
338 | |||
339 | switch (format) { | ||
340 | case SRP_NO_DATA_DESC: | ||
341 | break; | ||
342 | case SRP_DATA_DESC_DIRECT: | ||
343 | md = (struct srp_direct_buf *) | ||
344 | (cmd->add_data + offset); | ||
345 | err = srp_direct_data(sc, md, dir, rdma_io, dma_map, ext_desc); | ||
346 | break; | ||
347 | case SRP_DATA_DESC_INDIRECT: | ||
348 | id = (struct srp_indirect_buf *) | ||
349 | (cmd->add_data + offset); | ||
350 | err = srp_indirect_data(sc, cmd, id, dir, rdma_io, dma_map, | ||
351 | ext_desc); | ||
352 | break; | ||
353 | default: | ||
354 | eprintk("Unknown format %d %x\n", dir, format); | ||
355 | break; | ||
356 | } | ||
357 | |||
358 | return err; | ||
359 | } | ||
360 | EXPORT_SYMBOL_GPL(srp_transfer_data); | ||
361 | |||
362 | static int vscsis_data_length(struct srp_cmd *cmd, enum dma_data_direction dir) | ||
363 | { | ||
364 | struct srp_direct_buf *md; | ||
365 | struct srp_indirect_buf *id; | ||
366 | int len = 0, offset = cmd->add_cdb_len * 4; | ||
367 | u8 fmt; | ||
368 | |||
369 | if (dir == DMA_TO_DEVICE) | ||
370 | fmt = cmd->buf_fmt >> 4; | ||
371 | else { | ||
372 | fmt = cmd->buf_fmt & ((1U << 4) - 1); | ||
373 | offset += data_out_desc_size(cmd); | ||
374 | } | ||
375 | |||
376 | switch (fmt) { | ||
377 | case SRP_NO_DATA_DESC: | ||
378 | break; | ||
379 | case SRP_DATA_DESC_DIRECT: | ||
380 | md = (struct srp_direct_buf *) (cmd->add_data + offset); | ||
381 | len = md->len; | ||
382 | break; | ||
383 | case SRP_DATA_DESC_INDIRECT: | ||
384 | id = (struct srp_indirect_buf *) (cmd->add_data + offset); | ||
385 | len = id->len; | ||
386 | break; | ||
387 | default: | ||
388 | eprintk("invalid data format %x\n", fmt); | ||
389 | break; | ||
390 | } | ||
391 | return len; | ||
392 | } | ||
393 | |||
394 | int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info, | ||
395 | u64 addr) | ||
396 | { | ||
397 | enum dma_data_direction dir; | ||
398 | struct scsi_cmnd *sc; | ||
399 | int tag, len, err; | ||
400 | |||
401 | switch (cmd->task_attr) { | ||
402 | case SRP_SIMPLE_TASK: | ||
403 | tag = MSG_SIMPLE_TAG; | ||
404 | break; | ||
405 | case SRP_ORDERED_TASK: | ||
406 | tag = MSG_ORDERED_TAG; | ||
407 | break; | ||
408 | case SRP_HEAD_TASK: | ||
409 | tag = MSG_HEAD_TAG; | ||
410 | break; | ||
411 | default: | ||
412 | eprintk("Task attribute %d not supported\n", cmd->task_attr); | ||
413 | tag = MSG_ORDERED_TAG; | ||
414 | } | ||
415 | |||
416 | dir = srp_cmd_direction(cmd); | ||
417 | len = vscsis_data_length(cmd, dir); | ||
418 | |||
419 | dprintk("%p %x %lx %d %d %d %llx\n", info, cmd->cdb[0], | ||
420 | cmd->lun, dir, len, tag, (unsigned long long) cmd->tag); | ||
421 | |||
422 | sc = scsi_host_get_command(shost, dir, GFP_KERNEL); | ||
423 | if (!sc) | ||
424 | return -ENOMEM; | ||
425 | |||
426 | sc->SCp.ptr = info; | ||
427 | memcpy(sc->cmnd, cmd->cdb, MAX_COMMAND_SIZE); | ||
428 | sc->request_bufflen = len; | ||
429 | sc->request_buffer = (void *) (unsigned long) addr; | ||
430 | sc->tag = tag; | ||
431 | err = scsi_tgt_queue_command(sc, (struct scsi_lun *) &cmd->lun, cmd->tag); | ||
432 | if (err) | ||
433 | scsi_host_put_command(shost, sc); | ||
434 | |||
435 | return err; | ||
436 | } | ||
437 | EXPORT_SYMBOL_GPL(srp_cmd_queue); | ||
438 | |||
439 | MODULE_DESCRIPTION("SCSI RDAM Protocol lib functions"); | ||
440 | MODULE_AUTHOR("FUJITA Tomonori"); | ||
441 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 3f7f5f8abd75..a7de0bca5bdd 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -296,13 +296,17 @@ struct lpfc_hba { | |||
296 | uint32_t cfg_cr_delay; | 296 | uint32_t cfg_cr_delay; |
297 | uint32_t cfg_cr_count; | 297 | uint32_t cfg_cr_count; |
298 | uint32_t cfg_multi_ring_support; | 298 | uint32_t cfg_multi_ring_support; |
299 | uint32_t cfg_multi_ring_rctl; | ||
300 | uint32_t cfg_multi_ring_type; | ||
299 | uint32_t cfg_fdmi_on; | 301 | uint32_t cfg_fdmi_on; |
300 | uint32_t cfg_discovery_threads; | 302 | uint32_t cfg_discovery_threads; |
301 | uint32_t cfg_max_luns; | 303 | uint32_t cfg_max_luns; |
302 | uint32_t cfg_poll; | 304 | uint32_t cfg_poll; |
303 | uint32_t cfg_poll_tmo; | 305 | uint32_t cfg_poll_tmo; |
306 | uint32_t cfg_use_msi; | ||
304 | uint32_t cfg_sg_seg_cnt; | 307 | uint32_t cfg_sg_seg_cnt; |
305 | uint32_t cfg_sg_dma_buf_size; | 308 | uint32_t cfg_sg_dma_buf_size; |
309 | uint64_t cfg_soft_wwnn; | ||
306 | uint64_t cfg_soft_wwpn; | 310 | uint64_t cfg_soft_wwpn; |
307 | 311 | ||
308 | uint32_t dev_loss_tmo_changed; | 312 | uint32_t dev_loss_tmo_changed; |
@@ -355,7 +359,7 @@ struct lpfc_hba { | |||
355 | #define VPD_PORT 0x8 /* valid vpd port data */ | 359 | #define VPD_PORT 0x8 /* valid vpd port data */ |
356 | #define VPD_MASK 0xf /* mask for any vpd data */ | 360 | #define VPD_MASK 0xf /* mask for any vpd data */ |
357 | 361 | ||
358 | uint8_t soft_wwpn_enable; | 362 | uint8_t soft_wwn_enable; |
359 | 363 | ||
360 | struct timer_list fcp_poll_timer; | 364 | struct timer_list fcp_poll_timer; |
361 | struct timer_list els_tmofunc; | 365 | struct timer_list els_tmofunc; |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 2a4e02e7a392..f247e786af99 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -552,10 +552,10 @@ static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR, | |||
552 | static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset); | 552 | static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset); |
553 | 553 | ||
554 | 554 | ||
555 | static char *lpfc_soft_wwpn_key = "C99G71SL8032A"; | 555 | static char *lpfc_soft_wwn_key = "C99G71SL8032A"; |
556 | 556 | ||
557 | static ssize_t | 557 | static ssize_t |
558 | lpfc_soft_wwpn_enable_store(struct class_device *cdev, const char *buf, | 558 | lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf, |
559 | size_t count) | 559 | size_t count) |
560 | { | 560 | { |
561 | struct Scsi_Host *host = class_to_shost(cdev); | 561 | struct Scsi_Host *host = class_to_shost(cdev); |
@@ -579,15 +579,15 @@ lpfc_soft_wwpn_enable_store(struct class_device *cdev, const char *buf, | |||
579 | if (buf[cnt-1] == '\n') | 579 | if (buf[cnt-1] == '\n') |
580 | cnt--; | 580 | cnt--; |
581 | 581 | ||
582 | if ((cnt != strlen(lpfc_soft_wwpn_key)) || | 582 | if ((cnt != strlen(lpfc_soft_wwn_key)) || |
583 | (strncmp(buf, lpfc_soft_wwpn_key, strlen(lpfc_soft_wwpn_key)) != 0)) | 583 | (strncmp(buf, lpfc_soft_wwn_key, strlen(lpfc_soft_wwn_key)) != 0)) |
584 | return -EINVAL; | 584 | return -EINVAL; |
585 | 585 | ||
586 | phba->soft_wwpn_enable = 1; | 586 | phba->soft_wwn_enable = 1; |
587 | return count; | 587 | return count; |
588 | } | 588 | } |
589 | static CLASS_DEVICE_ATTR(lpfc_soft_wwpn_enable, S_IWUSR, NULL, | 589 | static CLASS_DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL, |
590 | lpfc_soft_wwpn_enable_store); | 590 | lpfc_soft_wwn_enable_store); |
591 | 591 | ||
592 | static ssize_t | 592 | static ssize_t |
593 | lpfc_soft_wwpn_show(struct class_device *cdev, char *buf) | 593 | lpfc_soft_wwpn_show(struct class_device *cdev, char *buf) |
@@ -613,12 +613,12 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) | |||
613 | if (buf[cnt-1] == '\n') | 613 | if (buf[cnt-1] == '\n') |
614 | cnt--; | 614 | cnt--; |
615 | 615 | ||
616 | if (!phba->soft_wwpn_enable || (cnt < 16) || (cnt > 18) || | 616 | if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) || |
617 | ((cnt == 17) && (*buf++ != 'x')) || | 617 | ((cnt == 17) && (*buf++ != 'x')) || |
618 | ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x')))) | 618 | ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x')))) |
619 | return -EINVAL; | 619 | return -EINVAL; |
620 | 620 | ||
621 | phba->soft_wwpn_enable = 0; | 621 | phba->soft_wwn_enable = 0; |
622 | 622 | ||
623 | memset(wwpn, 0, sizeof(wwpn)); | 623 | memset(wwpn, 0, sizeof(wwpn)); |
624 | 624 | ||
@@ -639,6 +639,8 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) | |||
639 | } | 639 | } |
640 | phba->cfg_soft_wwpn = wwn_to_u64(wwpn); | 640 | phba->cfg_soft_wwpn = wwn_to_u64(wwpn); |
641 | fc_host_port_name(host) = phba->cfg_soft_wwpn; | 641 | fc_host_port_name(host) = phba->cfg_soft_wwpn; |
642 | if (phba->cfg_soft_wwnn) | ||
643 | fc_host_node_name(host) = phba->cfg_soft_wwnn; | ||
642 | 644 | ||
643 | dev_printk(KERN_NOTICE, &phba->pcidev->dev, | 645 | dev_printk(KERN_NOTICE, &phba->pcidev->dev, |
644 | "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no); | 646 | "lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no); |
@@ -664,6 +666,66 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count) | |||
664 | static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ | 666 | static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\ |
665 | lpfc_soft_wwpn_show, lpfc_soft_wwpn_store); | 667 | lpfc_soft_wwpn_show, lpfc_soft_wwpn_store); |
666 | 668 | ||
669 | static ssize_t | ||
670 | lpfc_soft_wwnn_show(struct class_device *cdev, char *buf) | ||
671 | { | ||
672 | struct Scsi_Host *host = class_to_shost(cdev); | ||
673 | struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; | ||
674 | return snprintf(buf, PAGE_SIZE, "0x%llx\n", | ||
675 | (unsigned long long)phba->cfg_soft_wwnn); | ||
676 | } | ||
677 | |||
678 | |||
679 | static ssize_t | ||
680 | lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count) | ||
681 | { | ||
682 | struct Scsi_Host *host = class_to_shost(cdev); | ||
683 | struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; | ||
684 | unsigned int i, j, cnt=count; | ||
685 | u8 wwnn[8]; | ||
686 | |||
687 | /* count may include a LF at end of string */ | ||
688 | if (buf[cnt-1] == '\n') | ||
689 | cnt--; | ||
690 | |||
691 | if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) || | ||
692 | ((cnt == 17) && (*buf++ != 'x')) || | ||
693 | ((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x')))) | ||
694 | return -EINVAL; | ||
695 | |||
696 | /* | ||
697 | * Allow wwnn to be set many times, as long as the enable is set. | ||
698 | * However, once the wwpn is set, everything locks. | ||
699 | */ | ||
700 | |||
701 | memset(wwnn, 0, sizeof(wwnn)); | ||
702 | |||
703 | /* Validate and store the new name */ | ||
704 | for (i=0, j=0; i < 16; i++) { | ||
705 | if ((*buf >= 'a') && (*buf <= 'f')) | ||
706 | j = ((j << 4) | ((*buf++ -'a') + 10)); | ||
707 | else if ((*buf >= 'A') && (*buf <= 'F')) | ||
708 | j = ((j << 4) | ((*buf++ -'A') + 10)); | ||
709 | else if ((*buf >= '0') && (*buf <= '9')) | ||
710 | j = ((j << 4) | (*buf++ -'0')); | ||
711 | else | ||
712 | return -EINVAL; | ||
713 | if (i % 2) { | ||
714 | wwnn[i/2] = j & 0xff; | ||
715 | j = 0; | ||
716 | } | ||
717 | } | ||
718 | phba->cfg_soft_wwnn = wwn_to_u64(wwnn); | ||
719 | |||
720 | dev_printk(KERN_NOTICE, &phba->pcidev->dev, | ||
721 | "lpfc%d: soft_wwnn set. Value will take effect upon " | ||
722 | "setting of the soft_wwpn\n", phba->brd_no); | ||
723 | |||
724 | return count; | ||
725 | } | ||
726 | static CLASS_DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\ | ||
727 | lpfc_soft_wwnn_show, lpfc_soft_wwnn_store); | ||
728 | |||
667 | 729 | ||
668 | static int lpfc_poll = 0; | 730 | static int lpfc_poll = 0; |
669 | module_param(lpfc_poll, int, 0); | 731 | module_param(lpfc_poll, int, 0); |
@@ -802,12 +864,11 @@ static CLASS_DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR, | |||
802 | # LOG_MBOX 0x4 Mailbox events | 864 | # LOG_MBOX 0x4 Mailbox events |
803 | # LOG_INIT 0x8 Initialization events | 865 | # LOG_INIT 0x8 Initialization events |
804 | # LOG_LINK_EVENT 0x10 Link events | 866 | # LOG_LINK_EVENT 0x10 Link events |
805 | # LOG_IP 0x20 IP traffic history | ||
806 | # LOG_FCP 0x40 FCP traffic history | 867 | # LOG_FCP 0x40 FCP traffic history |
807 | # LOG_NODE 0x80 Node table events | 868 | # LOG_NODE 0x80 Node table events |
808 | # LOG_MISC 0x400 Miscellaneous events | 869 | # LOG_MISC 0x400 Miscellaneous events |
809 | # LOG_SLI 0x800 SLI events | 870 | # LOG_SLI 0x800 SLI events |
810 | # LOG_CHK_COND 0x1000 FCP Check condition flag | 871 | # LOG_FCP_ERROR 0x1000 Only log FCP errors |
811 | # LOG_LIBDFC 0x2000 LIBDFC events | 872 | # LOG_LIBDFC 0x2000 LIBDFC events |
812 | # LOG_ALL_MSG 0xffff LOG all messages | 873 | # LOG_ALL_MSG 0xffff LOG all messages |
813 | */ | 874 | */ |
@@ -916,6 +977,22 @@ LPFC_ATTR_R(multi_ring_support, 1, 1, 2, "Determines number of primary " | |||
916 | "SLI rings to spread IOCB entries across"); | 977 | "SLI rings to spread IOCB entries across"); |
917 | 978 | ||
918 | /* | 979 | /* |
980 | # lpfc_multi_ring_rctl: If lpfc_multi_ring_support is enabled, this | ||
981 | # identifies what rctl value to configure the additional ring for. | ||
982 | # Value range is [1,0xff]. Default value is 4 (Unsolicated Data). | ||
983 | */ | ||
984 | LPFC_ATTR_R(multi_ring_rctl, FC_UNSOL_DATA, 1, | ||
985 | 255, "Identifies RCTL for additional ring configuration"); | ||
986 | |||
987 | /* | ||
988 | # lpfc_multi_ring_type: If lpfc_multi_ring_support is enabled, this | ||
989 | # identifies what type value to configure the additional ring for. | ||
990 | # Value range is [1,0xff]. Default value is 5 (LLC/SNAP). | ||
991 | */ | ||
992 | LPFC_ATTR_R(multi_ring_type, FC_LLC_SNAP, 1, | ||
993 | 255, "Identifies TYPE for additional ring configuration"); | ||
994 | |||
995 | /* | ||
919 | # lpfc_fdmi_on: controls FDMI support. | 996 | # lpfc_fdmi_on: controls FDMI support. |
920 | # 0 = no FDMI support | 997 | # 0 = no FDMI support |
921 | # 1 = support FDMI without attribute of hostname | 998 | # 1 = support FDMI without attribute of hostname |
@@ -946,6 +1023,15 @@ LPFC_ATTR_R(max_luns, 255, 0, 65535, | |||
946 | LPFC_ATTR_RW(poll_tmo, 10, 1, 255, | 1023 | LPFC_ATTR_RW(poll_tmo, 10, 1, 255, |
947 | "Milliseconds driver will wait between polling FCP ring"); | 1024 | "Milliseconds driver will wait between polling FCP ring"); |
948 | 1025 | ||
1026 | /* | ||
1027 | # lpfc_use_msi: Use MSI (Message Signaled Interrupts) in systems that | ||
1028 | # support this feature | ||
1029 | # 0 = MSI disabled (default) | ||
1030 | # 1 = MSI enabled | ||
1031 | # Value range is [0,1]. Default value is 0. | ||
1032 | */ | ||
1033 | LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible"); | ||
1034 | |||
949 | 1035 | ||
950 | struct class_device_attribute *lpfc_host_attrs[] = { | 1036 | struct class_device_attribute *lpfc_host_attrs[] = { |
951 | &class_device_attr_info, | 1037 | &class_device_attr_info, |
@@ -974,6 +1060,8 @@ struct class_device_attribute *lpfc_host_attrs[] = { | |||
974 | &class_device_attr_lpfc_cr_delay, | 1060 | &class_device_attr_lpfc_cr_delay, |
975 | &class_device_attr_lpfc_cr_count, | 1061 | &class_device_attr_lpfc_cr_count, |
976 | &class_device_attr_lpfc_multi_ring_support, | 1062 | &class_device_attr_lpfc_multi_ring_support, |
1063 | &class_device_attr_lpfc_multi_ring_rctl, | ||
1064 | &class_device_attr_lpfc_multi_ring_type, | ||
977 | &class_device_attr_lpfc_fdmi_on, | 1065 | &class_device_attr_lpfc_fdmi_on, |
978 | &class_device_attr_lpfc_max_luns, | 1066 | &class_device_attr_lpfc_max_luns, |
979 | &class_device_attr_nport_evt_cnt, | 1067 | &class_device_attr_nport_evt_cnt, |
@@ -982,8 +1070,10 @@ struct class_device_attribute *lpfc_host_attrs[] = { | |||
982 | &class_device_attr_issue_reset, | 1070 | &class_device_attr_issue_reset, |
983 | &class_device_attr_lpfc_poll, | 1071 | &class_device_attr_lpfc_poll, |
984 | &class_device_attr_lpfc_poll_tmo, | 1072 | &class_device_attr_lpfc_poll_tmo, |
1073 | &class_device_attr_lpfc_use_msi, | ||
1074 | &class_device_attr_lpfc_soft_wwnn, | ||
985 | &class_device_attr_lpfc_soft_wwpn, | 1075 | &class_device_attr_lpfc_soft_wwpn, |
986 | &class_device_attr_lpfc_soft_wwpn_enable, | 1076 | &class_device_attr_lpfc_soft_wwn_enable, |
987 | NULL, | 1077 | NULL, |
988 | }; | 1078 | }; |
989 | 1079 | ||
@@ -1771,6 +1861,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
1771 | lpfc_cr_delay_init(phba, lpfc_cr_delay); | 1861 | lpfc_cr_delay_init(phba, lpfc_cr_delay); |
1772 | lpfc_cr_count_init(phba, lpfc_cr_count); | 1862 | lpfc_cr_count_init(phba, lpfc_cr_count); |
1773 | lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support); | 1863 | lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support); |
1864 | lpfc_multi_ring_rctl_init(phba, lpfc_multi_ring_rctl); | ||
1865 | lpfc_multi_ring_type_init(phba, lpfc_multi_ring_type); | ||
1774 | lpfc_lun_queue_depth_init(phba, lpfc_lun_queue_depth); | 1866 | lpfc_lun_queue_depth_init(phba, lpfc_lun_queue_depth); |
1775 | lpfc_fcp_class_init(phba, lpfc_fcp_class); | 1867 | lpfc_fcp_class_init(phba, lpfc_fcp_class); |
1776 | lpfc_use_adisc_init(phba, lpfc_use_adisc); | 1868 | lpfc_use_adisc_init(phba, lpfc_use_adisc); |
@@ -1782,9 +1874,11 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) | |||
1782 | lpfc_discovery_threads_init(phba, lpfc_discovery_threads); | 1874 | lpfc_discovery_threads_init(phba, lpfc_discovery_threads); |
1783 | lpfc_max_luns_init(phba, lpfc_max_luns); | 1875 | lpfc_max_luns_init(phba, lpfc_max_luns); |
1784 | lpfc_poll_tmo_init(phba, lpfc_poll_tmo); | 1876 | lpfc_poll_tmo_init(phba, lpfc_poll_tmo); |
1877 | lpfc_use_msi_init(phba, lpfc_use_msi); | ||
1785 | lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo); | 1878 | lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo); |
1786 | lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo); | 1879 | lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo); |
1787 | phba->cfg_poll = lpfc_poll; | 1880 | phba->cfg_poll = lpfc_poll; |
1881 | phba->cfg_soft_wwnn = 0L; | ||
1788 | phba->cfg_soft_wwpn = 0L; | 1882 | phba->cfg_soft_wwpn = 0L; |
1789 | 1883 | ||
1790 | /* | 1884 | /* |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 3add7c237859..a51a41b7f15d 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -558,6 +558,14 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
558 | return; | 558 | return; |
559 | } | 559 | } |
560 | 560 | ||
561 | static void | ||
562 | lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | ||
563 | struct lpfc_iocbq * rspiocb) | ||
564 | { | ||
565 | lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb); | ||
566 | return; | ||
567 | } | ||
568 | |||
561 | void | 569 | void |
562 | lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp) | 570 | lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp) |
563 | { | 571 | { |
@@ -629,6 +637,8 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode) | |||
629 | bpl->tus.f.bdeSize = RNN_REQUEST_SZ; | 637 | bpl->tus.f.bdeSize = RNN_REQUEST_SZ; |
630 | else if (cmdcode == SLI_CTNS_RSNN_NN) | 638 | else if (cmdcode == SLI_CTNS_RSNN_NN) |
631 | bpl->tus.f.bdeSize = RSNN_REQUEST_SZ; | 639 | bpl->tus.f.bdeSize = RSNN_REQUEST_SZ; |
640 | else if (cmdcode == SLI_CTNS_RFF_ID) | ||
641 | bpl->tus.f.bdeSize = RFF_REQUEST_SZ; | ||
632 | else | 642 | else |
633 | bpl->tus.f.bdeSize = 0; | 643 | bpl->tus.f.bdeSize = 0; |
634 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 644 | bpl->tus.w = le32_to_cpu(bpl->tus.w); |
@@ -660,6 +670,17 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode) | |||
660 | cmpl = lpfc_cmpl_ct_cmd_rft_id; | 670 | cmpl = lpfc_cmpl_ct_cmd_rft_id; |
661 | break; | 671 | break; |
662 | 672 | ||
673 | case SLI_CTNS_RFF_ID: | ||
674 | CtReq->CommandResponse.bits.CmdRsp = | ||
675 | be16_to_cpu(SLI_CTNS_RFF_ID); | ||
676 | CtReq->un.rff.PortId = be32_to_cpu(phba->fc_myDID); | ||
677 | CtReq->un.rff.feature_res = 0; | ||
678 | CtReq->un.rff.feature_tgt = 0; | ||
679 | CtReq->un.rff.type_code = FC_FCP_DATA; | ||
680 | CtReq->un.rff.feature_init = 1; | ||
681 | cmpl = lpfc_cmpl_ct_cmd_rff_id; | ||
682 | break; | ||
683 | |||
663 | case SLI_CTNS_RNN_ID: | 684 | case SLI_CTNS_RNN_ID: |
664 | CtReq->CommandResponse.bits.CmdRsp = | 685 | CtReq->CommandResponse.bits.CmdRsp = |
665 | be16_to_cpu(SLI_CTNS_RNN_ID); | 686 | be16_to_cpu(SLI_CTNS_RNN_ID); |
@@ -934,7 +955,8 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode) | |||
934 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 955 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); |
935 | ae->ad.bits.AttrType = be16_to_cpu(OS_NAME_VERSION); | 956 | ae->ad.bits.AttrType = be16_to_cpu(OS_NAME_VERSION); |
936 | sprintf(ae->un.OsNameVersion, "%s %s %s", | 957 | sprintf(ae->un.OsNameVersion, "%s %s %s", |
937 | init_utsname()->sysname, init_utsname()->release, | 958 | init_utsname()->sysname, |
959 | init_utsname()->release, | ||
938 | init_utsname()->version); | 960 | init_utsname()->version); |
939 | len = strlen(ae->un.OsNameVersion); | 961 | len = strlen(ae->un.OsNameVersion); |
940 | len += (len & 3) ? (4 - (len & 3)) : 4; | 962 | len += (len & 3) ? (4 - (len & 3)) : 4; |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 71864cdc6c71..a5f33a0dd4e7 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -243,6 +243,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
243 | struct serv_parm *sp, IOCB_t *irsp) | 243 | struct serv_parm *sp, IOCB_t *irsp) |
244 | { | 244 | { |
245 | LPFC_MBOXQ_t *mbox; | 245 | LPFC_MBOXQ_t *mbox; |
246 | struct lpfc_dmabuf *mp; | ||
246 | int rc; | 247 | int rc; |
247 | 248 | ||
248 | spin_lock_irq(phba->host->host_lock); | 249 | spin_lock_irq(phba->host->host_lock); |
@@ -307,10 +308,14 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, | |||
307 | 308 | ||
308 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); | 309 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); |
309 | if (rc == MBX_NOT_FINISHED) | 310 | if (rc == MBX_NOT_FINISHED) |
310 | goto fail_free_mbox; | 311 | goto fail_issue_reg_login; |
311 | 312 | ||
312 | return 0; | 313 | return 0; |
313 | 314 | ||
315 | fail_issue_reg_login: | ||
316 | mp = (struct lpfc_dmabuf *) mbox->context1; | ||
317 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | ||
318 | kfree(mp); | ||
314 | fail_free_mbox: | 319 | fail_free_mbox: |
315 | mempool_free(mbox, phba->mbox_mem_pool); | 320 | mempool_free(mbox, phba->mbox_mem_pool); |
316 | fail: | 321 | fail: |
@@ -657,6 +662,12 @@ lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp, | |||
657 | uint8_t name[sizeof (struct lpfc_name)]; | 662 | uint8_t name[sizeof (struct lpfc_name)]; |
658 | uint32_t rc; | 663 | uint32_t rc; |
659 | 664 | ||
665 | /* Fabric nodes can have the same WWPN so we don't bother searching | ||
666 | * by WWPN. Just return the ndlp that was given to us. | ||
667 | */ | ||
668 | if (ndlp->nlp_type & NLP_FABRIC) | ||
669 | return ndlp; | ||
670 | |||
660 | lp = (uint32_t *) prsp->virt; | 671 | lp = (uint32_t *) prsp->virt; |
661 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); | 672 | sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t)); |
662 | memset(name, 0, sizeof (struct lpfc_name)); | 673 | memset(name, 0, sizeof (struct lpfc_name)); |
@@ -1122,7 +1133,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1122 | mempool_free(mbox, | 1133 | mempool_free(mbox, |
1123 | phba->mbox_mem_pool); | 1134 | phba->mbox_mem_pool); |
1124 | lpfc_disc_flush_list(phba); | 1135 | lpfc_disc_flush_list(phba); |
1125 | psli->ring[(psli->ip_ring)]. | 1136 | psli->ring[(psli->extra_ring)]. |
1126 | flag &= | 1137 | flag &= |
1127 | ~LPFC_STOP_IOCB_EVENT; | 1138 | ~LPFC_STOP_IOCB_EVENT; |
1128 | psli->ring[(psli->fcp_ring)]. | 1139 | psli->ring[(psli->fcp_ring)]. |
@@ -1851,6 +1862,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1851 | IOCB_t *irsp; | 1862 | IOCB_t *irsp; |
1852 | struct lpfc_nodelist *ndlp; | 1863 | struct lpfc_nodelist *ndlp; |
1853 | LPFC_MBOXQ_t *mbox = NULL; | 1864 | LPFC_MBOXQ_t *mbox = NULL; |
1865 | struct lpfc_dmabuf *mp; | ||
1854 | 1866 | ||
1855 | irsp = &rspiocb->iocb; | 1867 | irsp = &rspiocb->iocb; |
1856 | 1868 | ||
@@ -1862,6 +1874,11 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1862 | /* Check to see if link went down during discovery */ | 1874 | /* Check to see if link went down during discovery */ |
1863 | if ((lpfc_els_chk_latt(phba)) || !ndlp) { | 1875 | if ((lpfc_els_chk_latt(phba)) || !ndlp) { |
1864 | if (mbox) { | 1876 | if (mbox) { |
1877 | mp = (struct lpfc_dmabuf *) mbox->context1; | ||
1878 | if (mp) { | ||
1879 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | ||
1880 | kfree(mp); | ||
1881 | } | ||
1865 | mempool_free( mbox, phba->mbox_mem_pool); | 1882 | mempool_free( mbox, phba->mbox_mem_pool); |
1866 | } | 1883 | } |
1867 | goto out; | 1884 | goto out; |
@@ -1893,9 +1910,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1893 | } | 1910 | } |
1894 | /* NOTE: we should have messages for unsuccessful | 1911 | /* NOTE: we should have messages for unsuccessful |
1895 | reglogin */ | 1912 | reglogin */ |
1896 | mempool_free( mbox, phba->mbox_mem_pool); | ||
1897 | } else { | 1913 | } else { |
1898 | mempool_free( mbox, phba->mbox_mem_pool); | ||
1899 | /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */ | 1914 | /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */ |
1900 | if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | 1915 | if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && |
1901 | ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || | 1916 | ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || |
@@ -1907,6 +1922,12 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | |||
1907 | } | 1922 | } |
1908 | } | 1923 | } |
1909 | } | 1924 | } |
1925 | mp = (struct lpfc_dmabuf *) mbox->context1; | ||
1926 | if (mp) { | ||
1927 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | ||
1928 | kfree(mp); | ||
1929 | } | ||
1930 | mempool_free(mbox, phba->mbox_mem_pool); | ||
1910 | } | 1931 | } |
1911 | out: | 1932 | out: |
1912 | if (ndlp) { | 1933 | if (ndlp) { |
@@ -2644,6 +2665,7 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba) | |||
2644 | ndlp->nlp_type |= NLP_FABRIC; | 2665 | ndlp->nlp_type |= NLP_FABRIC; |
2645 | ndlp->nlp_prev_state = ndlp->nlp_state; | 2666 | ndlp->nlp_prev_state = ndlp->nlp_state; |
2646 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; | 2667 | ndlp->nlp_state = NLP_STE_PLOGI_ISSUE; |
2668 | lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST); | ||
2647 | lpfc_issue_els_plogi(phba, NameServer_DID, 0); | 2669 | lpfc_issue_els_plogi(phba, NameServer_DID, 0); |
2648 | /* Wait for NameServer login cmpl before we can | 2670 | /* Wait for NameServer login cmpl before we can |
2649 | continue */ | 2671 | continue */ |
@@ -3039,7 +3061,7 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba, | |||
3039 | /* FARP-REQ received from DID <did> */ | 3061 | /* FARP-REQ received from DID <did> */ |
3040 | lpfc_printf_log(phba, | 3062 | lpfc_printf_log(phba, |
3041 | KERN_INFO, | 3063 | KERN_INFO, |
3042 | LOG_IP, | 3064 | LOG_ELS, |
3043 | "%d:0601 FARP-REQ received from DID x%x\n", | 3065 | "%d:0601 FARP-REQ received from DID x%x\n", |
3044 | phba->brd_no, did); | 3066 | phba->brd_no, did); |
3045 | 3067 | ||
@@ -3101,7 +3123,7 @@ lpfc_els_rcv_farpr(struct lpfc_hba * phba, | |||
3101 | /* FARP-RSP received from DID <did> */ | 3123 | /* FARP-RSP received from DID <did> */ |
3102 | lpfc_printf_log(phba, | 3124 | lpfc_printf_log(phba, |
3103 | KERN_INFO, | 3125 | KERN_INFO, |
3104 | LOG_IP, | 3126 | LOG_ELS, |
3105 | "%d:0600 FARP-RSP received from DID x%x\n", | 3127 | "%d:0600 FARP-RSP received from DID x%x\n", |
3106 | phba->brd_no, did); | 3128 | phba->brd_no, did); |
3107 | 3129 | ||
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 19c79a0549a7..c39564e85e94 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -525,7 +525,7 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
525 | psli = &phba->sli; | 525 | psli = &phba->sli; |
526 | mb = &pmb->mb; | 526 | mb = &pmb->mb; |
527 | /* Since we don't do discovery right now, turn these off here */ | 527 | /* Since we don't do discovery right now, turn these off here */ |
528 | psli->ring[psli->ip_ring].flag &= ~LPFC_STOP_IOCB_EVENT; | 528 | psli->ring[psli->extra_ring].flag &= ~LPFC_STOP_IOCB_EVENT; |
529 | psli->ring[psli->fcp_ring].flag &= ~LPFC_STOP_IOCB_EVENT; | 529 | psli->ring[psli->fcp_ring].flag &= ~LPFC_STOP_IOCB_EVENT; |
530 | psli->ring[psli->next_ring].flag &= ~LPFC_STOP_IOCB_EVENT; | 530 | psli->ring[psli->next_ring].flag &= ~LPFC_STOP_IOCB_EVENT; |
531 | 531 | ||
@@ -641,7 +641,7 @@ out: | |||
641 | if (rc == MBX_NOT_FINISHED) { | 641 | if (rc == MBX_NOT_FINISHED) { |
642 | mempool_free(pmb, phba->mbox_mem_pool); | 642 | mempool_free(pmb, phba->mbox_mem_pool); |
643 | lpfc_disc_flush_list(phba); | 643 | lpfc_disc_flush_list(phba); |
644 | psli->ring[(psli->ip_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; | 644 | psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; |
645 | psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; | 645 | psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; |
646 | psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; | 646 | psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; |
647 | phba->hba_state = LPFC_HBA_READY; | 647 | phba->hba_state = LPFC_HBA_READY; |
@@ -672,6 +672,8 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
672 | 672 | ||
673 | memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt, | 673 | memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt, |
674 | sizeof (struct serv_parm)); | 674 | sizeof (struct serv_parm)); |
675 | if (phba->cfg_soft_wwnn) | ||
676 | u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn); | ||
675 | if (phba->cfg_soft_wwpn) | 677 | if (phba->cfg_soft_wwpn) |
676 | u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn); | 678 | u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn); |
677 | memcpy((uint8_t *) & phba->fc_nodename, | 679 | memcpy((uint8_t *) & phba->fc_nodename, |
@@ -696,7 +698,7 @@ out: | |||
696 | == MBX_NOT_FINISHED) { | 698 | == MBX_NOT_FINISHED) { |
697 | mempool_free( pmb, phba->mbox_mem_pool); | 699 | mempool_free( pmb, phba->mbox_mem_pool); |
698 | lpfc_disc_flush_list(phba); | 700 | lpfc_disc_flush_list(phba); |
699 | psli->ring[(psli->ip_ring)].flag &= | 701 | psli->ring[(psli->extra_ring)].flag &= |
700 | ~LPFC_STOP_IOCB_EVENT; | 702 | ~LPFC_STOP_IOCB_EVENT; |
701 | psli->ring[(psli->fcp_ring)].flag &= | 703 | psli->ring[(psli->fcp_ring)].flag &= |
702 | ~LPFC_STOP_IOCB_EVENT; | 704 | ~LPFC_STOP_IOCB_EVENT; |
@@ -715,6 +717,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) | |||
715 | { | 717 | { |
716 | int i; | 718 | int i; |
717 | LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox; | 719 | LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox; |
720 | struct lpfc_dmabuf *mp; | ||
721 | int rc; | ||
722 | |||
718 | sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 723 | sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
719 | cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 724 | cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
720 | 725 | ||
@@ -793,16 +798,27 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) | |||
793 | if (sparam_mbox) { | 798 | if (sparam_mbox) { |
794 | lpfc_read_sparam(phba, sparam_mbox); | 799 | lpfc_read_sparam(phba, sparam_mbox); |
795 | sparam_mbox->mbox_cmpl = lpfc_mbx_cmpl_read_sparam; | 800 | sparam_mbox->mbox_cmpl = lpfc_mbx_cmpl_read_sparam; |
796 | lpfc_sli_issue_mbox(phba, sparam_mbox, | 801 | rc = lpfc_sli_issue_mbox(phba, sparam_mbox, |
797 | (MBX_NOWAIT | MBX_STOP_IOCB)); | 802 | (MBX_NOWAIT | MBX_STOP_IOCB)); |
803 | if (rc == MBX_NOT_FINISHED) { | ||
804 | mp = (struct lpfc_dmabuf *) sparam_mbox->context1; | ||
805 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | ||
806 | kfree(mp); | ||
807 | mempool_free(sparam_mbox, phba->mbox_mem_pool); | ||
808 | if (cfglink_mbox) | ||
809 | mempool_free(cfglink_mbox, phba->mbox_mem_pool); | ||
810 | return; | ||
811 | } | ||
798 | } | 812 | } |
799 | 813 | ||
800 | if (cfglink_mbox) { | 814 | if (cfglink_mbox) { |
801 | phba->hba_state = LPFC_LOCAL_CFG_LINK; | 815 | phba->hba_state = LPFC_LOCAL_CFG_LINK; |
802 | lpfc_config_link(phba, cfglink_mbox); | 816 | lpfc_config_link(phba, cfglink_mbox); |
803 | cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; | 817 | cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link; |
804 | lpfc_sli_issue_mbox(phba, cfglink_mbox, | 818 | rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, |
805 | (MBX_NOWAIT | MBX_STOP_IOCB)); | 819 | (MBX_NOWAIT | MBX_STOP_IOCB)); |
820 | if (rc == MBX_NOT_FINISHED) | ||
821 | mempool_free(cfglink_mbox, phba->mbox_mem_pool); | ||
806 | } | 822 | } |
807 | } | 823 | } |
808 | 824 | ||
@@ -1067,6 +1083,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) | |||
1067 | lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RNN_ID); | 1083 | lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RNN_ID); |
1068 | lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RSNN_NN); | 1084 | lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RSNN_NN); |
1069 | lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFT_ID); | 1085 | lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFT_ID); |
1086 | lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFF_ID); | ||
1070 | } | 1087 | } |
1071 | 1088 | ||
1072 | phba->fc_ns_retry = 0; | 1089 | phba->fc_ns_retry = 0; |
@@ -1423,7 +1440,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba, | |||
1423 | if (iocb->context1 == (uint8_t *) ndlp) | 1440 | if (iocb->context1 == (uint8_t *) ndlp) |
1424 | return 1; | 1441 | return 1; |
1425 | } | 1442 | } |
1426 | } else if (pring->ringno == psli->ip_ring) { | 1443 | } else if (pring->ringno == psli->extra_ring) { |
1427 | 1444 | ||
1428 | } else if (pring->ringno == psli->fcp_ring) { | 1445 | } else if (pring->ringno == psli->fcp_ring) { |
1429 | /* Skip match check if waiting to relogin to FCP target */ | 1446 | /* Skip match check if waiting to relogin to FCP target */ |
@@ -1680,112 +1697,38 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did) | |||
1680 | struct lpfc_nodelist * | 1697 | struct lpfc_nodelist * |
1681 | lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) | 1698 | lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) |
1682 | { | 1699 | { |
1683 | struct lpfc_nodelist *ndlp, *next_ndlp; | 1700 | struct lpfc_nodelist *ndlp; |
1701 | struct list_head *lists[]={&phba->fc_nlpunmap_list, | ||
1702 | &phba->fc_nlpmap_list, | ||
1703 | &phba->fc_plogi_list, | ||
1704 | &phba->fc_adisc_list, | ||
1705 | &phba->fc_reglogin_list, | ||
1706 | &phba->fc_prli_list, | ||
1707 | &phba->fc_npr_list, | ||
1708 | &phba->fc_unused_list}; | ||
1709 | uint32_t search[]={NLP_SEARCH_UNMAPPED, | ||
1710 | NLP_SEARCH_MAPPED, | ||
1711 | NLP_SEARCH_PLOGI, | ||
1712 | NLP_SEARCH_ADISC, | ||
1713 | NLP_SEARCH_REGLOGIN, | ||
1714 | NLP_SEARCH_PRLI, | ||
1715 | NLP_SEARCH_NPR, | ||
1716 | NLP_SEARCH_UNUSED}; | ||
1717 | int i; | ||
1684 | uint32_t data1; | 1718 | uint32_t data1; |
1685 | 1719 | ||
1686 | spin_lock_irq(phba->host->host_lock); | 1720 | spin_lock_irq(phba->host->host_lock); |
1687 | if (order & NLP_SEARCH_UNMAPPED) { | 1721 | for (i = 0; i < ARRAY_SIZE(lists); i++ ) { |
1688 | list_for_each_entry_safe(ndlp, next_ndlp, | 1722 | if (!(order & search[i])) |
1689 | &phba->fc_nlpunmap_list, nlp_listp) { | 1723 | continue; |
1690 | if (lpfc_matchdid(phba, ndlp, did)) { | 1724 | list_for_each_entry(ndlp, lists[i], nlp_listp) { |
1691 | data1 = (((uint32_t) ndlp->nlp_state << 24) | | ||
1692 | ((uint32_t) ndlp->nlp_xri << 16) | | ||
1693 | ((uint32_t) ndlp->nlp_type << 8) | | ||
1694 | ((uint32_t) ndlp->nlp_rpi & 0xff)); | ||
1695 | /* FIND node DID unmapped */ | ||
1696 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | ||
1697 | "%d:0929 FIND node DID unmapped" | ||
1698 | " Data: x%p x%x x%x x%x\n", | ||
1699 | phba->brd_no, | ||
1700 | ndlp, ndlp->nlp_DID, | ||
1701 | ndlp->nlp_flag, data1); | ||
1702 | spin_unlock_irq(phba->host->host_lock); | ||
1703 | return ndlp; | ||
1704 | } | ||
1705 | } | ||
1706 | } | ||
1707 | |||
1708 | if (order & NLP_SEARCH_MAPPED) { | ||
1709 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list, | ||
1710 | nlp_listp) { | ||
1711 | if (lpfc_matchdid(phba, ndlp, did)) { | ||
1712 | |||
1713 | data1 = (((uint32_t) ndlp->nlp_state << 24) | | ||
1714 | ((uint32_t) ndlp->nlp_xri << 16) | | ||
1715 | ((uint32_t) ndlp->nlp_type << 8) | | ||
1716 | ((uint32_t) ndlp->nlp_rpi & 0xff)); | ||
1717 | /* FIND node DID mapped */ | ||
1718 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | ||
1719 | "%d:0930 FIND node DID mapped " | ||
1720 | "Data: x%p x%x x%x x%x\n", | ||
1721 | phba->brd_no, | ||
1722 | ndlp, ndlp->nlp_DID, | ||
1723 | ndlp->nlp_flag, data1); | ||
1724 | spin_unlock_irq(phba->host->host_lock); | ||
1725 | return ndlp; | ||
1726 | } | ||
1727 | } | ||
1728 | } | ||
1729 | |||
1730 | if (order & NLP_SEARCH_PLOGI) { | ||
1731 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list, | ||
1732 | nlp_listp) { | ||
1733 | if (lpfc_matchdid(phba, ndlp, did)) { | ||
1734 | |||
1735 | data1 = (((uint32_t) ndlp->nlp_state << 24) | | ||
1736 | ((uint32_t) ndlp->nlp_xri << 16) | | ||
1737 | ((uint32_t) ndlp->nlp_type << 8) | | ||
1738 | ((uint32_t) ndlp->nlp_rpi & 0xff)); | ||
1739 | /* LOG change to PLOGI */ | ||
1740 | /* FIND node DID plogi */ | ||
1741 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | ||
1742 | "%d:0908 FIND node DID plogi " | ||
1743 | "Data: x%p x%x x%x x%x\n", | ||
1744 | phba->brd_no, | ||
1745 | ndlp, ndlp->nlp_DID, | ||
1746 | ndlp->nlp_flag, data1); | ||
1747 | spin_unlock_irq(phba->host->host_lock); | ||
1748 | return ndlp; | ||
1749 | } | ||
1750 | } | ||
1751 | } | ||
1752 | |||
1753 | if (order & NLP_SEARCH_ADISC) { | ||
1754 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, | ||
1755 | nlp_listp) { | ||
1756 | if (lpfc_matchdid(phba, ndlp, did)) { | ||
1757 | |||
1758 | data1 = (((uint32_t) ndlp->nlp_state << 24) | | ||
1759 | ((uint32_t) ndlp->nlp_xri << 16) | | ||
1760 | ((uint32_t) ndlp->nlp_type << 8) | | ||
1761 | ((uint32_t) ndlp->nlp_rpi & 0xff)); | ||
1762 | /* LOG change to ADISC */ | ||
1763 | /* FIND node DID adisc */ | ||
1764 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | ||
1765 | "%d:0931 FIND node DID adisc " | ||
1766 | "Data: x%p x%x x%x x%x\n", | ||
1767 | phba->brd_no, | ||
1768 | ndlp, ndlp->nlp_DID, | ||
1769 | ndlp->nlp_flag, data1); | ||
1770 | spin_unlock_irq(phba->host->host_lock); | ||
1771 | return ndlp; | ||
1772 | } | ||
1773 | } | ||
1774 | } | ||
1775 | |||
1776 | if (order & NLP_SEARCH_REGLOGIN) { | ||
1777 | list_for_each_entry_safe(ndlp, next_ndlp, | ||
1778 | &phba->fc_reglogin_list, nlp_listp) { | ||
1779 | if (lpfc_matchdid(phba, ndlp, did)) { | 1725 | if (lpfc_matchdid(phba, ndlp, did)) { |
1780 | |||
1781 | data1 = (((uint32_t) ndlp->nlp_state << 24) | | 1726 | data1 = (((uint32_t) ndlp->nlp_state << 24) | |
1782 | ((uint32_t) ndlp->nlp_xri << 16) | | 1727 | ((uint32_t) ndlp->nlp_xri << 16) | |
1783 | ((uint32_t) ndlp->nlp_type << 8) | | 1728 | ((uint32_t) ndlp->nlp_type << 8) | |
1784 | ((uint32_t) ndlp->nlp_rpi & 0xff)); | 1729 | ((uint32_t) ndlp->nlp_rpi & 0xff)); |
1785 | /* LOG change to REGLOGIN */ | ||
1786 | /* FIND node DID reglogin */ | ||
1787 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | 1730 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, |
1788 | "%d:0901 FIND node DID reglogin" | 1731 | "%d:0929 FIND node DID " |
1789 | " Data: x%p x%x x%x x%x\n", | 1732 | " Data: x%p x%x x%x x%x\n", |
1790 | phba->brd_no, | 1733 | phba->brd_no, |
1791 | ndlp, ndlp->nlp_DID, | 1734 | ndlp, ndlp->nlp_DID, |
@@ -1795,86 +1738,12 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) | |||
1795 | } | 1738 | } |
1796 | } | 1739 | } |
1797 | } | 1740 | } |
1798 | |||
1799 | if (order & NLP_SEARCH_PRLI) { | ||
1800 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list, | ||
1801 | nlp_listp) { | ||
1802 | if (lpfc_matchdid(phba, ndlp, did)) { | ||
1803 | |||
1804 | data1 = (((uint32_t) ndlp->nlp_state << 24) | | ||
1805 | ((uint32_t) ndlp->nlp_xri << 16) | | ||
1806 | ((uint32_t) ndlp->nlp_type << 8) | | ||
1807 | ((uint32_t) ndlp->nlp_rpi & 0xff)); | ||
1808 | /* LOG change to PRLI */ | ||
1809 | /* FIND node DID prli */ | ||
1810 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | ||
1811 | "%d:0902 FIND node DID prli " | ||
1812 | "Data: x%p x%x x%x x%x\n", | ||
1813 | phba->brd_no, | ||
1814 | ndlp, ndlp->nlp_DID, | ||
1815 | ndlp->nlp_flag, data1); | ||
1816 | spin_unlock_irq(phba->host->host_lock); | ||
1817 | return ndlp; | ||
1818 | } | ||
1819 | } | ||
1820 | } | ||
1821 | |||
1822 | if (order & NLP_SEARCH_NPR) { | ||
1823 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list, | ||
1824 | nlp_listp) { | ||
1825 | if (lpfc_matchdid(phba, ndlp, did)) { | ||
1826 | |||
1827 | data1 = (((uint32_t) ndlp->nlp_state << 24) | | ||
1828 | ((uint32_t) ndlp->nlp_xri << 16) | | ||
1829 | ((uint32_t) ndlp->nlp_type << 8) | | ||
1830 | ((uint32_t) ndlp->nlp_rpi & 0xff)); | ||
1831 | /* LOG change to NPR */ | ||
1832 | /* FIND node DID npr */ | ||
1833 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | ||
1834 | "%d:0903 FIND node DID npr " | ||
1835 | "Data: x%p x%x x%x x%x\n", | ||
1836 | phba->brd_no, | ||
1837 | ndlp, ndlp->nlp_DID, | ||
1838 | ndlp->nlp_flag, data1); | ||
1839 | spin_unlock_irq(phba->host->host_lock); | ||
1840 | return ndlp; | ||
1841 | } | ||
1842 | } | ||
1843 | } | ||
1844 | |||
1845 | if (order & NLP_SEARCH_UNUSED) { | ||
1846 | list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list, | ||
1847 | nlp_listp) { | ||
1848 | if (lpfc_matchdid(phba, ndlp, did)) { | ||
1849 | |||
1850 | data1 = (((uint32_t) ndlp->nlp_state << 24) | | ||
1851 | ((uint32_t) ndlp->nlp_xri << 16) | | ||
1852 | ((uint32_t) ndlp->nlp_type << 8) | | ||
1853 | ((uint32_t) ndlp->nlp_rpi & 0xff)); | ||
1854 | /* LOG change to UNUSED */ | ||
1855 | /* FIND node DID unused */ | ||
1856 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, | ||
1857 | "%d:0905 FIND node DID unused " | ||
1858 | "Data: x%p x%x x%x x%x\n", | ||
1859 | phba->brd_no, | ||
1860 | ndlp, ndlp->nlp_DID, | ||
1861 | ndlp->nlp_flag, data1); | ||
1862 | spin_unlock_irq(phba->host->host_lock); | ||
1863 | return ndlp; | ||
1864 | } | ||
1865 | } | ||
1866 | } | ||
1867 | |||
1868 | spin_unlock_irq(phba->host->host_lock); | 1741 | spin_unlock_irq(phba->host->host_lock); |
1869 | 1742 | ||
1870 | /* FIND node did <did> NOT FOUND */ | 1743 | /* FIND node did <did> NOT FOUND */ |
1871 | lpfc_printf_log(phba, | 1744 | lpfc_printf_log(phba, KERN_INFO, LOG_NODE, |
1872 | KERN_INFO, | ||
1873 | LOG_NODE, | ||
1874 | "%d:0932 FIND node did x%x NOT FOUND Data: x%x\n", | 1745 | "%d:0932 FIND node did x%x NOT FOUND Data: x%x\n", |
1875 | phba->brd_no, did, order); | 1746 | phba->brd_no, did, order); |
1876 | |||
1877 | /* no match found */ | ||
1878 | return NULL; | 1747 | return NULL; |
1879 | } | 1748 | } |
1880 | 1749 | ||
@@ -2036,7 +1905,7 @@ lpfc_disc_start(struct lpfc_hba * phba) | |||
2036 | if (rc == MBX_NOT_FINISHED) { | 1905 | if (rc == MBX_NOT_FINISHED) { |
2037 | mempool_free( mbox, phba->mbox_mem_pool); | 1906 | mempool_free( mbox, phba->mbox_mem_pool); |
2038 | lpfc_disc_flush_list(phba); | 1907 | lpfc_disc_flush_list(phba); |
2039 | psli->ring[(psli->ip_ring)].flag &= | 1908 | psli->ring[(psli->extra_ring)].flag &= |
2040 | ~LPFC_STOP_IOCB_EVENT; | 1909 | ~LPFC_STOP_IOCB_EVENT; |
2041 | psli->ring[(psli->fcp_ring)].flag &= | 1910 | psli->ring[(psli->fcp_ring)].flag &= |
2042 | ~LPFC_STOP_IOCB_EVENT; | 1911 | ~LPFC_STOP_IOCB_EVENT; |
@@ -2415,7 +2284,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) | |||
2415 | 2284 | ||
2416 | if (clrlaerr) { | 2285 | if (clrlaerr) { |
2417 | lpfc_disc_flush_list(phba); | 2286 | lpfc_disc_flush_list(phba); |
2418 | psli->ring[(psli->ip_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; | 2287 | psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; |
2419 | psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; | 2288 | psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; |
2420 | psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; | 2289 | psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT; |
2421 | phba->hba_state = LPFC_HBA_READY; | 2290 | phba->hba_state = LPFC_HBA_READY; |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index eedf98801366..f79cb6136906 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -42,14 +42,14 @@ | |||
42 | #define FCELSSIZE 1024 /* maximum ELS transfer size */ | 42 | #define FCELSSIZE 1024 /* maximum ELS transfer size */ |
43 | 43 | ||
44 | #define LPFC_FCP_RING 0 /* ring 0 for FCP initiator commands */ | 44 | #define LPFC_FCP_RING 0 /* ring 0 for FCP initiator commands */ |
45 | #define LPFC_IP_RING 1 /* ring 1 for IP commands */ | 45 | #define LPFC_EXTRA_RING 1 /* ring 1 for other protocols */ |
46 | #define LPFC_ELS_RING 2 /* ring 2 for ELS commands */ | 46 | #define LPFC_ELS_RING 2 /* ring 2 for ELS commands */ |
47 | #define LPFC_FCP_NEXT_RING 3 | 47 | #define LPFC_FCP_NEXT_RING 3 |
48 | 48 | ||
49 | #define SLI2_IOCB_CMD_R0_ENTRIES 172 /* SLI-2 FCP command ring entries */ | 49 | #define SLI2_IOCB_CMD_R0_ENTRIES 172 /* SLI-2 FCP command ring entries */ |
50 | #define SLI2_IOCB_RSP_R0_ENTRIES 134 /* SLI-2 FCP response ring entries */ | 50 | #define SLI2_IOCB_RSP_R0_ENTRIES 134 /* SLI-2 FCP response ring entries */ |
51 | #define SLI2_IOCB_CMD_R1_ENTRIES 4 /* SLI-2 IP command ring entries */ | 51 | #define SLI2_IOCB_CMD_R1_ENTRIES 4 /* SLI-2 extra command ring entries */ |
52 | #define SLI2_IOCB_RSP_R1_ENTRIES 4 /* SLI-2 IP response ring entries */ | 52 | #define SLI2_IOCB_RSP_R1_ENTRIES 4 /* SLI-2 extra response ring entries */ |
53 | #define SLI2_IOCB_CMD_R1XTRA_ENTRIES 36 /* SLI-2 extra FCP cmd ring entries */ | 53 | #define SLI2_IOCB_CMD_R1XTRA_ENTRIES 36 /* SLI-2 extra FCP cmd ring entries */ |
54 | #define SLI2_IOCB_RSP_R1XTRA_ENTRIES 52 /* SLI-2 extra FCP rsp ring entries */ | 54 | #define SLI2_IOCB_RSP_R1XTRA_ENTRIES 52 /* SLI-2 extra FCP rsp ring entries */ |
55 | #define SLI2_IOCB_CMD_R2_ENTRIES 20 /* SLI-2 ELS command ring entries */ | 55 | #define SLI2_IOCB_CMD_R2_ENTRIES 20 /* SLI-2 ELS command ring entries */ |
@@ -121,6 +121,20 @@ struct lpfc_sli_ct_request { | |||
121 | 121 | ||
122 | uint32_t rsvd[7]; | 122 | uint32_t rsvd[7]; |
123 | } rft; | 123 | } rft; |
124 | struct rff { | ||
125 | uint32_t PortId; | ||
126 | uint8_t reserved[2]; | ||
127 | #ifdef __BIG_ENDIAN_BITFIELD | ||
128 | uint8_t feature_res:6; | ||
129 | uint8_t feature_init:1; | ||
130 | uint8_t feature_tgt:1; | ||
131 | #else /* __LITTLE_ENDIAN_BITFIELD */ | ||
132 | uint8_t feature_tgt:1; | ||
133 | uint8_t feature_init:1; | ||
134 | uint8_t feature_res:6; | ||
135 | #endif | ||
136 | uint8_t type_code; /* type=8 for FCP */ | ||
137 | } rff; | ||
124 | struct rnn { | 138 | struct rnn { |
125 | uint32_t PortId; /* For RNN_ID requests */ | 139 | uint32_t PortId; /* For RNN_ID requests */ |
126 | uint8_t wwnn[8]; | 140 | uint8_t wwnn[8]; |
@@ -136,6 +150,7 @@ struct lpfc_sli_ct_request { | |||
136 | #define SLI_CT_REVISION 1 | 150 | #define SLI_CT_REVISION 1 |
137 | #define GID_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 260) | 151 | #define GID_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 260) |
138 | #define RFT_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 228) | 152 | #define RFT_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 228) |
153 | #define RFF_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 235) | ||
139 | #define RNN_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 252) | 154 | #define RNN_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 252) |
140 | #define RSNN_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request)) | 155 | #define RSNN_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request)) |
141 | 156 | ||
@@ -225,6 +240,7 @@ struct lpfc_sli_ct_request { | |||
225 | #define SLI_CTNS_RNN_ID 0x0213 | 240 | #define SLI_CTNS_RNN_ID 0x0213 |
226 | #define SLI_CTNS_RCS_ID 0x0214 | 241 | #define SLI_CTNS_RCS_ID 0x0214 |
227 | #define SLI_CTNS_RFT_ID 0x0217 | 242 | #define SLI_CTNS_RFT_ID 0x0217 |
243 | #define SLI_CTNS_RFF_ID 0x021F | ||
228 | #define SLI_CTNS_RSPN_ID 0x0218 | 244 | #define SLI_CTNS_RSPN_ID 0x0218 |
229 | #define SLI_CTNS_RPT_ID 0x021A | 245 | #define SLI_CTNS_RPT_ID 0x021A |
230 | #define SLI_CTNS_RIP_NN 0x0235 | 246 | #define SLI_CTNS_RIP_NN 0x0235 |
@@ -1089,12 +1105,6 @@ typedef struct { | |||
1089 | #define PCI_DEVICE_ID_ZEPHYR_SCSP 0xfe11 | 1105 | #define PCI_DEVICE_ID_ZEPHYR_SCSP 0xfe11 |
1090 | #define PCI_DEVICE_ID_ZEPHYR_DCSP 0xfe12 | 1106 | #define PCI_DEVICE_ID_ZEPHYR_DCSP 0xfe12 |
1091 | 1107 | ||
1092 | #define PCI_SUBSYSTEM_ID_LP11000S 0xfc11 | ||
1093 | #define PCI_SUBSYSTEM_ID_LP11002S 0xfc12 | ||
1094 | #define PCI_SUBSYSTEM_ID_LPE11000S 0xfc21 | ||
1095 | #define PCI_SUBSYSTEM_ID_LPE11002S 0xfc22 | ||
1096 | #define PCI_SUBSYSTEM_ID_LPE11010S 0xfc2A | ||
1097 | |||
1098 | #define JEDEC_ID_ADDRESS 0x0080001c | 1108 | #define JEDEC_ID_ADDRESS 0x0080001c |
1099 | #define FIREFLY_JEDEC_ID 0x1ACC | 1109 | #define FIREFLY_JEDEC_ID 0x1ACC |
1100 | #define SUPERFLY_JEDEC_ID 0x0020 | 1110 | #define SUPERFLY_JEDEC_ID 0x0020 |
@@ -1284,6 +1294,10 @@ typedef struct { /* FireFly BIU registers */ | |||
1284 | #define CMD_FCP_IREAD_CX 0x1B | 1294 | #define CMD_FCP_IREAD_CX 0x1B |
1285 | #define CMD_FCP_ICMND_CR 0x1C | 1295 | #define CMD_FCP_ICMND_CR 0x1C |
1286 | #define CMD_FCP_ICMND_CX 0x1D | 1296 | #define CMD_FCP_ICMND_CX 0x1D |
1297 | #define CMD_FCP_TSEND_CX 0x1F | ||
1298 | #define CMD_FCP_TRECEIVE_CX 0x21 | ||
1299 | #define CMD_FCP_TRSP_CX 0x23 | ||
1300 | #define CMD_FCP_AUTO_TRSP_CX 0x29 | ||
1287 | 1301 | ||
1288 | #define CMD_ADAPTER_MSG 0x20 | 1302 | #define CMD_ADAPTER_MSG 0x20 |
1289 | #define CMD_ADAPTER_DUMP 0x22 | 1303 | #define CMD_ADAPTER_DUMP 0x22 |
@@ -1310,6 +1324,9 @@ typedef struct { /* FireFly BIU registers */ | |||
1310 | #define CMD_FCP_IREAD64_CX 0x9B | 1324 | #define CMD_FCP_IREAD64_CX 0x9B |
1311 | #define CMD_FCP_ICMND64_CR 0x9C | 1325 | #define CMD_FCP_ICMND64_CR 0x9C |
1312 | #define CMD_FCP_ICMND64_CX 0x9D | 1326 | #define CMD_FCP_ICMND64_CX 0x9D |
1327 | #define CMD_FCP_TSEND64_CX 0x9F | ||
1328 | #define CMD_FCP_TRECEIVE64_CX 0xA1 | ||
1329 | #define CMD_FCP_TRSP64_CX 0xA3 | ||
1313 | 1330 | ||
1314 | #define CMD_GEN_REQUEST64_CR 0xC2 | 1331 | #define CMD_GEN_REQUEST64_CR 0xC2 |
1315 | #define CMD_GEN_REQUEST64_CX 0xC3 | 1332 | #define CMD_GEN_REQUEST64_CX 0xC3 |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index a5723ad0a099..afca45cdbcef 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -268,6 +268,8 @@ lpfc_config_port_post(struct lpfc_hba * phba) | |||
268 | kfree(mp); | 268 | kfree(mp); |
269 | pmb->context1 = NULL; | 269 | pmb->context1 = NULL; |
270 | 270 | ||
271 | if (phba->cfg_soft_wwnn) | ||
272 | u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn); | ||
271 | if (phba->cfg_soft_wwpn) | 273 | if (phba->cfg_soft_wwpn) |
272 | u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn); | 274 | u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn); |
273 | memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName, | 275 | memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName, |
@@ -349,8 +351,8 @@ lpfc_config_port_post(struct lpfc_hba * phba) | |||
349 | phba->hba_state = LPFC_LINK_DOWN; | 351 | phba->hba_state = LPFC_LINK_DOWN; |
350 | 352 | ||
351 | /* Only process IOCBs on ring 0 till hba_state is READY */ | 353 | /* Only process IOCBs on ring 0 till hba_state is READY */ |
352 | if (psli->ring[psli->ip_ring].cmdringaddr) | 354 | if (psli->ring[psli->extra_ring].cmdringaddr) |
353 | psli->ring[psli->ip_ring].flag |= LPFC_STOP_IOCB_EVENT; | 355 | psli->ring[psli->extra_ring].flag |= LPFC_STOP_IOCB_EVENT; |
354 | if (psli->ring[psli->fcp_ring].cmdringaddr) | 356 | if (psli->ring[psli->fcp_ring].cmdringaddr) |
355 | psli->ring[psli->fcp_ring].flag |= LPFC_STOP_IOCB_EVENT; | 357 | psli->ring[psli->fcp_ring].flag |= LPFC_STOP_IOCB_EVENT; |
356 | if (psli->ring[psli->next_ring].cmdringaddr) | 358 | if (psli->ring[psli->next_ring].cmdringaddr) |
@@ -517,7 +519,8 @@ lpfc_handle_eratt(struct lpfc_hba * phba) | |||
517 | struct lpfc_sli_ring *pring; | 519 | struct lpfc_sli_ring *pring; |
518 | uint32_t event_data; | 520 | uint32_t event_data; |
519 | 521 | ||
520 | if (phba->work_hs & HS_FFER6) { | 522 | if (phba->work_hs & HS_FFER6 || |
523 | phba->work_hs & HS_FFER5) { | ||
521 | /* Re-establishing Link */ | 524 | /* Re-establishing Link */ |
522 | lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, | 525 | lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, |
523 | "%d:1301 Re-establishing Link " | 526 | "%d:1301 Re-establishing Link " |
@@ -611,7 +614,7 @@ lpfc_handle_latt(struct lpfc_hba * phba) | |||
611 | pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la; | 614 | pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la; |
612 | rc = lpfc_sli_issue_mbox (phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)); | 615 | rc = lpfc_sli_issue_mbox (phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB)); |
613 | if (rc == MBX_NOT_FINISHED) | 616 | if (rc == MBX_NOT_FINISHED) |
614 | goto lpfc_handle_latt_free_mp; | 617 | goto lpfc_handle_latt_free_mbuf; |
615 | 618 | ||
616 | /* Clear Link Attention in HA REG */ | 619 | /* Clear Link Attention in HA REG */ |
617 | spin_lock_irq(phba->host->host_lock); | 620 | spin_lock_irq(phba->host->host_lock); |
@@ -621,6 +624,8 @@ lpfc_handle_latt(struct lpfc_hba * phba) | |||
621 | 624 | ||
622 | return; | 625 | return; |
623 | 626 | ||
627 | lpfc_handle_latt_free_mbuf: | ||
628 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | ||
624 | lpfc_handle_latt_free_mp: | 629 | lpfc_handle_latt_free_mp: |
625 | kfree(mp); | 630 | kfree(mp); |
626 | lpfc_handle_latt_free_pmb: | 631 | lpfc_handle_latt_free_pmb: |
@@ -802,19 +807,13 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) | |||
802 | { | 807 | { |
803 | lpfc_vpd_t *vp; | 808 | lpfc_vpd_t *vp; |
804 | uint16_t dev_id = phba->pcidev->device; | 809 | uint16_t dev_id = phba->pcidev->device; |
805 | uint16_t dev_subid = phba->pcidev->subsystem_device; | ||
806 | uint8_t hdrtype; | ||
807 | int max_speed; | 810 | int max_speed; |
808 | char * ports; | ||
809 | struct { | 811 | struct { |
810 | char * name; | 812 | char * name; |
811 | int max_speed; | 813 | int max_speed; |
812 | char * ports; | ||
813 | char * bus; | 814 | char * bus; |
814 | } m = {"<Unknown>", 0, "", ""}; | 815 | } m = {"<Unknown>", 0, ""}; |
815 | 816 | ||
816 | pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype); | ||
817 | ports = (hdrtype == 0x80) ? "2-port " : ""; | ||
818 | if (mdp && mdp[0] != '\0' | 817 | if (mdp && mdp[0] != '\0' |
819 | && descp && descp[0] != '\0') | 818 | && descp && descp[0] != '\0') |
820 | return; | 819 | return; |
@@ -834,130 +833,93 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) | |||
834 | 833 | ||
835 | switch (dev_id) { | 834 | switch (dev_id) { |
836 | case PCI_DEVICE_ID_FIREFLY: | 835 | case PCI_DEVICE_ID_FIREFLY: |
837 | m = (typeof(m)){"LP6000", max_speed, "", "PCI"}; | 836 | m = (typeof(m)){"LP6000", max_speed, "PCI"}; |
838 | break; | 837 | break; |
839 | case PCI_DEVICE_ID_SUPERFLY: | 838 | case PCI_DEVICE_ID_SUPERFLY: |
840 | if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3) | 839 | if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3) |
841 | m = (typeof(m)){"LP7000", max_speed, "", "PCI"}; | 840 | m = (typeof(m)){"LP7000", max_speed, "PCI"}; |
842 | else | 841 | else |
843 | m = (typeof(m)){"LP7000E", max_speed, "", "PCI"}; | 842 | m = (typeof(m)){"LP7000E", max_speed, "PCI"}; |
844 | break; | 843 | break; |
845 | case PCI_DEVICE_ID_DRAGONFLY: | 844 | case PCI_DEVICE_ID_DRAGONFLY: |
846 | m = (typeof(m)){"LP8000", max_speed, "", "PCI"}; | 845 | m = (typeof(m)){"LP8000", max_speed, "PCI"}; |
847 | break; | 846 | break; |
848 | case PCI_DEVICE_ID_CENTAUR: | 847 | case PCI_DEVICE_ID_CENTAUR: |
849 | if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) | 848 | if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) |
850 | m = (typeof(m)){"LP9002", max_speed, "", "PCI"}; | 849 | m = (typeof(m)){"LP9002", max_speed, "PCI"}; |
851 | else | 850 | else |
852 | m = (typeof(m)){"LP9000", max_speed, "", "PCI"}; | 851 | m = (typeof(m)){"LP9000", max_speed, "PCI"}; |
853 | break; | 852 | break; |
854 | case PCI_DEVICE_ID_RFLY: | 853 | case PCI_DEVICE_ID_RFLY: |
855 | m = (typeof(m)){"LP952", max_speed, "", "PCI"}; | 854 | m = (typeof(m)){"LP952", max_speed, "PCI"}; |
856 | break; | 855 | break; |
857 | case PCI_DEVICE_ID_PEGASUS: | 856 | case PCI_DEVICE_ID_PEGASUS: |
858 | m = (typeof(m)){"LP9802", max_speed, "", "PCI-X"}; | 857 | m = (typeof(m)){"LP9802", max_speed, "PCI-X"}; |
859 | break; | 858 | break; |
860 | case PCI_DEVICE_ID_THOR: | 859 | case PCI_DEVICE_ID_THOR: |
861 | if (hdrtype == 0x80) | 860 | m = (typeof(m)){"LP10000", max_speed, "PCI-X"}; |
862 | m = (typeof(m)){"LP10000DC", | ||
863 | max_speed, ports, "PCI-X"}; | ||
864 | else | ||
865 | m = (typeof(m)){"LP10000", | ||
866 | max_speed, ports, "PCI-X"}; | ||
867 | break; | 861 | break; |
868 | case PCI_DEVICE_ID_VIPER: | 862 | case PCI_DEVICE_ID_VIPER: |
869 | m = (typeof(m)){"LPX1000", max_speed, "", "PCI-X"}; | 863 | m = (typeof(m)){"LPX1000", max_speed, "PCI-X"}; |
870 | break; | 864 | break; |
871 | case PCI_DEVICE_ID_PFLY: | 865 | case PCI_DEVICE_ID_PFLY: |
872 | m = (typeof(m)){"LP982", max_speed, "", "PCI-X"}; | 866 | m = (typeof(m)){"LP982", max_speed, "PCI-X"}; |
873 | break; | 867 | break; |
874 | case PCI_DEVICE_ID_TFLY: | 868 | case PCI_DEVICE_ID_TFLY: |
875 | if (hdrtype == 0x80) | 869 | m = (typeof(m)){"LP1050", max_speed, "PCI-X"}; |
876 | m = (typeof(m)){"LP1050DC", max_speed, ports, "PCI-X"}; | ||
877 | else | ||
878 | m = (typeof(m)){"LP1050", max_speed, ports, "PCI-X"}; | ||
879 | break; | 870 | break; |
880 | case PCI_DEVICE_ID_HELIOS: | 871 | case PCI_DEVICE_ID_HELIOS: |
881 | if (hdrtype == 0x80) | 872 | m = (typeof(m)){"LP11000", max_speed, "PCI-X2"}; |
882 | m = (typeof(m)){"LP11002", max_speed, ports, "PCI-X2"}; | ||
883 | else | ||
884 | m = (typeof(m)){"LP11000", max_speed, ports, "PCI-X2"}; | ||
885 | break; | 873 | break; |
886 | case PCI_DEVICE_ID_HELIOS_SCSP: | 874 | case PCI_DEVICE_ID_HELIOS_SCSP: |
887 | m = (typeof(m)){"LP11000-SP", max_speed, ports, "PCI-X2"}; | 875 | m = (typeof(m)){"LP11000-SP", max_speed, "PCI-X2"}; |
888 | break; | 876 | break; |
889 | case PCI_DEVICE_ID_HELIOS_DCSP: | 877 | case PCI_DEVICE_ID_HELIOS_DCSP: |
890 | m = (typeof(m)){"LP11002-SP", max_speed, ports, "PCI-X2"}; | 878 | m = (typeof(m)){"LP11002-SP", max_speed, "PCI-X2"}; |
891 | break; | 879 | break; |
892 | case PCI_DEVICE_ID_NEPTUNE: | 880 | case PCI_DEVICE_ID_NEPTUNE: |
893 | if (hdrtype == 0x80) | 881 | m = (typeof(m)){"LPe1000", max_speed, "PCIe"}; |
894 | m = (typeof(m)){"LPe1002", max_speed, ports, "PCIe"}; | ||
895 | else | ||
896 | m = (typeof(m)){"LPe1000", max_speed, ports, "PCIe"}; | ||
897 | break; | 882 | break; |
898 | case PCI_DEVICE_ID_NEPTUNE_SCSP: | 883 | case PCI_DEVICE_ID_NEPTUNE_SCSP: |
899 | m = (typeof(m)){"LPe1000-SP", max_speed, ports, "PCIe"}; | 884 | m = (typeof(m)){"LPe1000-SP", max_speed, "PCIe"}; |
900 | break; | 885 | break; |
901 | case PCI_DEVICE_ID_NEPTUNE_DCSP: | 886 | case PCI_DEVICE_ID_NEPTUNE_DCSP: |
902 | m = (typeof(m)){"LPe1002-SP", max_speed, ports, "PCIe"}; | 887 | m = (typeof(m)){"LPe1002-SP", max_speed, "PCIe"}; |
903 | break; | 888 | break; |
904 | case PCI_DEVICE_ID_BMID: | 889 | case PCI_DEVICE_ID_BMID: |
905 | m = (typeof(m)){"LP1150", max_speed, ports, "PCI-X2"}; | 890 | m = (typeof(m)){"LP1150", max_speed, "PCI-X2"}; |
906 | break; | 891 | break; |
907 | case PCI_DEVICE_ID_BSMB: | 892 | case PCI_DEVICE_ID_BSMB: |
908 | m = (typeof(m)){"LP111", max_speed, ports, "PCI-X2"}; | 893 | m = (typeof(m)){"LP111", max_speed, "PCI-X2"}; |
909 | break; | 894 | break; |
910 | case PCI_DEVICE_ID_ZEPHYR: | 895 | case PCI_DEVICE_ID_ZEPHYR: |
911 | if (hdrtype == 0x80) | 896 | m = (typeof(m)){"LPe11000", max_speed, "PCIe"}; |
912 | m = (typeof(m)){"LPe11002", max_speed, ports, "PCIe"}; | ||
913 | else | ||
914 | m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"}; | ||
915 | break; | 897 | break; |
916 | case PCI_DEVICE_ID_ZEPHYR_SCSP: | 898 | case PCI_DEVICE_ID_ZEPHYR_SCSP: |
917 | m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"}; | 899 | m = (typeof(m)){"LPe11000", max_speed, "PCIe"}; |
918 | break; | 900 | break; |
919 | case PCI_DEVICE_ID_ZEPHYR_DCSP: | 901 | case PCI_DEVICE_ID_ZEPHYR_DCSP: |
920 | m = (typeof(m)){"LPe11002-SP", max_speed, ports, "PCIe"}; | 902 | m = (typeof(m)){"LPe11002-SP", max_speed, "PCIe"}; |
921 | break; | 903 | break; |
922 | case PCI_DEVICE_ID_ZMID: | 904 | case PCI_DEVICE_ID_ZMID: |
923 | m = (typeof(m)){"LPe1150", max_speed, ports, "PCIe"}; | 905 | m = (typeof(m)){"LPe1150", max_speed, "PCIe"}; |
924 | break; | 906 | break; |
925 | case PCI_DEVICE_ID_ZSMB: | 907 | case PCI_DEVICE_ID_ZSMB: |
926 | m = (typeof(m)){"LPe111", max_speed, ports, "PCIe"}; | 908 | m = (typeof(m)){"LPe111", max_speed, "PCIe"}; |
927 | break; | 909 | break; |
928 | case PCI_DEVICE_ID_LP101: | 910 | case PCI_DEVICE_ID_LP101: |
929 | m = (typeof(m)){"LP101", max_speed, ports, "PCI-X"}; | 911 | m = (typeof(m)){"LP101", max_speed, "PCI-X"}; |
930 | break; | 912 | break; |
931 | case PCI_DEVICE_ID_LP10000S: | 913 | case PCI_DEVICE_ID_LP10000S: |
932 | m = (typeof(m)){"LP10000-S", max_speed, ports, "PCI"}; | 914 | m = (typeof(m)){"LP10000-S", max_speed, "PCI"}; |
933 | break; | 915 | break; |
934 | case PCI_DEVICE_ID_LP11000S: | 916 | case PCI_DEVICE_ID_LP11000S: |
917 | m = (typeof(m)){"LP11000-S", max_speed, | ||
918 | "PCI-X2"}; | ||
919 | break; | ||
935 | case PCI_DEVICE_ID_LPE11000S: | 920 | case PCI_DEVICE_ID_LPE11000S: |
936 | switch (dev_subid) { | 921 | m = (typeof(m)){"LPe11000-S", max_speed, |
937 | case PCI_SUBSYSTEM_ID_LP11000S: | 922 | "PCIe"}; |
938 | m = (typeof(m)){"LP11000-S", max_speed, | ||
939 | ports, "PCI-X2"}; | ||
940 | break; | ||
941 | case PCI_SUBSYSTEM_ID_LP11002S: | ||
942 | m = (typeof(m)){"LP11002-S", max_speed, | ||
943 | ports, "PCI-X2"}; | ||
944 | break; | ||
945 | case PCI_SUBSYSTEM_ID_LPE11000S: | ||
946 | m = (typeof(m)){"LPe11000-S", max_speed, | ||
947 | ports, "PCIe"}; | ||
948 | break; | ||
949 | case PCI_SUBSYSTEM_ID_LPE11002S: | ||
950 | m = (typeof(m)){"LPe11002-S", max_speed, | ||
951 | ports, "PCIe"}; | ||
952 | break; | ||
953 | case PCI_SUBSYSTEM_ID_LPE11010S: | ||
954 | m = (typeof(m)){"LPe11010-S", max_speed, | ||
955 | "10-port ", "PCIe"}; | ||
956 | break; | ||
957 | default: | ||
958 | m = (typeof(m)){ NULL }; | ||
959 | break; | ||
960 | } | ||
961 | break; | 923 | break; |
962 | default: | 924 | default: |
963 | m = (typeof(m)){ NULL }; | 925 | m = (typeof(m)){ NULL }; |
@@ -968,8 +930,8 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp) | |||
968 | snprintf(mdp, 79,"%s", m.name); | 930 | snprintf(mdp, 79,"%s", m.name); |
969 | if (descp && descp[0] == '\0') | 931 | if (descp && descp[0] == '\0') |
970 | snprintf(descp, 255, | 932 | snprintf(descp, 255, |
971 | "Emulex %s %dGb %s%s Fibre Channel Adapter", | 933 | "Emulex %s %dGb %s Fibre Channel Adapter", |
972 | m.name, m.max_speed, m.ports, m.bus); | 934 | m.name, m.max_speed, m.bus); |
973 | } | 935 | } |
974 | 936 | ||
975 | /**************************************************/ | 937 | /**************************************************/ |
@@ -1651,6 +1613,14 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1651 | if (error) | 1613 | if (error) |
1652 | goto out_remove_host; | 1614 | goto out_remove_host; |
1653 | 1615 | ||
1616 | if (phba->cfg_use_msi) { | ||
1617 | error = pci_enable_msi(phba->pcidev); | ||
1618 | if (error) | ||
1619 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "%d:0452 " | ||
1620 | "Enable MSI failed, continuing with " | ||
1621 | "IRQ\n", phba->brd_no); | ||
1622 | } | ||
1623 | |||
1654 | error = request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED, | 1624 | error = request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED, |
1655 | LPFC_DRIVER_NAME, phba); | 1625 | LPFC_DRIVER_NAME, phba); |
1656 | if (error) { | 1626 | if (error) { |
@@ -1730,6 +1700,7 @@ out_free_irq: | |||
1730 | lpfc_stop_timer(phba); | 1700 | lpfc_stop_timer(phba); |
1731 | phba->work_hba_events = 0; | 1701 | phba->work_hba_events = 0; |
1732 | free_irq(phba->pcidev->irq, phba); | 1702 | free_irq(phba->pcidev->irq, phba); |
1703 | pci_disable_msi(phba->pcidev); | ||
1733 | out_free_sysfs_attr: | 1704 | out_free_sysfs_attr: |
1734 | lpfc_free_sysfs_attr(phba); | 1705 | lpfc_free_sysfs_attr(phba); |
1735 | out_remove_host: | 1706 | out_remove_host: |
@@ -1796,6 +1767,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
1796 | 1767 | ||
1797 | /* Release the irq reservation */ | 1768 | /* Release the irq reservation */ |
1798 | free_irq(phba->pcidev->irq, phba); | 1769 | free_irq(phba->pcidev->irq, phba); |
1770 | pci_disable_msi(phba->pcidev); | ||
1799 | 1771 | ||
1800 | lpfc_cleanup(phba, 0); | 1772 | lpfc_cleanup(phba, 0); |
1801 | lpfc_stop_timer(phba); | 1773 | lpfc_stop_timer(phba); |
diff --git a/drivers/scsi/lpfc/lpfc_logmsg.h b/drivers/scsi/lpfc/lpfc_logmsg.h index 62c8ca862e9e..438cbcd9eb13 100644 --- a/drivers/scsi/lpfc/lpfc_logmsg.h +++ b/drivers/scsi/lpfc/lpfc_logmsg.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #define LOG_NODE 0x80 /* Node table events */ | 28 | #define LOG_NODE 0x80 /* Node table events */ |
29 | #define LOG_MISC 0x400 /* Miscellaneous events */ | 29 | #define LOG_MISC 0x400 /* Miscellaneous events */ |
30 | #define LOG_SLI 0x800 /* SLI events */ | 30 | #define LOG_SLI 0x800 /* SLI events */ |
31 | #define LOG_CHK_COND 0x1000 /* FCP Check condition flag */ | 31 | #define LOG_FCP_ERROR 0x1000 /* log errors, not underruns */ |
32 | #define LOG_LIBDFC 0x2000 /* Libdfc events */ | 32 | #define LOG_LIBDFC 0x2000 /* Libdfc events */ |
33 | #define LOG_ALL_MSG 0xffff /* LOG all messages */ | 33 | #define LOG_ALL_MSG 0xffff /* LOG all messages */ |
34 | 34 | ||
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index d5f415007db2..0c7e731dc45a 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -739,7 +739,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, | |||
739 | uint32_t evt) | 739 | uint32_t evt) |
740 | { | 740 | { |
741 | struct lpfc_iocbq *cmdiocb, *rspiocb; | 741 | struct lpfc_iocbq *cmdiocb, *rspiocb; |
742 | struct lpfc_dmabuf *pcmd, *prsp; | 742 | struct lpfc_dmabuf *pcmd, *prsp, *mp; |
743 | uint32_t *lp; | 743 | uint32_t *lp; |
744 | IOCB_t *irsp; | 744 | IOCB_t *irsp; |
745 | struct serv_parm *sp; | 745 | struct serv_parm *sp; |
@@ -829,6 +829,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba, | |||
829 | NLP_REGLOGIN_LIST); | 829 | NLP_REGLOGIN_LIST); |
830 | return ndlp->nlp_state; | 830 | return ndlp->nlp_state; |
831 | } | 831 | } |
832 | mp = (struct lpfc_dmabuf *)mbox->context1; | ||
833 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | ||
834 | kfree(mp); | ||
832 | mempool_free(mbox, phba->mbox_mem_pool); | 835 | mempool_free(mbox, phba->mbox_mem_pool); |
833 | } else { | 836 | } else { |
834 | mempool_free(mbox, phba->mbox_mem_pool); | 837 | mempool_free(mbox, phba->mbox_mem_pool); |
@@ -1620,8 +1623,8 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba, | |||
1620 | * or discovery in progress for this node. Starting discovery | 1623 | * or discovery in progress for this node. Starting discovery |
1621 | * here will affect the counting of discovery threads. | 1624 | * here will affect the counting of discovery threads. |
1622 | */ | 1625 | */ |
1623 | if ((!(ndlp->nlp_flag & NLP_DELAY_TMO)) && | 1626 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO) && |
1624 | (ndlp->nlp_flag & NLP_NPR_2B_DISC)){ | 1627 | !(ndlp->nlp_flag & NLP_NPR_2B_DISC)){ |
1625 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { | 1628 | if (ndlp->nlp_flag & NLP_NPR_ADISC) { |
1626 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | 1629 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; |
1627 | ndlp->nlp_state = NLP_STE_ADISC_ISSUE; | 1630 | ndlp->nlp_state = NLP_STE_ADISC_ISSUE; |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 97ae98dc95d0..c3e68e0d8f74 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -297,8 +297,10 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) | |||
297 | uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm; | 297 | uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm; |
298 | uint32_t resp_info = fcprsp->rspStatus2; | 298 | uint32_t resp_info = fcprsp->rspStatus2; |
299 | uint32_t scsi_status = fcprsp->rspStatus3; | 299 | uint32_t scsi_status = fcprsp->rspStatus3; |
300 | uint32_t *lp; | ||
300 | uint32_t host_status = DID_OK; | 301 | uint32_t host_status = DID_OK; |
301 | uint32_t rsplen = 0; | 302 | uint32_t rsplen = 0; |
303 | uint32_t logit = LOG_FCP | LOG_FCP_ERROR; | ||
302 | 304 | ||
303 | /* | 305 | /* |
304 | * If this is a task management command, there is no | 306 | * If this is a task management command, there is no |
@@ -310,10 +312,25 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) | |||
310 | goto out; | 312 | goto out; |
311 | } | 313 | } |
312 | 314 | ||
313 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, | 315 | if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen) { |
314 | "%d:0730 FCP command failed: RSP " | 316 | uint32_t snslen = be32_to_cpu(fcprsp->rspSnsLen); |
315 | "Data: x%x x%x x%x x%x x%x x%x\n", | 317 | if (snslen > SCSI_SENSE_BUFFERSIZE) |
316 | phba->brd_no, resp_info, scsi_status, | 318 | snslen = SCSI_SENSE_BUFFERSIZE; |
319 | |||
320 | if (resp_info & RSP_LEN_VALID) | ||
321 | rsplen = be32_to_cpu(fcprsp->rspRspLen); | ||
322 | memcpy(cmnd->sense_buffer, &fcprsp->rspInfo0 + rsplen, snslen); | ||
323 | } | ||
324 | lp = (uint32_t *)cmnd->sense_buffer; | ||
325 | |||
326 | if (!scsi_status && (resp_info & RESID_UNDER)) | ||
327 | logit = LOG_FCP; | ||
328 | |||
329 | lpfc_printf_log(phba, KERN_WARNING, logit, | ||
330 | "%d:0730 FCP command x%x failed: x%x SNS x%x x%x " | ||
331 | "Data: x%x x%x x%x x%x x%x\n", | ||
332 | phba->brd_no, cmnd->cmnd[0], scsi_status, | ||
333 | be32_to_cpu(*lp), be32_to_cpu(*(lp + 3)), resp_info, | ||
317 | be32_to_cpu(fcprsp->rspResId), | 334 | be32_to_cpu(fcprsp->rspResId), |
318 | be32_to_cpu(fcprsp->rspSnsLen), | 335 | be32_to_cpu(fcprsp->rspSnsLen), |
319 | be32_to_cpu(fcprsp->rspRspLen), | 336 | be32_to_cpu(fcprsp->rspRspLen), |
@@ -328,14 +345,6 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) | |||
328 | } | 345 | } |
329 | } | 346 | } |
330 | 347 | ||
331 | if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen) { | ||
332 | uint32_t snslen = be32_to_cpu(fcprsp->rspSnsLen); | ||
333 | if (snslen > SCSI_SENSE_BUFFERSIZE) | ||
334 | snslen = SCSI_SENSE_BUFFERSIZE; | ||
335 | |||
336 | memcpy(cmnd->sense_buffer, &fcprsp->rspInfo0 + rsplen, snslen); | ||
337 | } | ||
338 | |||
339 | cmnd->resid = 0; | 348 | cmnd->resid = 0; |
340 | if (resp_info & RESID_UNDER) { | 349 | if (resp_info & RESID_UNDER) { |
341 | cmnd->resid = be32_to_cpu(fcprsp->rspResId); | 350 | cmnd->resid = be32_to_cpu(fcprsp->rspResId); |
@@ -378,7 +387,7 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd) | |||
378 | */ | 387 | */ |
379 | } else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm && | 388 | } else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm && |
380 | (cmnd->sc_data_direction == DMA_FROM_DEVICE)) { | 389 | (cmnd->sc_data_direction == DMA_FROM_DEVICE)) { |
381 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP, | 390 | lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR, |
382 | "%d:0734 FCP Read Check Error Data: " | 391 | "%d:0734 FCP Read Check Error Data: " |
383 | "x%x x%x x%x x%x\n", phba->brd_no, | 392 | "x%x x%x x%x x%x\n", phba->brd_no, |
384 | be32_to_cpu(fcpcmd->fcpDl), | 393 | be32_to_cpu(fcpcmd->fcpDl), |
@@ -670,6 +679,9 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba, | |||
670 | struct lpfc_iocbq *iocbqrsp; | 679 | struct lpfc_iocbq *iocbqrsp; |
671 | int ret; | 680 | int ret; |
672 | 681 | ||
682 | if (!rdata->pnode) | ||
683 | return FAILED; | ||
684 | |||
673 | lpfc_cmd->rdata = rdata; | 685 | lpfc_cmd->rdata = rdata; |
674 | ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, lun, | 686 | ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, lun, |
675 | FCP_TARGET_RESET); | 687 | FCP_TARGET_RESET); |
@@ -976,20 +988,34 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) | |||
976 | 988 | ||
977 | lpfc_block_error_handler(cmnd); | 989 | lpfc_block_error_handler(cmnd); |
978 | spin_lock_irq(shost->host_lock); | 990 | spin_lock_irq(shost->host_lock); |
991 | loopcnt = 0; | ||
979 | /* | 992 | /* |
980 | * If target is not in a MAPPED state, delay the reset until | 993 | * If target is not in a MAPPED state, delay the reset until |
981 | * target is rediscovered or devloss timeout expires. | 994 | * target is rediscovered or devloss timeout expires. |
982 | */ | 995 | */ |
983 | while ( 1 ) { | 996 | while ( 1 ) { |
984 | if (!pnode) | 997 | if (!pnode) |
985 | break; | 998 | return FAILED; |
986 | 999 | ||
987 | if (pnode->nlp_state != NLP_STE_MAPPED_NODE) { | 1000 | if (pnode->nlp_state != NLP_STE_MAPPED_NODE) { |
988 | spin_unlock_irq(phba->host->host_lock); | 1001 | spin_unlock_irq(phba->host->host_lock); |
989 | schedule_timeout_uninterruptible(msecs_to_jiffies(500)); | 1002 | schedule_timeout_uninterruptible(msecs_to_jiffies(500)); |
990 | spin_lock_irq(phba->host->host_lock); | 1003 | spin_lock_irq(phba->host->host_lock); |
1004 | loopcnt++; | ||
1005 | rdata = cmnd->device->hostdata; | ||
1006 | if (!rdata || | ||
1007 | (loopcnt > ((phba->cfg_devloss_tmo * 2) + 1))) { | ||
1008 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | ||
1009 | "%d:0721 LUN Reset rport failure:" | ||
1010 | " cnt x%x rdata x%p\n", | ||
1011 | phba->brd_no, loopcnt, rdata); | ||
1012 | goto out; | ||
1013 | } | ||
1014 | pnode = rdata->pnode; | ||
1015 | if (!pnode) | ||
1016 | return FAILED; | ||
991 | } | 1017 | } |
992 | if ((pnode) && (pnode->nlp_state == NLP_STE_MAPPED_NODE)) | 1018 | if (pnode->nlp_state == NLP_STE_MAPPED_NODE) |
993 | break; | 1019 | break; |
994 | } | 1020 | } |
995 | 1021 | ||
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 582f5ea4e84e..a4128e19338a 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -117,6 +117,10 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) | |||
117 | case CMD_FCP_IREAD_CX: | 117 | case CMD_FCP_IREAD_CX: |
118 | case CMD_FCP_ICMND_CR: | 118 | case CMD_FCP_ICMND_CR: |
119 | case CMD_FCP_ICMND_CX: | 119 | case CMD_FCP_ICMND_CX: |
120 | case CMD_FCP_TSEND_CX: | ||
121 | case CMD_FCP_TRSP_CX: | ||
122 | case CMD_FCP_TRECEIVE_CX: | ||
123 | case CMD_FCP_AUTO_TRSP_CX: | ||
120 | case CMD_ADAPTER_MSG: | 124 | case CMD_ADAPTER_MSG: |
121 | case CMD_ADAPTER_DUMP: | 125 | case CMD_ADAPTER_DUMP: |
122 | case CMD_XMIT_SEQUENCE64_CR: | 126 | case CMD_XMIT_SEQUENCE64_CR: |
@@ -131,6 +135,9 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd) | |||
131 | case CMD_FCP_IREAD64_CX: | 135 | case CMD_FCP_IREAD64_CX: |
132 | case CMD_FCP_ICMND64_CR: | 136 | case CMD_FCP_ICMND64_CR: |
133 | case CMD_FCP_ICMND64_CX: | 137 | case CMD_FCP_ICMND64_CX: |
138 | case CMD_FCP_TSEND64_CX: | ||
139 | case CMD_FCP_TRSP64_CX: | ||
140 | case CMD_FCP_TRECEIVE64_CX: | ||
134 | case CMD_GEN_REQUEST64_CR: | 141 | case CMD_GEN_REQUEST64_CR: |
135 | case CMD_GEN_REQUEST64_CX: | 142 | case CMD_GEN_REQUEST64_CX: |
136 | case CMD_XMIT_ELS_RSP64_CX: | 143 | case CMD_XMIT_ELS_RSP64_CX: |
@@ -1098,6 +1105,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, | |||
1098 | lpfc_sli_pcimem_bcopy((uint32_t *) entry, | 1105 | lpfc_sli_pcimem_bcopy((uint32_t *) entry, |
1099 | (uint32_t *) &rspiocbq.iocb, | 1106 | (uint32_t *) &rspiocbq.iocb, |
1100 | sizeof (IOCB_t)); | 1107 | sizeof (IOCB_t)); |
1108 | INIT_LIST_HEAD(&(rspiocbq.list)); | ||
1101 | irsp = &rspiocbq.iocb; | 1109 | irsp = &rspiocbq.iocb; |
1102 | 1110 | ||
1103 | type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK); | 1111 | type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK); |
@@ -1149,6 +1157,11 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, | |||
1149 | } | 1157 | } |
1150 | } | 1158 | } |
1151 | break; | 1159 | break; |
1160 | case LPFC_UNSOL_IOCB: | ||
1161 | spin_unlock_irqrestore(phba->host->host_lock, iflag); | ||
1162 | lpfc_sli_process_unsol_iocb(phba, pring, &rspiocbq); | ||
1163 | spin_lock_irqsave(phba->host->host_lock, iflag); | ||
1164 | break; | ||
1152 | default: | 1165 | default: |
1153 | if (irsp->ulpCommand == CMD_ADAPTER_MSG) { | 1166 | if (irsp->ulpCommand == CMD_ADAPTER_MSG) { |
1154 | char adaptermsg[LPFC_MAX_ADPTMSG]; | 1167 | char adaptermsg[LPFC_MAX_ADPTMSG]; |
@@ -2472,13 +2485,17 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) | |||
2472 | psli = &phba->sli; | 2485 | psli = &phba->sli; |
2473 | 2486 | ||
2474 | /* Adjust cmd/rsp ring iocb entries more evenly */ | 2487 | /* Adjust cmd/rsp ring iocb entries more evenly */ |
2488 | |||
2489 | /* Take some away from the FCP ring */ | ||
2475 | pring = &psli->ring[psli->fcp_ring]; | 2490 | pring = &psli->ring[psli->fcp_ring]; |
2476 | pring->numCiocb -= SLI2_IOCB_CMD_R1XTRA_ENTRIES; | 2491 | pring->numCiocb -= SLI2_IOCB_CMD_R1XTRA_ENTRIES; |
2477 | pring->numRiocb -= SLI2_IOCB_RSP_R1XTRA_ENTRIES; | 2492 | pring->numRiocb -= SLI2_IOCB_RSP_R1XTRA_ENTRIES; |
2478 | pring->numCiocb -= SLI2_IOCB_CMD_R3XTRA_ENTRIES; | 2493 | pring->numCiocb -= SLI2_IOCB_CMD_R3XTRA_ENTRIES; |
2479 | pring->numRiocb -= SLI2_IOCB_RSP_R3XTRA_ENTRIES; | 2494 | pring->numRiocb -= SLI2_IOCB_RSP_R3XTRA_ENTRIES; |
2480 | 2495 | ||
2481 | pring = &psli->ring[1]; | 2496 | /* and give them to the extra ring */ |
2497 | pring = &psli->ring[psli->extra_ring]; | ||
2498 | |||
2482 | pring->numCiocb += SLI2_IOCB_CMD_R1XTRA_ENTRIES; | 2499 | pring->numCiocb += SLI2_IOCB_CMD_R1XTRA_ENTRIES; |
2483 | pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES; | 2500 | pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES; |
2484 | pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES; | 2501 | pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES; |
@@ -2488,8 +2505,8 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba) | |||
2488 | pring->iotag_max = 4096; | 2505 | pring->iotag_max = 4096; |
2489 | pring->num_mask = 1; | 2506 | pring->num_mask = 1; |
2490 | pring->prt[0].profile = 0; /* Mask 0 */ | 2507 | pring->prt[0].profile = 0; /* Mask 0 */ |
2491 | pring->prt[0].rctl = FC_UNSOL_DATA; | 2508 | pring->prt[0].rctl = phba->cfg_multi_ring_rctl; |
2492 | pring->prt[0].type = 5; | 2509 | pring->prt[0].type = phba->cfg_multi_ring_type; |
2493 | pring->prt[0].lpfc_sli_rcv_unsol_event = NULL; | 2510 | pring->prt[0].lpfc_sli_rcv_unsol_event = NULL; |
2494 | return 0; | 2511 | return 0; |
2495 | } | 2512 | } |
@@ -2505,7 +2522,7 @@ lpfc_sli_setup(struct lpfc_hba *phba) | |||
2505 | psli->sli_flag = 0; | 2522 | psli->sli_flag = 0; |
2506 | psli->fcp_ring = LPFC_FCP_RING; | 2523 | psli->fcp_ring = LPFC_FCP_RING; |
2507 | psli->next_ring = LPFC_FCP_NEXT_RING; | 2524 | psli->next_ring = LPFC_FCP_NEXT_RING; |
2508 | psli->ip_ring = LPFC_IP_RING; | 2525 | psli->extra_ring = LPFC_EXTRA_RING; |
2509 | 2526 | ||
2510 | psli->iocbq_lookup = NULL; | 2527 | psli->iocbq_lookup = NULL; |
2511 | psli->iocbq_lookup_len = 0; | 2528 | psli->iocbq_lookup_len = 0; |
@@ -2528,7 +2545,7 @@ lpfc_sli_setup(struct lpfc_hba *phba) | |||
2528 | pring->fast_iotag = pring->iotag_max; | 2545 | pring->fast_iotag = pring->iotag_max; |
2529 | pring->num_mask = 0; | 2546 | pring->num_mask = 0; |
2530 | break; | 2547 | break; |
2531 | case LPFC_IP_RING: /* ring 1 - IP */ | 2548 | case LPFC_EXTRA_RING: /* ring 1 - EXTRA */ |
2532 | /* numCiocb and numRiocb are used in config_port */ | 2549 | /* numCiocb and numRiocb are used in config_port */ |
2533 | pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES; | 2550 | pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES; |
2534 | pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES; | 2551 | pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES; |
@@ -3238,6 +3255,21 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
3238 | lpfc_sli_handle_fast_ring_event(phba, | 3255 | lpfc_sli_handle_fast_ring_event(phba, |
3239 | &phba->sli.ring[LPFC_FCP_RING], | 3256 | &phba->sli.ring[LPFC_FCP_RING], |
3240 | status); | 3257 | status); |
3258 | |||
3259 | if (phba->cfg_multi_ring_support == 2) { | ||
3260 | /* | ||
3261 | * Process all events on extra ring. Take the optimized path | ||
3262 | * for extra ring IO. Any other IO is slow path and is handled | ||
3263 | * by the worker thread. | ||
3264 | */ | ||
3265 | status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING))); | ||
3266 | status >>= (4*LPFC_EXTRA_RING); | ||
3267 | if (status & HA_RXATT) { | ||
3268 | lpfc_sli_handle_fast_ring_event(phba, | ||
3269 | &phba->sli.ring[LPFC_EXTRA_RING], | ||
3270 | status); | ||
3271 | } | ||
3272 | } | ||
3241 | return IRQ_HANDLED; | 3273 | return IRQ_HANDLED; |
3242 | 3274 | ||
3243 | } /* lpfc_intr_handler */ | 3275 | } /* lpfc_intr_handler */ |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index e26de6809358..a43549959dc7 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -198,7 +198,7 @@ struct lpfc_sli { | |||
198 | int fcp_ring; /* ring used for FCP initiator commands */ | 198 | int fcp_ring; /* ring used for FCP initiator commands */ |
199 | int next_ring; | 199 | int next_ring; |
200 | 200 | ||
201 | int ip_ring; /* ring used for IP network drv cmds */ | 201 | int extra_ring; /* extra ring used for other protocols */ |
202 | 202 | ||
203 | struct lpfc_sli_stat slistat; /* SLI statistical info */ | 203 | struct lpfc_sli_stat slistat; /* SLI statistical info */ |
204 | struct list_head mboxq; | 204 | struct list_head mboxq; |
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index ac417908b407..a61ef3d1e7f1 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h | |||
@@ -18,7 +18,7 @@ | |||
18 | * included with this package. * | 18 | * included with this package. * |
19 | *******************************************************************/ | 19 | *******************************************************************/ |
20 | 20 | ||
21 | #define LPFC_DRIVER_VERSION "8.1.10" | 21 | #define LPFC_DRIVER_VERSION "8.1.11" |
22 | 22 | ||
23 | #define LPFC_DRIVER_NAME "lpfc" | 23 | #define LPFC_DRIVER_NAME "lpfc" |
24 | 24 | ||
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 86099fde1b2a..77d9d3804ccf 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c | |||
@@ -73,10 +73,10 @@ static unsigned short int max_mbox_busy_wait = MBOX_BUSY_WAIT; | |||
73 | module_param(max_mbox_busy_wait, ushort, 0); | 73 | module_param(max_mbox_busy_wait, ushort, 0); |
74 | MODULE_PARM_DESC(max_mbox_busy_wait, "Maximum wait for mailbox in microseconds if busy (default=MBOX_BUSY_WAIT=10)"); | 74 | MODULE_PARM_DESC(max_mbox_busy_wait, "Maximum wait for mailbox in microseconds if busy (default=MBOX_BUSY_WAIT=10)"); |
75 | 75 | ||
76 | #define RDINDOOR(adapter) readl((adapter)->base + 0x20) | 76 | #define RDINDOOR(adapter) readl((adapter)->mmio_base + 0x20) |
77 | #define RDOUTDOOR(adapter) readl((adapter)->base + 0x2C) | 77 | #define RDOUTDOOR(adapter) readl((adapter)->mmio_base + 0x2C) |
78 | #define WRINDOOR(adapter,value) writel(value, (adapter)->base + 0x20) | 78 | #define WRINDOOR(adapter,value) writel(value, (adapter)->mmio_base + 0x20) |
79 | #define WROUTDOOR(adapter,value) writel(value, (adapter)->base + 0x2C) | 79 | #define WROUTDOOR(adapter,value) writel(value, (adapter)->mmio_base + 0x2C) |
80 | 80 | ||
81 | /* | 81 | /* |
82 | * Global variables | 82 | * Global variables |
@@ -1386,7 +1386,8 @@ megaraid_isr_memmapped(int irq, void *devp) | |||
1386 | 1386 | ||
1387 | handled = 1; | 1387 | handled = 1; |
1388 | 1388 | ||
1389 | while( RDINDOOR(adapter) & 0x02 ) cpu_relax(); | 1389 | while( RDINDOOR(adapter) & 0x02 ) |
1390 | cpu_relax(); | ||
1390 | 1391 | ||
1391 | mega_cmd_done(adapter, completed, nstatus, status); | 1392 | mega_cmd_done(adapter, completed, nstatus, status); |
1392 | 1393 | ||
@@ -4668,6 +4669,8 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
4668 | host->host_no, mega_baseport, irq); | 4669 | host->host_no, mega_baseport, irq); |
4669 | 4670 | ||
4670 | adapter->base = mega_baseport; | 4671 | adapter->base = mega_baseport; |
4672 | if (flag & BOARD_MEMMAP) | ||
4673 | adapter->mmio_base = (void __iomem *) mega_baseport; | ||
4671 | 4674 | ||
4672 | INIT_LIST_HEAD(&adapter->free_list); | 4675 | INIT_LIST_HEAD(&adapter->free_list); |
4673 | INIT_LIST_HEAD(&adapter->pending_list); | 4676 | INIT_LIST_HEAD(&adapter->pending_list); |
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h index 66529f11d23c..c6e74643abe2 100644 --- a/drivers/scsi/megaraid.h +++ b/drivers/scsi/megaraid.h | |||
@@ -801,7 +801,8 @@ typedef struct { | |||
801 | clustering is available */ | 801 | clustering is available */ |
802 | u32 flag; | 802 | u32 flag; |
803 | 803 | ||
804 | unsigned long base; | 804 | unsigned long base; |
805 | void __iomem *mmio_base; | ||
805 | 806 | ||
806 | /* mbox64 with mbox not aligned on 16-byte boundry */ | 807 | /* mbox64 with mbox not aligned on 16-byte boundry */ |
807 | mbox64_t *una_mbox64; | 808 | mbox64_t *una_mbox64; |
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 7e4262f2af96..046223b4ae57 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -517,7 +517,7 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
517 | * Returns the number of frames required for numnber of sge's (sge_count) | 517 | * Returns the number of frames required for numnber of sge's (sge_count) |
518 | */ | 518 | */ |
519 | 519 | ||
520 | u32 megasas_get_frame_count(u8 sge_count) | 520 | static u32 megasas_get_frame_count(u8 sge_count) |
521 | { | 521 | { |
522 | int num_cnt; | 522 | int num_cnt; |
523 | int sge_bytes; | 523 | int sge_bytes; |
@@ -1733,7 +1733,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance, | |||
1733 | * | 1733 | * |
1734 | * Tasklet to complete cmds | 1734 | * Tasklet to complete cmds |
1735 | */ | 1735 | */ |
1736 | void megasas_complete_cmd_dpc(unsigned long instance_addr) | 1736 | static void megasas_complete_cmd_dpc(unsigned long instance_addr) |
1737 | { | 1737 | { |
1738 | u32 producer; | 1738 | u32 producer; |
1739 | u32 consumer; | 1739 | u32 consumer; |
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index adb8eb4f5fd1..bbf521cbc55d 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c | |||
@@ -589,10 +589,12 @@ static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd) | |||
589 | static struct ncr_driver_setup | 589 | static struct ncr_driver_setup |
590 | driver_setup = SCSI_NCR_DRIVER_SETUP; | 590 | driver_setup = SCSI_NCR_DRIVER_SETUP; |
591 | 591 | ||
592 | #ifndef MODULE | ||
592 | #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT | 593 | #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT |
593 | static struct ncr_driver_setup | 594 | static struct ncr_driver_setup |
594 | driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP; | 595 | driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP; |
595 | #endif | 596 | #endif |
597 | #endif /* !MODULE */ | ||
596 | 598 | ||
597 | #define initverbose (driver_setup.verbose) | 599 | #define initverbose (driver_setup.verbose) |
598 | #define bootverbose (np->verbose) | 600 | #define bootverbose (np->verbose) |
@@ -641,6 +643,13 @@ static struct ncr_driver_setup | |||
641 | #define OPT_IARB 26 | 643 | #define OPT_IARB 26 |
642 | #endif | 644 | #endif |
643 | 645 | ||
646 | #ifdef MODULE | ||
647 | #define ARG_SEP ' ' | ||
648 | #else | ||
649 | #define ARG_SEP ',' | ||
650 | #endif | ||
651 | |||
652 | #ifndef MODULE | ||
644 | static char setup_token[] __initdata = | 653 | static char setup_token[] __initdata = |
645 | "tags:" "mpar:" | 654 | "tags:" "mpar:" |
646 | "spar:" "disc:" | 655 | "spar:" "disc:" |
@@ -660,12 +669,6 @@ static char setup_token[] __initdata = | |||
660 | #endif | 669 | #endif |
661 | ; /* DONNOT REMOVE THIS ';' */ | 670 | ; /* DONNOT REMOVE THIS ';' */ |
662 | 671 | ||
663 | #ifdef MODULE | ||
664 | #define ARG_SEP ' ' | ||
665 | #else | ||
666 | #define ARG_SEP ',' | ||
667 | #endif | ||
668 | |||
669 | static int __init get_setup_token(char *p) | 672 | static int __init get_setup_token(char *p) |
670 | { | 673 | { |
671 | char *cur = setup_token; | 674 | char *cur = setup_token; |
@@ -682,7 +685,6 @@ static int __init get_setup_token(char *p) | |||
682 | return 0; | 685 | return 0; |
683 | } | 686 | } |
684 | 687 | ||
685 | |||
686 | static int __init sym53c8xx__setup(char *str) | 688 | static int __init sym53c8xx__setup(char *str) |
687 | { | 689 | { |
688 | #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT | 690 | #ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT |
@@ -804,6 +806,7 @@ static int __init sym53c8xx__setup(char *str) | |||
804 | #endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */ | 806 | #endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */ |
805 | return 1; | 807 | return 1; |
806 | } | 808 | } |
809 | #endif /* !MODULE */ | ||
807 | 810 | ||
808 | /*=================================================================== | 811 | /*=================================================================== |
809 | ** | 812 | ** |
@@ -8321,12 +8324,12 @@ char *ncr53c8xx; /* command line passed by insmod */ | |||
8321 | module_param(ncr53c8xx, charp, 0); | 8324 | module_param(ncr53c8xx, charp, 0); |
8322 | #endif | 8325 | #endif |
8323 | 8326 | ||
8327 | #ifndef MODULE | ||
8324 | static int __init ncr53c8xx_setup(char *str) | 8328 | static int __init ncr53c8xx_setup(char *str) |
8325 | { | 8329 | { |
8326 | return sym53c8xx__setup(str); | 8330 | return sym53c8xx__setup(str); |
8327 | } | 8331 | } |
8328 | 8332 | ||
8329 | #ifndef MODULE | ||
8330 | __setup("ncr53c8xx=", ncr53c8xx_setup); | 8333 | __setup("ncr53c8xx=", ncr53c8xx_setup); |
8331 | #endif | 8334 | #endif |
8332 | 8335 | ||
diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index ee449b29fc82..aad362ba02e0 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c | |||
@@ -154,16 +154,11 @@ static int aha152x_config_cs(struct pcmcia_device *link) | |||
154 | 154 | ||
155 | DEBUG(0, "aha152x_config(0x%p)\n", link); | 155 | DEBUG(0, "aha152x_config(0x%p)\n", link); |
156 | 156 | ||
157 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
158 | tuple.TupleData = tuple_data; | 157 | tuple.TupleData = tuple_data; |
159 | tuple.TupleDataMax = 64; | 158 | tuple.TupleDataMax = 64; |
160 | tuple.TupleOffset = 0; | 159 | tuple.TupleOffset = 0; |
161 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
162 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
163 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
164 | link->conf.ConfigBase = parse.config.base; | ||
165 | |||
166 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 160 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
161 | tuple.Attributes = 0; | ||
167 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 162 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
168 | while (1) { | 163 | while (1) { |
169 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || | 164 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || |
diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 85f7ffac19a0..a1c5f265069f 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c | |||
@@ -136,14 +136,9 @@ static int fdomain_config(struct pcmcia_device *link) | |||
136 | 136 | ||
137 | DEBUG(0, "fdomain_config(0x%p)\n", link); | 137 | DEBUG(0, "fdomain_config(0x%p)\n", link); |
138 | 138 | ||
139 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
140 | tuple.TupleData = tuple_data; | 139 | tuple.TupleData = tuple_data; |
141 | tuple.TupleDataMax = 64; | 140 | tuple.TupleDataMax = 64; |
142 | tuple.TupleOffset = 0; | 141 | tuple.TupleOffset = 0; |
143 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
144 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
145 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
146 | link->conf.ConfigBase = parse.config.base; | ||
147 | 142 | ||
148 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 143 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
149 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 144 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index f2d79c3f0b8e..d72df5dae4ee 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c | |||
@@ -1685,16 +1685,10 @@ static int nsp_cs_config(struct pcmcia_device *link) | |||
1685 | 1685 | ||
1686 | nsp_dbg(NSP_DEBUG_INIT, "in"); | 1686 | nsp_dbg(NSP_DEBUG_INIT, "in"); |
1687 | 1687 | ||
1688 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
1689 | tuple.Attributes = 0; | 1688 | tuple.Attributes = 0; |
1690 | tuple.TupleData = tuple_data; | 1689 | tuple.TupleData = tuple_data; |
1691 | tuple.TupleDataMax = sizeof(tuple_data); | 1690 | tuple.TupleDataMax = sizeof(tuple_data); |
1692 | tuple.TupleOffset = 0; | 1691 | tuple.TupleOffset = 0; |
1693 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
1694 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
1695 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
1696 | link->conf.ConfigBase = parse.config.base; | ||
1697 | link->conf.Present = parse.config.rmask[0]; | ||
1698 | 1692 | ||
1699 | /* Look up the current Vcc */ | 1693 | /* Look up the current Vcc */ |
1700 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); | 1694 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf)); |
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 86c2ac6ae623..9d431fe7f47f 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c | |||
@@ -208,18 +208,11 @@ static int qlogic_config(struct pcmcia_device * link) | |||
208 | 208 | ||
209 | DEBUG(0, "qlogic_config(0x%p)\n", link); | 209 | DEBUG(0, "qlogic_config(0x%p)\n", link); |
210 | 210 | ||
211 | info->manf_id = link->manf_id; | ||
212 | |||
211 | tuple.TupleData = (cisdata_t *) tuple_data; | 213 | tuple.TupleData = (cisdata_t *) tuple_data; |
212 | tuple.TupleDataMax = 64; | 214 | tuple.TupleDataMax = 64; |
213 | tuple.TupleOffset = 0; | 215 | tuple.TupleOffset = 0; |
214 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
215 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
216 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
217 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
218 | link->conf.ConfigBase = parse.config.base; | ||
219 | |||
220 | tuple.DesiredTuple = CISTPL_MANFID; | ||
221 | if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) | ||
222 | info->manf_id = le16_to_cpu(tuple.TupleData[0]); | ||
223 | 216 | ||
224 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 217 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
225 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 218 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 72fe5d055de1..fb7acea60286 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c | |||
@@ -722,19 +722,11 @@ SYM53C500_config(struct pcmcia_device *link) | |||
722 | 722 | ||
723 | DEBUG(0, "SYM53C500_config(0x%p)\n", link); | 723 | DEBUG(0, "SYM53C500_config(0x%p)\n", link); |
724 | 724 | ||
725 | info->manf_id = link->manf_id; | ||
726 | |||
725 | tuple.TupleData = (cisdata_t *)tuple_data; | 727 | tuple.TupleData = (cisdata_t *)tuple_data; |
726 | tuple.TupleDataMax = 64; | 728 | tuple.TupleDataMax = 64; |
727 | tuple.TupleOffset = 0; | 729 | tuple.TupleOffset = 0; |
728 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
729 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
730 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
731 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
732 | link->conf.ConfigBase = parse.config.base; | ||
733 | |||
734 | tuple.DesiredTuple = CISTPL_MANFID; | ||
735 | if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && | ||
736 | (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) | ||
737 | info->manf_id = le16_to_cpu(tuple.TupleData[0]); | ||
738 | 730 | ||
739 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 731 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
740 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 732 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 285c8e8ff1a0..7b18a6c7b7eb 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -390,7 +390,7 @@ static struct sysfs_entry { | |||
390 | { "optrom_ctl", &sysfs_optrom_ctl_attr, }, | 390 | { "optrom_ctl", &sysfs_optrom_ctl_attr, }, |
391 | { "vpd", &sysfs_vpd_attr, 1 }, | 391 | { "vpd", &sysfs_vpd_attr, 1 }, |
392 | { "sfp", &sysfs_sfp_attr, 1 }, | 392 | { "sfp", &sysfs_sfp_attr, 1 }, |
393 | { 0 }, | 393 | { NULL }, |
394 | }; | 394 | }; |
395 | 395 | ||
396 | void | 396 | void |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 08cb5e3fb553..a823f0bc519d 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -59,9 +59,6 @@ int | |||
59 | qla2x00_initialize_adapter(scsi_qla_host_t *ha) | 59 | qla2x00_initialize_adapter(scsi_qla_host_t *ha) |
60 | { | 60 | { |
61 | int rval; | 61 | int rval; |
62 | uint8_t restart_risc = 0; | ||
63 | uint8_t retry; | ||
64 | uint32_t wait_time; | ||
65 | 62 | ||
66 | /* Clear adapter flags. */ | 63 | /* Clear adapter flags. */ |
67 | ha->flags.online = 0; | 64 | ha->flags.online = 0; |
@@ -104,87 +101,15 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
104 | 101 | ||
105 | qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); | 102 | qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); |
106 | 103 | ||
107 | retry = 10; | 104 | if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { |
108 | /* | 105 | rval = ha->isp_ops.chip_diag(ha); |
109 | * Try to configure the loop. | 106 | if (rval) |
110 | */ | 107 | return (rval); |
111 | do { | 108 | rval = qla2x00_setup_chip(ha); |
112 | restart_risc = 0; | 109 | if (rval) |
113 | 110 | return (rval); | |
114 | /* If firmware needs to be loaded */ | ||
115 | if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { | ||
116 | if ((rval = ha->isp_ops.chip_diag(ha)) == QLA_SUCCESS) { | ||
117 | rval = qla2x00_setup_chip(ha); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | if (rval == QLA_SUCCESS && | ||
122 | (rval = qla2x00_init_rings(ha)) == QLA_SUCCESS) { | ||
123 | check_fw_ready_again: | ||
124 | /* | ||
125 | * Wait for a successful LIP up to a maximum | ||
126 | * of (in seconds): RISC login timeout value, | ||
127 | * RISC retry count value, and port down retry | ||
128 | * value OR a minimum of 4 seconds OR If no | ||
129 | * cable, only 5 seconds. | ||
130 | */ | ||
131 | rval = qla2x00_fw_ready(ha); | ||
132 | if (rval == QLA_SUCCESS) { | ||
133 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | ||
134 | |||
135 | /* Issue a marker after FW becomes ready. */ | ||
136 | qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); | ||
137 | |||
138 | /* | ||
139 | * Wait at most MAX_TARGET RSCNs for a stable | ||
140 | * link. | ||
141 | */ | ||
142 | wait_time = 256; | ||
143 | do { | ||
144 | clear_bit(LOOP_RESYNC_NEEDED, | ||
145 | &ha->dpc_flags); | ||
146 | rval = qla2x00_configure_loop(ha); | ||
147 | |||
148 | if (test_and_clear_bit(ISP_ABORT_NEEDED, | ||
149 | &ha->dpc_flags)) { | ||
150 | restart_risc = 1; | ||
151 | break; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * If loop state change while we were | ||
156 | * discoverying devices then wait for | ||
157 | * LIP to complete | ||
158 | */ | ||
159 | |||
160 | if (atomic_read(&ha->loop_state) != | ||
161 | LOOP_READY && retry--) { | ||
162 | goto check_fw_ready_again; | ||
163 | } | ||
164 | wait_time--; | ||
165 | } while (!atomic_read(&ha->loop_down_timer) && | ||
166 | retry && | ||
167 | wait_time && | ||
168 | (test_bit(LOOP_RESYNC_NEEDED, | ||
169 | &ha->dpc_flags))); | ||
170 | |||
171 | if (wait_time == 0) | ||
172 | rval = QLA_FUNCTION_FAILED; | ||
173 | } else if (ha->device_flags & DFLG_NO_CABLE) | ||
174 | /* If no cable, then all is good. */ | ||
175 | rval = QLA_SUCCESS; | ||
176 | } | ||
177 | } while (restart_risc && retry--); | ||
178 | |||
179 | if (rval == QLA_SUCCESS) { | ||
180 | clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); | ||
181 | qla2x00_marker(ha, 0, 0, MK_SYNC_ALL); | ||
182 | ha->marker_needed = 0; | ||
183 | |||
184 | ha->flags.online = 1; | ||
185 | } else { | ||
186 | DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__)); | ||
187 | } | 111 | } |
112 | rval = qla2x00_init_rings(ha); | ||
188 | 113 | ||
189 | return (rval); | 114 | return (rval); |
190 | } | 115 | } |
@@ -2208,8 +2133,7 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) | |||
2208 | 2133 | ||
2209 | atomic_set(&fcport->state, FCS_ONLINE); | 2134 | atomic_set(&fcport->state, FCS_ONLINE); |
2210 | 2135 | ||
2211 | if (ha->flags.init_done) | 2136 | qla2x00_reg_remote_port(ha, fcport); |
2212 | qla2x00_reg_remote_port(ha, fcport); | ||
2213 | } | 2137 | } |
2214 | 2138 | ||
2215 | void | 2139 | void |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 208607be78c7..cbe0cad83b68 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -95,6 +95,8 @@ MODULE_PARM_DESC(ql2xqfullrampup, | |||
95 | */ | 95 | */ |
96 | static int qla2xxx_slave_configure(struct scsi_device * device); | 96 | static int qla2xxx_slave_configure(struct scsi_device * device); |
97 | static int qla2xxx_slave_alloc(struct scsi_device *); | 97 | static int qla2xxx_slave_alloc(struct scsi_device *); |
98 | static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time); | ||
99 | static void qla2xxx_scan_start(struct Scsi_Host *); | ||
98 | static void qla2xxx_slave_destroy(struct scsi_device *); | 100 | static void qla2xxx_slave_destroy(struct scsi_device *); |
99 | static int qla2x00_queuecommand(struct scsi_cmnd *cmd, | 101 | static int qla2x00_queuecommand(struct scsi_cmnd *cmd, |
100 | void (*fn)(struct scsi_cmnd *)); | 102 | void (*fn)(struct scsi_cmnd *)); |
@@ -124,6 +126,8 @@ static struct scsi_host_template qla2x00_driver_template = { | |||
124 | 126 | ||
125 | .slave_alloc = qla2xxx_slave_alloc, | 127 | .slave_alloc = qla2xxx_slave_alloc, |
126 | .slave_destroy = qla2xxx_slave_destroy, | 128 | .slave_destroy = qla2xxx_slave_destroy, |
129 | .scan_finished = qla2xxx_scan_finished, | ||
130 | .scan_start = qla2xxx_scan_start, | ||
127 | .change_queue_depth = qla2x00_change_queue_depth, | 131 | .change_queue_depth = qla2x00_change_queue_depth, |
128 | .change_queue_type = qla2x00_change_queue_type, | 132 | .change_queue_type = qla2x00_change_queue_type, |
129 | .this_id = -1, | 133 | .this_id = -1, |
@@ -287,7 +291,7 @@ qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str) | |||
287 | return str; | 291 | return str; |
288 | } | 292 | } |
289 | 293 | ||
290 | char * | 294 | static char * |
291 | qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str) | 295 | qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str) |
292 | { | 296 | { |
293 | char un_str[10]; | 297 | char un_str[10]; |
@@ -325,7 +329,7 @@ qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str) | |||
325 | return (str); | 329 | return (str); |
326 | } | 330 | } |
327 | 331 | ||
328 | char * | 332 | static char * |
329 | qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str) | 333 | qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str) |
330 | { | 334 | { |
331 | sprintf(str, "%d.%02d.%02d ", ha->fw_major_version, | 335 | sprintf(str, "%d.%02d.%02d ", ha->fw_major_version, |
@@ -634,7 +638,7 @@ qla2x00_block_error_handler(struct scsi_cmnd *cmnd) | |||
634 | * Note: | 638 | * Note: |
635 | * Only return FAILED if command not returned by firmware. | 639 | * Only return FAILED if command not returned by firmware. |
636 | **************************************************************************/ | 640 | **************************************************************************/ |
637 | int | 641 | static int |
638 | qla2xxx_eh_abort(struct scsi_cmnd *cmd) | 642 | qla2xxx_eh_abort(struct scsi_cmnd *cmd) |
639 | { | 643 | { |
640 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 644 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
@@ -771,7 +775,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) | |||
771 | * SUCCESS/FAILURE (defined as macro in scsi.h). | 775 | * SUCCESS/FAILURE (defined as macro in scsi.h). |
772 | * | 776 | * |
773 | **************************************************************************/ | 777 | **************************************************************************/ |
774 | int | 778 | static int |
775 | qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) | 779 | qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) |
776 | { | 780 | { |
777 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 781 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
@@ -902,7 +906,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha) | |||
902 | * SUCCESS/FAILURE (defined as macro in scsi.h). | 906 | * SUCCESS/FAILURE (defined as macro in scsi.h). |
903 | * | 907 | * |
904 | **************************************************************************/ | 908 | **************************************************************************/ |
905 | int | 909 | static int |
906 | qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | 910 | qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) |
907 | { | 911 | { |
908 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 912 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
@@ -963,7 +967,7 @@ eh_bus_reset_done: | |||
963 | * | 967 | * |
964 | * Note: | 968 | * Note: |
965 | **************************************************************************/ | 969 | **************************************************************************/ |
966 | int | 970 | static int |
967 | qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | 971 | qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) |
968 | { | 972 | { |
969 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); | 973 | scsi_qla_host_t *ha = to_qla_host(cmd->device->host); |
@@ -1366,6 +1370,29 @@ qla24xx_disable_intrs(scsi_qla_host_t *ha) | |||
1366 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1370 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
1367 | } | 1371 | } |
1368 | 1372 | ||
1373 | static void | ||
1374 | qla2xxx_scan_start(struct Scsi_Host *shost) | ||
1375 | { | ||
1376 | scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; | ||
1377 | |||
1378 | set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); | ||
1379 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); | ||
1380 | set_bit(RSCN_UPDATE, &ha->dpc_flags); | ||
1381 | } | ||
1382 | |||
1383 | static int | ||
1384 | qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time) | ||
1385 | { | ||
1386 | scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; | ||
1387 | |||
1388 | if (!ha->host) | ||
1389 | return 1; | ||
1390 | if (time > ha->loop_reset_delay * HZ) | ||
1391 | return 1; | ||
1392 | |||
1393 | return atomic_read(&ha->loop_state) == LOOP_READY; | ||
1394 | } | ||
1395 | |||
1369 | /* | 1396 | /* |
1370 | * PCI driver interface | 1397 | * PCI driver interface |
1371 | */ | 1398 | */ |
@@ -1377,10 +1404,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1377 | struct Scsi_Host *host; | 1404 | struct Scsi_Host *host; |
1378 | scsi_qla_host_t *ha; | 1405 | scsi_qla_host_t *ha; |
1379 | unsigned long flags = 0; | 1406 | unsigned long flags = 0; |
1380 | unsigned long wait_switch = 0; | ||
1381 | char pci_info[20]; | 1407 | char pci_info[20]; |
1382 | char fw_str[30]; | 1408 | char fw_str[30]; |
1383 | fc_port_t *fcport; | ||
1384 | struct scsi_host_template *sht; | 1409 | struct scsi_host_template *sht; |
1385 | 1410 | ||
1386 | if (pci_enable_device(pdev)) | 1411 | if (pci_enable_device(pdev)) |
@@ -1631,30 +1656,19 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1631 | 1656 | ||
1632 | ha->isp_ops.enable_intrs(ha); | 1657 | ha->isp_ops.enable_intrs(ha); |
1633 | 1658 | ||
1634 | /* v2.19.5b6 */ | ||
1635 | /* | ||
1636 | * Wait around max loop_reset_delay secs for the devices to come | ||
1637 | * on-line. We don't want Linux scanning before we are ready. | ||
1638 | * | ||
1639 | */ | ||
1640 | for (wait_switch = jiffies + (ha->loop_reset_delay * HZ); | ||
1641 | time_before(jiffies,wait_switch) && | ||
1642 | !(ha->device_flags & (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES)) | ||
1643 | && (ha->device_flags & SWITCH_FOUND) ;) { | ||
1644 | |||
1645 | qla2x00_check_fabric_devices(ha); | ||
1646 | |||
1647 | msleep(10); | ||
1648 | } | ||
1649 | |||
1650 | pci_set_drvdata(pdev, ha); | 1659 | pci_set_drvdata(pdev, ha); |
1660 | |||
1651 | ha->flags.init_done = 1; | 1661 | ha->flags.init_done = 1; |
1662 | ha->flags.online = 1; | ||
1663 | |||
1652 | num_hosts++; | 1664 | num_hosts++; |
1653 | 1665 | ||
1654 | ret = scsi_add_host(host, &pdev->dev); | 1666 | ret = scsi_add_host(host, &pdev->dev); |
1655 | if (ret) | 1667 | if (ret) |
1656 | goto probe_failed; | 1668 | goto probe_failed; |
1657 | 1669 | ||
1670 | scsi_scan_host(host); | ||
1671 | |||
1658 | qla2x00_alloc_sysfs_attr(ha); | 1672 | qla2x00_alloc_sysfs_attr(ha); |
1659 | 1673 | ||
1660 | qla2x00_init_host_attr(ha); | 1674 | qla2x00_init_host_attr(ha); |
@@ -1669,10 +1683,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1669 | ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, | 1683 | ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no, |
1670 | ha->isp_ops.fw_version_str(ha, fw_str)); | 1684 | ha->isp_ops.fw_version_str(ha, fw_str)); |
1671 | 1685 | ||
1672 | /* Go with fc_rport registration. */ | ||
1673 | list_for_each_entry(fcport, &ha->fcports, list) | ||
1674 | qla2x00_reg_remote_port(ha, fcport); | ||
1675 | |||
1676 | return 0; | 1686 | return 0; |
1677 | 1687 | ||
1678 | probe_failed: | 1688 | probe_failed: |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index c71dbd5bd543..15390ad87456 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -449,7 +449,7 @@ nvram_data_to_access_addr(uint32_t naddr) | |||
449 | return FARX_ACCESS_NVRAM_DATA | naddr; | 449 | return FARX_ACCESS_NVRAM_DATA | naddr; |
450 | } | 450 | } |
451 | 451 | ||
452 | uint32_t | 452 | static uint32_t |
453 | qla24xx_read_flash_dword(scsi_qla_host_t *ha, uint32_t addr) | 453 | qla24xx_read_flash_dword(scsi_qla_host_t *ha, uint32_t addr) |
454 | { | 454 | { |
455 | int rval; | 455 | int rval; |
@@ -490,7 +490,7 @@ qla24xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | |||
490 | return dwptr; | 490 | return dwptr; |
491 | } | 491 | } |
492 | 492 | ||
493 | int | 493 | static int |
494 | qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data) | 494 | qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data) |
495 | { | 495 | { |
496 | int rval; | 496 | int rval; |
@@ -512,7 +512,7 @@ qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data) | |||
512 | return rval; | 512 | return rval; |
513 | } | 513 | } |
514 | 514 | ||
515 | void | 515 | static void |
516 | qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, | 516 | qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, |
517 | uint8_t *flash_id) | 517 | uint8_t *flash_id) |
518 | { | 518 | { |
@@ -537,7 +537,7 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, | |||
537 | } | 537 | } |
538 | } | 538 | } |
539 | 539 | ||
540 | int | 540 | static int |
541 | qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | 541 | qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, |
542 | uint32_t dwords) | 542 | uint32_t dwords) |
543 | { | 543 | { |
diff --git a/drivers/scsi/qla4xxx/ql4_dbg.c b/drivers/scsi/qla4xxx/ql4_dbg.c index 752031fadfef..7b4e077a39c1 100644 --- a/drivers/scsi/qla4xxx/ql4_dbg.c +++ b/drivers/scsi/qla4xxx/ql4_dbg.c | |||
@@ -71,7 +71,7 @@ void __dump_registers(struct scsi_qla_host *ha) | |||
71 | readw(&ha->reg->u1.isp4010.nvram)); | 71 | readw(&ha->reg->u1.isp4010.nvram)); |
72 | } | 72 | } |
73 | 73 | ||
74 | else if (is_qla4022(ha)) { | 74 | else if (is_qla4022(ha) | is_qla4032(ha)) { |
75 | printk(KERN_INFO "0x%02X intr_mask = 0x%08X\n", | 75 | printk(KERN_INFO "0x%02X intr_mask = 0x%08X\n", |
76 | (uint8_t) offsetof(struct isp_reg, | 76 | (uint8_t) offsetof(struct isp_reg, |
77 | u1.isp4022.intr_mask), | 77 | u1.isp4022.intr_mask), |
@@ -119,7 +119,7 @@ void __dump_registers(struct scsi_qla_host *ha) | |||
119 | readw(&ha->reg->u2.isp4010.port_err_status)); | 119 | readw(&ha->reg->u2.isp4010.port_err_status)); |
120 | } | 120 | } |
121 | 121 | ||
122 | else if (is_qla4022(ha)) { | 122 | else if (is_qla4022(ha) | is_qla4032(ha)) { |
123 | printk(KERN_INFO "Page 0 Registers:\n"); | 123 | printk(KERN_INFO "Page 0 Registers:\n"); |
124 | printk(KERN_INFO "0x%02X ext_hw_conf = 0x%08X\n", | 124 | printk(KERN_INFO "0x%02X ext_hw_conf = 0x%08X\n", |
125 | (uint8_t) offsetof(struct isp_reg, | 125 | (uint8_t) offsetof(struct isp_reg, |
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index a7f6c7b1c590..4249e52a5592 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -40,7 +40,11 @@ | |||
40 | 40 | ||
41 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP4022 | 41 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP4022 |
42 | #define PCI_DEVICE_ID_QLOGIC_ISP4022 0x4022 | 42 | #define PCI_DEVICE_ID_QLOGIC_ISP4022 0x4022 |
43 | #endif /* */ | 43 | #endif |
44 | |||
45 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP4032 | ||
46 | #define PCI_DEVICE_ID_QLOGIC_ISP4032 0x4032 | ||
47 | #endif | ||
44 | 48 | ||
45 | #define QLA_SUCCESS 0 | 49 | #define QLA_SUCCESS 0 |
46 | #define QLA_ERROR 1 | 50 | #define QLA_ERROR 1 |
@@ -277,7 +281,6 @@ struct scsi_qla_host { | |||
277 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 Not Used */ | 281 | #define AF_INTERRUPTS_ON 6 /* 0x00000040 Not Used */ |
278 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ | 282 | #define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ |
279 | #define AF_LINK_UP 8 /* 0x00000100 */ | 283 | #define AF_LINK_UP 8 /* 0x00000100 */ |
280 | #define AF_TOPCAT_CHIP_PRESENT 9 /* 0x00000200 */ | ||
281 | #define AF_IRQ_ATTACHED 10 /* 0x00000400 */ | 284 | #define AF_IRQ_ATTACHED 10 /* 0x00000400 */ |
282 | #define AF_ISNS_CMD_IN_PROCESS 12 /* 0x00001000 */ | 285 | #define AF_ISNS_CMD_IN_PROCESS 12 /* 0x00001000 */ |
283 | #define AF_ISNS_CMD_DONE 13 /* 0x00002000 */ | 286 | #define AF_ISNS_CMD_DONE 13 /* 0x00002000 */ |
@@ -317,16 +320,17 @@ struct scsi_qla_host { | |||
317 | /* NVRAM registers */ | 320 | /* NVRAM registers */ |
318 | struct eeprom_data *nvram; | 321 | struct eeprom_data *nvram; |
319 | spinlock_t hardware_lock ____cacheline_aligned; | 322 | spinlock_t hardware_lock ____cacheline_aligned; |
320 | spinlock_t list_lock; | ||
321 | uint32_t eeprom_cmd_data; | 323 | uint32_t eeprom_cmd_data; |
322 | 324 | ||
323 | /* Counters for general statistics */ | 325 | /* Counters for general statistics */ |
326 | uint64_t isr_count; | ||
324 | uint64_t adapter_error_count; | 327 | uint64_t adapter_error_count; |
325 | uint64_t device_error_count; | 328 | uint64_t device_error_count; |
326 | uint64_t total_io_count; | 329 | uint64_t total_io_count; |
327 | uint64_t total_mbytes_xferred; | 330 | uint64_t total_mbytes_xferred; |
328 | uint64_t link_failure_count; | 331 | uint64_t link_failure_count; |
329 | uint64_t invalid_crc_count; | 332 | uint64_t invalid_crc_count; |
333 | uint32_t bytes_xfered; | ||
330 | uint32_t spurious_int_count; | 334 | uint32_t spurious_int_count; |
331 | uint32_t aborted_io_count; | 335 | uint32_t aborted_io_count; |
332 | uint32_t io_timeout_count; | 336 | uint32_t io_timeout_count; |
@@ -438,6 +442,11 @@ static inline int is_qla4022(struct scsi_qla_host *ha) | |||
438 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4022; | 442 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4022; |
439 | } | 443 | } |
440 | 444 | ||
445 | static inline int is_qla4032(struct scsi_qla_host *ha) | ||
446 | { | ||
447 | return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032; | ||
448 | } | ||
449 | |||
441 | static inline int adapter_up(struct scsi_qla_host *ha) | 450 | static inline int adapter_up(struct scsi_qla_host *ha) |
442 | { | 451 | { |
443 | return (test_bit(AF_ONLINE, &ha->flags) != 0) && | 452 | return (test_bit(AF_ONLINE, &ha->flags) != 0) && |
@@ -451,58 +460,58 @@ static inline struct scsi_qla_host* to_qla_host(struct Scsi_Host *shost) | |||
451 | 460 | ||
452 | static inline void __iomem* isp_semaphore(struct scsi_qla_host *ha) | 461 | static inline void __iomem* isp_semaphore(struct scsi_qla_host *ha) |
453 | { | 462 | { |
454 | return (is_qla4022(ha) ? | 463 | return (is_qla4010(ha) ? |
455 | &ha->reg->u1.isp4022.semaphore : | 464 | &ha->reg->u1.isp4010.nvram : |
456 | &ha->reg->u1.isp4010.nvram); | 465 | &ha->reg->u1.isp4022.semaphore); |
457 | } | 466 | } |
458 | 467 | ||
459 | static inline void __iomem* isp_nvram(struct scsi_qla_host *ha) | 468 | static inline void __iomem* isp_nvram(struct scsi_qla_host *ha) |
460 | { | 469 | { |
461 | return (is_qla4022(ha) ? | 470 | return (is_qla4010(ha) ? |
462 | &ha->reg->u1.isp4022.nvram : | 471 | &ha->reg->u1.isp4010.nvram : |
463 | &ha->reg->u1.isp4010.nvram); | 472 | &ha->reg->u1.isp4022.nvram); |
464 | } | 473 | } |
465 | 474 | ||
466 | static inline void __iomem* isp_ext_hw_conf(struct scsi_qla_host *ha) | 475 | static inline void __iomem* isp_ext_hw_conf(struct scsi_qla_host *ha) |
467 | { | 476 | { |
468 | return (is_qla4022(ha) ? | 477 | return (is_qla4010(ha) ? |
469 | &ha->reg->u2.isp4022.p0.ext_hw_conf : | 478 | &ha->reg->u2.isp4010.ext_hw_conf : |
470 | &ha->reg->u2.isp4010.ext_hw_conf); | 479 | &ha->reg->u2.isp4022.p0.ext_hw_conf); |
471 | } | 480 | } |
472 | 481 | ||
473 | static inline void __iomem* isp_port_status(struct scsi_qla_host *ha) | 482 | static inline void __iomem* isp_port_status(struct scsi_qla_host *ha) |
474 | { | 483 | { |
475 | return (is_qla4022(ha) ? | 484 | return (is_qla4010(ha) ? |
476 | &ha->reg->u2.isp4022.p0.port_status : | 485 | &ha->reg->u2.isp4010.port_status : |
477 | &ha->reg->u2.isp4010.port_status); | 486 | &ha->reg->u2.isp4022.p0.port_status); |
478 | } | 487 | } |
479 | 488 | ||
480 | static inline void __iomem* isp_port_ctrl(struct scsi_qla_host *ha) | 489 | static inline void __iomem* isp_port_ctrl(struct scsi_qla_host *ha) |
481 | { | 490 | { |
482 | return (is_qla4022(ha) ? | 491 | return (is_qla4010(ha) ? |
483 | &ha->reg->u2.isp4022.p0.port_ctrl : | 492 | &ha->reg->u2.isp4010.port_ctrl : |
484 | &ha->reg->u2.isp4010.port_ctrl); | 493 | &ha->reg->u2.isp4022.p0.port_ctrl); |
485 | } | 494 | } |
486 | 495 | ||
487 | static inline void __iomem* isp_port_error_status(struct scsi_qla_host *ha) | 496 | static inline void __iomem* isp_port_error_status(struct scsi_qla_host *ha) |
488 | { | 497 | { |
489 | return (is_qla4022(ha) ? | 498 | return (is_qla4010(ha) ? |
490 | &ha->reg->u2.isp4022.p0.port_err_status : | 499 | &ha->reg->u2.isp4010.port_err_status : |
491 | &ha->reg->u2.isp4010.port_err_status); | 500 | &ha->reg->u2.isp4022.p0.port_err_status); |
492 | } | 501 | } |
493 | 502 | ||
494 | static inline void __iomem * isp_gp_out(struct scsi_qla_host *ha) | 503 | static inline void __iomem * isp_gp_out(struct scsi_qla_host *ha) |
495 | { | 504 | { |
496 | return (is_qla4022(ha) ? | 505 | return (is_qla4010(ha) ? |
497 | &ha->reg->u2.isp4022.p0.gp_out : | 506 | &ha->reg->u2.isp4010.gp_out : |
498 | &ha->reg->u2.isp4010.gp_out); | 507 | &ha->reg->u2.isp4022.p0.gp_out); |
499 | } | 508 | } |
500 | 509 | ||
501 | static inline int eeprom_ext_hw_conf_offset(struct scsi_qla_host *ha) | 510 | static inline int eeprom_ext_hw_conf_offset(struct scsi_qla_host *ha) |
502 | { | 511 | { |
503 | return (is_qla4022(ha) ? | 512 | return (is_qla4010(ha) ? |
504 | offsetof(struct eeprom_data, isp4022.ext_hw_conf) / 2 : | 513 | offsetof(struct eeprom_data, isp4010.ext_hw_conf) / 2 : |
505 | offsetof(struct eeprom_data, isp4010.ext_hw_conf) / 2); | 514 | offsetof(struct eeprom_data, isp4022.ext_hw_conf) / 2); |
506 | } | 515 | } |
507 | 516 | ||
508 | int ql4xxx_sem_spinlock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits); | 517 | int ql4xxx_sem_spinlock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits); |
@@ -511,59 +520,59 @@ int ql4xxx_sem_lock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits); | |||
511 | 520 | ||
512 | static inline int ql4xxx_lock_flash(struct scsi_qla_host *a) | 521 | static inline int ql4xxx_lock_flash(struct scsi_qla_host *a) |
513 | { | 522 | { |
514 | if (is_qla4022(a)) | 523 | if (is_qla4010(a)) |
524 | return ql4xxx_sem_spinlock(a, QL4010_FLASH_SEM_MASK, | ||
525 | QL4010_FLASH_SEM_BITS); | ||
526 | else | ||
515 | return ql4xxx_sem_spinlock(a, QL4022_FLASH_SEM_MASK, | 527 | return ql4xxx_sem_spinlock(a, QL4022_FLASH_SEM_MASK, |
516 | (QL4022_RESOURCE_BITS_BASE_CODE | | 528 | (QL4022_RESOURCE_BITS_BASE_CODE | |
517 | (a->mac_index)) << 13); | 529 | (a->mac_index)) << 13); |
518 | else | ||
519 | return ql4xxx_sem_spinlock(a, QL4010_FLASH_SEM_MASK, | ||
520 | QL4010_FLASH_SEM_BITS); | ||
521 | } | 530 | } |
522 | 531 | ||
523 | static inline void ql4xxx_unlock_flash(struct scsi_qla_host *a) | 532 | static inline void ql4xxx_unlock_flash(struct scsi_qla_host *a) |
524 | { | 533 | { |
525 | if (is_qla4022(a)) | 534 | if (is_qla4010(a)) |
526 | ql4xxx_sem_unlock(a, QL4022_FLASH_SEM_MASK); | ||
527 | else | ||
528 | ql4xxx_sem_unlock(a, QL4010_FLASH_SEM_MASK); | 535 | ql4xxx_sem_unlock(a, QL4010_FLASH_SEM_MASK); |
536 | else | ||
537 | ql4xxx_sem_unlock(a, QL4022_FLASH_SEM_MASK); | ||
529 | } | 538 | } |
530 | 539 | ||
531 | static inline int ql4xxx_lock_nvram(struct scsi_qla_host *a) | 540 | static inline int ql4xxx_lock_nvram(struct scsi_qla_host *a) |
532 | { | 541 | { |
533 | if (is_qla4022(a)) | 542 | if (is_qla4010(a)) |
543 | return ql4xxx_sem_spinlock(a, QL4010_NVRAM_SEM_MASK, | ||
544 | QL4010_NVRAM_SEM_BITS); | ||
545 | else | ||
534 | return ql4xxx_sem_spinlock(a, QL4022_NVRAM_SEM_MASK, | 546 | return ql4xxx_sem_spinlock(a, QL4022_NVRAM_SEM_MASK, |
535 | (QL4022_RESOURCE_BITS_BASE_CODE | | 547 | (QL4022_RESOURCE_BITS_BASE_CODE | |
536 | (a->mac_index)) << 10); | 548 | (a->mac_index)) << 10); |
537 | else | ||
538 | return ql4xxx_sem_spinlock(a, QL4010_NVRAM_SEM_MASK, | ||
539 | QL4010_NVRAM_SEM_BITS); | ||
540 | } | 549 | } |
541 | 550 | ||
542 | static inline void ql4xxx_unlock_nvram(struct scsi_qla_host *a) | 551 | static inline void ql4xxx_unlock_nvram(struct scsi_qla_host *a) |
543 | { | 552 | { |
544 | if (is_qla4022(a)) | 553 | if (is_qla4010(a)) |
545 | ql4xxx_sem_unlock(a, QL4022_NVRAM_SEM_MASK); | ||
546 | else | ||
547 | ql4xxx_sem_unlock(a, QL4010_NVRAM_SEM_MASK); | 554 | ql4xxx_sem_unlock(a, QL4010_NVRAM_SEM_MASK); |
555 | else | ||
556 | ql4xxx_sem_unlock(a, QL4022_NVRAM_SEM_MASK); | ||
548 | } | 557 | } |
549 | 558 | ||
550 | static inline int ql4xxx_lock_drvr(struct scsi_qla_host *a) | 559 | static inline int ql4xxx_lock_drvr(struct scsi_qla_host *a) |
551 | { | 560 | { |
552 | if (is_qla4022(a)) | 561 | if (is_qla4010(a)) |
562 | return ql4xxx_sem_lock(a, QL4010_DRVR_SEM_MASK, | ||
563 | QL4010_DRVR_SEM_BITS); | ||
564 | else | ||
553 | return ql4xxx_sem_lock(a, QL4022_DRVR_SEM_MASK, | 565 | return ql4xxx_sem_lock(a, QL4022_DRVR_SEM_MASK, |
554 | (QL4022_RESOURCE_BITS_BASE_CODE | | 566 | (QL4022_RESOURCE_BITS_BASE_CODE | |
555 | (a->mac_index)) << 1); | 567 | (a->mac_index)) << 1); |
556 | else | ||
557 | return ql4xxx_sem_lock(a, QL4010_DRVR_SEM_MASK, | ||
558 | QL4010_DRVR_SEM_BITS); | ||
559 | } | 568 | } |
560 | 569 | ||
561 | static inline void ql4xxx_unlock_drvr(struct scsi_qla_host *a) | 570 | static inline void ql4xxx_unlock_drvr(struct scsi_qla_host *a) |
562 | { | 571 | { |
563 | if (is_qla4022(a)) | 572 | if (is_qla4010(a)) |
564 | ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK); | ||
565 | else | ||
566 | ql4xxx_sem_unlock(a, QL4010_DRVR_SEM_MASK); | 573 | ql4xxx_sem_unlock(a, QL4010_DRVR_SEM_MASK); |
574 | else | ||
575 | ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK); | ||
567 | } | 576 | } |
568 | 577 | ||
569 | /*---------------------------------------------------------------------------*/ | 578 | /*---------------------------------------------------------------------------*/ |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 427489de64bc..4eea8c571916 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
@@ -296,7 +296,6 @@ static inline uint32_t clr_rmask(uint32_t val) | |||
296 | /* ISP Semaphore definitions */ | 296 | /* ISP Semaphore definitions */ |
297 | 297 | ||
298 | /* ISP General Purpose Output definitions */ | 298 | /* ISP General Purpose Output definitions */ |
299 | #define GPOR_TOPCAT_RESET 0x00000004 | ||
300 | 299 | ||
301 | /* shadow registers (DMA'd from HA to system memory. read only) */ | 300 | /* shadow registers (DMA'd from HA to system memory. read only) */ |
302 | struct shadow_regs { | 301 | struct shadow_regs { |
@@ -339,10 +338,13 @@ union external_hw_config_reg { | |||
339 | /* Mailbox command definitions */ | 338 | /* Mailbox command definitions */ |
340 | #define MBOX_CMD_ABOUT_FW 0x0009 | 339 | #define MBOX_CMD_ABOUT_FW 0x0009 |
341 | #define MBOX_CMD_LUN_RESET 0x0016 | 340 | #define MBOX_CMD_LUN_RESET 0x0016 |
341 | #define MBOX_CMD_GET_MANAGEMENT_DATA 0x001E | ||
342 | #define MBOX_CMD_GET_FW_STATUS 0x001F | 342 | #define MBOX_CMD_GET_FW_STATUS 0x001F |
343 | #define MBOX_CMD_SET_ISNS_SERVICE 0x0021 | 343 | #define MBOX_CMD_SET_ISNS_SERVICE 0x0021 |
344 | #define ISNS_DISABLE 0 | 344 | #define ISNS_DISABLE 0 |
345 | #define ISNS_ENABLE 1 | 345 | #define ISNS_ENABLE 1 |
346 | #define MBOX_CMD_COPY_FLASH 0x0024 | ||
347 | #define MBOX_CMD_WRITE_FLASH 0x0025 | ||
346 | #define MBOX_CMD_READ_FLASH 0x0026 | 348 | #define MBOX_CMD_READ_FLASH 0x0026 |
347 | #define MBOX_CMD_CLEAR_DATABASE_ENTRY 0x0031 | 349 | #define MBOX_CMD_CLEAR_DATABASE_ENTRY 0x0031 |
348 | #define MBOX_CMD_CONN_CLOSE_SESS_LOGOUT 0x0056 | 350 | #define MBOX_CMD_CONN_CLOSE_SESS_LOGOUT 0x0056 |
@@ -360,10 +362,13 @@ union external_hw_config_reg { | |||
360 | #define DDB_DS_SESSION_FAILED 0x06 | 362 | #define DDB_DS_SESSION_FAILED 0x06 |
361 | #define DDB_DS_LOGIN_IN_PROCESS 0x07 | 363 | #define DDB_DS_LOGIN_IN_PROCESS 0x07 |
362 | #define MBOX_CMD_GET_FW_STATE 0x0069 | 364 | #define MBOX_CMD_GET_FW_STATE 0x0069 |
365 | #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A | ||
366 | #define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087 | ||
363 | 367 | ||
364 | /* Mailbox 1 */ | 368 | /* Mailbox 1 */ |
365 | #define FW_STATE_READY 0x0000 | 369 | #define FW_STATE_READY 0x0000 |
366 | #define FW_STATE_CONFIG_WAIT 0x0001 | 370 | #define FW_STATE_CONFIG_WAIT 0x0001 |
371 | #define FW_STATE_WAIT_LOGIN 0x0002 | ||
367 | #define FW_STATE_ERROR 0x0004 | 372 | #define FW_STATE_ERROR 0x0004 |
368 | #define FW_STATE_DHCP_IN_PROGRESS 0x0008 | 373 | #define FW_STATE_DHCP_IN_PROGRESS 0x0008 |
369 | 374 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 1b221ff0f6f7..2122967bbf0b 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #ifndef __QLA4x_GBL_H | 8 | #ifndef __QLA4x_GBL_H |
9 | #define __QLA4x_GBL_H | 9 | #define __QLA4x_GBL_H |
10 | 10 | ||
11 | int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); | ||
11 | int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port); | 12 | int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port); |
12 | int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb); | 13 | int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb); |
13 | int qla4xxx_initialize_adapter(struct scsi_qla_host * ha, | 14 | int qla4xxx_initialize_adapter(struct scsi_qla_host * ha, |
@@ -75,4 +76,4 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha, | |||
75 | extern int ql4xextended_error_logging; | 76 | extern int ql4xextended_error_logging; |
76 | extern int ql4xdiscoverywait; | 77 | extern int ql4xdiscoverywait; |
77 | extern int ql4xdontresethba; | 78 | extern int ql4xdontresethba; |
78 | #endif /* _QLA4x_GBL_H */ | 79 | #endif /* _QLA4x_GBL_H */ |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index bb3a1c11f44c..cc210f297a78 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
@@ -259,10 +259,16 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) | |||
259 | "seconds expired= %d\n", ha->host_no, __func__, | 259 | "seconds expired= %d\n", ha->host_no, __func__, |
260 | ha->firmware_state, ha->addl_fw_state, | 260 | ha->firmware_state, ha->addl_fw_state, |
261 | timeout_count)); | 261 | timeout_count)); |
262 | if (is_qla4032(ha) && | ||
263 | !(ha->addl_fw_state & FW_ADDSTATE_LINK_UP) && | ||
264 | (timeout_count < ADAPTER_INIT_TOV - 5)) { | ||
265 | break; | ||
266 | } | ||
267 | |||
262 | msleep(1000); | 268 | msleep(1000); |
263 | } /* end of for */ | 269 | } /* end of for */ |
264 | 270 | ||
265 | if (timeout_count <= 0) | 271 | if (timeout_count == 0) |
266 | DEBUG2(printk("scsi%ld: %s: FW Initialization timed out!\n", | 272 | DEBUG2(printk("scsi%ld: %s: FW Initialization timed out!\n", |
267 | ha->host_no, __func__)); | 273 | ha->host_no, __func__)); |
268 | 274 | ||
@@ -806,32 +812,6 @@ int qla4xxx_relogin_device(struct scsi_qla_host *ha, | |||
806 | return QLA_SUCCESS; | 812 | return QLA_SUCCESS; |
807 | } | 813 | } |
808 | 814 | ||
809 | /** | ||
810 | * qla4010_get_topcat_presence - check if it is QLA4040 TopCat Chip | ||
811 | * @ha: Pointer to host adapter structure. | ||
812 | * | ||
813 | **/ | ||
814 | static int qla4010_get_topcat_presence(struct scsi_qla_host *ha) | ||
815 | { | ||
816 | unsigned long flags; | ||
817 | uint16_t topcat; | ||
818 | |||
819 | if (ql4xxx_lock_nvram(ha) != QLA_SUCCESS) | ||
820 | return QLA_ERROR; | ||
821 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
822 | topcat = rd_nvram_word(ha, offsetof(struct eeprom_data, | ||
823 | isp4010.topcat)); | ||
824 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
825 | |||
826 | if ((topcat & TOPCAT_MASK) == TOPCAT_PRESENT) | ||
827 | set_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags); | ||
828 | else | ||
829 | clear_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags); | ||
830 | ql4xxx_unlock_nvram(ha); | ||
831 | return QLA_SUCCESS; | ||
832 | } | ||
833 | |||
834 | |||
835 | static int qla4xxx_config_nvram(struct scsi_qla_host *ha) | 815 | static int qla4xxx_config_nvram(struct scsi_qla_host *ha) |
836 | { | 816 | { |
837 | unsigned long flags; | 817 | unsigned long flags; |
@@ -866,7 +846,7 @@ static int qla4xxx_config_nvram(struct scsi_qla_host *ha) | |||
866 | /* set defaults */ | 846 | /* set defaults */ |
867 | if (is_qla4010(ha)) | 847 | if (is_qla4010(ha)) |
868 | extHwConfig.Asuint32_t = 0x1912; | 848 | extHwConfig.Asuint32_t = 0x1912; |
869 | else if (is_qla4022(ha)) | 849 | else if (is_qla4022(ha) | is_qla4032(ha)) |
870 | extHwConfig.Asuint32_t = 0x0023; | 850 | extHwConfig.Asuint32_t = 0x0023; |
871 | } | 851 | } |
872 | DEBUG(printk("scsi%ld: %s: Setting extHwConfig to 0xFFFF%04x\n", | 852 | DEBUG(printk("scsi%ld: %s: Setting extHwConfig to 0xFFFF%04x\n", |
@@ -927,7 +907,7 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) | |||
927 | 907 | ||
928 | spin_lock_irqsave(&ha->hardware_lock, flags); | 908 | spin_lock_irqsave(&ha->hardware_lock, flags); |
929 | writel(jiffies, &ha->reg->mailbox[7]); | 909 | writel(jiffies, &ha->reg->mailbox[7]); |
930 | if (is_qla4022(ha)) | 910 | if (is_qla4022(ha) | is_qla4032(ha)) |
931 | writel(set_rmask(NVR_WRITE_ENABLE), | 911 | writel(set_rmask(NVR_WRITE_ENABLE), |
932 | &ha->reg->u1.isp4022.nvram); | 912 | &ha->reg->u1.isp4022.nvram); |
933 | 913 | ||
@@ -978,7 +958,7 @@ static int qla4xxx_start_firmware_from_flash(struct scsi_qla_host *ha) | |||
978 | return status; | 958 | return status; |
979 | } | 959 | } |
980 | 960 | ||
981 | static int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) | 961 | int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) |
982 | { | 962 | { |
983 | #define QL4_LOCK_DRVR_WAIT 300 | 963 | #define QL4_LOCK_DRVR_WAIT 300 |
984 | #define QL4_LOCK_DRVR_SLEEP 100 | 964 | #define QL4_LOCK_DRVR_SLEEP 100 |
@@ -1018,12 +998,7 @@ static int qla4xxx_start_firmware(struct scsi_qla_host *ha) | |||
1018 | int soft_reset = 1; | 998 | int soft_reset = 1; |
1019 | int config_chip = 0; | 999 | int config_chip = 0; |
1020 | 1000 | ||
1021 | if (is_qla4010(ha)){ | 1001 | if (is_qla4022(ha) | is_qla4032(ha)) |
1022 | if (qla4010_get_topcat_presence(ha) != QLA_SUCCESS) | ||
1023 | return QLA_ERROR; | ||
1024 | } | ||
1025 | |||
1026 | if (is_qla4022(ha)) | ||
1027 | ql4xxx_set_mac_number(ha); | 1002 | ql4xxx_set_mac_number(ha); |
1028 | 1003 | ||
1029 | if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS) | 1004 | if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS) |
diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h index 0d61797af7da..6375eb017dd3 100644 --- a/drivers/scsi/qla4xxx/ql4_inline.h +++ b/drivers/scsi/qla4xxx/ql4_inline.h | |||
@@ -38,7 +38,7 @@ qla4xxx_lookup_ddb_by_fw_index(struct scsi_qla_host *ha, uint32_t fw_ddb_index) | |||
38 | static inline void | 38 | static inline void |
39 | __qla4xxx_enable_intrs(struct scsi_qla_host *ha) | 39 | __qla4xxx_enable_intrs(struct scsi_qla_host *ha) |
40 | { | 40 | { |
41 | if (is_qla4022(ha)) { | 41 | if (is_qla4022(ha) | is_qla4032(ha)) { |
42 | writel(set_rmask(IMR_SCSI_INTR_ENABLE), | 42 | writel(set_rmask(IMR_SCSI_INTR_ENABLE), |
43 | &ha->reg->u1.isp4022.intr_mask); | 43 | &ha->reg->u1.isp4022.intr_mask); |
44 | readl(&ha->reg->u1.isp4022.intr_mask); | 44 | readl(&ha->reg->u1.isp4022.intr_mask); |
@@ -52,7 +52,7 @@ __qla4xxx_enable_intrs(struct scsi_qla_host *ha) | |||
52 | static inline void | 52 | static inline void |
53 | __qla4xxx_disable_intrs(struct scsi_qla_host *ha) | 53 | __qla4xxx_disable_intrs(struct scsi_qla_host *ha) |
54 | { | 54 | { |
55 | if (is_qla4022(ha)) { | 55 | if (is_qla4022(ha) | is_qla4032(ha)) { |
56 | writel(clr_rmask(IMR_SCSI_INTR_ENABLE), | 56 | writel(clr_rmask(IMR_SCSI_INTR_ENABLE), |
57 | &ha->reg->u1.isp4022.intr_mask); | 57 | &ha->reg->u1.isp4022.intr_mask); |
58 | readl(&ha->reg->u1.isp4022.intr_mask); | 58 | readl(&ha->reg->u1.isp4022.intr_mask); |
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index c0a254b89a30..d41ce380eedc 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c | |||
@@ -294,6 +294,12 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) | |||
294 | cmd_entry->control_flags = CF_WRITE; | 294 | cmd_entry->control_flags = CF_WRITE; |
295 | else if (cmd->sc_data_direction == DMA_FROM_DEVICE) | 295 | else if (cmd->sc_data_direction == DMA_FROM_DEVICE) |
296 | cmd_entry->control_flags = CF_READ; | 296 | cmd_entry->control_flags = CF_READ; |
297 | |||
298 | ha->bytes_xfered += cmd->request_bufflen; | ||
299 | if (ha->bytes_xfered & ~0xFFFFF){ | ||
300 | ha->total_mbytes_xferred += ha->bytes_xfered >> 20; | ||
301 | ha->bytes_xfered &= 0xFFFFF; | ||
302 | } | ||
297 | } | 303 | } |
298 | 304 | ||
299 | /* Set tagged queueing control flags */ | 305 | /* Set tagged queueing control flags */ |
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 1e283321a59d..ef975e0dc87f 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -627,6 +627,7 @@ irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id) | |||
627 | 627 | ||
628 | spin_lock_irqsave(&ha->hardware_lock, flags); | 628 | spin_lock_irqsave(&ha->hardware_lock, flags); |
629 | 629 | ||
630 | ha->isr_count++; | ||
630 | /* | 631 | /* |
631 | * Repeatedly service interrupts up to a maximum of | 632 | * Repeatedly service interrupts up to a maximum of |
632 | * MAX_REQS_SERVICED_PER_INTR | 633 | * MAX_REQS_SERVICED_PER_INTR |
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.c b/drivers/scsi/qla4xxx/ql4_nvram.c index e3957ca5b645..58afd135aa1d 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.c +++ b/drivers/scsi/qla4xxx/ql4_nvram.c | |||
@@ -7,15 +7,22 @@ | |||
7 | 7 | ||
8 | #include "ql4_def.h" | 8 | #include "ql4_def.h" |
9 | 9 | ||
10 | static inline void eeprom_cmd(uint32_t cmd, struct scsi_qla_host *ha) | ||
11 | { | ||
12 | writel(cmd, isp_nvram(ha)); | ||
13 | readl(isp_nvram(ha)); | ||
14 | udelay(1); | ||
15 | } | ||
16 | |||
10 | static inline int eeprom_size(struct scsi_qla_host *ha) | 17 | static inline int eeprom_size(struct scsi_qla_host *ha) |
11 | { | 18 | { |
12 | return is_qla4022(ha) ? FM93C86A_SIZE_16 : FM93C66A_SIZE_16; | 19 | return is_qla4010(ha) ? FM93C66A_SIZE_16 : FM93C86A_SIZE_16; |
13 | } | 20 | } |
14 | 21 | ||
15 | static inline int eeprom_no_addr_bits(struct scsi_qla_host *ha) | 22 | static inline int eeprom_no_addr_bits(struct scsi_qla_host *ha) |
16 | { | 23 | { |
17 | return is_qla4022(ha) ? FM93C86A_NO_ADDR_BITS_16 : | 24 | return is_qla4010(ha) ? FM93C56A_NO_ADDR_BITS_16 : |
18 | FM93C56A_NO_ADDR_BITS_16; | 25 | FM93C86A_NO_ADDR_BITS_16 ; |
19 | } | 26 | } |
20 | 27 | ||
21 | static inline int eeprom_no_data_bits(struct scsi_qla_host *ha) | 28 | static inline int eeprom_no_data_bits(struct scsi_qla_host *ha) |
@@ -28,8 +35,7 @@ static int fm93c56a_select(struct scsi_qla_host * ha) | |||
28 | DEBUG5(printk(KERN_ERR "fm93c56a_select:\n")); | 35 | DEBUG5(printk(KERN_ERR "fm93c56a_select:\n")); |
29 | 36 | ||
30 | ha->eeprom_cmd_data = AUBURN_EEPROM_CS_1 | 0x000f0000; | 37 | ha->eeprom_cmd_data = AUBURN_EEPROM_CS_1 | 0x000f0000; |
31 | writel(ha->eeprom_cmd_data, isp_nvram(ha)); | 38 | eeprom_cmd(ha->eeprom_cmd_data, ha); |
32 | readl(isp_nvram(ha)); | ||
33 | return 1; | 39 | return 1; |
34 | } | 40 | } |
35 | 41 | ||
@@ -41,12 +47,13 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) | |||
41 | int previousBit; | 47 | int previousBit; |
42 | 48 | ||
43 | /* Clock in a zero, then do the start bit. */ | 49 | /* Clock in a zero, then do the start bit. */ |
44 | writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1, isp_nvram(ha)); | 50 | eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1, ha); |
45 | writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | | 51 | |
46 | AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); | 52 | eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | |
47 | writel(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | | 53 | AUBURN_EEPROM_CLK_RISE, ha); |
48 | AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); | 54 | eeprom_cmd(ha->eeprom_cmd_data | AUBURN_EEPROM_DO_1 | |
49 | readl(isp_nvram(ha)); | 55 | AUBURN_EEPROM_CLK_FALL, ha); |
56 | |||
50 | mask = 1 << (FM93C56A_CMD_BITS - 1); | 57 | mask = 1 << (FM93C56A_CMD_BITS - 1); |
51 | 58 | ||
52 | /* Force the previous data bit to be different. */ | 59 | /* Force the previous data bit to be different. */ |
@@ -60,14 +67,14 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) | |||
60 | * If the bit changed, then change the DO state to | 67 | * If the bit changed, then change the DO state to |
61 | * match. | 68 | * match. |
62 | */ | 69 | */ |
63 | writel(ha->eeprom_cmd_data | dataBit, isp_nvram(ha)); | 70 | eeprom_cmd(ha->eeprom_cmd_data | dataBit, ha); |
64 | previousBit = dataBit; | 71 | previousBit = dataBit; |
65 | } | 72 | } |
66 | writel(ha->eeprom_cmd_data | dataBit | | 73 | eeprom_cmd(ha->eeprom_cmd_data | dataBit | |
67 | AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); | 74 | AUBURN_EEPROM_CLK_RISE, ha); |
68 | writel(ha->eeprom_cmd_data | dataBit | | 75 | eeprom_cmd(ha->eeprom_cmd_data | dataBit | |
69 | AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); | 76 | AUBURN_EEPROM_CLK_FALL, ha); |
70 | readl(isp_nvram(ha)); | 77 | |
71 | cmd = cmd << 1; | 78 | cmd = cmd << 1; |
72 | } | 79 | } |
73 | mask = 1 << (eeprom_no_addr_bits(ha) - 1); | 80 | mask = 1 << (eeprom_no_addr_bits(ha) - 1); |
@@ -82,14 +89,15 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) | |||
82 | * If the bit changed, then change the DO state to | 89 | * If the bit changed, then change the DO state to |
83 | * match. | 90 | * match. |
84 | */ | 91 | */ |
85 | writel(ha->eeprom_cmd_data | dataBit, isp_nvram(ha)); | 92 | eeprom_cmd(ha->eeprom_cmd_data | dataBit, ha); |
93 | |||
86 | previousBit = dataBit; | 94 | previousBit = dataBit; |
87 | } | 95 | } |
88 | writel(ha->eeprom_cmd_data | dataBit | | 96 | eeprom_cmd(ha->eeprom_cmd_data | dataBit | |
89 | AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); | 97 | AUBURN_EEPROM_CLK_RISE, ha); |
90 | writel(ha->eeprom_cmd_data | dataBit | | 98 | eeprom_cmd(ha->eeprom_cmd_data | dataBit | |
91 | AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); | 99 | AUBURN_EEPROM_CLK_FALL, ha); |
92 | readl(isp_nvram(ha)); | 100 | |
93 | addr = addr << 1; | 101 | addr = addr << 1; |
94 | } | 102 | } |
95 | return 1; | 103 | return 1; |
@@ -98,8 +106,7 @@ static int fm93c56a_cmd(struct scsi_qla_host * ha, int cmd, int addr) | |||
98 | static int fm93c56a_deselect(struct scsi_qla_host * ha) | 106 | static int fm93c56a_deselect(struct scsi_qla_host * ha) |
99 | { | 107 | { |
100 | ha->eeprom_cmd_data = AUBURN_EEPROM_CS_0 | 0x000f0000; | 108 | ha->eeprom_cmd_data = AUBURN_EEPROM_CS_0 | 0x000f0000; |
101 | writel(ha->eeprom_cmd_data, isp_nvram(ha)); | 109 | eeprom_cmd(ha->eeprom_cmd_data, ha); |
102 | readl(isp_nvram(ha)); | ||
103 | return 1; | 110 | return 1; |
104 | } | 111 | } |
105 | 112 | ||
@@ -112,12 +119,13 @@ static int fm93c56a_datain(struct scsi_qla_host * ha, unsigned short *value) | |||
112 | /* Read the data bits | 119 | /* Read the data bits |
113 | * The first bit is a dummy. Clock right over it. */ | 120 | * The first bit is a dummy. Clock right over it. */ |
114 | for (i = 0; i < eeprom_no_data_bits(ha); i++) { | 121 | for (i = 0; i < eeprom_no_data_bits(ha); i++) { |
115 | writel(ha->eeprom_cmd_data | | 122 | eeprom_cmd(ha->eeprom_cmd_data | |
116 | AUBURN_EEPROM_CLK_RISE, isp_nvram(ha)); | 123 | AUBURN_EEPROM_CLK_RISE, ha); |
117 | writel(ha->eeprom_cmd_data | | 124 | eeprom_cmd(ha->eeprom_cmd_data | |
118 | AUBURN_EEPROM_CLK_FALL, isp_nvram(ha)); | 125 | AUBURN_EEPROM_CLK_FALL, ha); |
119 | dataBit = | 126 | |
120 | (readw(isp_nvram(ha)) & AUBURN_EEPROM_DI_1) ? 1 : 0; | 127 | dataBit = (readw(isp_nvram(ha)) & AUBURN_EEPROM_DI_1) ? 1 : 0; |
128 | |||
121 | data = (data << 1) | dataBit; | 129 | data = (data << 1) | dataBit; |
122 | } | 130 | } |
123 | 131 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_nvram.h b/drivers/scsi/qla4xxx/ql4_nvram.h index 08e2aed8c6cc..b47b4fc59d83 100644 --- a/drivers/scsi/qla4xxx/ql4_nvram.h +++ b/drivers/scsi/qla4xxx/ql4_nvram.h | |||
@@ -134,9 +134,7 @@ struct eeprom_data { | |||
134 | u16 phyConfig; /* x36 */ | 134 | u16 phyConfig; /* x36 */ |
135 | #define PHY_CONFIG_PHY_ADDR_MASK 0x1f | 135 | #define PHY_CONFIG_PHY_ADDR_MASK 0x1f |
136 | #define PHY_CONFIG_ENABLE_FW_MANAGEMENT_MASK 0x20 | 136 | #define PHY_CONFIG_ENABLE_FW_MANAGEMENT_MASK 0x20 |
137 | u16 topcat; /* x38 */ | 137 | u16 reserved_56; /* x38 */ |
138 | #define TOPCAT_PRESENT 0x0100 | ||
139 | #define TOPCAT_MASK 0xFF00 | ||
140 | 138 | ||
141 | #define EEPROM_UNUSED_1_SIZE 2 | 139 | #define EEPROM_UNUSED_1_SIZE 2 |
142 | u8 unused_1[EEPROM_UNUSED_1_SIZE]; /* x3A */ | 140 | u8 unused_1[EEPROM_UNUSED_1_SIZE]; /* x3A */ |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index bbbc9d039baa..969c9e431028 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -708,10 +708,10 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) | |||
708 | } | 708 | } |
709 | 709 | ||
710 | /** | 710 | /** |
711 | * qla4010_soft_reset - performs soft reset. | 711 | * qla4xxx_soft_reset - performs soft reset. |
712 | * @ha: Pointer to host adapter structure. | 712 | * @ha: Pointer to host adapter structure. |
713 | **/ | 713 | **/ |
714 | static int qla4010_soft_reset(struct scsi_qla_host *ha) | 714 | int qla4xxx_soft_reset(struct scsi_qla_host *ha) |
715 | { | 715 | { |
716 | uint32_t max_wait_time; | 716 | uint32_t max_wait_time; |
717 | unsigned long flags = 0; | 717 | unsigned long flags = 0; |
@@ -817,29 +817,6 @@ static int qla4010_soft_reset(struct scsi_qla_host *ha) | |||
817 | } | 817 | } |
818 | 818 | ||
819 | /** | 819 | /** |
820 | * qla4xxx_topcat_reset - performs hard reset of TopCat Chip. | ||
821 | * @ha: Pointer to host adapter structure. | ||
822 | **/ | ||
823 | static int qla4xxx_topcat_reset(struct scsi_qla_host *ha) | ||
824 | { | ||
825 | unsigned long flags; | ||
826 | |||
827 | ql4xxx_lock_nvram(ha); | ||
828 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
829 | writel(set_rmask(GPOR_TOPCAT_RESET), isp_gp_out(ha)); | ||
830 | readl(isp_gp_out(ha)); | ||
831 | mdelay(1); | ||
832 | |||
833 | writel(clr_rmask(GPOR_TOPCAT_RESET), isp_gp_out(ha)); | ||
834 | readl(isp_gp_out(ha)); | ||
835 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
836 | mdelay(2523); | ||
837 | |||
838 | ql4xxx_unlock_nvram(ha); | ||
839 | return QLA_SUCCESS; | ||
840 | } | ||
841 | |||
842 | /** | ||
843 | * qla4xxx_flush_active_srbs - returns all outstanding i/o requests to O.S. | 820 | * qla4xxx_flush_active_srbs - returns all outstanding i/o requests to O.S. |
844 | * @ha: Pointer to host adapter structure. | 821 | * @ha: Pointer to host adapter structure. |
845 | * | 822 | * |
@@ -867,26 +844,6 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) | |||
867 | } | 844 | } |
868 | 845 | ||
869 | /** | 846 | /** |
870 | * qla4xxx_hard_reset - performs HBA Hard Reset | ||
871 | * @ha: Pointer to host adapter structure. | ||
872 | **/ | ||
873 | static int qla4xxx_hard_reset(struct scsi_qla_host *ha) | ||
874 | { | ||
875 | /* The QLA4010 really doesn't have an equivalent to a hard reset */ | ||
876 | qla4xxx_flush_active_srbs(ha); | ||
877 | if (test_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags)) { | ||
878 | int status = QLA_ERROR; | ||
879 | |||
880 | if ((qla4010_soft_reset(ha) == QLA_SUCCESS) && | ||
881 | (qla4xxx_topcat_reset(ha) == QLA_SUCCESS) && | ||
882 | (qla4010_soft_reset(ha) == QLA_SUCCESS)) | ||
883 | status = QLA_SUCCESS; | ||
884 | return status; | ||
885 | } else | ||
886 | return qla4010_soft_reset(ha); | ||
887 | } | ||
888 | |||
889 | /** | ||
890 | * qla4xxx_recover_adapter - recovers adapter after a fatal error | 847 | * qla4xxx_recover_adapter - recovers adapter after a fatal error |
891 | * @ha: Pointer to host adapter structure. | 848 | * @ha: Pointer to host adapter structure. |
892 | * @renew_ddb_list: Indicates what to do with the adapter's ddb list | 849 | * @renew_ddb_list: Indicates what to do with the adapter's ddb list |
@@ -919,18 +876,11 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, | |||
919 | if (status == QLA_SUCCESS) { | 876 | if (status == QLA_SUCCESS) { |
920 | DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", | 877 | DEBUG2(printk("scsi%ld: %s - Performing soft reset..\n", |
921 | ha->host_no, __func__)); | 878 | ha->host_no, __func__)); |
922 | status = qla4xxx_soft_reset(ha); | 879 | qla4xxx_flush_active_srbs(ha); |
923 | } | 880 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) |
924 | /* FIXMEkaren: Do we want to keep interrupts enabled and process | 881 | status = qla4xxx_soft_reset(ha); |
925 | AENs after soft reset */ | 882 | else |
926 | 883 | status = QLA_ERROR; | |
927 | /* If firmware (SOFT) reset failed, or if all outstanding | ||
928 | * commands have not returned, then do a HARD reset. | ||
929 | */ | ||
930 | if (status == QLA_ERROR) { | ||
931 | DEBUG2(printk("scsi%ld: %s - Performing hard reset..\n", | ||
932 | ha->host_no, __func__)); | ||
933 | status = qla4xxx_hard_reset(ha); | ||
934 | } | 884 | } |
935 | 885 | ||
936 | /* Flush any pending ddb changed AENs */ | 886 | /* Flush any pending ddb changed AENs */ |
@@ -1017,13 +967,9 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1017 | container_of(work, struct scsi_qla_host, dpc_work); | 967 | container_of(work, struct scsi_qla_host, dpc_work); |
1018 | struct ddb_entry *ddb_entry, *dtemp; | 968 | struct ddb_entry *ddb_entry, *dtemp; |
1019 | 969 | ||
1020 | DEBUG2(printk("scsi%ld: %s: DPC handler waking up.\n", | 970 | DEBUG2(printk("scsi%ld: %s: DPC handler waking up." |
1021 | ha->host_no, __func__)); | 971 | "flags = 0x%08lx, dpc_flags = 0x%08lx\n", |
1022 | 972 | ha->host_no, __func__, ha->flags, ha->dpc_flags)); | |
1023 | DEBUG2(printk("scsi%ld: %s: ha->flags = 0x%08lx\n", | ||
1024 | ha->host_no, __func__, ha->flags)); | ||
1025 | DEBUG2(printk("scsi%ld: %s: ha->dpc_flags = 0x%08lx\n", | ||
1026 | ha->host_no, __func__, ha->dpc_flags)); | ||
1027 | 973 | ||
1028 | /* Initialization not yet finished. Don't do anything yet. */ | 974 | /* Initialization not yet finished. Don't do anything yet. */ |
1029 | if (!test_bit(AF_INIT_DONE, &ha->flags)) | 975 | if (!test_bit(AF_INIT_DONE, &ha->flags)) |
@@ -1033,16 +979,8 @@ static void qla4xxx_do_dpc(struct work_struct *work) | |||
1033 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || | 979 | test_bit(DPC_RESET_HA, &ha->dpc_flags) || |
1034 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || | 980 | test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || |
1035 | test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) { | 981 | test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) { |
1036 | if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags)) | 982 | if (test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || |
1037 | /* | 983 | test_bit(DPC_RESET_HA, &ha->dpc_flags)) |
1038 | * dg 09/23 Never initialize ddb list | ||
1039 | * once we up and running | ||
1040 | * qla4xxx_recover_adapter(ha, | ||
1041 | * REBUILD_DDB_LIST); | ||
1042 | */ | ||
1043 | qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); | ||
1044 | |||
1045 | if (test_bit(DPC_RESET_HA, &ha->dpc_flags)) | ||
1046 | qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); | 984 | qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST); |
1047 | 985 | ||
1048 | if (test_and_clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { | 986 | if (test_and_clear_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) { |
@@ -1123,7 +1061,8 @@ static void qla4xxx_free_adapter(struct scsi_qla_host *ha) | |||
1123 | destroy_workqueue(ha->dpc_thread); | 1061 | destroy_workqueue(ha->dpc_thread); |
1124 | 1062 | ||
1125 | /* Issue Soft Reset to put firmware in unknown state */ | 1063 | /* Issue Soft Reset to put firmware in unknown state */ |
1126 | qla4xxx_soft_reset(ha); | 1064 | if (ql4xxx_lock_drvr_wait(ha) == QLA_SUCCESS) |
1065 | qla4xxx_soft_reset(ha); | ||
1127 | 1066 | ||
1128 | /* Remove timer thread, if present */ | 1067 | /* Remove timer thread, if present */ |
1129 | if (ha->timer_active) | 1068 | if (ha->timer_active) |
@@ -1262,7 +1201,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1262 | init_waitqueue_head(&ha->mailbox_wait_queue); | 1201 | init_waitqueue_head(&ha->mailbox_wait_queue); |
1263 | 1202 | ||
1264 | spin_lock_init(&ha->hardware_lock); | 1203 | spin_lock_init(&ha->hardware_lock); |
1265 | spin_lock_init(&ha->list_lock); | ||
1266 | 1204 | ||
1267 | /* Allocate dma buffers */ | 1205 | /* Allocate dma buffers */ |
1268 | if (qla4xxx_mem_alloc(ha)) { | 1206 | if (qla4xxx_mem_alloc(ha)) { |
@@ -1469,27 +1407,6 @@ struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t in | |||
1469 | } | 1407 | } |
1470 | 1408 | ||
1471 | /** | 1409 | /** |
1472 | * qla4xxx_soft_reset - performs a SOFT RESET of hba. | ||
1473 | * @ha: Pointer to host adapter structure. | ||
1474 | **/ | ||
1475 | int qla4xxx_soft_reset(struct scsi_qla_host *ha) | ||
1476 | { | ||
1477 | |||
1478 | DEBUG2(printk(KERN_WARNING "scsi%ld: %s: chip reset!\n", ha->host_no, | ||
1479 | __func__)); | ||
1480 | if (test_bit(AF_TOPCAT_CHIP_PRESENT, &ha->flags)) { | ||
1481 | int status = QLA_ERROR; | ||
1482 | |||
1483 | if ((qla4010_soft_reset(ha) == QLA_SUCCESS) && | ||
1484 | (qla4xxx_topcat_reset(ha) == QLA_SUCCESS) && | ||
1485 | (qla4010_soft_reset(ha) == QLA_SUCCESS) ) | ||
1486 | status = QLA_SUCCESS; | ||
1487 | return status; | ||
1488 | } else | ||
1489 | return qla4010_soft_reset(ha); | ||
1490 | } | ||
1491 | |||
1492 | /** | ||
1493 | * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware | 1410 | * qla4xxx_eh_wait_on_command - waits for command to be returned by firmware |
1494 | * @ha: actual ha whose done queue will contain the comd returned by firmware. | 1411 | * @ha: actual ha whose done queue will contain the comd returned by firmware. |
1495 | * @cmd: Scsi Command to wait on. | 1412 | * @cmd: Scsi Command to wait on. |
@@ -1687,6 +1604,12 @@ static struct pci_device_id qla4xxx_pci_tbl[] = { | |||
1687 | .subvendor = PCI_ANY_ID, | 1604 | .subvendor = PCI_ANY_ID, |
1688 | .subdevice = PCI_ANY_ID, | 1605 | .subdevice = PCI_ANY_ID, |
1689 | }, | 1606 | }, |
1607 | { | ||
1608 | .vendor = PCI_VENDOR_ID_QLOGIC, | ||
1609 | .device = PCI_DEVICE_ID_QLOGIC_ISP4032, | ||
1610 | .subvendor = PCI_ANY_ID, | ||
1611 | .subdevice = PCI_ANY_ID, | ||
1612 | }, | ||
1690 | {0, 0}, | 1613 | {0, 0}, |
1691 | }; | 1614 | }; |
1692 | MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); | 1615 | MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); |
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index b3fe7e68988e..454e19c8ad68 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
@@ -5,9 +5,4 @@ | |||
5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define QLA4XXX_DRIVER_VERSION "5.00.05b9-k" | 8 | #define QLA4XXX_DRIVER_VERSION "5.00.07-k" |
9 | |||
10 | #define QL4_DRIVER_MAJOR_VER 5 | ||
11 | #define QL4_DRIVER_MINOR_VER 0 | ||
12 | #define QL4_DRIVER_PATCH_VER 5 | ||
13 | #define QL4_DRIVER_BETA_VER 9 | ||
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index c59f31533ab4..fafc00deaade 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -156,8 +156,7 @@ static struct scsi_host_cmd_pool scsi_cmd_dma_pool = { | |||
156 | 156 | ||
157 | static DEFINE_MUTEX(host_cmd_pool_mutex); | 157 | static DEFINE_MUTEX(host_cmd_pool_mutex); |
158 | 158 | ||
159 | static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, | 159 | struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) |
160 | gfp_t gfp_mask) | ||
161 | { | 160 | { |
162 | struct scsi_cmnd *cmd; | 161 | struct scsi_cmnd *cmd; |
163 | 162 | ||
@@ -178,6 +177,7 @@ static struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, | |||
178 | 177 | ||
179 | return cmd; | 178 | return cmd; |
180 | } | 179 | } |
180 | EXPORT_SYMBOL_GPL(__scsi_get_command); | ||
181 | 181 | ||
182 | /* | 182 | /* |
183 | * Function: scsi_get_command() | 183 | * Function: scsi_get_command() |
@@ -214,9 +214,29 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask) | |||
214 | put_device(&dev->sdev_gendev); | 214 | put_device(&dev->sdev_gendev); |
215 | 215 | ||
216 | return cmd; | 216 | return cmd; |
217 | } | 217 | } |
218 | EXPORT_SYMBOL(scsi_get_command); | 218 | EXPORT_SYMBOL(scsi_get_command); |
219 | 219 | ||
220 | void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd, | ||
221 | struct device *dev) | ||
222 | { | ||
223 | unsigned long flags; | ||
224 | |||
225 | /* changing locks here, don't need to restore the irq state */ | ||
226 | spin_lock_irqsave(&shost->free_list_lock, flags); | ||
227 | if (unlikely(list_empty(&shost->free_list))) { | ||
228 | list_add(&cmd->list, &shost->free_list); | ||
229 | cmd = NULL; | ||
230 | } | ||
231 | spin_unlock_irqrestore(&shost->free_list_lock, flags); | ||
232 | |||
233 | if (likely(cmd != NULL)) | ||
234 | kmem_cache_free(shost->cmd_pool->slab, cmd); | ||
235 | |||
236 | put_device(dev); | ||
237 | } | ||
238 | EXPORT_SYMBOL(__scsi_put_command); | ||
239 | |||
220 | /* | 240 | /* |
221 | * Function: scsi_put_command() | 241 | * Function: scsi_put_command() |
222 | * | 242 | * |
@@ -231,26 +251,15 @@ EXPORT_SYMBOL(scsi_get_command); | |||
231 | void scsi_put_command(struct scsi_cmnd *cmd) | 251 | void scsi_put_command(struct scsi_cmnd *cmd) |
232 | { | 252 | { |
233 | struct scsi_device *sdev = cmd->device; | 253 | struct scsi_device *sdev = cmd->device; |
234 | struct Scsi_Host *shost = sdev->host; | ||
235 | unsigned long flags; | 254 | unsigned long flags; |
236 | 255 | ||
237 | /* serious error if the command hasn't come from a device list */ | 256 | /* serious error if the command hasn't come from a device list */ |
238 | spin_lock_irqsave(&cmd->device->list_lock, flags); | 257 | spin_lock_irqsave(&cmd->device->list_lock, flags); |
239 | BUG_ON(list_empty(&cmd->list)); | 258 | BUG_ON(list_empty(&cmd->list)); |
240 | list_del_init(&cmd->list); | 259 | list_del_init(&cmd->list); |
241 | spin_unlock(&cmd->device->list_lock); | 260 | spin_unlock_irqrestore(&cmd->device->list_lock, flags); |
242 | /* changing locks here, don't need to restore the irq state */ | ||
243 | spin_lock(&shost->free_list_lock); | ||
244 | if (unlikely(list_empty(&shost->free_list))) { | ||
245 | list_add(&cmd->list, &shost->free_list); | ||
246 | cmd = NULL; | ||
247 | } | ||
248 | spin_unlock_irqrestore(&shost->free_list_lock, flags); | ||
249 | |||
250 | if (likely(cmd != NULL)) | ||
251 | kmem_cache_free(shost->cmd_pool->slab, cmd); | ||
252 | 261 | ||
253 | put_device(&sdev->sdev_gendev); | 262 | __scsi_put_command(cmd->device->host, cmd, &sdev->sdev_gendev); |
254 | } | 263 | } |
255 | EXPORT_SYMBOL(scsi_put_command); | 264 | EXPORT_SYMBOL(scsi_put_command); |
256 | 265 | ||
@@ -871,9 +880,9 @@ EXPORT_SYMBOL(scsi_device_get); | |||
871 | */ | 880 | */ |
872 | void scsi_device_put(struct scsi_device *sdev) | 881 | void scsi_device_put(struct scsi_device *sdev) |
873 | { | 882 | { |
883 | #ifdef CONFIG_MODULE_UNLOAD | ||
874 | struct module *module = sdev->host->hostt->module; | 884 | struct module *module = sdev->host->hostt->module; |
875 | 885 | ||
876 | #ifdef CONFIG_MODULE_UNLOAD | ||
877 | /* The module refcount will be zero if scsi_device_get() | 886 | /* The module refcount will be zero if scsi_device_get() |
878 | * was called from a module removal routine */ | 887 | * was called from a module removal routine */ |
879 | if (module && module_refcount(module) != 0) | 888 | if (module && module_refcount(module) != 0) |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index aff1b0cfd4b2..2ecb6ff42444 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -453,9 +453,18 @@ static void scsi_eh_done(struct scsi_cmnd *scmd) | |||
453 | } | 453 | } |
454 | 454 | ||
455 | /** | 455 | /** |
456 | * scsi_send_eh_cmnd - send a cmd to a device as part of error recovery. | 456 | * scsi_send_eh_cmnd - submit a scsi command as part of error recory |
457 | * @scmd: SCSI Cmd to send. | 457 | * @scmd: SCSI command structure to hijack |
458 | * @timeout: Timeout for cmd. | 458 | * @cmnd: CDB to send |
459 | * @cmnd_size: size in bytes of @cmnd | ||
460 | * @timeout: timeout for this request | ||
461 | * @copy_sense: request sense data if set to 1 | ||
462 | * | ||
463 | * This function is used to send a scsi command down to a target device | ||
464 | * as part of the error recovery process. If @copy_sense is 0 the command | ||
465 | * sent must be one that does not transfer any data. If @copy_sense is 1 | ||
466 | * the command must be REQUEST_SENSE and this functions copies out the | ||
467 | * sense buffer it got into @scmd->sense_buffer. | ||
459 | * | 468 | * |
460 | * Return value: | 469 | * Return value: |
461 | * SUCCESS or FAILED or NEEDS_RETRY | 470 | * SUCCESS or FAILED or NEEDS_RETRY |
@@ -469,6 +478,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
469 | DECLARE_COMPLETION_ONSTACK(done); | 478 | DECLARE_COMPLETION_ONSTACK(done); |
470 | unsigned long timeleft; | 479 | unsigned long timeleft; |
471 | unsigned long flags; | 480 | unsigned long flags; |
481 | struct scatterlist sgl; | ||
472 | unsigned char old_cmnd[MAX_COMMAND_SIZE]; | 482 | unsigned char old_cmnd[MAX_COMMAND_SIZE]; |
473 | enum dma_data_direction old_data_direction; | 483 | enum dma_data_direction old_data_direction; |
474 | unsigned short old_use_sg; | 484 | unsigned short old_use_sg; |
@@ -500,19 +510,24 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
500 | if (shost->hostt->unchecked_isa_dma) | 510 | if (shost->hostt->unchecked_isa_dma) |
501 | gfp_mask |= __GFP_DMA; | 511 | gfp_mask |= __GFP_DMA; |
502 | 512 | ||
503 | scmd->sc_data_direction = DMA_FROM_DEVICE; | 513 | sgl.page = alloc_page(gfp_mask); |
504 | scmd->request_bufflen = 252; | 514 | if (!sgl.page) |
505 | scmd->request_buffer = kzalloc(scmd->request_bufflen, gfp_mask); | ||
506 | if (!scmd->request_buffer) | ||
507 | return FAILED; | 515 | return FAILED; |
516 | sgl.offset = 0; | ||
517 | sgl.length = 252; | ||
518 | |||
519 | scmd->sc_data_direction = DMA_FROM_DEVICE; | ||
520 | scmd->request_bufflen = sgl.length; | ||
521 | scmd->request_buffer = &sgl; | ||
522 | scmd->use_sg = 1; | ||
508 | } else { | 523 | } else { |
509 | scmd->request_buffer = NULL; | 524 | scmd->request_buffer = NULL; |
510 | scmd->request_bufflen = 0; | 525 | scmd->request_bufflen = 0; |
511 | scmd->sc_data_direction = DMA_NONE; | 526 | scmd->sc_data_direction = DMA_NONE; |
527 | scmd->use_sg = 0; | ||
512 | } | 528 | } |
513 | 529 | ||
514 | scmd->underflow = 0; | 530 | scmd->underflow = 0; |
515 | scmd->use_sg = 0; | ||
516 | scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); | 531 | scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); |
517 | 532 | ||
518 | if (sdev->scsi_level <= SCSI_2) | 533 | if (sdev->scsi_level <= SCSI_2) |
@@ -583,7 +598,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
583 | memcpy(scmd->sense_buffer, scmd->request_buffer, | 598 | memcpy(scmd->sense_buffer, scmd->request_buffer, |
584 | sizeof(scmd->sense_buffer)); | 599 | sizeof(scmd->sense_buffer)); |
585 | } | 600 | } |
586 | kfree(scmd->request_buffer); | 601 | __free_page(sgl.page); |
587 | } | 602 | } |
588 | 603 | ||
589 | 604 | ||
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 3ac4890ce086..fb616c69151f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -704,7 +704,7 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, | |||
704 | return NULL; | 704 | return NULL; |
705 | } | 705 | } |
706 | 706 | ||
707 | static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) | 707 | struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_mask) |
708 | { | 708 | { |
709 | struct scsi_host_sg_pool *sgp; | 709 | struct scsi_host_sg_pool *sgp; |
710 | struct scatterlist *sgl; | 710 | struct scatterlist *sgl; |
@@ -745,7 +745,9 @@ static struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *cmd, gfp_t gfp_m | |||
745 | return sgl; | 745 | return sgl; |
746 | } | 746 | } |
747 | 747 | ||
748 | static void scsi_free_sgtable(struct scatterlist *sgl, int index) | 748 | EXPORT_SYMBOL(scsi_alloc_sgtable); |
749 | |||
750 | void scsi_free_sgtable(struct scatterlist *sgl, int index) | ||
749 | { | 751 | { |
750 | struct scsi_host_sg_pool *sgp; | 752 | struct scsi_host_sg_pool *sgp; |
751 | 753 | ||
@@ -755,6 +757,8 @@ static void scsi_free_sgtable(struct scatterlist *sgl, int index) | |||
755 | mempool_free(sgl, sgp->pool); | 757 | mempool_free(sgl, sgp->pool); |
756 | } | 758 | } |
757 | 759 | ||
760 | EXPORT_SYMBOL(scsi_free_sgtable); | ||
761 | |||
758 | /* | 762 | /* |
759 | * Function: scsi_release_buffers() | 763 | * Function: scsi_release_buffers() |
760 | * | 764 | * |
@@ -996,25 +1000,14 @@ static int scsi_init_io(struct scsi_cmnd *cmd) | |||
996 | int count; | 1000 | int count; |
997 | 1001 | ||
998 | /* | 1002 | /* |
999 | * if this is a rq->data based REQ_BLOCK_PC, setup for a non-sg xfer | 1003 | * We used to not use scatter-gather for single segment request, |
1000 | */ | ||
1001 | if (blk_pc_request(req) && !req->bio) { | ||
1002 | cmd->request_bufflen = req->data_len; | ||
1003 | cmd->request_buffer = req->data; | ||
1004 | req->buffer = req->data; | ||
1005 | cmd->use_sg = 0; | ||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | /* | ||
1010 | * we used to not use scatter-gather for single segment request, | ||
1011 | * but now we do (it makes highmem I/O easier to support without | 1004 | * but now we do (it makes highmem I/O easier to support without |
1012 | * kmapping pages) | 1005 | * kmapping pages) |
1013 | */ | 1006 | */ |
1014 | cmd->use_sg = req->nr_phys_segments; | 1007 | cmd->use_sg = req->nr_phys_segments; |
1015 | 1008 | ||
1016 | /* | 1009 | /* |
1017 | * if sg table allocation fails, requeue request later. | 1010 | * If sg table allocation fails, requeue request later. |
1018 | */ | 1011 | */ |
1019 | sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC); | 1012 | sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC); |
1020 | if (unlikely(!sgpnt)) { | 1013 | if (unlikely(!sgpnt)) { |
@@ -1022,24 +1015,21 @@ static int scsi_init_io(struct scsi_cmnd *cmd) | |||
1022 | return BLKPREP_DEFER; | 1015 | return BLKPREP_DEFER; |
1023 | } | 1016 | } |
1024 | 1017 | ||
1018 | req->buffer = NULL; | ||
1025 | cmd->request_buffer = (char *) sgpnt; | 1019 | cmd->request_buffer = (char *) sgpnt; |
1026 | cmd->request_bufflen = req->nr_sectors << 9; | ||
1027 | if (blk_pc_request(req)) | 1020 | if (blk_pc_request(req)) |
1028 | cmd->request_bufflen = req->data_len; | 1021 | cmd->request_bufflen = req->data_len; |
1029 | req->buffer = NULL; | 1022 | else |
1023 | cmd->request_bufflen = req->nr_sectors << 9; | ||
1030 | 1024 | ||
1031 | /* | 1025 | /* |
1032 | * Next, walk the list, and fill in the addresses and sizes of | 1026 | * Next, walk the list, and fill in the addresses and sizes of |
1033 | * each segment. | 1027 | * each segment. |
1034 | */ | 1028 | */ |
1035 | count = blk_rq_map_sg(req->q, req, cmd->request_buffer); | 1029 | count = blk_rq_map_sg(req->q, req, cmd->request_buffer); |
1036 | |||
1037 | /* | ||
1038 | * mapped well, send it off | ||
1039 | */ | ||
1040 | if (likely(count <= cmd->use_sg)) { | 1030 | if (likely(count <= cmd->use_sg)) { |
1041 | cmd->use_sg = count; | 1031 | cmd->use_sg = count; |
1042 | return 0; | 1032 | return BLKPREP_OK; |
1043 | } | 1033 | } |
1044 | 1034 | ||
1045 | printk(KERN_ERR "Incorrect number of segments after building list\n"); | 1035 | printk(KERN_ERR "Incorrect number of segments after building list\n"); |
@@ -1069,6 +1059,27 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, | |||
1069 | return -EOPNOTSUPP; | 1059 | return -EOPNOTSUPP; |
1070 | } | 1060 | } |
1071 | 1061 | ||
1062 | static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, | ||
1063 | struct request *req) | ||
1064 | { | ||
1065 | struct scsi_cmnd *cmd; | ||
1066 | |||
1067 | if (!req->special) { | ||
1068 | cmd = scsi_get_command(sdev, GFP_ATOMIC); | ||
1069 | if (unlikely(!cmd)) | ||
1070 | return NULL; | ||
1071 | req->special = cmd; | ||
1072 | } else { | ||
1073 | cmd = req->special; | ||
1074 | } | ||
1075 | |||
1076 | /* pull a tag out of the request if we have one */ | ||
1077 | cmd->tag = req->tag; | ||
1078 | cmd->request = req; | ||
1079 | |||
1080 | return cmd; | ||
1081 | } | ||
1082 | |||
1072 | static void scsi_blk_pc_done(struct scsi_cmnd *cmd) | 1083 | static void scsi_blk_pc_done(struct scsi_cmnd *cmd) |
1073 | { | 1084 | { |
1074 | BUG_ON(!blk_pc_request(cmd->request)); | 1085 | BUG_ON(!blk_pc_request(cmd->request)); |
@@ -1081,9 +1092,37 @@ static void scsi_blk_pc_done(struct scsi_cmnd *cmd) | |||
1081 | scsi_io_completion(cmd, cmd->request_bufflen); | 1092 | scsi_io_completion(cmd, cmd->request_bufflen); |
1082 | } | 1093 | } |
1083 | 1094 | ||
1084 | static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) | 1095 | static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) |
1085 | { | 1096 | { |
1086 | struct request *req = cmd->request; | 1097 | struct scsi_cmnd *cmd; |
1098 | |||
1099 | cmd = scsi_get_cmd_from_req(sdev, req); | ||
1100 | if (unlikely(!cmd)) | ||
1101 | return BLKPREP_DEFER; | ||
1102 | |||
1103 | /* | ||
1104 | * BLOCK_PC requests may transfer data, in which case they must | ||
1105 | * a bio attached to them. Or they might contain a SCSI command | ||
1106 | * that does not transfer data, in which case they may optionally | ||
1107 | * submit a request without an attached bio. | ||
1108 | */ | ||
1109 | if (req->bio) { | ||
1110 | int ret; | ||
1111 | |||
1112 | BUG_ON(!req->nr_phys_segments); | ||
1113 | |||
1114 | ret = scsi_init_io(cmd); | ||
1115 | if (unlikely(ret)) | ||
1116 | return ret; | ||
1117 | } else { | ||
1118 | BUG_ON(req->data_len); | ||
1119 | BUG_ON(req->data); | ||
1120 | |||
1121 | cmd->request_bufflen = 0; | ||
1122 | cmd->request_buffer = NULL; | ||
1123 | cmd->use_sg = 0; | ||
1124 | req->buffer = NULL; | ||
1125 | } | ||
1087 | 1126 | ||
1088 | BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd)); | 1127 | BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd)); |
1089 | memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); | 1128 | memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); |
@@ -1099,154 +1138,138 @@ static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) | |||
1099 | cmd->allowed = req->retries; | 1138 | cmd->allowed = req->retries; |
1100 | cmd->timeout_per_command = req->timeout; | 1139 | cmd->timeout_per_command = req->timeout; |
1101 | cmd->done = scsi_blk_pc_done; | 1140 | cmd->done = scsi_blk_pc_done; |
1141 | return BLKPREP_OK; | ||
1102 | } | 1142 | } |
1103 | 1143 | ||
1104 | static int scsi_prep_fn(struct request_queue *q, struct request *req) | 1144 | /* |
1145 | * Setup a REQ_TYPE_FS command. These are simple read/write request | ||
1146 | * from filesystems that still need to be translated to SCSI CDBs from | ||
1147 | * the ULD. | ||
1148 | */ | ||
1149 | static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) | ||
1105 | { | 1150 | { |
1106 | struct scsi_device *sdev = q->queuedata; | ||
1107 | struct scsi_cmnd *cmd; | 1151 | struct scsi_cmnd *cmd; |
1108 | int specials_only = 0; | 1152 | struct scsi_driver *drv; |
1153 | int ret; | ||
1109 | 1154 | ||
1110 | /* | 1155 | /* |
1111 | * Just check to see if the device is online. If it isn't, we | 1156 | * Filesystem requests must transfer data. |
1112 | * refuse to process any commands. The device must be brought | ||
1113 | * online before trying any recovery commands | ||
1114 | */ | 1157 | */ |
1115 | if (unlikely(!scsi_device_online(sdev))) { | 1158 | BUG_ON(!req->nr_phys_segments); |
1116 | sdev_printk(KERN_ERR, sdev, | 1159 | |
1117 | "rejecting I/O to offline device\n"); | 1160 | cmd = scsi_get_cmd_from_req(sdev, req); |
1118 | goto kill; | 1161 | if (unlikely(!cmd)) |
1119 | } | 1162 | return BLKPREP_DEFER; |
1120 | if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { | 1163 | |
1121 | /* OK, we're not in a running state don't prep | 1164 | ret = scsi_init_io(cmd); |
1122 | * user commands */ | 1165 | if (unlikely(ret)) |
1123 | if (sdev->sdev_state == SDEV_DEL) { | 1166 | return ret; |
1124 | /* Device is fully deleted, no commands | 1167 | |
1125 | * at all allowed down */ | 1168 | /* |
1126 | sdev_printk(KERN_ERR, sdev, | 1169 | * Initialize the actual SCSI command for this request. |
1127 | "rejecting I/O to dead device\n"); | 1170 | */ |
1128 | goto kill; | 1171 | drv = *(struct scsi_driver **)req->rq_disk->private_data; |
1129 | } | 1172 | if (unlikely(!drv->init_command(cmd))) { |
1130 | /* OK, we only allow special commands (i.e. not | 1173 | scsi_release_buffers(cmd); |
1131 | * user initiated ones */ | 1174 | scsi_put_command(cmd); |
1132 | specials_only = sdev->sdev_state; | 1175 | return BLKPREP_KILL; |
1133 | } | 1176 | } |
1134 | 1177 | ||
1178 | return BLKPREP_OK; | ||
1179 | } | ||
1180 | |||
1181 | static int scsi_prep_fn(struct request_queue *q, struct request *req) | ||
1182 | { | ||
1183 | struct scsi_device *sdev = q->queuedata; | ||
1184 | int ret = BLKPREP_OK; | ||
1185 | |||
1135 | /* | 1186 | /* |
1136 | * Find the actual device driver associated with this command. | 1187 | * If the device is not in running state we will reject some |
1137 | * The SPECIAL requests are things like character device or | 1188 | * or all commands. |
1138 | * ioctls, which did not originate from ll_rw_blk. Note that | ||
1139 | * the special field is also used to indicate the cmd for | ||
1140 | * the remainder of a partially fulfilled request that can | ||
1141 | * come up when there is a medium error. We have to treat | ||
1142 | * these two cases differently. We differentiate by looking | ||
1143 | * at request->cmd, as this tells us the real story. | ||
1144 | */ | 1189 | */ |
1145 | if (blk_special_request(req) && req->special) | 1190 | if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { |
1146 | cmd = req->special; | 1191 | switch (sdev->sdev_state) { |
1147 | else if (blk_pc_request(req) || blk_fs_request(req)) { | 1192 | case SDEV_OFFLINE: |
1148 | if (unlikely(specials_only) && !(req->cmd_flags & REQ_PREEMPT)){ | 1193 | /* |
1149 | if (specials_only == SDEV_QUIESCE || | 1194 | * If the device is offline we refuse to process any |
1150 | specials_only == SDEV_BLOCK) | 1195 | * commands. The device must be brought online |
1151 | goto defer; | 1196 | * before trying any recovery commands. |
1152 | 1197 | */ | |
1153 | sdev_printk(KERN_ERR, sdev, | 1198 | sdev_printk(KERN_ERR, sdev, |
1154 | "rejecting I/O to device being removed\n"); | 1199 | "rejecting I/O to offline device\n"); |
1155 | goto kill; | 1200 | ret = BLKPREP_KILL; |
1201 | break; | ||
1202 | case SDEV_DEL: | ||
1203 | /* | ||
1204 | * If the device is fully deleted, we refuse to | ||
1205 | * process any commands as well. | ||
1206 | */ | ||
1207 | sdev_printk(KERN_ERR, sdev, | ||
1208 | "rejecting I/O to dead device\n"); | ||
1209 | ret = BLKPREP_KILL; | ||
1210 | break; | ||
1211 | case SDEV_QUIESCE: | ||
1212 | case SDEV_BLOCK: | ||
1213 | /* | ||
1214 | * If the devices is blocked we defer normal commands. | ||
1215 | */ | ||
1216 | if (!(req->cmd_flags & REQ_PREEMPT)) | ||
1217 | ret = BLKPREP_DEFER; | ||
1218 | break; | ||
1219 | default: | ||
1220 | /* | ||
1221 | * For any other not fully online state we only allow | ||
1222 | * special commands. In particular any user initiated | ||
1223 | * command is not allowed. | ||
1224 | */ | ||
1225 | if (!(req->cmd_flags & REQ_PREEMPT)) | ||
1226 | ret = BLKPREP_KILL; | ||
1227 | break; | ||
1156 | } | 1228 | } |
1157 | 1229 | ||
1158 | /* | 1230 | if (ret != BLKPREP_OK) |
1159 | * Now try and find a command block that we can use. | 1231 | goto out; |
1160 | */ | ||
1161 | if (!req->special) { | ||
1162 | cmd = scsi_get_command(sdev, GFP_ATOMIC); | ||
1163 | if (unlikely(!cmd)) | ||
1164 | goto defer; | ||
1165 | } else | ||
1166 | cmd = req->special; | ||
1167 | |||
1168 | /* pull a tag out of the request if we have one */ | ||
1169 | cmd->tag = req->tag; | ||
1170 | } else { | ||
1171 | blk_dump_rq_flags(req, "SCSI bad req"); | ||
1172 | goto kill; | ||
1173 | } | 1232 | } |
1174 | |||
1175 | /* note the overloading of req->special. When the tag | ||
1176 | * is active it always means cmd. If the tag goes | ||
1177 | * back for re-queueing, it may be reset */ | ||
1178 | req->special = cmd; | ||
1179 | cmd->request = req; | ||
1180 | |||
1181 | /* | ||
1182 | * FIXME: drop the lock here because the functions below | ||
1183 | * expect to be called without the queue lock held. Also, | ||
1184 | * previously, we dequeued the request before dropping the | ||
1185 | * lock. We hope REQ_STARTED prevents anything untoward from | ||
1186 | * happening now. | ||
1187 | */ | ||
1188 | if (blk_fs_request(req) || blk_pc_request(req)) { | ||
1189 | int ret; | ||
1190 | 1233 | ||
1234 | switch (req->cmd_type) { | ||
1235 | case REQ_TYPE_BLOCK_PC: | ||
1236 | ret = scsi_setup_blk_pc_cmnd(sdev, req); | ||
1237 | break; | ||
1238 | case REQ_TYPE_FS: | ||
1239 | ret = scsi_setup_fs_cmnd(sdev, req); | ||
1240 | break; | ||
1241 | default: | ||
1191 | /* | 1242 | /* |
1192 | * This will do a couple of things: | 1243 | * All other command types are not supported. |
1193 | * 1) Fill in the actual SCSI command. | ||
1194 | * 2) Fill in any other upper-level specific fields | ||
1195 | * (timeout). | ||
1196 | * | 1244 | * |
1197 | * If this returns 0, it means that the request failed | 1245 | * Note that these days the SCSI subsystem does not use |
1198 | * (reading past end of disk, reading offline device, | 1246 | * REQ_TYPE_SPECIAL requests anymore. These are only used |
1199 | * etc). This won't actually talk to the device, but | 1247 | * (directly or via blk_insert_request) by non-SCSI drivers. |
1200 | * some kinds of consistency checking may cause the | ||
1201 | * request to be rejected immediately. | ||
1202 | */ | 1248 | */ |
1249 | blk_dump_rq_flags(req, "SCSI bad req"); | ||
1250 | ret = BLKPREP_KILL; | ||
1251 | break; | ||
1252 | } | ||
1203 | 1253 | ||
1204 | /* | 1254 | out: |
1205 | * This sets up the scatter-gather table (allocating if | 1255 | switch (ret) { |
1206 | * required). | 1256 | case BLKPREP_KILL: |
1207 | */ | 1257 | req->errors = DID_NO_CONNECT << 16; |
1208 | ret = scsi_init_io(cmd); | 1258 | break; |
1209 | switch(ret) { | 1259 | case BLKPREP_DEFER: |
1210 | /* For BLKPREP_KILL/DEFER the cmd was released */ | ||
1211 | case BLKPREP_KILL: | ||
1212 | goto kill; | ||
1213 | case BLKPREP_DEFER: | ||
1214 | goto defer; | ||
1215 | } | ||
1216 | |||
1217 | /* | 1260 | /* |
1218 | * Initialize the actual SCSI command for this request. | 1261 | * If we defer, the elv_next_request() returns NULL, but the |
1262 | * queue must be restarted, so we plug here if no returning | ||
1263 | * command will automatically do that. | ||
1219 | */ | 1264 | */ |
1220 | if (blk_pc_request(req)) { | 1265 | if (sdev->device_busy == 0) |
1221 | scsi_setup_blk_pc_cmnd(cmd); | 1266 | blk_plug_device(q); |
1222 | } else if (req->rq_disk) { | 1267 | break; |
1223 | struct scsi_driver *drv; | 1268 | default: |
1224 | 1269 | req->cmd_flags |= REQ_DONTPREP; | |
1225 | drv = *(struct scsi_driver **)req->rq_disk->private_data; | ||
1226 | if (unlikely(!drv->init_command(cmd))) { | ||
1227 | scsi_release_buffers(cmd); | ||
1228 | scsi_put_command(cmd); | ||
1229 | goto kill; | ||
1230 | } | ||
1231 | } | ||
1232 | } | 1270 | } |
1233 | 1271 | ||
1234 | /* | 1272 | return ret; |
1235 | * The request is now prepped, no need to come back here | ||
1236 | */ | ||
1237 | req->cmd_flags |= REQ_DONTPREP; | ||
1238 | return BLKPREP_OK; | ||
1239 | |||
1240 | defer: | ||
1241 | /* If we defer, the elv_next_request() returns NULL, but the | ||
1242 | * queue must be restarted, so we plug here if no returning | ||
1243 | * command will automatically do that. */ | ||
1244 | if (sdev->device_busy == 0) | ||
1245 | blk_plug_device(q); | ||
1246 | return BLKPREP_DEFER; | ||
1247 | kill: | ||
1248 | req->errors = DID_NO_CONNECT << 16; | ||
1249 | return BLKPREP_KILL; | ||
1250 | } | 1273 | } |
1251 | 1274 | ||
1252 | /* | 1275 | /* |
@@ -1548,29 +1571,40 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) | |||
1548 | } | 1571 | } |
1549 | EXPORT_SYMBOL(scsi_calculate_bounce_limit); | 1572 | EXPORT_SYMBOL(scsi_calculate_bounce_limit); |
1550 | 1573 | ||
1551 | struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) | 1574 | struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, |
1575 | request_fn_proc *request_fn) | ||
1552 | { | 1576 | { |
1553 | struct Scsi_Host *shost = sdev->host; | ||
1554 | struct request_queue *q; | 1577 | struct request_queue *q; |
1555 | 1578 | ||
1556 | q = blk_init_queue(scsi_request_fn, NULL); | 1579 | q = blk_init_queue(request_fn, NULL); |
1557 | if (!q) | 1580 | if (!q) |
1558 | return NULL; | 1581 | return NULL; |
1559 | 1582 | ||
1560 | blk_queue_prep_rq(q, scsi_prep_fn); | ||
1561 | |||
1562 | blk_queue_max_hw_segments(q, shost->sg_tablesize); | 1583 | blk_queue_max_hw_segments(q, shost->sg_tablesize); |
1563 | blk_queue_max_phys_segments(q, SCSI_MAX_PHYS_SEGMENTS); | 1584 | blk_queue_max_phys_segments(q, SCSI_MAX_PHYS_SEGMENTS); |
1564 | blk_queue_max_sectors(q, shost->max_sectors); | 1585 | blk_queue_max_sectors(q, shost->max_sectors); |
1565 | blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); | 1586 | blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); |
1566 | blk_queue_segment_boundary(q, shost->dma_boundary); | 1587 | blk_queue_segment_boundary(q, shost->dma_boundary); |
1567 | blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); | ||
1568 | blk_queue_softirq_done(q, scsi_softirq_done); | ||
1569 | 1588 | ||
1570 | if (!shost->use_clustering) | 1589 | if (!shost->use_clustering) |
1571 | clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); | 1590 | clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); |
1572 | return q; | 1591 | return q; |
1573 | } | 1592 | } |
1593 | EXPORT_SYMBOL(__scsi_alloc_queue); | ||
1594 | |||
1595 | struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) | ||
1596 | { | ||
1597 | struct request_queue *q; | ||
1598 | |||
1599 | q = __scsi_alloc_queue(sdev->host, scsi_request_fn); | ||
1600 | if (!q) | ||
1601 | return NULL; | ||
1602 | |||
1603 | blk_queue_prep_rq(q, scsi_prep_fn); | ||
1604 | blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); | ||
1605 | blk_queue_softirq_done(q, scsi_softirq_done); | ||
1606 | return q; | ||
1607 | } | ||
1574 | 1608 | ||
1575 | void scsi_free_queue(struct request_queue *q) | 1609 | void scsi_free_queue(struct request_queue *q) |
1576 | { | 1610 | { |
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 5d023d44e5e7..f458c2f686d2 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h | |||
@@ -39,6 +39,9 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) | |||
39 | { }; | 39 | { }; |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | /* scsi_scan.c */ | ||
43 | int scsi_complete_async_scans(void); | ||
44 | |||
42 | /* scsi_devinfo.c */ | 45 | /* scsi_devinfo.c */ |
43 | extern int scsi_get_device_flags(struct scsi_device *sdev, | 46 | extern int scsi_get_device_flags(struct scsi_device *sdev, |
44 | const unsigned char *vendor, | 47 | const unsigned char *vendor, |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index d3c5e964c964..14e635aa44ce 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -29,7 +29,9 @@ | |||
29 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/blkdev.h> | 31 | #include <linux/blkdev.h> |
32 | #include <asm/semaphore.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/kthread.h> | ||
34 | #include <linux/spinlock.h> | ||
33 | 35 | ||
34 | #include <scsi/scsi.h> | 36 | #include <scsi/scsi.h> |
35 | #include <scsi/scsi_cmnd.h> | 37 | #include <scsi/scsi_cmnd.h> |
@@ -87,6 +89,17 @@ module_param_named(max_luns, max_scsi_luns, int, S_IRUGO|S_IWUSR); | |||
87 | MODULE_PARM_DESC(max_luns, | 89 | MODULE_PARM_DESC(max_luns, |
88 | "last scsi LUN (should be between 1 and 2^32-1)"); | 90 | "last scsi LUN (should be between 1 and 2^32-1)"); |
89 | 91 | ||
92 | #ifdef CONFIG_SCSI_SCAN_ASYNC | ||
93 | #define SCSI_SCAN_TYPE_DEFAULT "async" | ||
94 | #else | ||
95 | #define SCSI_SCAN_TYPE_DEFAULT "sync" | ||
96 | #endif | ||
97 | |||
98 | static char scsi_scan_type[6] = SCSI_SCAN_TYPE_DEFAULT; | ||
99 | |||
100 | module_param_string(scan, scsi_scan_type, sizeof(scsi_scan_type), S_IRUGO); | ||
101 | MODULE_PARM_DESC(scan, "sync, async or none"); | ||
102 | |||
90 | /* | 103 | /* |
91 | * max_scsi_report_luns: the maximum number of LUNS that will be | 104 | * max_scsi_report_luns: the maximum number of LUNS that will be |
92 | * returned from the REPORT LUNS command. 8 times this value must | 105 | * returned from the REPORT LUNS command. 8 times this value must |
@@ -108,6 +121,68 @@ MODULE_PARM_DESC(inq_timeout, | |||
108 | "Timeout (in seconds) waiting for devices to answer INQUIRY." | 121 | "Timeout (in seconds) waiting for devices to answer INQUIRY." |
109 | " Default is 5. Some non-compliant devices need more."); | 122 | " Default is 5. Some non-compliant devices need more."); |
110 | 123 | ||
124 | static DEFINE_SPINLOCK(async_scan_lock); | ||
125 | static LIST_HEAD(scanning_hosts); | ||
126 | |||
127 | struct async_scan_data { | ||
128 | struct list_head list; | ||
129 | struct Scsi_Host *shost; | ||
130 | struct completion prev_finished; | ||
131 | }; | ||
132 | |||
133 | /** | ||
134 | * scsi_complete_async_scans - Wait for asynchronous scans to complete | ||
135 | * | ||
136 | * Asynchronous scans add themselves to the scanning_hosts list. Once | ||
137 | * that list is empty, we know that the scans are complete. Rather than | ||
138 | * waking up periodically to check the state of the list, we pretend to be | ||
139 | * a scanning task by adding ourselves at the end of the list and going to | ||
140 | * sleep. When the task before us wakes us up, we take ourselves off the | ||
141 | * list and return. | ||
142 | */ | ||
143 | int scsi_complete_async_scans(void) | ||
144 | { | ||
145 | struct async_scan_data *data; | ||
146 | |||
147 | do { | ||
148 | if (list_empty(&scanning_hosts)) | ||
149 | return 0; | ||
150 | /* If we can't get memory immediately, that's OK. Just | ||
151 | * sleep a little. Even if we never get memory, the async | ||
152 | * scans will finish eventually. | ||
153 | */ | ||
154 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
155 | if (!data) | ||
156 | msleep(1); | ||
157 | } while (!data); | ||
158 | |||
159 | data->shost = NULL; | ||
160 | init_completion(&data->prev_finished); | ||
161 | |||
162 | spin_lock(&async_scan_lock); | ||
163 | /* Check that there's still somebody else on the list */ | ||
164 | if (list_empty(&scanning_hosts)) | ||
165 | goto done; | ||
166 | list_add_tail(&data->list, &scanning_hosts); | ||
167 | spin_unlock(&async_scan_lock); | ||
168 | |||
169 | printk(KERN_INFO "scsi: waiting for bus probes to complete ...\n"); | ||
170 | wait_for_completion(&data->prev_finished); | ||
171 | |||
172 | spin_lock(&async_scan_lock); | ||
173 | list_del(&data->list); | ||
174 | done: | ||
175 | spin_unlock(&async_scan_lock); | ||
176 | |||
177 | kfree(data); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | #ifdef MODULE | ||
182 | /* Only exported for the benefit of scsi_wait_scan */ | ||
183 | EXPORT_SYMBOL_GPL(scsi_complete_async_scans); | ||
184 | #endif | ||
185 | |||
111 | /** | 186 | /** |
112 | * scsi_unlock_floptical - unlock device via a special MODE SENSE command | 187 | * scsi_unlock_floptical - unlock device via a special MODE SENSE command |
113 | * @sdev: scsi device to send command to | 188 | * @sdev: scsi device to send command to |
@@ -620,7 +695,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
620 | * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized | 695 | * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized |
621 | **/ | 696 | **/ |
622 | static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | 697 | static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, |
623 | int *bflags) | 698 | int *bflags, int async) |
624 | { | 699 | { |
625 | /* | 700 | /* |
626 | * XXX do not save the inquiry, since it can change underneath us, | 701 | * XXX do not save the inquiry, since it can change underneath us, |
@@ -806,7 +881,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
806 | * register it and tell the rest of the kernel | 881 | * register it and tell the rest of the kernel |
807 | * about it. | 882 | * about it. |
808 | */ | 883 | */ |
809 | if (scsi_sysfs_add_sdev(sdev) != 0) | 884 | if (!async && scsi_sysfs_add_sdev(sdev) != 0) |
810 | return SCSI_SCAN_NO_RESPONSE; | 885 | return SCSI_SCAN_NO_RESPONSE; |
811 | 886 | ||
812 | return SCSI_SCAN_LUN_PRESENT; | 887 | return SCSI_SCAN_LUN_PRESENT; |
@@ -975,7 +1050,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
975 | goto out_free_result; | 1050 | goto out_free_result; |
976 | } | 1051 | } |
977 | 1052 | ||
978 | res = scsi_add_lun(sdev, result, &bflags); | 1053 | res = scsi_add_lun(sdev, result, &bflags, shost->async_scan); |
979 | if (res == SCSI_SCAN_LUN_PRESENT) { | 1054 | if (res == SCSI_SCAN_LUN_PRESENT) { |
980 | if (bflags & BLIST_KEY) { | 1055 | if (bflags & BLIST_KEY) { |
981 | sdev->lockable = 0; | 1056 | sdev->lockable = 0; |
@@ -1475,6 +1550,12 @@ void scsi_scan_target(struct device *parent, unsigned int channel, | |||
1475 | { | 1550 | { |
1476 | struct Scsi_Host *shost = dev_to_shost(parent); | 1551 | struct Scsi_Host *shost = dev_to_shost(parent); |
1477 | 1552 | ||
1553 | if (strncmp(scsi_scan_type, "none", 4) == 0) | ||
1554 | return; | ||
1555 | |||
1556 | if (!shost->async_scan) | ||
1557 | scsi_complete_async_scans(); | ||
1558 | |||
1478 | mutex_lock(&shost->scan_mutex); | 1559 | mutex_lock(&shost->scan_mutex); |
1479 | if (scsi_host_scan_allowed(shost)) | 1560 | if (scsi_host_scan_allowed(shost)) |
1480 | __scsi_scan_target(parent, channel, id, lun, rescan); | 1561 | __scsi_scan_target(parent, channel, id, lun, rescan); |
@@ -1520,6 +1601,9 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | |||
1520 | "%s: <%u:%u:%u>\n", | 1601 | "%s: <%u:%u:%u>\n", |
1521 | __FUNCTION__, channel, id, lun)); | 1602 | __FUNCTION__, channel, id, lun)); |
1522 | 1603 | ||
1604 | if (!shost->async_scan) | ||
1605 | scsi_complete_async_scans(); | ||
1606 | |||
1523 | if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || | 1607 | if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || |
1524 | ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || | 1608 | ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || |
1525 | ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) | 1609 | ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) |
@@ -1540,14 +1624,143 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | |||
1540 | return 0; | 1624 | return 0; |
1541 | } | 1625 | } |
1542 | 1626 | ||
1627 | static void scsi_sysfs_add_devices(struct Scsi_Host *shost) | ||
1628 | { | ||
1629 | struct scsi_device *sdev; | ||
1630 | shost_for_each_device(sdev, shost) { | ||
1631 | if (scsi_sysfs_add_sdev(sdev) != 0) | ||
1632 | scsi_destroy_sdev(sdev); | ||
1633 | } | ||
1634 | } | ||
1635 | |||
1636 | /** | ||
1637 | * scsi_prep_async_scan - prepare for an async scan | ||
1638 | * @shost: the host which will be scanned | ||
1639 | * Returns: a cookie to be passed to scsi_finish_async_scan() | ||
1640 | * | ||
1641 | * Tells the midlayer this host is going to do an asynchronous scan. | ||
1642 | * It reserves the host's position in the scanning list and ensures | ||
1643 | * that other asynchronous scans started after this one won't affect the | ||
1644 | * ordering of the discovered devices. | ||
1645 | */ | ||
1646 | static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) | ||
1647 | { | ||
1648 | struct async_scan_data *data; | ||
1649 | |||
1650 | if (strncmp(scsi_scan_type, "sync", 4) == 0) | ||
1651 | return NULL; | ||
1652 | |||
1653 | if (shost->async_scan) { | ||
1654 | printk("%s called twice for host %d", __FUNCTION__, | ||
1655 | shost->host_no); | ||
1656 | dump_stack(); | ||
1657 | return NULL; | ||
1658 | } | ||
1659 | |||
1660 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
1661 | if (!data) | ||
1662 | goto err; | ||
1663 | data->shost = scsi_host_get(shost); | ||
1664 | if (!data->shost) | ||
1665 | goto err; | ||
1666 | init_completion(&data->prev_finished); | ||
1667 | |||
1668 | spin_lock(&async_scan_lock); | ||
1669 | shost->async_scan = 1; | ||
1670 | if (list_empty(&scanning_hosts)) | ||
1671 | complete(&data->prev_finished); | ||
1672 | list_add_tail(&data->list, &scanning_hosts); | ||
1673 | spin_unlock(&async_scan_lock); | ||
1674 | |||
1675 | return data; | ||
1676 | |||
1677 | err: | ||
1678 | kfree(data); | ||
1679 | return NULL; | ||
1680 | } | ||
1681 | |||
1682 | /** | ||
1683 | * scsi_finish_async_scan - asynchronous scan has finished | ||
1684 | * @data: cookie returned from earlier call to scsi_prep_async_scan() | ||
1685 | * | ||
1686 | * All the devices currently attached to this host have been found. | ||
1687 | * This function announces all the devices it has found to the rest | ||
1688 | * of the system. | ||
1689 | */ | ||
1690 | static void scsi_finish_async_scan(struct async_scan_data *data) | ||
1691 | { | ||
1692 | struct Scsi_Host *shost; | ||
1693 | |||
1694 | if (!data) | ||
1695 | return; | ||
1696 | |||
1697 | shost = data->shost; | ||
1698 | if (!shost->async_scan) { | ||
1699 | printk("%s called twice for host %d", __FUNCTION__, | ||
1700 | shost->host_no); | ||
1701 | dump_stack(); | ||
1702 | return; | ||
1703 | } | ||
1704 | |||
1705 | wait_for_completion(&data->prev_finished); | ||
1706 | |||
1707 | scsi_sysfs_add_devices(shost); | ||
1708 | |||
1709 | spin_lock(&async_scan_lock); | ||
1710 | shost->async_scan = 0; | ||
1711 | list_del(&data->list); | ||
1712 | if (!list_empty(&scanning_hosts)) { | ||
1713 | struct async_scan_data *next = list_entry(scanning_hosts.next, | ||
1714 | struct async_scan_data, list); | ||
1715 | complete(&next->prev_finished); | ||
1716 | } | ||
1717 | spin_unlock(&async_scan_lock); | ||
1718 | |||
1719 | scsi_host_put(shost); | ||
1720 | kfree(data); | ||
1721 | } | ||
1722 | |||
1723 | static void do_scsi_scan_host(struct Scsi_Host *shost) | ||
1724 | { | ||
1725 | if (shost->hostt->scan_finished) { | ||
1726 | unsigned long start = jiffies; | ||
1727 | if (shost->hostt->scan_start) | ||
1728 | shost->hostt->scan_start(shost); | ||
1729 | |||
1730 | while (!shost->hostt->scan_finished(shost, jiffies - start)) | ||
1731 | msleep(10); | ||
1732 | } else { | ||
1733 | scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, | ||
1734 | SCAN_WILD_CARD, 0); | ||
1735 | } | ||
1736 | } | ||
1737 | |||
1738 | static int do_scan_async(void *_data) | ||
1739 | { | ||
1740 | struct async_scan_data *data = _data; | ||
1741 | do_scsi_scan_host(data->shost); | ||
1742 | scsi_finish_async_scan(data); | ||
1743 | return 0; | ||
1744 | } | ||
1745 | |||
1543 | /** | 1746 | /** |
1544 | * scsi_scan_host - scan the given adapter | 1747 | * scsi_scan_host - scan the given adapter |
1545 | * @shost: adapter to scan | 1748 | * @shost: adapter to scan |
1546 | **/ | 1749 | **/ |
1547 | void scsi_scan_host(struct Scsi_Host *shost) | 1750 | void scsi_scan_host(struct Scsi_Host *shost) |
1548 | { | 1751 | { |
1549 | scsi_scan_host_selected(shost, SCAN_WILD_CARD, SCAN_WILD_CARD, | 1752 | struct async_scan_data *data; |
1550 | SCAN_WILD_CARD, 0); | 1753 | |
1754 | if (strncmp(scsi_scan_type, "none", 4) == 0) | ||
1755 | return; | ||
1756 | |||
1757 | data = scsi_prep_async_scan(shost); | ||
1758 | if (!data) { | ||
1759 | do_scsi_scan_host(shost); | ||
1760 | return; | ||
1761 | } | ||
1762 | |||
1763 | kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); | ||
1551 | } | 1764 | } |
1552 | EXPORT_SYMBOL(scsi_scan_host); | 1765 | EXPORT_SYMBOL(scsi_scan_host); |
1553 | 1766 | ||
diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c new file mode 100644 index 000000000000..37bbfbdb870f --- /dev/null +++ b/drivers/scsi/scsi_tgt_if.c | |||
@@ -0,0 +1,352 @@ | |||
1 | /* | ||
2 | * SCSI target kernel/user interface functions | ||
3 | * | ||
4 | * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org> | ||
5 | * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of the | ||
10 | * License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | */ | ||
22 | #include <linux/miscdevice.h> | ||
23 | #include <linux/file.h> | ||
24 | #include <net/tcp.h> | ||
25 | #include <scsi/scsi.h> | ||
26 | #include <scsi/scsi_cmnd.h> | ||
27 | #include <scsi/scsi_device.h> | ||
28 | #include <scsi/scsi_host.h> | ||
29 | #include <scsi/scsi_tgt.h> | ||
30 | #include <scsi/scsi_tgt_if.h> | ||
31 | |||
32 | #include <asm/cacheflush.h> | ||
33 | |||
34 | #include "scsi_tgt_priv.h" | ||
35 | |||
36 | struct tgt_ring { | ||
37 | u32 tr_idx; | ||
38 | unsigned long tr_pages[TGT_RING_PAGES]; | ||
39 | spinlock_t tr_lock; | ||
40 | }; | ||
41 | |||
42 | /* tx_ring : kernel->user, rx_ring : user->kernel */ | ||
43 | static struct tgt_ring tx_ring, rx_ring; | ||
44 | static DECLARE_WAIT_QUEUE_HEAD(tgt_poll_wait); | ||
45 | |||
46 | static inline void tgt_ring_idx_inc(struct tgt_ring *ring) | ||
47 | { | ||
48 | if (ring->tr_idx == TGT_MAX_EVENTS - 1) | ||
49 | ring->tr_idx = 0; | ||
50 | else | ||
51 | ring->tr_idx++; | ||
52 | } | ||
53 | |||
54 | static struct tgt_event *tgt_head_event(struct tgt_ring *ring, u32 idx) | ||
55 | { | ||
56 | u32 pidx, off; | ||
57 | |||
58 | pidx = idx / TGT_EVENT_PER_PAGE; | ||
59 | off = idx % TGT_EVENT_PER_PAGE; | ||
60 | |||
61 | return (struct tgt_event *) | ||
62 | (ring->tr_pages[pidx] + sizeof(struct tgt_event) * off); | ||
63 | } | ||
64 | |||
65 | static int tgt_uspace_send_event(u32 type, struct tgt_event *p) | ||
66 | { | ||
67 | struct tgt_event *ev; | ||
68 | struct tgt_ring *ring = &tx_ring; | ||
69 | unsigned long flags; | ||
70 | int err = 0; | ||
71 | |||
72 | spin_lock_irqsave(&ring->tr_lock, flags); | ||
73 | |||
74 | ev = tgt_head_event(ring, ring->tr_idx); | ||
75 | if (!ev->hdr.status) | ||
76 | tgt_ring_idx_inc(ring); | ||
77 | else | ||
78 | err = -BUSY; | ||
79 | |||
80 | spin_unlock_irqrestore(&ring->tr_lock, flags); | ||
81 | |||
82 | if (err) | ||
83 | return err; | ||
84 | |||
85 | memcpy(ev, p, sizeof(*ev)); | ||
86 | ev->hdr.type = type; | ||
87 | mb(); | ||
88 | ev->hdr.status = 1; | ||
89 | |||
90 | flush_dcache_page(virt_to_page(ev)); | ||
91 | |||
92 | wake_up_interruptible(&tgt_poll_wait); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag) | ||
98 | { | ||
99 | struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); | ||
100 | struct tgt_event ev; | ||
101 | int err; | ||
102 | |||
103 | memset(&ev, 0, sizeof(ev)); | ||
104 | ev.p.cmd_req.host_no = shost->host_no; | ||
105 | ev.p.cmd_req.data_len = cmd->request_bufflen; | ||
106 | memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb)); | ||
107 | memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun)); | ||
108 | ev.p.cmd_req.attribute = cmd->tag; | ||
109 | ev.p.cmd_req.tag = tag; | ||
110 | |||
111 | dprintk("%p %d %u %x %llx\n", cmd, shost->host_no, | ||
112 | ev.p.cmd_req.data_len, cmd->tag, | ||
113 | (unsigned long long) ev.p.cmd_req.tag); | ||
114 | |||
115 | err = tgt_uspace_send_event(TGT_KEVENT_CMD_REQ, &ev); | ||
116 | if (err) | ||
117 | eprintk("tx buf is full, could not send\n"); | ||
118 | |||
119 | return err; | ||
120 | } | ||
121 | |||
122 | int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) | ||
123 | { | ||
124 | struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); | ||
125 | struct tgt_event ev; | ||
126 | int err; | ||
127 | |||
128 | memset(&ev, 0, sizeof(ev)); | ||
129 | ev.p.cmd_done.host_no = shost->host_no; | ||
130 | ev.p.cmd_done.tag = tag; | ||
131 | ev.p.cmd_done.result = cmd->result; | ||
132 | |||
133 | dprintk("%p %d %llu %u %x\n", cmd, shost->host_no, | ||
134 | (unsigned long long) ev.p.cmd_req.tag, | ||
135 | ev.p.cmd_req.data_len, cmd->tag); | ||
136 | |||
137 | err = tgt_uspace_send_event(TGT_KEVENT_CMD_DONE, &ev); | ||
138 | if (err) | ||
139 | eprintk("tx buf is full, could not send\n"); | ||
140 | |||
141 | return err; | ||
142 | } | ||
143 | |||
144 | int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, | ||
145 | struct scsi_lun *scsilun, void *data) | ||
146 | { | ||
147 | struct tgt_event ev; | ||
148 | int err; | ||
149 | |||
150 | memset(&ev, 0, sizeof(ev)); | ||
151 | ev.p.tsk_mgmt_req.host_no = host_no; | ||
152 | ev.p.tsk_mgmt_req.function = function; | ||
153 | ev.p.tsk_mgmt_req.tag = tag; | ||
154 | memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun)); | ||
155 | ev.p.tsk_mgmt_req.mid = (u64) (unsigned long) data; | ||
156 | |||
157 | dprintk("%d %x %llx %llx\n", host_no, function, (unsigned long long) tag, | ||
158 | (unsigned long long) ev.p.tsk_mgmt_req.mid); | ||
159 | |||
160 | err = tgt_uspace_send_event(TGT_KEVENT_TSK_MGMT_REQ, &ev); | ||
161 | if (err) | ||
162 | eprintk("tx buf is full, could not send\n"); | ||
163 | |||
164 | return err; | ||
165 | } | ||
166 | |||
167 | static int event_recv_msg(struct tgt_event *ev) | ||
168 | { | ||
169 | int err = 0; | ||
170 | |||
171 | switch (ev->hdr.type) { | ||
172 | case TGT_UEVENT_CMD_RSP: | ||
173 | err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no, | ||
174 | ev->p.cmd_rsp.tag, | ||
175 | ev->p.cmd_rsp.result, | ||
176 | ev->p.cmd_rsp.len, | ||
177 | ev->p.cmd_rsp.uaddr, | ||
178 | ev->p.cmd_rsp.rw); | ||
179 | break; | ||
180 | case TGT_UEVENT_TSK_MGMT_RSP: | ||
181 | err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no, | ||
182 | ev->p.tsk_mgmt_rsp.mid, | ||
183 | ev->p.tsk_mgmt_rsp.result); | ||
184 | break; | ||
185 | default: | ||
186 | eprintk("unknown type %d\n", ev->hdr.type); | ||
187 | err = -EINVAL; | ||
188 | } | ||
189 | |||
190 | return err; | ||
191 | } | ||
192 | |||
193 | static ssize_t tgt_write(struct file *file, const char __user * buffer, | ||
194 | size_t count, loff_t * ppos) | ||
195 | { | ||
196 | struct tgt_event *ev; | ||
197 | struct tgt_ring *ring = &rx_ring; | ||
198 | |||
199 | while (1) { | ||
200 | ev = tgt_head_event(ring, ring->tr_idx); | ||
201 | /* do we need this? */ | ||
202 | flush_dcache_page(virt_to_page(ev)); | ||
203 | |||
204 | if (!ev->hdr.status) | ||
205 | break; | ||
206 | |||
207 | tgt_ring_idx_inc(ring); | ||
208 | event_recv_msg(ev); | ||
209 | ev->hdr.status = 0; | ||
210 | }; | ||
211 | |||
212 | return count; | ||
213 | } | ||
214 | |||
215 | static unsigned int tgt_poll(struct file * file, struct poll_table_struct *wait) | ||
216 | { | ||
217 | struct tgt_event *ev; | ||
218 | struct tgt_ring *ring = &tx_ring; | ||
219 | unsigned long flags; | ||
220 | unsigned int mask = 0; | ||
221 | u32 idx; | ||
222 | |||
223 | poll_wait(file, &tgt_poll_wait, wait); | ||
224 | |||
225 | spin_lock_irqsave(&ring->tr_lock, flags); | ||
226 | |||
227 | idx = ring->tr_idx ? ring->tr_idx - 1 : TGT_MAX_EVENTS - 1; | ||
228 | ev = tgt_head_event(ring, idx); | ||
229 | if (ev->hdr.status) | ||
230 | mask |= POLLIN | POLLRDNORM; | ||
231 | |||
232 | spin_unlock_irqrestore(&ring->tr_lock, flags); | ||
233 | |||
234 | return mask; | ||
235 | } | ||
236 | |||
237 | static int uspace_ring_map(struct vm_area_struct *vma, unsigned long addr, | ||
238 | struct tgt_ring *ring) | ||
239 | { | ||
240 | int i, err; | ||
241 | |||
242 | for (i = 0; i < TGT_RING_PAGES; i++) { | ||
243 | struct page *page = virt_to_page(ring->tr_pages[i]); | ||
244 | err = vm_insert_page(vma, addr, page); | ||
245 | if (err) | ||
246 | return err; | ||
247 | addr += PAGE_SIZE; | ||
248 | } | ||
249 | |||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static int tgt_mmap(struct file *filp, struct vm_area_struct *vma) | ||
254 | { | ||
255 | unsigned long addr; | ||
256 | int err; | ||
257 | |||
258 | if (vma->vm_pgoff) | ||
259 | return -EINVAL; | ||
260 | |||
261 | if (vma->vm_end - vma->vm_start != TGT_RING_SIZE * 2) { | ||
262 | eprintk("mmap size must be %lu, not %lu \n", | ||
263 | TGT_RING_SIZE * 2, vma->vm_end - vma->vm_start); | ||
264 | return -EINVAL; | ||
265 | } | ||
266 | |||
267 | addr = vma->vm_start; | ||
268 | err = uspace_ring_map(vma, addr, &tx_ring); | ||
269 | if (err) | ||
270 | return err; | ||
271 | err = uspace_ring_map(vma, addr + TGT_RING_SIZE, &rx_ring); | ||
272 | |||
273 | return err; | ||
274 | } | ||
275 | |||
276 | static int tgt_open(struct inode *inode, struct file *file) | ||
277 | { | ||
278 | tx_ring.tr_idx = rx_ring.tr_idx = 0; | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static struct file_operations tgt_fops = { | ||
284 | .owner = THIS_MODULE, | ||
285 | .open = tgt_open, | ||
286 | .poll = tgt_poll, | ||
287 | .write = tgt_write, | ||
288 | .mmap = tgt_mmap, | ||
289 | }; | ||
290 | |||
291 | static struct miscdevice tgt_miscdev = { | ||
292 | .minor = MISC_DYNAMIC_MINOR, | ||
293 | .name = "tgt", | ||
294 | .fops = &tgt_fops, | ||
295 | }; | ||
296 | |||
297 | static void tgt_ring_exit(struct tgt_ring *ring) | ||
298 | { | ||
299 | int i; | ||
300 | |||
301 | for (i = 0; i < TGT_RING_PAGES; i++) | ||
302 | free_page(ring->tr_pages[i]); | ||
303 | } | ||
304 | |||
305 | static int tgt_ring_init(struct tgt_ring *ring) | ||
306 | { | ||
307 | int i; | ||
308 | |||
309 | spin_lock_init(&ring->tr_lock); | ||
310 | |||
311 | for (i = 0; i < TGT_RING_PAGES; i++) { | ||
312 | ring->tr_pages[i] = get_zeroed_page(GFP_KERNEL); | ||
313 | if (!ring->tr_pages[i]) { | ||
314 | eprintk("out of memory\n"); | ||
315 | return -ENOMEM; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | void scsi_tgt_if_exit(void) | ||
323 | { | ||
324 | tgt_ring_exit(&tx_ring); | ||
325 | tgt_ring_exit(&rx_ring); | ||
326 | misc_deregister(&tgt_miscdev); | ||
327 | } | ||
328 | |||
329 | int scsi_tgt_if_init(void) | ||
330 | { | ||
331 | int err; | ||
332 | |||
333 | err = tgt_ring_init(&tx_ring); | ||
334 | if (err) | ||
335 | return err; | ||
336 | |||
337 | err = tgt_ring_init(&rx_ring); | ||
338 | if (err) | ||
339 | goto free_tx_ring; | ||
340 | |||
341 | err = misc_register(&tgt_miscdev); | ||
342 | if (err) | ||
343 | goto free_rx_ring; | ||
344 | |||
345 | return 0; | ||
346 | free_rx_ring: | ||
347 | tgt_ring_exit(&rx_ring); | ||
348 | free_tx_ring: | ||
349 | tgt_ring_exit(&tx_ring); | ||
350 | |||
351 | return err; | ||
352 | } | ||
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c new file mode 100644 index 000000000000..39da5cd6fb6f --- /dev/null +++ b/drivers/scsi/scsi_tgt_lib.c | |||
@@ -0,0 +1,742 @@ | |||
1 | /* | ||
2 | * SCSI target lib functions | ||
3 | * | ||
4 | * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu> | ||
5 | * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of the | ||
10 | * License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | */ | ||
22 | #include <linux/blkdev.h> | ||
23 | #include <linux/hash.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/pagemap.h> | ||
26 | #include <scsi/scsi.h> | ||
27 | #include <scsi/scsi_cmnd.h> | ||
28 | #include <scsi/scsi_device.h> | ||
29 | #include <scsi/scsi_host.h> | ||
30 | #include <scsi/scsi_tgt.h> | ||
31 | #include <../drivers/md/dm-bio-list.h> | ||
32 | |||
33 | #include "scsi_tgt_priv.h" | ||
34 | |||
35 | static struct workqueue_struct *scsi_tgtd; | ||
36 | static kmem_cache_t *scsi_tgt_cmd_cache; | ||
37 | |||
38 | /* | ||
39 | * TODO: this struct will be killed when the block layer supports large bios | ||
40 | * and James's work struct code is in | ||
41 | */ | ||
42 | struct scsi_tgt_cmd { | ||
43 | /* TODO replace work with James b's code */ | ||
44 | struct work_struct work; | ||
45 | /* TODO replace the lists with a large bio */ | ||
46 | struct bio_list xfer_done_list; | ||
47 | struct bio_list xfer_list; | ||
48 | |||
49 | struct list_head hash_list; | ||
50 | struct request *rq; | ||
51 | u64 tag; | ||
52 | |||
53 | void *buffer; | ||
54 | unsigned bufflen; | ||
55 | }; | ||
56 | |||
57 | #define TGT_HASH_ORDER 4 | ||
58 | #define cmd_hashfn(tag) hash_long((unsigned long) (tag), TGT_HASH_ORDER) | ||
59 | |||
60 | struct scsi_tgt_queuedata { | ||
61 | struct Scsi_Host *shost; | ||
62 | struct list_head cmd_hash[1 << TGT_HASH_ORDER]; | ||
63 | spinlock_t cmd_hash_lock; | ||
64 | }; | ||
65 | |||
66 | /* | ||
67 | * Function: scsi_host_get_command() | ||
68 | * | ||
69 | * Purpose: Allocate and setup a scsi command block and blk request | ||
70 | * | ||
71 | * Arguments: shost - scsi host | ||
72 | * data_dir - dma data dir | ||
73 | * gfp_mask- allocator flags | ||
74 | * | ||
75 | * Returns: The allocated scsi command structure. | ||
76 | * | ||
77 | * This should be called by target LLDs to get a command. | ||
78 | */ | ||
79 | struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, | ||
80 | enum dma_data_direction data_dir, | ||
81 | gfp_t gfp_mask) | ||
82 | { | ||
83 | int write = (data_dir == DMA_TO_DEVICE); | ||
84 | struct request *rq; | ||
85 | struct scsi_cmnd *cmd; | ||
86 | struct scsi_tgt_cmd *tcmd; | ||
87 | |||
88 | /* Bail if we can't get a reference to the device */ | ||
89 | if (!get_device(&shost->shost_gendev)) | ||
90 | return NULL; | ||
91 | |||
92 | tcmd = kmem_cache_alloc(scsi_tgt_cmd_cache, GFP_ATOMIC); | ||
93 | if (!tcmd) | ||
94 | goto put_dev; | ||
95 | |||
96 | rq = blk_get_request(shost->uspace_req_q, write, gfp_mask); | ||
97 | if (!rq) | ||
98 | goto free_tcmd; | ||
99 | |||
100 | cmd = __scsi_get_command(shost, gfp_mask); | ||
101 | if (!cmd) | ||
102 | goto release_rq; | ||
103 | |||
104 | memset(cmd, 0, sizeof(*cmd)); | ||
105 | cmd->sc_data_direction = data_dir; | ||
106 | cmd->jiffies_at_alloc = jiffies; | ||
107 | cmd->request = rq; | ||
108 | |||
109 | rq->special = cmd; | ||
110 | rq->cmd_type = REQ_TYPE_SPECIAL; | ||
111 | rq->cmd_flags |= REQ_TYPE_BLOCK_PC; | ||
112 | rq->end_io_data = tcmd; | ||
113 | |||
114 | bio_list_init(&tcmd->xfer_list); | ||
115 | bio_list_init(&tcmd->xfer_done_list); | ||
116 | tcmd->rq = rq; | ||
117 | |||
118 | return cmd; | ||
119 | |||
120 | release_rq: | ||
121 | blk_put_request(rq); | ||
122 | free_tcmd: | ||
123 | kmem_cache_free(scsi_tgt_cmd_cache, tcmd); | ||
124 | put_dev: | ||
125 | put_device(&shost->shost_gendev); | ||
126 | return NULL; | ||
127 | |||
128 | } | ||
129 | EXPORT_SYMBOL_GPL(scsi_host_get_command); | ||
130 | |||
131 | /* | ||
132 | * Function: scsi_host_put_command() | ||
133 | * | ||
134 | * Purpose: Free a scsi command block | ||
135 | * | ||
136 | * Arguments: shost - scsi host | ||
137 | * cmd - command block to free | ||
138 | * | ||
139 | * Returns: Nothing. | ||
140 | * | ||
141 | * Notes: The command must not belong to any lists. | ||
142 | */ | ||
143 | void scsi_host_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) | ||
144 | { | ||
145 | struct request_queue *q = shost->uspace_req_q; | ||
146 | struct request *rq = cmd->request; | ||
147 | struct scsi_tgt_cmd *tcmd = rq->end_io_data; | ||
148 | unsigned long flags; | ||
149 | |||
150 | kmem_cache_free(scsi_tgt_cmd_cache, tcmd); | ||
151 | |||
152 | spin_lock_irqsave(q->queue_lock, flags); | ||
153 | __blk_put_request(q, rq); | ||
154 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
155 | |||
156 | __scsi_put_command(shost, cmd, &shost->shost_gendev); | ||
157 | } | ||
158 | EXPORT_SYMBOL_GPL(scsi_host_put_command); | ||
159 | |||
160 | static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd) | ||
161 | { | ||
162 | struct bio *bio; | ||
163 | |||
164 | /* must call bio_endio in case bio was bounced */ | ||
165 | while ((bio = bio_list_pop(&tcmd->xfer_done_list))) { | ||
166 | bio_endio(bio, bio->bi_size, 0); | ||
167 | bio_unmap_user(bio); | ||
168 | } | ||
169 | |||
170 | while ((bio = bio_list_pop(&tcmd->xfer_list))) { | ||
171 | bio_endio(bio, bio->bi_size, 0); | ||
172 | bio_unmap_user(bio); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | static void cmd_hashlist_del(struct scsi_cmnd *cmd) | ||
177 | { | ||
178 | struct request_queue *q = cmd->request->q; | ||
179 | struct scsi_tgt_queuedata *qdata = q->queuedata; | ||
180 | unsigned long flags; | ||
181 | struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; | ||
182 | |||
183 | spin_lock_irqsave(&qdata->cmd_hash_lock, flags); | ||
184 | list_del(&tcmd->hash_list); | ||
185 | spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); | ||
186 | } | ||
187 | |||
188 | static void scsi_tgt_cmd_destroy(void *data) | ||
189 | { | ||
190 | struct scsi_cmnd *cmd = data; | ||
191 | struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; | ||
192 | |||
193 | dprintk("cmd %p %d %lu\n", cmd, cmd->sc_data_direction, | ||
194 | rq_data_dir(cmd->request)); | ||
195 | /* | ||
196 | * We fix rq->cmd_flags here since when we told bio_map_user | ||
197 | * to write vm for WRITE commands, blk_rq_bio_prep set | ||
198 | * rq_data_dir the flags to READ. | ||
199 | */ | ||
200 | if (cmd->sc_data_direction == DMA_TO_DEVICE) | ||
201 | cmd->request->cmd_flags |= REQ_RW; | ||
202 | else | ||
203 | cmd->request->cmd_flags &= ~REQ_RW; | ||
204 | |||
205 | scsi_unmap_user_pages(tcmd); | ||
206 | scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); | ||
207 | } | ||
208 | |||
209 | static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, | ||
210 | u64 tag) | ||
211 | { | ||
212 | struct scsi_tgt_queuedata *qdata = rq->q->queuedata; | ||
213 | unsigned long flags; | ||
214 | struct list_head *head; | ||
215 | |||
216 | tcmd->tag = tag; | ||
217 | spin_lock_irqsave(&qdata->cmd_hash_lock, flags); | ||
218 | head = &qdata->cmd_hash[cmd_hashfn(tag)]; | ||
219 | list_add(&tcmd->hash_list, head); | ||
220 | spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * scsi_tgt_alloc_queue - setup queue used for message passing | ||
225 | * shost: scsi host | ||
226 | * | ||
227 | * This should be called by the LLD after host allocation. | ||
228 | * And will be released when the host is released. | ||
229 | */ | ||
230 | int scsi_tgt_alloc_queue(struct Scsi_Host *shost) | ||
231 | { | ||
232 | struct scsi_tgt_queuedata *queuedata; | ||
233 | struct request_queue *q; | ||
234 | int err, i; | ||
235 | |||
236 | /* | ||
237 | * Do we need to send a netlink event or should uspace | ||
238 | * just respond to the hotplug event? | ||
239 | */ | ||
240 | q = __scsi_alloc_queue(shost, NULL); | ||
241 | if (!q) | ||
242 | return -ENOMEM; | ||
243 | |||
244 | queuedata = kzalloc(sizeof(*queuedata), GFP_KERNEL); | ||
245 | if (!queuedata) { | ||
246 | err = -ENOMEM; | ||
247 | goto cleanup_queue; | ||
248 | } | ||
249 | queuedata->shost = shost; | ||
250 | q->queuedata = queuedata; | ||
251 | |||
252 | /* | ||
253 | * this is a silly hack. We should probably just queue as many | ||
254 | * command as is recvd to userspace. uspace can then make | ||
255 | * sure we do not overload the HBA | ||
256 | */ | ||
257 | q->nr_requests = shost->hostt->can_queue; | ||
258 | /* | ||
259 | * We currently only support software LLDs so this does | ||
260 | * not matter for now. Do we need this for the cards we support? | ||
261 | * If so we should make it a host template value. | ||
262 | */ | ||
263 | blk_queue_dma_alignment(q, 0); | ||
264 | shost->uspace_req_q = q; | ||
265 | |||
266 | for (i = 0; i < ARRAY_SIZE(queuedata->cmd_hash); i++) | ||
267 | INIT_LIST_HEAD(&queuedata->cmd_hash[i]); | ||
268 | spin_lock_init(&queuedata->cmd_hash_lock); | ||
269 | |||
270 | return 0; | ||
271 | |||
272 | cleanup_queue: | ||
273 | blk_cleanup_queue(q); | ||
274 | return err; | ||
275 | } | ||
276 | EXPORT_SYMBOL_GPL(scsi_tgt_alloc_queue); | ||
277 | |||
278 | void scsi_tgt_free_queue(struct Scsi_Host *shost) | ||
279 | { | ||
280 | int i; | ||
281 | unsigned long flags; | ||
282 | struct request_queue *q = shost->uspace_req_q; | ||
283 | struct scsi_cmnd *cmd; | ||
284 | struct scsi_tgt_queuedata *qdata = q->queuedata; | ||
285 | struct scsi_tgt_cmd *tcmd, *n; | ||
286 | LIST_HEAD(cmds); | ||
287 | |||
288 | spin_lock_irqsave(&qdata->cmd_hash_lock, flags); | ||
289 | |||
290 | for (i = 0; i < ARRAY_SIZE(qdata->cmd_hash); i++) { | ||
291 | list_for_each_entry_safe(tcmd, n, &qdata->cmd_hash[i], | ||
292 | hash_list) { | ||
293 | list_del(&tcmd->hash_list); | ||
294 | list_add(&tcmd->hash_list, &cmds); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); | ||
299 | |||
300 | while (!list_empty(&cmds)) { | ||
301 | tcmd = list_entry(cmds.next, struct scsi_tgt_cmd, hash_list); | ||
302 | list_del(&tcmd->hash_list); | ||
303 | cmd = tcmd->rq->special; | ||
304 | |||
305 | shost->hostt->eh_abort_handler(cmd); | ||
306 | scsi_tgt_cmd_destroy(cmd); | ||
307 | } | ||
308 | } | ||
309 | EXPORT_SYMBOL_GPL(scsi_tgt_free_queue); | ||
310 | |||
311 | struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *cmd) | ||
312 | { | ||
313 | struct scsi_tgt_queuedata *queue = cmd->request->q->queuedata; | ||
314 | return queue->shost; | ||
315 | } | ||
316 | EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host); | ||
317 | |||
318 | /* | ||
319 | * scsi_tgt_queue_command - queue command for userspace processing | ||
320 | * @cmd: scsi command | ||
321 | * @scsilun: scsi lun | ||
322 | * @tag: unique value to identify this command for tmf | ||
323 | */ | ||
324 | int scsi_tgt_queue_command(struct scsi_cmnd *cmd, struct scsi_lun *scsilun, | ||
325 | u64 tag) | ||
326 | { | ||
327 | struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; | ||
328 | int err; | ||
329 | |||
330 | init_scsi_tgt_cmd(cmd->request, tcmd, tag); | ||
331 | err = scsi_tgt_uspace_send_cmd(cmd, scsilun, tag); | ||
332 | if (err) | ||
333 | cmd_hashlist_del(cmd); | ||
334 | |||
335 | return err; | ||
336 | } | ||
337 | EXPORT_SYMBOL_GPL(scsi_tgt_queue_command); | ||
338 | |||
339 | /* | ||
340 | * This is run from a interrpt handler normally and the unmap | ||
341 | * needs process context so we must queue | ||
342 | */ | ||
343 | static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd) | ||
344 | { | ||
345 | struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; | ||
346 | |||
347 | dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); | ||
348 | |||
349 | scsi_tgt_uspace_send_status(cmd, tcmd->tag); | ||
350 | INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy, cmd); | ||
351 | queue_work(scsi_tgtd, &tcmd->work); | ||
352 | } | ||
353 | |||
354 | static int __scsi_tgt_transfer_response(struct scsi_cmnd *cmd) | ||
355 | { | ||
356 | struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); | ||
357 | int err; | ||
358 | |||
359 | dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); | ||
360 | |||
361 | err = shost->hostt->transfer_response(cmd, scsi_tgt_cmd_done); | ||
362 | switch (err) { | ||
363 | case SCSI_MLQUEUE_HOST_BUSY: | ||
364 | case SCSI_MLQUEUE_DEVICE_BUSY: | ||
365 | return -EAGAIN; | ||
366 | } | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static void scsi_tgt_transfer_response(struct scsi_cmnd *cmd) | ||
372 | { | ||
373 | struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; | ||
374 | int err; | ||
375 | |||
376 | err = __scsi_tgt_transfer_response(cmd); | ||
377 | if (!err) | ||
378 | return; | ||
379 | |||
380 | cmd->result = DID_BUS_BUSY << 16; | ||
381 | err = scsi_tgt_uspace_send_status(cmd, tcmd->tag); | ||
382 | if (err <= 0) | ||
383 | /* the eh will have to pick this up */ | ||
384 | printk(KERN_ERR "Could not send cmd %p status\n", cmd); | ||
385 | } | ||
386 | |||
387 | static int scsi_tgt_init_cmd(struct scsi_cmnd *cmd, gfp_t gfp_mask) | ||
388 | { | ||
389 | struct request *rq = cmd->request; | ||
390 | struct scsi_tgt_cmd *tcmd = rq->end_io_data; | ||
391 | int count; | ||
392 | |||
393 | cmd->use_sg = rq->nr_phys_segments; | ||
394 | cmd->request_buffer = scsi_alloc_sgtable(cmd, gfp_mask); | ||
395 | if (!cmd->request_buffer) | ||
396 | return -ENOMEM; | ||
397 | |||
398 | cmd->request_bufflen = rq->data_len; | ||
399 | |||
400 | dprintk("cmd %p addr %p cnt %d %lu\n", cmd, tcmd->buffer, cmd->use_sg, | ||
401 | rq_data_dir(rq)); | ||
402 | count = blk_rq_map_sg(rq->q, rq, cmd->request_buffer); | ||
403 | if (likely(count <= cmd->use_sg)) { | ||
404 | cmd->use_sg = count; | ||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | eprintk("cmd %p addr %p cnt %d\n", cmd, tcmd->buffer, cmd->use_sg); | ||
409 | scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); | ||
410 | return -EINVAL; | ||
411 | } | ||
412 | |||
413 | /* TODO: test this crap and replace bio_map_user with new interface maybe */ | ||
414 | static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, | ||
415 | int rw) | ||
416 | { | ||
417 | struct request_queue *q = cmd->request->q; | ||
418 | struct request *rq = cmd->request; | ||
419 | void *uaddr = tcmd->buffer; | ||
420 | unsigned int len = tcmd->bufflen; | ||
421 | struct bio *bio; | ||
422 | int err; | ||
423 | |||
424 | while (len > 0) { | ||
425 | dprintk("%lx %u\n", (unsigned long) uaddr, len); | ||
426 | bio = bio_map_user(q, NULL, (unsigned long) uaddr, len, rw); | ||
427 | if (IS_ERR(bio)) { | ||
428 | err = PTR_ERR(bio); | ||
429 | dprintk("fail to map %lx %u %d %x\n", | ||
430 | (unsigned long) uaddr, len, err, cmd->cmnd[0]); | ||
431 | goto unmap_bios; | ||
432 | } | ||
433 | |||
434 | uaddr += bio->bi_size; | ||
435 | len -= bio->bi_size; | ||
436 | |||
437 | /* | ||
438 | * The first bio is added and merged. We could probably | ||
439 | * try to add others using scsi_merge_bio() but for now | ||
440 | * we keep it simple. The first bio should be pretty large | ||
441 | * (either hitting the 1 MB bio pages limit or a queue limit) | ||
442 | * already but for really large IO we may want to try and | ||
443 | * merge these. | ||
444 | */ | ||
445 | if (!rq->bio) { | ||
446 | blk_rq_bio_prep(q, rq, bio); | ||
447 | rq->data_len = bio->bi_size; | ||
448 | } else | ||
449 | /* put list of bios to transfer in next go around */ | ||
450 | bio_list_add(&tcmd->xfer_list, bio); | ||
451 | } | ||
452 | |||
453 | cmd->offset = 0; | ||
454 | err = scsi_tgt_init_cmd(cmd, GFP_KERNEL); | ||
455 | if (err) | ||
456 | goto unmap_bios; | ||
457 | |||
458 | return 0; | ||
459 | |||
460 | unmap_bios: | ||
461 | if (rq->bio) { | ||
462 | bio_unmap_user(rq->bio); | ||
463 | while ((bio = bio_list_pop(&tcmd->xfer_list))) | ||
464 | bio_unmap_user(bio); | ||
465 | } | ||
466 | |||
467 | return err; | ||
468 | } | ||
469 | |||
470 | static int scsi_tgt_transfer_data(struct scsi_cmnd *); | ||
471 | |||
472 | static void scsi_tgt_data_transfer_done(struct scsi_cmnd *cmd) | ||
473 | { | ||
474 | struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; | ||
475 | struct bio *bio; | ||
476 | int err; | ||
477 | |||
478 | /* should we free resources here on error ? */ | ||
479 | if (cmd->result) { | ||
480 | send_uspace_err: | ||
481 | err = scsi_tgt_uspace_send_status(cmd, tcmd->tag); | ||
482 | if (err <= 0) | ||
483 | /* the tgt uspace eh will have to pick this up */ | ||
484 | printk(KERN_ERR "Could not send cmd %p status\n", cmd); | ||
485 | return; | ||
486 | } | ||
487 | |||
488 | dprintk("cmd %p request_bufflen %u bufflen %u\n", | ||
489 | cmd, cmd->request_bufflen, tcmd->bufflen); | ||
490 | |||
491 | scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); | ||
492 | bio_list_add(&tcmd->xfer_done_list, cmd->request->bio); | ||
493 | |||
494 | tcmd->buffer += cmd->request_bufflen; | ||
495 | cmd->offset += cmd->request_bufflen; | ||
496 | |||
497 | if (!tcmd->xfer_list.head) { | ||
498 | scsi_tgt_transfer_response(cmd); | ||
499 | return; | ||
500 | } | ||
501 | |||
502 | dprintk("cmd2 %p request_bufflen %u bufflen %u\n", | ||
503 | cmd, cmd->request_bufflen, tcmd->bufflen); | ||
504 | |||
505 | bio = bio_list_pop(&tcmd->xfer_list); | ||
506 | BUG_ON(!bio); | ||
507 | |||
508 | blk_rq_bio_prep(cmd->request->q, cmd->request, bio); | ||
509 | cmd->request->data_len = bio->bi_size; | ||
510 | err = scsi_tgt_init_cmd(cmd, GFP_ATOMIC); | ||
511 | if (err) { | ||
512 | cmd->result = DID_ERROR << 16; | ||
513 | goto send_uspace_err; | ||
514 | } | ||
515 | |||
516 | if (scsi_tgt_transfer_data(cmd)) { | ||
517 | cmd->result = DID_NO_CONNECT << 16; | ||
518 | goto send_uspace_err; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | static int scsi_tgt_transfer_data(struct scsi_cmnd *cmd) | ||
523 | { | ||
524 | int err; | ||
525 | struct Scsi_Host *host = scsi_tgt_cmd_to_host(cmd); | ||
526 | |||
527 | err = host->hostt->transfer_data(cmd, scsi_tgt_data_transfer_done); | ||
528 | switch (err) { | ||
529 | case SCSI_MLQUEUE_HOST_BUSY: | ||
530 | case SCSI_MLQUEUE_DEVICE_BUSY: | ||
531 | return -EAGAIN; | ||
532 | default: | ||
533 | return 0; | ||
534 | } | ||
535 | } | ||
536 | |||
537 | static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr, | ||
538 | unsigned len) | ||
539 | { | ||
540 | char __user *p = (char __user *) uaddr; | ||
541 | |||
542 | if (copy_from_user(cmd->sense_buffer, p, | ||
543 | min_t(unsigned, SCSI_SENSE_BUFFERSIZE, len))) { | ||
544 | printk(KERN_ERR "Could not copy the sense buffer\n"); | ||
545 | return -EIO; | ||
546 | } | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | static int scsi_tgt_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd) | ||
551 | { | ||
552 | int err; | ||
553 | |||
554 | err = shost->hostt->eh_abort_handler(cmd); | ||
555 | if (err) | ||
556 | eprintk("fail to abort %p\n", cmd); | ||
557 | |||
558 | scsi_tgt_cmd_destroy(cmd); | ||
559 | return err; | ||
560 | } | ||
561 | |||
562 | static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) | ||
563 | { | ||
564 | struct scsi_tgt_queuedata *qdata = q->queuedata; | ||
565 | struct request *rq = NULL; | ||
566 | struct list_head *head; | ||
567 | struct scsi_tgt_cmd *tcmd; | ||
568 | unsigned long flags; | ||
569 | |||
570 | head = &qdata->cmd_hash[cmd_hashfn(tag)]; | ||
571 | spin_lock_irqsave(&qdata->cmd_hash_lock, flags); | ||
572 | list_for_each_entry(tcmd, head, hash_list) { | ||
573 | if (tcmd->tag == tag) { | ||
574 | rq = tcmd->rq; | ||
575 | list_del(&tcmd->hash_list); | ||
576 | break; | ||
577 | } | ||
578 | } | ||
579 | spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); | ||
580 | |||
581 | return rq; | ||
582 | } | ||
583 | |||
584 | int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len, | ||
585 | unsigned long uaddr, u8 rw) | ||
586 | { | ||
587 | struct Scsi_Host *shost; | ||
588 | struct scsi_cmnd *cmd; | ||
589 | struct request *rq; | ||
590 | struct scsi_tgt_cmd *tcmd; | ||
591 | int err = 0; | ||
592 | |||
593 | dprintk("%d %llu %d %u %lx %u\n", host_no, (unsigned long long) tag, | ||
594 | result, len, uaddr, rw); | ||
595 | |||
596 | /* TODO: replace with a O(1) alg */ | ||
597 | shost = scsi_host_lookup(host_no); | ||
598 | if (IS_ERR(shost)) { | ||
599 | printk(KERN_ERR "Could not find host no %d\n", host_no); | ||
600 | return -EINVAL; | ||
601 | } | ||
602 | |||
603 | if (!shost->uspace_req_q) { | ||
604 | printk(KERN_ERR "Not target scsi host %d\n", host_no); | ||
605 | goto done; | ||
606 | } | ||
607 | |||
608 | rq = tgt_cmd_hash_lookup(shost->uspace_req_q, tag); | ||
609 | if (!rq) { | ||
610 | printk(KERN_ERR "Could not find tag %llu\n", | ||
611 | (unsigned long long) tag); | ||
612 | err = -EINVAL; | ||
613 | goto done; | ||
614 | } | ||
615 | cmd = rq->special; | ||
616 | |||
617 | dprintk("cmd %p result %d len %d bufflen %u %lu %x\n", cmd, | ||
618 | result, len, cmd->request_bufflen, rq_data_dir(rq), cmd->cmnd[0]); | ||
619 | |||
620 | if (result == TASK_ABORTED) { | ||
621 | scsi_tgt_abort_cmd(shost, cmd); | ||
622 | goto done; | ||
623 | } | ||
624 | /* | ||
625 | * store the userspace values here, the working values are | ||
626 | * in the request_* values | ||
627 | */ | ||
628 | tcmd = cmd->request->end_io_data; | ||
629 | tcmd->buffer = (void *)uaddr; | ||
630 | tcmd->bufflen = len; | ||
631 | cmd->result = result; | ||
632 | |||
633 | if (!tcmd->bufflen || cmd->request_buffer) { | ||
634 | err = __scsi_tgt_transfer_response(cmd); | ||
635 | goto done; | ||
636 | } | ||
637 | |||
638 | /* | ||
639 | * TODO: Do we need to handle case where request does not | ||
640 | * align with LLD. | ||
641 | */ | ||
642 | err = scsi_map_user_pages(rq->end_io_data, cmd, rw); | ||
643 | if (err) { | ||
644 | eprintk("%p %d\n", cmd, err); | ||
645 | err = -EAGAIN; | ||
646 | goto done; | ||
647 | } | ||
648 | |||
649 | /* userspace failure */ | ||
650 | if (cmd->result) { | ||
651 | if (status_byte(cmd->result) == CHECK_CONDITION) | ||
652 | scsi_tgt_copy_sense(cmd, uaddr, len); | ||
653 | err = __scsi_tgt_transfer_response(cmd); | ||
654 | goto done; | ||
655 | } | ||
656 | /* ask the target LLD to transfer the data to the buffer */ | ||
657 | err = scsi_tgt_transfer_data(cmd); | ||
658 | |||
659 | done: | ||
660 | scsi_host_put(shost); | ||
661 | return err; | ||
662 | } | ||
663 | |||
664 | int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, int function, u64 tag, | ||
665 | struct scsi_lun *scsilun, void *data) | ||
666 | { | ||
667 | int err; | ||
668 | |||
669 | /* TODO: need to retry if this fails. */ | ||
670 | err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, function, | ||
671 | tag, scsilun, data); | ||
672 | if (err < 0) | ||
673 | eprintk("The task management request lost!\n"); | ||
674 | return err; | ||
675 | } | ||
676 | EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); | ||
677 | |||
678 | int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) | ||
679 | { | ||
680 | struct Scsi_Host *shost; | ||
681 | int err = -EINVAL; | ||
682 | |||
683 | dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); | ||
684 | |||
685 | shost = scsi_host_lookup(host_no); | ||
686 | if (IS_ERR(shost)) { | ||
687 | printk(KERN_ERR "Could not find host no %d\n", host_no); | ||
688 | return err; | ||
689 | } | ||
690 | |||
691 | if (!shost->uspace_req_q) { | ||
692 | printk(KERN_ERR "Not target scsi host %d\n", host_no); | ||
693 | goto done; | ||
694 | } | ||
695 | |||
696 | err = shost->hostt->tsk_mgmt_response(mid, result); | ||
697 | done: | ||
698 | scsi_host_put(shost); | ||
699 | return err; | ||
700 | } | ||
701 | |||
702 | static int __init scsi_tgt_init(void) | ||
703 | { | ||
704 | int err; | ||
705 | |||
706 | scsi_tgt_cmd_cache = kmem_cache_create("scsi_tgt_cmd", | ||
707 | sizeof(struct scsi_tgt_cmd), | ||
708 | 0, 0, NULL, NULL); | ||
709 | if (!scsi_tgt_cmd_cache) | ||
710 | return -ENOMEM; | ||
711 | |||
712 | scsi_tgtd = create_workqueue("scsi_tgtd"); | ||
713 | if (!scsi_tgtd) { | ||
714 | err = -ENOMEM; | ||
715 | goto free_kmemcache; | ||
716 | } | ||
717 | |||
718 | err = scsi_tgt_if_init(); | ||
719 | if (err) | ||
720 | goto destroy_wq; | ||
721 | |||
722 | return 0; | ||
723 | |||
724 | destroy_wq: | ||
725 | destroy_workqueue(scsi_tgtd); | ||
726 | free_kmemcache: | ||
727 | kmem_cache_destroy(scsi_tgt_cmd_cache); | ||
728 | return err; | ||
729 | } | ||
730 | |||
731 | static void __exit scsi_tgt_exit(void) | ||
732 | { | ||
733 | destroy_workqueue(scsi_tgtd); | ||
734 | scsi_tgt_if_exit(); | ||
735 | kmem_cache_destroy(scsi_tgt_cmd_cache); | ||
736 | } | ||
737 | |||
738 | module_init(scsi_tgt_init); | ||
739 | module_exit(scsi_tgt_exit); | ||
740 | |||
741 | MODULE_DESCRIPTION("SCSI target core"); | ||
742 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h new file mode 100644 index 000000000000..84488c51ff62 --- /dev/null +++ b/drivers/scsi/scsi_tgt_priv.h | |||
@@ -0,0 +1,25 @@ | |||
1 | struct scsi_cmnd; | ||
2 | struct scsi_lun; | ||
3 | struct Scsi_Host; | ||
4 | struct task_struct; | ||
5 | |||
6 | /* tmp - will replace with SCSI logging stuff */ | ||
7 | #define eprintk(fmt, args...) \ | ||
8 | do { \ | ||
9 | printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \ | ||
10 | } while (0) | ||
11 | |||
12 | #define dprintk(fmt, args...) | ||
13 | /* #define dprintk eprintk */ | ||
14 | |||
15 | extern void scsi_tgt_if_exit(void); | ||
16 | extern int scsi_tgt_if_init(void); | ||
17 | |||
18 | extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, | ||
19 | u64 tag); | ||
20 | extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag); | ||
21 | extern int scsi_tgt_kspace_exec(int host_no, u64 tag, int result, u32 len, | ||
22 | unsigned long uaddr, u8 rw); | ||
23 | extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, | ||
24 | struct scsi_lun *scsilun, void *data); | ||
25 | extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result); | ||
diff --git a/drivers/scsi/scsi_wait_scan.c b/drivers/scsi/scsi_wait_scan.c new file mode 100644 index 000000000000..8a636103083d --- /dev/null +++ b/drivers/scsi/scsi_wait_scan.c | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * scsi_wait_scan.c | ||
3 | * | ||
4 | * Copyright (C) 2006 James Bottomley <James.Bottomley@SteelEye.com> | ||
5 | * | ||
6 | * This is a simple module to wait until all the async scans are | ||
7 | * complete. The idea is to use it in initrd/initramfs scripts. You | ||
8 | * modprobe it after all the modprobes of the root SCSI drivers and it | ||
9 | * will wait until they have all finished scanning their busses before | ||
10 | * allowing the boot to proceed | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include "scsi_priv.h" | ||
15 | |||
16 | static int __init wait_scan_init(void) | ||
17 | { | ||
18 | scsi_complete_async_scans(); | ||
19 | return 0; | ||
20 | } | ||
21 | |||
22 | static void __exit wait_scan_exit(void) | ||
23 | { | ||
24 | } | ||
25 | |||
26 | MODULE_DESCRIPTION("SCSI wait for scans"); | ||
27 | MODULE_AUTHOR("James Bottomley"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | late_initcall(wait_scan_init); | ||
31 | module_exit(wait_scan_exit); | ||
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 84ff203ffedd..f6a452846fab 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -1051,6 +1051,14 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) | |||
1051 | &sshdr, SD_TIMEOUT, | 1051 | &sshdr, SD_TIMEOUT, |
1052 | SD_MAX_RETRIES); | 1052 | SD_MAX_RETRIES); |
1053 | 1053 | ||
1054 | /* | ||
1055 | * If the drive has indicated to us that it | ||
1056 | * doesn't have any media in it, don't bother | ||
1057 | * with any more polling. | ||
1058 | */ | ||
1059 | if (media_not_present(sdkp, &sshdr)) | ||
1060 | return; | ||
1061 | |||
1054 | if (the_result) | 1062 | if (the_result) |
1055 | sense_valid = scsi_sense_valid(&sshdr); | 1063 | sense_valid = scsi_sense_valid(&sshdr); |
1056 | retries++; | 1064 | retries++; |
@@ -1059,14 +1067,6 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) | |||
1059 | ((driver_byte(the_result) & DRIVER_SENSE) && | 1067 | ((driver_byte(the_result) & DRIVER_SENSE) && |
1060 | sense_valid && sshdr.sense_key == UNIT_ATTENTION))); | 1068 | sense_valid && sshdr.sense_key == UNIT_ATTENTION))); |
1061 | 1069 | ||
1062 | /* | ||
1063 | * If the drive has indicated to us that it doesn't have | ||
1064 | * any media in it, don't bother with any of the rest of | ||
1065 | * this crap. | ||
1066 | */ | ||
1067 | if (media_not_present(sdkp, &sshdr)) | ||
1068 | return; | ||
1069 | |||
1070 | if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { | 1070 | if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { |
1071 | /* no sense, TUR either succeeded or failed | 1071 | /* no sense, TUR either succeeded or failed |
1072 | * with a status error */ | 1072 | * with a status error */ |
@@ -1467,7 +1467,6 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | |||
1467 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); | 1467 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); |
1468 | 1468 | ||
1469 | if (scsi_status_is_good(res)) { | 1469 | if (scsi_status_is_good(res)) { |
1470 | int ct = 0; | ||
1471 | int offset = data.header_length + data.block_descriptor_length; | 1470 | int offset = data.header_length + data.block_descriptor_length; |
1472 | 1471 | ||
1473 | if (offset >= SD_BUF_SIZE - 2) { | 1472 | if (offset >= SD_BUF_SIZE - 2) { |
@@ -1496,11 +1495,13 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | |||
1496 | sdkp->DPOFUA = 0; | 1495 | sdkp->DPOFUA = 0; |
1497 | } | 1496 | } |
1498 | 1497 | ||
1499 | ct = sdkp->RCD + 2*sdkp->WCE; | 1498 | printk(KERN_NOTICE "SCSI device %s: " |
1500 | 1499 | "write cache: %s, read cache: %s, %s\n", | |
1501 | printk(KERN_NOTICE "SCSI device %s: drive cache: %s%s\n", | 1500 | diskname, |
1502 | diskname, sd_cache_types[ct], | 1501 | sdkp->WCE ? "enabled" : "disabled", |
1503 | sdkp->DPOFUA ? " w/ FUA" : ""); | 1502 | sdkp->RCD ? "disabled" : "enabled", |
1503 | sdkp->DPOFUA ? "supports DPO and FUA" | ||
1504 | : "doesn't support DPO or FUA"); | ||
1504 | 1505 | ||
1505 | return; | 1506 | return; |
1506 | } | 1507 | } |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index e1a52c525ed4..587274dd7059 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -9,7 +9,7 @@ | |||
9 | Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky, | 9 | Steve Hirsch, Andreas Koppenh"ofer, Michael Leodolter, Eyal Lebedinsky, |
10 | Michael Schaefer, J"org Weule, and Eric Youngdale. | 10 | Michael Schaefer, J"org Weule, and Eric Youngdale. |
11 | 11 | ||
12 | Copyright 1992 - 2005 Kai Makisara | 12 | Copyright 1992 - 2006 Kai Makisara |
13 | email Kai.Makisara@kolumbus.fi | 13 | email Kai.Makisara@kolumbus.fi |
14 | 14 | ||
15 | Some small formal changes - aeb, 950809 | 15 | Some small formal changes - aeb, 950809 |
@@ -17,7 +17,7 @@ | |||
17 | Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support | 17 | Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support |
18 | */ | 18 | */ |
19 | 19 | ||
20 | static const char *verstr = "20050830"; | 20 | static const char *verstr = "20061107"; |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | 23 | ||
@@ -999,7 +999,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) | |||
999 | STp->min_block = ((STp->buffer)->b_data[4] << 8) | | 999 | STp->min_block = ((STp->buffer)->b_data[4] << 8) | |
1000 | (STp->buffer)->b_data[5]; | 1000 | (STp->buffer)->b_data[5]; |
1001 | if ( DEB( debugging || ) !STp->inited) | 1001 | if ( DEB( debugging || ) !STp->inited) |
1002 | printk(KERN_WARNING | 1002 | printk(KERN_INFO |
1003 | "%s: Block limits %d - %d bytes.\n", name, | 1003 | "%s: Block limits %d - %d bytes.\n", name, |
1004 | STp->min_block, STp->max_block); | 1004 | STp->min_block, STp->max_block); |
1005 | } else { | 1005 | } else { |
@@ -1224,7 +1224,7 @@ static int st_flush(struct file *filp, fl_owner_t id) | |||
1224 | } | 1224 | } |
1225 | 1225 | ||
1226 | DEBC( if (STp->nbr_requests) | 1226 | DEBC( if (STp->nbr_requests) |
1227 | printk(KERN_WARNING "%s: Number of r/w requests %d, dio used in %d, pages %d (%d).\n", | 1227 | printk(KERN_DEBUG "%s: Number of r/w requests %d, dio used in %d, pages %d (%d).\n", |
1228 | name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages, STp->nbr_combinable)); | 1228 | name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages, STp->nbr_combinable)); |
1229 | 1229 | ||
1230 | if (STps->rw == ST_WRITING && !STp->pos_unknown) { | 1230 | if (STps->rw == ST_WRITING && !STp->pos_unknown) { |
@@ -4056,11 +4056,11 @@ static int st_probe(struct device *dev) | |||
4056 | goto out_free_tape; | 4056 | goto out_free_tape; |
4057 | } | 4057 | } |
4058 | 4058 | ||
4059 | sdev_printk(KERN_WARNING, SDp, | 4059 | sdev_printk(KERN_NOTICE, SDp, |
4060 | "Attached scsi tape %s\n", tape_name(tpnt)); | 4060 | "Attached scsi tape %s\n", tape_name(tpnt)); |
4061 | printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n", | 4061 | sdev_printk(KERN_INFO, SDp, "%s: try direct i/o: %s (alignment %d B)\n", |
4062 | tape_name(tpnt), tpnt->try_dio ? "yes" : "no", | 4062 | tape_name(tpnt), tpnt->try_dio ? "yes" : "no", |
4063 | queue_dma_alignment(SDp->request_queue) + 1); | 4063 | queue_dma_alignment(SDp->request_queue) + 1); |
4064 | 4064 | ||
4065 | return 0; | 4065 | return 0; |
4066 | 4066 | ||
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 185c270bb043..ba6bcdaf2a6a 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c | |||
@@ -11,8 +11,6 @@ | |||
11 | * Written By: | 11 | * Written By: |
12 | * Ed Lin <promise_linux@promise.com> | 12 | * Ed Lin <promise_linux@promise.com> |
13 | * | 13 | * |
14 | * Version: 3.0.0.1 | ||
15 | * | ||
16 | */ | 14 | */ |
17 | 15 | ||
18 | #include <linux/init.h> | 16 | #include <linux/init.h> |
@@ -37,9 +35,9 @@ | |||
37 | #include <scsi/scsi_tcq.h> | 35 | #include <scsi/scsi_tcq.h> |
38 | 36 | ||
39 | #define DRV_NAME "stex" | 37 | #define DRV_NAME "stex" |
40 | #define ST_DRIVER_VERSION "3.0.0.1" | 38 | #define ST_DRIVER_VERSION "3.1.0.1" |
41 | #define ST_VER_MAJOR 3 | 39 | #define ST_VER_MAJOR 3 |
42 | #define ST_VER_MINOR 0 | 40 | #define ST_VER_MINOR 1 |
43 | #define ST_OEM 0 | 41 | #define ST_OEM 0 |
44 | #define ST_BUILD_VER 1 | 42 | #define ST_BUILD_VER 1 |
45 | 43 | ||
@@ -76,8 +74,10 @@ enum { | |||
76 | MU_STATE_STARTED = 4, | 74 | MU_STATE_STARTED = 4, |
77 | MU_STATE_RESETTING = 5, | 75 | MU_STATE_RESETTING = 5, |
78 | 76 | ||
79 | MU_MAX_DELAY_TIME = 240000, | 77 | MU_MAX_DELAY = 120, |
80 | MU_HANDSHAKE_SIGNATURE = 0x55aaaa55, | 78 | MU_HANDSHAKE_SIGNATURE = 0x55aaaa55, |
79 | MU_HANDSHAKE_SIGNATURE_HALF = 0x5a5a0000, | ||
80 | MU_HARD_RESET_WAIT = 30000, | ||
81 | HMU_PARTNER_TYPE = 2, | 81 | HMU_PARTNER_TYPE = 2, |
82 | 82 | ||
83 | /* firmware returned values */ | 83 | /* firmware returned values */ |
@@ -120,7 +120,8 @@ enum { | |||
120 | 120 | ||
121 | st_shasta = 0, | 121 | st_shasta = 0, |
122 | st_vsc = 1, | 122 | st_vsc = 1, |
123 | st_yosemite = 2, | 123 | st_vsc1 = 2, |
124 | st_yosemite = 3, | ||
124 | 125 | ||
125 | PASSTHRU_REQ_TYPE = 0x00000001, | 126 | PASSTHRU_REQ_TYPE = 0x00000001, |
126 | PASSTHRU_REQ_NO_WAKEUP = 0x00000100, | 127 | PASSTHRU_REQ_NO_WAKEUP = 0x00000100, |
@@ -150,6 +151,8 @@ enum { | |||
150 | MGT_CMD_SIGNATURE = 0xba, | 151 | MGT_CMD_SIGNATURE = 0xba, |
151 | 152 | ||
152 | INQUIRY_EVPD = 0x01, | 153 | INQUIRY_EVPD = 0x01, |
154 | |||
155 | ST_ADDITIONAL_MEM = 0x200000, | ||
153 | }; | 156 | }; |
154 | 157 | ||
155 | /* SCSI inquiry data */ | 158 | /* SCSI inquiry data */ |
@@ -211,7 +214,9 @@ struct handshake_frame { | |||
211 | __le32 partner_ver_minor; | 214 | __le32 partner_ver_minor; |
212 | __le32 partner_ver_oem; | 215 | __le32 partner_ver_oem; |
213 | __le32 partner_ver_build; | 216 | __le32 partner_ver_build; |
214 | u32 reserved1[4]; | 217 | __le32 extra_offset; /* NEW */ |
218 | __le32 extra_size; /* NEW */ | ||
219 | u32 reserved1[2]; | ||
215 | }; | 220 | }; |
216 | 221 | ||
217 | struct req_msg { | 222 | struct req_msg { |
@@ -302,6 +307,7 @@ struct st_hba { | |||
302 | void __iomem *mmio_base; /* iomapped PCI memory space */ | 307 | void __iomem *mmio_base; /* iomapped PCI memory space */ |
303 | void *dma_mem; | 308 | void *dma_mem; |
304 | dma_addr_t dma_handle; | 309 | dma_addr_t dma_handle; |
310 | size_t dma_size; | ||
305 | 311 | ||
306 | struct Scsi_Host *host; | 312 | struct Scsi_Host *host; |
307 | struct pci_dev *pdev; | 313 | struct pci_dev *pdev; |
@@ -507,6 +513,7 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb) | |||
507 | size_t count = sizeof(struct st_frame); | 513 | size_t count = sizeof(struct st_frame); |
508 | 514 | ||
509 | p = hba->copy_buffer; | 515 | p = hba->copy_buffer; |
516 | stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_FROM_CMD); | ||
510 | memset(p->base, 0, sizeof(u32)*6); | 517 | memset(p->base, 0, sizeof(u32)*6); |
511 | *(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0); | 518 | *(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0); |
512 | p->rom_addr = 0; | 519 | p->rom_addr = 0; |
@@ -901,27 +908,34 @@ static int stex_handshake(struct st_hba *hba) | |||
901 | void __iomem *base = hba->mmio_base; | 908 | void __iomem *base = hba->mmio_base; |
902 | struct handshake_frame *h; | 909 | struct handshake_frame *h; |
903 | dma_addr_t status_phys; | 910 | dma_addr_t status_phys; |
904 | int i; | 911 | u32 data; |
912 | unsigned long before; | ||
905 | 913 | ||
906 | if (readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE) { | 914 | if (readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE) { |
907 | writel(MU_INBOUND_DOORBELL_HANDSHAKE, base + IDBL); | 915 | writel(MU_INBOUND_DOORBELL_HANDSHAKE, base + IDBL); |
908 | readl(base + IDBL); | 916 | readl(base + IDBL); |
909 | for (i = 0; readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE | 917 | before = jiffies; |
910 | && i < MU_MAX_DELAY_TIME; i++) { | 918 | while (readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE) { |
919 | if (time_after(jiffies, before + MU_MAX_DELAY * HZ)) { | ||
920 | printk(KERN_ERR DRV_NAME | ||
921 | "(%s): no handshake signature\n", | ||
922 | pci_name(hba->pdev)); | ||
923 | return -1; | ||
924 | } | ||
911 | rmb(); | 925 | rmb(); |
912 | msleep(1); | 926 | msleep(1); |
913 | } | 927 | } |
914 | |||
915 | if (i == MU_MAX_DELAY_TIME) { | ||
916 | printk(KERN_ERR DRV_NAME | ||
917 | "(%s): no handshake signature\n", | ||
918 | pci_name(hba->pdev)); | ||
919 | return -1; | ||
920 | } | ||
921 | } | 928 | } |
922 | 929 | ||
923 | udelay(10); | 930 | udelay(10); |
924 | 931 | ||
932 | data = readl(base + OMR1); | ||
933 | if ((data & 0xffff0000) == MU_HANDSHAKE_SIGNATURE_HALF) { | ||
934 | data &= 0x0000ffff; | ||
935 | if (hba->host->can_queue > data) | ||
936 | hba->host->can_queue = data; | ||
937 | } | ||
938 | |||
925 | h = (struct handshake_frame *)(hba->dma_mem + MU_REQ_BUFFER_SIZE); | 939 | h = (struct handshake_frame *)(hba->dma_mem + MU_REQ_BUFFER_SIZE); |
926 | h->rb_phy = cpu_to_le32(hba->dma_handle); | 940 | h->rb_phy = cpu_to_le32(hba->dma_handle); |
927 | h->rb_phy_hi = cpu_to_le32((hba->dma_handle >> 16) >> 16); | 941 | h->rb_phy_hi = cpu_to_le32((hba->dma_handle >> 16) >> 16); |
@@ -931,6 +945,11 @@ static int stex_handshake(struct st_hba *hba) | |||
931 | h->status_cnt = cpu_to_le16(MU_STATUS_COUNT); | 945 | h->status_cnt = cpu_to_le16(MU_STATUS_COUNT); |
932 | stex_gettime(&h->hosttime); | 946 | stex_gettime(&h->hosttime); |
933 | h->partner_type = HMU_PARTNER_TYPE; | 947 | h->partner_type = HMU_PARTNER_TYPE; |
948 | if (hba->dma_size > STEX_BUFFER_SIZE) { | ||
949 | h->extra_offset = cpu_to_le32(STEX_BUFFER_SIZE); | ||
950 | h->extra_size = cpu_to_le32(ST_ADDITIONAL_MEM); | ||
951 | } else | ||
952 | h->extra_offset = h->extra_size = 0; | ||
934 | 953 | ||
935 | status_phys = hba->dma_handle + MU_REQ_BUFFER_SIZE; | 954 | status_phys = hba->dma_handle + MU_REQ_BUFFER_SIZE; |
936 | writel(status_phys, base + IMR0); | 955 | writel(status_phys, base + IMR0); |
@@ -944,19 +963,18 @@ static int stex_handshake(struct st_hba *hba) | |||
944 | readl(base + IDBL); /* flush */ | 963 | readl(base + IDBL); /* flush */ |
945 | 964 | ||
946 | udelay(10); | 965 | udelay(10); |
947 | for (i = 0; readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE | 966 | before = jiffies; |
948 | && i < MU_MAX_DELAY_TIME; i++) { | 967 | while (readl(base + OMR0) != MU_HANDSHAKE_SIGNATURE) { |
968 | if (time_after(jiffies, before + MU_MAX_DELAY * HZ)) { | ||
969 | printk(KERN_ERR DRV_NAME | ||
970 | "(%s): no signature after handshake frame\n", | ||
971 | pci_name(hba->pdev)); | ||
972 | return -1; | ||
973 | } | ||
949 | rmb(); | 974 | rmb(); |
950 | msleep(1); | 975 | msleep(1); |
951 | } | 976 | } |
952 | 977 | ||
953 | if (i == MU_MAX_DELAY_TIME) { | ||
954 | printk(KERN_ERR DRV_NAME | ||
955 | "(%s): no signature after handshake frame\n", | ||
956 | pci_name(hba->pdev)); | ||
957 | return -1; | ||
958 | } | ||
959 | |||
960 | writel(0, base + IMR0); | 978 | writel(0, base + IMR0); |
961 | readl(base + IMR0); | 979 | readl(base + IMR0); |
962 | writel(0, base + OMR0); | 980 | writel(0, base + OMR0); |
@@ -1038,9 +1056,9 @@ static void stex_hard_reset(struct st_hba *hba) | |||
1038 | pci_bctl &= ~PCI_BRIDGE_CTL_BUS_RESET; | 1056 | pci_bctl &= ~PCI_BRIDGE_CTL_BUS_RESET; |
1039 | pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl); | 1057 | pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, pci_bctl); |
1040 | 1058 | ||
1041 | for (i = 0; i < MU_MAX_DELAY_TIME; i++) { | 1059 | for (i = 0; i < MU_HARD_RESET_WAIT; i++) { |
1042 | pci_read_config_word(hba->pdev, PCI_COMMAND, &pci_cmd); | 1060 | pci_read_config_word(hba->pdev, PCI_COMMAND, &pci_cmd); |
1043 | if (pci_cmd & PCI_COMMAND_MASTER) | 1061 | if (pci_cmd != 0xffff && (pci_cmd & PCI_COMMAND_MASTER)) |
1044 | break; | 1062 | break; |
1045 | msleep(1); | 1063 | msleep(1); |
1046 | } | 1064 | } |
@@ -1100,18 +1118,18 @@ static int stex_reset(struct scsi_cmnd *cmd) | |||
1100 | static int stex_biosparam(struct scsi_device *sdev, | 1118 | static int stex_biosparam(struct scsi_device *sdev, |
1101 | struct block_device *bdev, sector_t capacity, int geom[]) | 1119 | struct block_device *bdev, sector_t capacity, int geom[]) |
1102 | { | 1120 | { |
1103 | int heads = 255, sectors = 63, cylinders; | 1121 | int heads = 255, sectors = 63; |
1104 | 1122 | ||
1105 | if (capacity < 0x200000) { | 1123 | if (capacity < 0x200000) { |
1106 | heads = 64; | 1124 | heads = 64; |
1107 | sectors = 32; | 1125 | sectors = 32; |
1108 | } | 1126 | } |
1109 | 1127 | ||
1110 | cylinders = sector_div(capacity, heads * sectors); | 1128 | sector_div(capacity, heads * sectors); |
1111 | 1129 | ||
1112 | geom[0] = heads; | 1130 | geom[0] = heads; |
1113 | geom[1] = sectors; | 1131 | geom[1] = sectors; |
1114 | geom[2] = cylinders; | 1132 | geom[2] = capacity; |
1115 | 1133 | ||
1116 | return 0; | 1134 | return 0; |
1117 | } | 1135 | } |
@@ -1193,8 +1211,13 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1193 | goto out_iounmap; | 1211 | goto out_iounmap; |
1194 | } | 1212 | } |
1195 | 1213 | ||
1214 | hba->cardtype = (unsigned int) id->driver_data; | ||
1215 | if (hba->cardtype == st_vsc && (pdev->subsystem_device & 0xf) == 0x1) | ||
1216 | hba->cardtype = st_vsc1; | ||
1217 | hba->dma_size = (hba->cardtype == st_vsc1) ? | ||
1218 | (STEX_BUFFER_SIZE + ST_ADDITIONAL_MEM) : (STEX_BUFFER_SIZE); | ||
1196 | hba->dma_mem = dma_alloc_coherent(&pdev->dev, | 1219 | hba->dma_mem = dma_alloc_coherent(&pdev->dev, |
1197 | STEX_BUFFER_SIZE, &hba->dma_handle, GFP_KERNEL); | 1220 | hba->dma_size, &hba->dma_handle, GFP_KERNEL); |
1198 | if (!hba->dma_mem) { | 1221 | if (!hba->dma_mem) { |
1199 | err = -ENOMEM; | 1222 | err = -ENOMEM; |
1200 | printk(KERN_ERR DRV_NAME "(%s): dma mem alloc failed\n", | 1223 | printk(KERN_ERR DRV_NAME "(%s): dma mem alloc failed\n", |
@@ -1207,8 +1230,6 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1207 | hba->copy_buffer = hba->dma_mem + MU_BUFFER_SIZE; | 1230 | hba->copy_buffer = hba->dma_mem + MU_BUFFER_SIZE; |
1208 | hba->mu_status = MU_STATE_STARTING; | 1231 | hba->mu_status = MU_STATE_STARTING; |
1209 | 1232 | ||
1210 | hba->cardtype = (unsigned int) id->driver_data; | ||
1211 | |||
1212 | /* firmware uses id/lun pair for a logical drive, but lun would be | 1233 | /* firmware uses id/lun pair for a logical drive, but lun would be |
1213 | always 0 if CONFIG_SCSI_MULTI_LUN not configured, so we use | 1234 | always 0 if CONFIG_SCSI_MULTI_LUN not configured, so we use |
1214 | channel to map lun here */ | 1235 | channel to map lun here */ |
@@ -1233,7 +1254,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1233 | if (err) | 1254 | if (err) |
1234 | goto out_free_irq; | 1255 | goto out_free_irq; |
1235 | 1256 | ||
1236 | err = scsi_init_shared_tag_map(host, ST_CAN_QUEUE); | 1257 | err = scsi_init_shared_tag_map(host, host->can_queue); |
1237 | if (err) { | 1258 | if (err) { |
1238 | printk(KERN_ERR DRV_NAME "(%s): init shared queue failed\n", | 1259 | printk(KERN_ERR DRV_NAME "(%s): init shared queue failed\n", |
1239 | pci_name(pdev)); | 1260 | pci_name(pdev)); |
@@ -1256,7 +1277,7 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1256 | out_free_irq: | 1277 | out_free_irq: |
1257 | free_irq(pdev->irq, hba); | 1278 | free_irq(pdev->irq, hba); |
1258 | out_pci_free: | 1279 | out_pci_free: |
1259 | dma_free_coherent(&pdev->dev, STEX_BUFFER_SIZE, | 1280 | dma_free_coherent(&pdev->dev, hba->dma_size, |
1260 | hba->dma_mem, hba->dma_handle); | 1281 | hba->dma_mem, hba->dma_handle); |
1261 | out_iounmap: | 1282 | out_iounmap: |
1262 | iounmap(hba->mmio_base); | 1283 | iounmap(hba->mmio_base); |
@@ -1317,7 +1338,7 @@ static void stex_hba_free(struct st_hba *hba) | |||
1317 | 1338 | ||
1318 | pci_release_regions(hba->pdev); | 1339 | pci_release_regions(hba->pdev); |
1319 | 1340 | ||
1320 | dma_free_coherent(&hba->pdev->dev, STEX_BUFFER_SIZE, | 1341 | dma_free_coherent(&hba->pdev->dev, hba->dma_size, |
1321 | hba->dma_mem, hba->dma_handle); | 1342 | hba->dma_mem, hba->dma_handle); |
1322 | } | 1343 | } |
1323 | 1344 | ||
@@ -1346,15 +1367,32 @@ static void stex_shutdown(struct pci_dev *pdev) | |||
1346 | } | 1367 | } |
1347 | 1368 | ||
1348 | static struct pci_device_id stex_pci_tbl[] = { | 1369 | static struct pci_device_id stex_pci_tbl[] = { |
1349 | { 0x105a, 0x8350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, | 1370 | /* st_shasta */ |
1350 | { 0x105a, 0xc350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, | 1371 | { 0x105a, 0x8350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
1351 | { 0x105a, 0xf350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, | 1372 | st_shasta }, /* SuperTrak EX8350/8300/16350/16300 */ |
1352 | { 0x105a, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, | 1373 | { 0x105a, 0xc350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
1353 | { 0x105a, 0x4302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, | 1374 | st_shasta }, /* SuperTrak EX12350 */ |
1354 | { 0x105a, 0x8301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, | 1375 | { 0x105a, 0x4302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
1355 | { 0x105a, 0x8302, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_shasta }, | 1376 | st_shasta }, /* SuperTrak EX4350 */ |
1356 | { 0x1725, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc }, | 1377 | { 0x105a, 0xe350, PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
1357 | { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_yosemite }, | 1378 | st_shasta }, /* SuperTrak EX24350 */ |
1379 | |||
1380 | /* st_vsc */ | ||
1381 | { 0x105a, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc }, | ||
1382 | |||
1383 | /* st_yosemite */ | ||
1384 | { 0x105a, 0x8650, PCI_ANY_ID, 0x4600, 0, 0, | ||
1385 | st_yosemite }, /* SuperTrak EX4650 */ | ||
1386 | { 0x105a, 0x8650, PCI_ANY_ID, 0x4610, 0, 0, | ||
1387 | st_yosemite }, /* SuperTrak EX4650o */ | ||
1388 | { 0x105a, 0x8650, PCI_ANY_ID, 0x8600, 0, 0, | ||
1389 | st_yosemite }, /* SuperTrak EX8650EL */ | ||
1390 | { 0x105a, 0x8650, PCI_ANY_ID, 0x8601, 0, 0, | ||
1391 | st_yosemite }, /* SuperTrak EX8650 */ | ||
1392 | { 0x105a, 0x8650, PCI_ANY_ID, 0x8602, 0, 0, | ||
1393 | st_yosemite }, /* SuperTrak EX8654 */ | ||
1394 | { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
1395 | st_yosemite }, /* generic st_yosemite */ | ||
1358 | { } /* terminate list */ | 1396 | { } /* terminate list */ |
1359 | }; | 1397 | }; |
1360 | MODULE_DEVICE_TABLE(pci, stex_pci_tbl); | 1398 | MODULE_DEVICE_TABLE(pci, stex_pci_tbl); |
diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index 646e840266e2..76a069b7ac0b 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h | |||
@@ -8,20 +8,20 @@ | |||
8 | * drew@colorado.edu | 8 | * drew@colorado.edu |
9 | * +1 (303) 440-4894 | 9 | * +1 (303) 440-4894 |
10 | * | 10 | * |
11 | * DISTRIBUTION RELEASE 3. | 11 | * DISTRIBUTION RELEASE 3. |
12 | * | 12 | * |
13 | * For more information, please consult | 13 | * For more information, please consult |
14 | * | 14 | * |
15 | * Trantor Systems, Ltd. | 15 | * Trantor Systems, Ltd. |
16 | * T128/T128F/T228 SCSI Host Adapter | 16 | * T128/T128F/T228 SCSI Host Adapter |
17 | * Hardware Specifications | 17 | * Hardware Specifications |
18 | * | 18 | * |
19 | * Trantor Systems, Ltd. | 19 | * Trantor Systems, Ltd. |
20 | * 5415 Randall Place | 20 | * 5415 Randall Place |
21 | * Fremont, CA 94538 | 21 | * Fremont, CA 94538 |
22 | * 1+ (415) 770-1400, FAX 1+ (415) 770-9910 | 22 | * 1+ (415) 770-1400, FAX 1+ (415) 770-9910 |
23 | * | 23 | * |
24 | * and | 24 | * and |
25 | * | 25 | * |
26 | * NCR 5380 Family | 26 | * NCR 5380 Family |
27 | * SCSI Protocol Controller | 27 | * SCSI Protocol Controller |
@@ -48,15 +48,15 @@ | |||
48 | #define TDEBUG_TRANSFER 0x2 | 48 | #define TDEBUG_TRANSFER 0x2 |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * The trantor boards are memory mapped. They use an NCR5380 or | 51 | * The trantor boards are memory mapped. They use an NCR5380 or |
52 | * equivalent (my sample board had part second sourced from ZILOG). | 52 | * equivalent (my sample board had part second sourced from ZILOG). |
53 | * NCR's recommended "Pseudo-DMA" architecture is used, where | 53 | * NCR's recommended "Pseudo-DMA" architecture is used, where |
54 | * a PAL drives the DMA signals on the 5380 allowing fast, blind | 54 | * a PAL drives the DMA signals on the 5380 allowing fast, blind |
55 | * transfers with proper handshaking. | 55 | * transfers with proper handshaking. |
56 | */ | 56 | */ |
57 | 57 | ||
58 | /* | 58 | /* |
59 | * Note : a boot switch is provided for the purpose of informing the | 59 | * Note : a boot switch is provided for the purpose of informing the |
60 | * firmware to boot or not boot from attached SCSI devices. So, I imagine | 60 | * firmware to boot or not boot from attached SCSI devices. So, I imagine |
61 | * there are fewer people who've yanked the ROM like they do on the Seagate | 61 | * there are fewer people who've yanked the ROM like they do on the Seagate |
62 | * to make bootup faster, and I'll probably use this for autodetection. | 62 | * to make bootup faster, and I'll probably use this for autodetection. |
@@ -92,19 +92,20 @@ | |||
92 | #define T_DATA_REG_OFFSET 0x1e00 /* rw 512 bytes long */ | 92 | #define T_DATA_REG_OFFSET 0x1e00 /* rw 512 bytes long */ |
93 | 93 | ||
94 | #ifndef ASM | 94 | #ifndef ASM |
95 | static int t128_abort(Scsi_Cmnd *); | 95 | static int t128_abort(struct scsi_cmnd *); |
96 | static int t128_biosparam(struct scsi_device *, struct block_device *, | 96 | static int t128_biosparam(struct scsi_device *, struct block_device *, |
97 | sector_t, int*); | 97 | sector_t, int*); |
98 | static int t128_detect(struct scsi_host_template *); | 98 | static int t128_detect(struct scsi_host_template *); |
99 | static int t128_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); | 99 | static int t128_queue_command(struct scsi_cmnd *, |
100 | static int t128_bus_reset(Scsi_Cmnd *); | 100 | void (*done)(struct scsi_cmnd *)); |
101 | static int t128_bus_reset(struct scsi_cmnd *); | ||
101 | 102 | ||
102 | #ifndef CMD_PER_LUN | 103 | #ifndef CMD_PER_LUN |
103 | #define CMD_PER_LUN 2 | 104 | #define CMD_PER_LUN 2 |
104 | #endif | 105 | #endif |
105 | 106 | ||
106 | #ifndef CAN_QUEUE | 107 | #ifndef CAN_QUEUE |
107 | #define CAN_QUEUE 32 | 108 | #define CAN_QUEUE 32 |
108 | #endif | 109 | #endif |
109 | 110 | ||
110 | #ifndef HOSTS_C | 111 | #ifndef HOSTS_C |
@@ -120,7 +121,7 @@ static int t128_bus_reset(Scsi_Cmnd *); | |||
120 | 121 | ||
121 | #define T128_address(reg) (base + T_5380_OFFSET + ((reg) * 0x20)) | 122 | #define T128_address(reg) (base + T_5380_OFFSET + ((reg) * 0x20)) |
122 | 123 | ||
123 | #if !(TDEBUG & TDEBUG_TRANSFER) | 124 | #if !(TDEBUG & TDEBUG_TRANSFER) |
124 | #define NCR5380_read(reg) readb(T128_address(reg)) | 125 | #define NCR5380_read(reg) readb(T128_address(reg)) |
125 | #define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) | 126 | #define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) |
126 | #else | 127 | #else |
@@ -129,7 +130,7 @@ static int t128_bus_reset(Scsi_Cmnd *); | |||
129 | , instance->hostno, (reg), T128_address(reg))), readb(T128_address(reg))) | 130 | , instance->hostno, (reg), T128_address(reg))), readb(T128_address(reg))) |
130 | 131 | ||
131 | #define NCR5380_write(reg, value) { \ | 132 | #define NCR5380_write(reg, value) { \ |
132 | printk("scsi%d : write %02x to register %d at address %08x\n", \ | 133 | printk("scsi%d : write %02x to register %d at address %08x\n", \ |
133 | instance->hostno, (value), (reg), T128_address(reg)); \ | 134 | instance->hostno, (value), (reg), T128_address(reg)); \ |
134 | writeb((value), (T128_address(reg))); \ | 135 | writeb((value), (T128_address(reg))); \ |
135 | } | 136 | } |
@@ -142,10 +143,10 @@ static int t128_bus_reset(Scsi_Cmnd *); | |||
142 | #define NCR5380_bus_reset t128_bus_reset | 143 | #define NCR5380_bus_reset t128_bus_reset |
143 | #define NCR5380_proc_info t128_proc_info | 144 | #define NCR5380_proc_info t128_proc_info |
144 | 145 | ||
145 | /* 15 14 12 10 7 5 3 | 146 | /* 15 14 12 10 7 5 3 |
146 | 1101 0100 1010 1000 */ | 147 | 1101 0100 1010 1000 */ |
147 | 148 | ||
148 | #define T128_IRQS 0xc4a8 | 149 | #define T128_IRQS 0xc4a8 |
149 | 150 | ||
150 | #endif /* else def HOSTS_C */ | 151 | #endif /* else def HOSTS_C */ |
151 | #endif /* ndef ASM */ | 152 | #endif /* ndef ASM */ |
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 00f9ffd69489..431433f4dd6d 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -723,7 +723,7 @@ static int serial_config(struct pcmcia_device * link) | |||
723 | u_char *buf; | 723 | u_char *buf; |
724 | cisparse_t *parse; | 724 | cisparse_t *parse; |
725 | cistpl_cftable_entry_t *cf; | 725 | cistpl_cftable_entry_t *cf; |
726 | int i, last_ret, last_fn; | 726 | int i; |
727 | 727 | ||
728 | DEBUG(0, "serial_config(0x%p)\n", link); | 728 | DEBUG(0, "serial_config(0x%p)\n", link); |
729 | 729 | ||
@@ -740,15 +740,6 @@ static int serial_config(struct pcmcia_device * link) | |||
740 | tuple->TupleOffset = 0; | 740 | tuple->TupleOffset = 0; |
741 | tuple->TupleDataMax = 255; | 741 | tuple->TupleDataMax = 255; |
742 | tuple->Attributes = 0; | 742 | tuple->Attributes = 0; |
743 | /* Get configuration register information */ | ||
744 | tuple->DesiredTuple = CISTPL_CONFIG; | ||
745 | last_ret = first_tuple(link, tuple, parse); | ||
746 | if (last_ret != CS_SUCCESS) { | ||
747 | last_fn = ParseTuple; | ||
748 | goto cs_failed; | ||
749 | } | ||
750 | link->conf.ConfigBase = parse->config.base; | ||
751 | link->conf.Present = parse->config.rmask[0]; | ||
752 | 743 | ||
753 | /* Is this a compliant multifunction card? */ | 744 | /* Is this a compliant multifunction card? */ |
754 | tuple->DesiredTuple = CISTPL_LONGLINK_MFC; | 745 | tuple->DesiredTuple = CISTPL_LONGLINK_MFC; |
@@ -757,27 +748,25 @@ static int serial_config(struct pcmcia_device * link) | |||
757 | 748 | ||
758 | /* Is this a multiport card? */ | 749 | /* Is this a multiport card? */ |
759 | tuple->DesiredTuple = CISTPL_MANFID; | 750 | tuple->DesiredTuple = CISTPL_MANFID; |
760 | if (first_tuple(link, tuple, parse) == CS_SUCCESS) { | 751 | info->manfid = link->manf_id; |
761 | info->manfid = parse->manfid.manf; | 752 | info->prodid = link->card_id; |
762 | info->prodid = parse->manfid.card; | 753 | |
763 | 754 | for (i = 0; i < ARRAY_SIZE(quirks); i++) | |
764 | for (i = 0; i < ARRAY_SIZE(quirks); i++) | 755 | if ((quirks[i].manfid == ~0 || |
765 | if ((quirks[i].manfid == ~0 || | 756 | quirks[i].manfid == info->manfid) && |
766 | quirks[i].manfid == info->manfid) && | 757 | (quirks[i].prodid == ~0 || |
767 | (quirks[i].prodid == ~0 || | 758 | quirks[i].prodid == info->prodid)) { |
768 | quirks[i].prodid == info->prodid)) { | 759 | info->quirk = &quirks[i]; |
769 | info->quirk = &quirks[i]; | 760 | break; |
770 | break; | 761 | } |
771 | } | ||
772 | } | ||
773 | 762 | ||
774 | /* Another check for dual-serial cards: look for either serial or | 763 | /* Another check for dual-serial cards: look for either serial or |
775 | multifunction cards that ask for appropriate IO port ranges */ | 764 | multifunction cards that ask for appropriate IO port ranges */ |
776 | tuple->DesiredTuple = CISTPL_FUNCID; | 765 | tuple->DesiredTuple = CISTPL_FUNCID; |
777 | if ((info->multi == 0) && | 766 | if ((info->multi == 0) && |
778 | ((first_tuple(link, tuple, parse) != CS_SUCCESS) || | 767 | (link->has_func_id) && |
779 | (parse->funcid.func == CISTPL_FUNCID_MULTI) || | 768 | ((link->func_id == CISTPL_FUNCID_MULTI) || |
780 | (parse->funcid.func == CISTPL_FUNCID_SERIAL))) { | 769 | (link->func_id == CISTPL_FUNCID_SERIAL))) { |
781 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; | 770 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; |
782 | if (first_tuple(link, tuple, parse) == CS_SUCCESS) { | 771 | if (first_tuple(link, tuple, parse) == CS_SUCCESS) { |
783 | if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) | 772 | if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) |
@@ -814,8 +803,6 @@ static int serial_config(struct pcmcia_device * link) | |||
814 | kfree(cfg_mem); | 803 | kfree(cfg_mem); |
815 | return 0; | 804 | return 0; |
816 | 805 | ||
817 | cs_failed: | ||
818 | cs_error(link, last_fn, last_ret); | ||
819 | failed: | 806 | failed: |
820 | serial_remove(link); | 807 | serial_remove(link); |
821 | kfree(cfg_mem); | 808 | kfree(cfg_mem); |
@@ -925,6 +912,30 @@ static struct pcmcia_device_id serial_ids[] = { | |||
925 | PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), | 912 | PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), |
926 | PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"), | 913 | PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "RS-COM-2P.cis"), |
927 | PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "GLOBETROTTER.cis"), | 914 | PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "GLOBETROTTER.cis"), |
915 | PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100 1.00.",0x19ca78af,0xf964f42b), | ||
916 | PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100",0x19ca78af,0x71d98e83), | ||
917 | PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232 1.00.",0x19ca78af,0x69fb7490), | ||
918 | PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL232",0x19ca78af,0xb6bc0235), | ||
919 | PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232",0x63f2e0bd,0xb9e175d3), | ||
920 | PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c2000.","SERIAL CARD: CF232-5",0x63f2e0bd,0xfce33442), | ||
921 | PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232",0x3beb8cf2,0x171e7190), | ||
922 | PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF232-5",0x3beb8cf2,0x20da4262), | ||
923 | PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF428",0x3beb8cf2,0xea5dd57d), | ||
924 | PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: CF500",0x3beb8cf2,0xd77255fa), | ||
925 | PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: IC232",0x3beb8cf2,0x6a709903), | ||
926 | PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: SL232",0x3beb8cf2,0x18430676), | ||
927 | PCMCIA_DEVICE_PROD_ID12("Elan","Serial Port: XL232",0x3beb8cf2,0x6f933767), | ||
928 | PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), | ||
929 | PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), | ||
930 | PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), | ||
931 | PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), | ||
932 | PCMCIA_MFC_DEVICE_PROD_ID12(0,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc), | ||
933 | PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: CF332",0x3beb8cf2,0x16dc1ba7), | ||
934 | PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL332",0x3beb8cf2,0x19816c41), | ||
935 | PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL385",0x3beb8cf2,0x64112029), | ||
936 | PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), | ||
937 | PCMCIA_MFC_DEVICE_PROD_ID12(2,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), | ||
938 | PCMCIA_MFC_DEVICE_PROD_ID12(3,"Elan","Serial Port: SL432",0x3beb8cf2,0x1cce7ac4), | ||
928 | /* too generic */ | 939 | /* too generic */ |
929 | /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ | 940 | /* PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0160, 0x0002), */ |
930 | /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */ | 941 | /* PCMCIA_MFC_DEVICE_MANF_CARD(1, 0x0160, 0x0002), */ |
diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index dda0ca45d904..164a5dcf1f1e 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c | |||
@@ -69,25 +69,21 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
69 | 69 | ||
70 | static void ixj_get_serial(struct pcmcia_device * link, IXJ * j) | 70 | static void ixj_get_serial(struct pcmcia_device * link, IXJ * j) |
71 | { | 71 | { |
72 | tuple_t tuple; | ||
73 | u_short buf[128]; | ||
74 | char *str; | 72 | char *str; |
75 | int last_ret, last_fn, i, place; | 73 | int i, place; |
76 | DEBUG(0, "ixj_get_serial(0x%p)\n", link); | 74 | DEBUG(0, "ixj_get_serial(0x%p)\n", link); |
77 | tuple.TupleData = (cisdata_t *) buf; | 75 | |
78 | tuple.TupleOffset = 0; | 76 | str = link->prod_id[0]; |
79 | tuple.TupleDataMax = 80; | 77 | if (!str) |
80 | tuple.Attributes = 0; | 78 | goto cs_failed; |
81 | tuple.DesiredTuple = CISTPL_VERS_1; | ||
82 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
83 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
84 | str = (char *) buf; | ||
85 | printk("PCMCIA Version %d.%d\n", str[0], str[1]); | ||
86 | str += 2; | ||
87 | printk("%s", str); | 79 | printk("%s", str); |
88 | str = str + strlen(str) + 1; | 80 | str = link->prod_id[1]; |
81 | if (!str) | ||
82 | goto cs_failed; | ||
89 | printk(" %s", str); | 83 | printk(" %s", str); |
90 | str = str + strlen(str) + 1; | 84 | str = link->prod_id[2]; |
85 | if (!str) | ||
86 | goto cs_failed; | ||
91 | place = 1; | 87 | place = 1; |
92 | for (i = strlen(str) - 1; i >= 0; i--) { | 88 | for (i = strlen(str) - 1; i >= 0; i--) { |
93 | switch (str[i]) { | 89 | switch (str[i]) { |
@@ -122,7 +118,9 @@ static void ixj_get_serial(struct pcmcia_device * link, IXJ * j) | |||
122 | } | 118 | } |
123 | place = place * 0x10; | 119 | place = place * 0x10; |
124 | } | 120 | } |
125 | str = str + strlen(str) + 1; | 121 | str = link->prod_id[3]; |
122 | if (!str) | ||
123 | goto cs_failed; | ||
126 | printk(" version %s\n", str); | 124 | printk(" version %s\n", str); |
127 | cs_failed: | 125 | cs_failed: |
128 | return; | 126 | return; |
@@ -146,13 +144,6 @@ static int ixj_config(struct pcmcia_device * link) | |||
146 | tuple.TupleData = (cisdata_t *) buf; | 144 | tuple.TupleData = (cisdata_t *) buf; |
147 | tuple.TupleOffset = 0; | 145 | tuple.TupleOffset = 0; |
148 | tuple.TupleDataMax = 255; | 146 | tuple.TupleDataMax = 255; |
149 | tuple.Attributes = 0; | ||
150 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
151 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
152 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
153 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
154 | link->conf.ConfigBase = parse.config.base; | ||
155 | link->conf.Present = parse.config.rmask[0]; | ||
156 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 147 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
157 | tuple.Attributes = 0; | 148 | tuple.Attributes = 0; |
158 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 149 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 54f554e0f0ad..ac9f11d19817 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c | |||
@@ -169,21 +169,14 @@ static int sl811_cs_config(struct pcmcia_device *link) | |||
169 | 169 | ||
170 | DBG(0, "sl811_cs_config(0x%p)\n", link); | 170 | DBG(0, "sl811_cs_config(0x%p)\n", link); |
171 | 171 | ||
172 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
173 | tuple.Attributes = 0; | ||
174 | tuple.TupleData = buf; | ||
175 | tuple.TupleDataMax = sizeof(buf); | ||
176 | tuple.TupleOffset = 0; | ||
177 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
178 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
179 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | ||
180 | link->conf.ConfigBase = parse.config.base; | ||
181 | link->conf.Present = parse.config.rmask[0]; | ||
182 | |||
183 | /* Look up the current Vcc */ | 172 | /* Look up the current Vcc */ |
184 | CS_CHECK(GetConfigurationInfo, | 173 | CS_CHECK(GetConfigurationInfo, |
185 | pcmcia_get_configuration_info(link, &conf)); | 174 | pcmcia_get_configuration_info(link, &conf)); |
186 | 175 | ||
176 | tuple.Attributes = 0; | ||
177 | tuple.TupleData = buf; | ||
178 | tuple.TupleDataMax = sizeof(buf); | ||
179 | tuple.TupleOffset = 0; | ||
187 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 180 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
188 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | 181 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
189 | while (1) { | 182 | while (1) { |
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index ede639812f8a..623a0fc0dae1 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h | |||
@@ -262,9 +262,10 @@ struct pcmcia_socket { | |||
262 | u8 present:1, /* PCMCIA card is present in socket */ | 262 | u8 present:1, /* PCMCIA card is present in socket */ |
263 | busy:1, /* "master" ioctl is used */ | 263 | busy:1, /* "master" ioctl is used */ |
264 | dead:1, /* pcmcia module is being unloaded */ | 264 | dead:1, /* pcmcia module is being unloaded */ |
265 | device_add_pending:1, /* a pseudo-multifunction-device | 265 | device_add_pending:1, /* a multifunction-device |
266 | * add event is pending */ | 266 | * add event is pending */ |
267 | reserved:4; | 267 | mfc_pfc:1, /* the pending event adds a mfc (1) or pfc (0) */ |
268 | reserved:3; | ||
268 | } pcmcia_state; | 269 | } pcmcia_state; |
269 | 270 | ||
270 | struct work_struct device_add; /* for adding further pseudo-multifunction | 271 | struct work_struct device_add; /* for adding further pseudo-multifunction |
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 1f989fb42c70..b09bdd8c3394 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h | |||
@@ -354,6 +354,8 @@ struct sas_ha_struct { | |||
354 | void (*notify_phy_event)(struct asd_sas_phy *, enum phy_event); | 354 | void (*notify_phy_event)(struct asd_sas_phy *, enum phy_event); |
355 | 355 | ||
356 | void *lldd_ha; /* not touched by sas class code */ | 356 | void *lldd_ha; /* not touched by sas class code */ |
357 | |||
358 | struct list_head eh_done_q; | ||
357 | }; | 359 | }; |
358 | 360 | ||
359 | #define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata) | 361 | #define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata) |
@@ -542,13 +544,16 @@ struct sas_task { | |||
542 | 544 | ||
543 | void *lldd_task; /* for use by LLDDs */ | 545 | void *lldd_task; /* for use by LLDDs */ |
544 | void *uldd_task; | 546 | void *uldd_task; |
547 | |||
548 | struct work_struct abort_work; | ||
545 | }; | 549 | }; |
546 | 550 | ||
547 | 551 | ||
548 | 552 | ||
549 | #define SAS_TASK_STATE_PENDING 1 | 553 | #define SAS_TASK_STATE_PENDING 1 |
550 | #define SAS_TASK_STATE_DONE 2 | 554 | #define SAS_TASK_STATE_DONE 2 |
551 | #define SAS_TASK_STATE_ABORTED 4 | 555 | #define SAS_TASK_STATE_ABORTED 4 |
556 | #define SAS_TASK_INITIATOR_ABORTED 8 | ||
552 | 557 | ||
553 | static inline struct sas_task *sas_alloc_task(gfp_t flags) | 558 | static inline struct sas_task *sas_alloc_task(gfp_t flags) |
554 | { | 559 | { |
@@ -608,6 +613,7 @@ struct sas_domain_function_template { | |||
608 | extern int sas_register_ha(struct sas_ha_struct *); | 613 | extern int sas_register_ha(struct sas_ha_struct *); |
609 | extern int sas_unregister_ha(struct sas_ha_struct *); | 614 | extern int sas_unregister_ha(struct sas_ha_struct *); |
610 | 615 | ||
616 | int sas_phy_reset(struct sas_phy *phy, int hard_reset); | ||
611 | extern int sas_queuecommand(struct scsi_cmnd *, | 617 | extern int sas_queuecommand(struct scsi_cmnd *, |
612 | void (*scsi_done)(struct scsi_cmnd *)); | 618 | void (*scsi_done)(struct scsi_cmnd *)); |
613 | extern int sas_target_alloc(struct scsi_target *); | 619 | extern int sas_target_alloc(struct scsi_target *); |
@@ -640,4 +646,6 @@ void sas_unregister_dev(struct domain_device *); | |||
640 | 646 | ||
641 | void sas_init_dev(struct domain_device *); | 647 | void sas_init_dev(struct domain_device *); |
642 | 648 | ||
649 | void sas_task_abort(struct sas_task *task); | ||
650 | |||
643 | #endif /* _SASLIB_H_ */ | 651 | #endif /* _SASLIB_H_ */ |
diff --git a/include/scsi/libsrp.h b/include/scsi/libsrp.h new file mode 100644 index 000000000000..d143171896ae --- /dev/null +++ b/include/scsi/libsrp.h | |||
@@ -0,0 +1,77 @@ | |||
1 | #ifndef __LIBSRP_H__ | ||
2 | #define __LIBSRP_H__ | ||
3 | |||
4 | #include <linux/list.h> | ||
5 | #include <scsi/scsi_cmnd.h> | ||
6 | #include <scsi/scsi_host.h> | ||
7 | #include <scsi/srp.h> | ||
8 | |||
9 | enum iue_flags { | ||
10 | V_DIOVER, | ||
11 | V_WRITE, | ||
12 | V_LINKED, | ||
13 | V_FLYING, | ||
14 | }; | ||
15 | |||
16 | struct srp_buf { | ||
17 | dma_addr_t dma; | ||
18 | void *buf; | ||
19 | }; | ||
20 | |||
21 | struct srp_queue { | ||
22 | void *pool; | ||
23 | void *items; | ||
24 | struct kfifo *queue; | ||
25 | spinlock_t lock; | ||
26 | }; | ||
27 | |||
28 | struct srp_target { | ||
29 | struct Scsi_Host *shost; | ||
30 | struct device *dev; | ||
31 | |||
32 | spinlock_t lock; | ||
33 | struct list_head cmd_queue; | ||
34 | |||
35 | size_t srp_iu_size; | ||
36 | struct srp_queue iu_queue; | ||
37 | size_t rx_ring_size; | ||
38 | struct srp_buf **rx_ring; | ||
39 | |||
40 | void *ldata; | ||
41 | }; | ||
42 | |||
43 | struct iu_entry { | ||
44 | struct srp_target *target; | ||
45 | |||
46 | struct list_head ilist; | ||
47 | dma_addr_t remote_token; | ||
48 | unsigned long flags; | ||
49 | |||
50 | struct srp_buf *sbuf; | ||
51 | }; | ||
52 | |||
53 | typedef int (srp_rdma_t)(struct scsi_cmnd *, struct scatterlist *, int, | ||
54 | struct srp_direct_buf *, int, | ||
55 | enum dma_data_direction, unsigned int); | ||
56 | extern int srp_target_alloc(struct srp_target *, struct device *, size_t, size_t); | ||
57 | extern void srp_target_free(struct srp_target *); | ||
58 | |||
59 | extern struct iu_entry *srp_iu_get(struct srp_target *); | ||
60 | extern void srp_iu_put(struct iu_entry *); | ||
61 | |||
62 | extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64); | ||
63 | extern int srp_transfer_data(struct scsi_cmnd *, struct srp_cmd *, | ||
64 | srp_rdma_t, int, int); | ||
65 | |||
66 | |||
67 | static inline struct srp_target *host_to_srp_target(struct Scsi_Host *host) | ||
68 | { | ||
69 | return (struct srp_target *) host->hostdata; | ||
70 | } | ||
71 | |||
72 | static inline int srp_cmd_direction(struct srp_cmd *cmd) | ||
73 | { | ||
74 | return (cmd->buf_fmt >> 4) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
75 | } | ||
76 | |||
77 | #endif | ||
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index be117f812deb..d6948d0e8cdb 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | struct request; | 9 | struct request; |
10 | struct scatterlist; | 10 | struct scatterlist; |
11 | struct Scsi_Host; | ||
11 | struct scsi_device; | 12 | struct scsi_device; |
12 | 13 | ||
13 | 14 | ||
@@ -72,6 +73,9 @@ struct scsi_cmnd { | |||
72 | unsigned short use_sg; /* Number of pieces of scatter-gather */ | 73 | unsigned short use_sg; /* Number of pieces of scatter-gather */ |
73 | unsigned short sglist_len; /* size of malloc'd scatter-gather list */ | 74 | unsigned short sglist_len; /* size of malloc'd scatter-gather list */ |
74 | 75 | ||
76 | /* offset in cmd we are at (for multi-transfer tgt cmds) */ | ||
77 | unsigned offset; | ||
78 | |||
75 | unsigned underflow; /* Return error if less than | 79 | unsigned underflow; /* Return error if less than |
76 | this amount is transferred */ | 80 | this amount is transferred */ |
77 | 81 | ||
@@ -119,7 +123,10 @@ struct scsi_cmnd { | |||
119 | }; | 123 | }; |
120 | 124 | ||
121 | extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); | 125 | extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); |
126 | extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t); | ||
122 | extern void scsi_put_command(struct scsi_cmnd *); | 127 | extern void scsi_put_command(struct scsi_cmnd *); |
128 | extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *, | ||
129 | struct device *); | ||
123 | extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); | 130 | extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); |
124 | extern void scsi_finish_command(struct scsi_cmnd *cmd); | 131 | extern void scsi_finish_command(struct scsi_cmnd *cmd); |
125 | extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd); | 132 | extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd); |
@@ -128,4 +135,7 @@ extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count, | |||
128 | size_t *offset, size_t *len); | 135 | size_t *offset, size_t *len); |
129 | extern void scsi_kunmap_atomic_sg(void *virt); | 136 | extern void scsi_kunmap_atomic_sg(void *virt); |
130 | 137 | ||
138 | extern struct scatterlist *scsi_alloc_sgtable(struct scsi_cmnd *, gfp_t); | ||
139 | extern void scsi_free_sgtable(struct scatterlist *, int); | ||
140 | |||
131 | #endif /* _SCSI_SCSI_CMND_H */ | 141 | #endif /* _SCSI_SCSI_CMND_H */ |
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index b401c82036be..ebf31b16dc49 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h | |||
@@ -223,13 +223,13 @@ extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *, | |||
223 | struct scsi_device *); | 223 | struct scsi_device *); |
224 | 224 | ||
225 | /** | 225 | /** |
226 | * shost_for_each_device - iterate over all devices of a host | 226 | * shost_for_each_device - iterate over all devices of a host |
227 | * @sdev: iterator | 227 | * @sdev: the &struct scsi_device to use as a cursor |
228 | * @host: host whiches devices we want to iterate over | 228 | * @shost: the &struct scsi_host to iterate over |
229 | * | 229 | * |
230 | * This traverses over each devices of @shost. The devices have | 230 | * Iterator that returns each device attached to @shost. This loop |
231 | * a reference that must be released by scsi_host_put when breaking | 231 | * takes a reference on each device and releases it at the end. If |
232 | * out of the loop. | 232 | * you break out of the loop, you must call scsi_device_put(sdev). |
233 | */ | 233 | */ |
234 | #define shost_for_each_device(sdev, shost) \ | 234 | #define shost_for_each_device(sdev, shost) \ |
235 | for ((sdev) = __scsi_iterate_devices((shost), NULL); \ | 235 | for ((sdev) = __scsi_iterate_devices((shost), NULL); \ |
@@ -237,17 +237,17 @@ extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *, | |||
237 | (sdev) = __scsi_iterate_devices((shost), (sdev))) | 237 | (sdev) = __scsi_iterate_devices((shost), (sdev))) |
238 | 238 | ||
239 | /** | 239 | /** |
240 | * __shost_for_each_device - iterate over all devices of a host (UNLOCKED) | 240 | * __shost_for_each_device - iterate over all devices of a host (UNLOCKED) |
241 | * @sdev: iterator | 241 | * @sdev: the &struct scsi_device to use as a cursor |
242 | * @host: host whiches devices we want to iterate over | 242 | * @shost: the &struct scsi_host to iterate over |
243 | * | 243 | * |
244 | * This traverses over each devices of @shost. It does _not_ take a | 244 | * Iterator that returns each device attached to @shost. It does _not_ |
245 | * reference on the scsi_device, thus it the whole loop must be protected | 245 | * take a reference on the scsi_device, so the whole loop must be |
246 | * by shost->host_lock. | 246 | * protected by shost->host_lock. |
247 | * | 247 | * |
248 | * Note: The only reason why drivers would want to use this is because | 248 | * Note: The only reason to use this is because you need to access the |
249 | * they're need to access the device list in irq context. Otherwise you | 249 | * device list in interrupt context. Otherwise you really want to use |
250 | * really want to use shost_for_each_device instead. | 250 | * shost_for_each_device instead. |
251 | */ | 251 | */ |
252 | #define __shost_for_each_device(sdev, shost) \ | 252 | #define __shost_for_each_device(sdev, shost) \ |
253 | list_for_each_entry((sdev), &((shost)->__devices), siblings) | 253 | list_for_each_entry((sdev), &((shost)->__devices), siblings) |
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 39c6f8cc20c3..7f1f411d07af 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/workqueue.h> | 7 | #include <linux/workqueue.h> |
8 | #include <linux/mutex.h> | 8 | #include <linux/mutex.h> |
9 | 9 | ||
10 | struct request_queue; | ||
10 | struct block_device; | 11 | struct block_device; |
11 | struct completion; | 12 | struct completion; |
12 | struct module; | 13 | struct module; |
@@ -124,6 +125,39 @@ struct scsi_host_template { | |||
124 | void (*done)(struct scsi_cmnd *)); | 125 | void (*done)(struct scsi_cmnd *)); |
125 | 126 | ||
126 | /* | 127 | /* |
128 | * The transfer functions are used to queue a scsi command to | ||
129 | * the LLD. When the driver is finished processing the command | ||
130 | * the done callback is invoked. | ||
131 | * | ||
132 | * return values: see queuecommand | ||
133 | * | ||
134 | * If the LLD accepts the cmd, it should set the result to an | ||
135 | * appropriate value when completed before calling the done function. | ||
136 | * | ||
137 | * STATUS: REQUIRED FOR TARGET DRIVERS | ||
138 | */ | ||
139 | /* TODO: rename */ | ||
140 | int (* transfer_response)(struct scsi_cmnd *, | ||
141 | void (*done)(struct scsi_cmnd *)); | ||
142 | /* | ||
143 | * This is called to inform the LLD to transfer cmd->request_bufflen | ||
144 | * bytes of the cmd at cmd->offset in the cmd. The cmd->use_sg | ||
145 | * speciefies the number of scatterlist entried in the command | ||
146 | * and cmd->request_buffer contains the scatterlist. | ||
147 | * | ||
148 | * If the command cannot be processed in one transfer_data call | ||
149 | * becuase a scatterlist within the LLD's limits cannot be | ||
150 | * created then transfer_data will be called multiple times. | ||
151 | * It is initially called from process context, and later | ||
152 | * calls are from the interrup context. | ||
153 | */ | ||
154 | int (* transfer_data)(struct scsi_cmnd *, | ||
155 | void (*done)(struct scsi_cmnd *)); | ||
156 | |||
157 | /* Used as callback for the completion of task management request. */ | ||
158 | int (* tsk_mgmt_response)(u64 mid, int result); | ||
159 | |||
160 | /* | ||
127 | * This is an error handling strategy routine. You don't need to | 161 | * This is an error handling strategy routine. You don't need to |
128 | * define one of these if you don't want to - there is a default | 162 | * define one of these if you don't want to - there is a default |
129 | * routine that is present that should work in most cases. For those | 163 | * routine that is present that should work in most cases. For those |
@@ -241,6 +275,24 @@ struct scsi_host_template { | |||
241 | void (* target_destroy)(struct scsi_target *); | 275 | void (* target_destroy)(struct scsi_target *); |
242 | 276 | ||
243 | /* | 277 | /* |
278 | * If a host has the ability to discover targets on its own instead | ||
279 | * of scanning the entire bus, it can fill in this function and | ||
280 | * call scsi_scan_host(). This function will be called periodically | ||
281 | * until it returns 1 with the scsi_host and the elapsed time of | ||
282 | * the scan in jiffies. | ||
283 | * | ||
284 | * Status: OPTIONAL | ||
285 | */ | ||
286 | int (* scan_finished)(struct Scsi_Host *, unsigned long); | ||
287 | |||
288 | /* | ||
289 | * If the host wants to be called before the scan starts, but | ||
290 | * after the midlayer has set up ready for the scan, it can fill | ||
291 | * in this function. | ||
292 | */ | ||
293 | void (* scan_start)(struct Scsi_Host *); | ||
294 | |||
295 | /* | ||
244 | * fill in this function to allow the queue depth of this host | 296 | * fill in this function to allow the queue depth of this host |
245 | * to be changeable (on a per device basis). returns either | 297 | * to be changeable (on a per device basis). returns either |
246 | * the current queue depth setting (may be different from what | 298 | * the current queue depth setting (may be different from what |
@@ -552,6 +604,9 @@ struct Scsi_Host { | |||
552 | /* task mgmt function in progress */ | 604 | /* task mgmt function in progress */ |
553 | unsigned tmf_in_progress:1; | 605 | unsigned tmf_in_progress:1; |
554 | 606 | ||
607 | /* Asynchronous scan in progress */ | ||
608 | unsigned async_scan:1; | ||
609 | |||
555 | /* | 610 | /* |
556 | * Optional work queue to be utilized by the transport | 611 | * Optional work queue to be utilized by the transport |
557 | */ | 612 | */ |
@@ -568,6 +623,12 @@ struct Scsi_Host { | |||
568 | */ | 623 | */ |
569 | unsigned int max_host_blocked; | 624 | unsigned int max_host_blocked; |
570 | 625 | ||
626 | /* | ||
627 | * q used for scsi_tgt msgs, async events or any other requests that | ||
628 | * need to be processed in userspace | ||
629 | */ | ||
630 | struct request_queue *uspace_req_q; | ||
631 | |||
571 | /* legacy crap */ | 632 | /* legacy crap */ |
572 | unsigned long base; | 633 | unsigned long base; |
573 | unsigned long io_port; | 634 | unsigned long io_port; |
@@ -648,11 +709,6 @@ extern const char *scsi_host_state_name(enum scsi_host_state); | |||
648 | 709 | ||
649 | extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *); | 710 | extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *); |
650 | 711 | ||
651 | static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock) | ||
652 | { | ||
653 | shost->host_lock = lock; | ||
654 | } | ||
655 | |||
656 | static inline struct device *scsi_get_device(struct Scsi_Host *shost) | 712 | static inline struct device *scsi_get_device(struct Scsi_Host *shost) |
657 | { | 713 | { |
658 | return shost->shost_gendev.parent; | 714 | return shost->shost_gendev.parent; |
@@ -671,6 +727,9 @@ extern void scsi_unblock_requests(struct Scsi_Host *); | |||
671 | extern void scsi_block_requests(struct Scsi_Host *); | 727 | extern void scsi_block_requests(struct Scsi_Host *); |
672 | 728 | ||
673 | struct class_container; | 729 | struct class_container; |
730 | |||
731 | extern struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, | ||
732 | void (*) (struct request_queue *)); | ||
674 | /* | 733 | /* |
675 | * These two functions are used to allocate and free a pseudo device | 734 | * These two functions are used to allocate and free a pseudo device |
676 | * which will connect to the host adapter itself rather than any | 735 | * which will connect to the host adapter itself rather than any |
diff --git a/include/scsi/scsi_tgt.h b/include/scsi/scsi_tgt.h new file mode 100644 index 000000000000..4f4427937af2 --- /dev/null +++ b/include/scsi/scsi_tgt.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * SCSI target definitions | ||
3 | */ | ||
4 | |||
5 | #include <linux/dma-mapping.h> | ||
6 | |||
7 | struct Scsi_Host; | ||
8 | struct scsi_cmnd; | ||
9 | struct scsi_lun; | ||
10 | |||
11 | extern struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *); | ||
12 | extern int scsi_tgt_alloc_queue(struct Scsi_Host *); | ||
13 | extern void scsi_tgt_free_queue(struct Scsi_Host *); | ||
14 | extern int scsi_tgt_queue_command(struct scsi_cmnd *, struct scsi_lun *, u64); | ||
15 | extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, int, u64, struct scsi_lun *, | ||
16 | void *); | ||
17 | extern struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *, | ||
18 | enum dma_data_direction, gfp_t); | ||
19 | extern void scsi_host_put_command(struct Scsi_Host *, struct scsi_cmnd *); | ||
diff --git a/include/scsi/scsi_tgt_if.h b/include/scsi/scsi_tgt_if.h new file mode 100644 index 000000000000..46d5e70d7215 --- /dev/null +++ b/include/scsi/scsi_tgt_if.h | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * SCSI target kernel/user interface | ||
3 | * | ||
4 | * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org> | ||
5 | * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of the | ||
10 | * License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | */ | ||
22 | #ifndef __SCSI_TARGET_IF_H | ||
23 | #define __SCSI_TARGET_IF_H | ||
24 | |||
25 | /* user -> kernel */ | ||
26 | #define TGT_UEVENT_CMD_RSP 0x0001 | ||
27 | #define TGT_UEVENT_TSK_MGMT_RSP 0x0002 | ||
28 | |||
29 | /* kernel -> user */ | ||
30 | #define TGT_KEVENT_CMD_REQ 0x1001 | ||
31 | #define TGT_KEVENT_CMD_DONE 0x1002 | ||
32 | #define TGT_KEVENT_TSK_MGMT_REQ 0x1003 | ||
33 | |||
34 | struct tgt_event_hdr { | ||
35 | uint16_t version; | ||
36 | uint16_t status; | ||
37 | uint16_t type; | ||
38 | uint16_t len; | ||
39 | } __attribute__ ((aligned (sizeof(uint64_t)))); | ||
40 | |||
41 | struct tgt_event { | ||
42 | struct tgt_event_hdr hdr; | ||
43 | |||
44 | union { | ||
45 | /* user-> kernel */ | ||
46 | struct { | ||
47 | int host_no; | ||
48 | uint32_t len; | ||
49 | int result; | ||
50 | aligned_u64 uaddr; | ||
51 | uint8_t rw; | ||
52 | aligned_u64 tag; | ||
53 | } cmd_rsp; | ||
54 | struct { | ||
55 | int host_no; | ||
56 | aligned_u64 mid; | ||
57 | int result; | ||
58 | } tsk_mgmt_rsp; | ||
59 | |||
60 | |||
61 | /* kernel -> user */ | ||
62 | struct { | ||
63 | int host_no; | ||
64 | uint32_t data_len; | ||
65 | uint8_t scb[16]; | ||
66 | uint8_t lun[8]; | ||
67 | int attribute; | ||
68 | aligned_u64 tag; | ||
69 | } cmd_req; | ||
70 | struct { | ||
71 | int host_no; | ||
72 | aligned_u64 tag; | ||
73 | int result; | ||
74 | } cmd_done; | ||
75 | struct { | ||
76 | int host_no; | ||
77 | int function; | ||
78 | aligned_u64 tag; | ||
79 | uint8_t lun[8]; | ||
80 | aligned_u64 mid; | ||
81 | } tsk_mgmt_req; | ||
82 | } p; | ||
83 | } __attribute__ ((aligned (sizeof(uint64_t)))); | ||
84 | |||
85 | #define TGT_RING_SIZE (1UL << 16) | ||
86 | #define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT) | ||
87 | #define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event)) | ||
88 | #define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES) | ||
89 | |||
90 | #endif | ||
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h index 53024377f3b8..59633a82de47 100644 --- a/include/scsi/scsi_transport_sas.h +++ b/include/scsi/scsi_transport_sas.h | |||
@@ -73,6 +73,8 @@ struct sas_phy { | |||
73 | 73 | ||
74 | /* for the list of phys belonging to a port */ | 74 | /* for the list of phys belonging to a port */ |
75 | struct list_head port_siblings; | 75 | struct list_head port_siblings; |
76 | |||
77 | struct work_struct reset_work; | ||
76 | }; | 78 | }; |
77 | 79 | ||
78 | #define dev_to_phy(d) \ | 80 | #define dev_to_phy(d) \ |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index fd3590fcaedb..2d40cc72f236 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c | |||
@@ -219,35 +219,15 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
219 | static int pdacf_config(struct pcmcia_device *link) | 219 | static int pdacf_config(struct pcmcia_device *link) |
220 | { | 220 | { |
221 | struct snd_pdacf *pdacf = link->priv; | 221 | struct snd_pdacf *pdacf = link->priv; |
222 | tuple_t tuple; | ||
223 | cisparse_t *parse = NULL; | ||
224 | u_short buf[32]; | ||
225 | int last_fn, last_ret; | 222 | int last_fn, last_ret; |
226 | 223 | ||
227 | snd_printdd(KERN_DEBUG "pdacf_config called\n"); | 224 | snd_printdd(KERN_DEBUG "pdacf_config called\n"); |
228 | parse = kmalloc(sizeof(*parse), GFP_KERNEL); | ||
229 | if (! parse) { | ||
230 | snd_printk(KERN_ERR "pdacf_config: cannot allocate\n"); | ||
231 | return -ENOMEM; | ||
232 | } | ||
233 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
234 | tuple.Attributes = 0; | ||
235 | tuple.TupleData = (cisdata_t *)buf; | ||
236 | tuple.TupleDataMax = sizeof(buf); | ||
237 | tuple.TupleOffset = 0; | ||
238 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
239 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
240 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
241 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse)); | ||
242 | link->conf.ConfigBase = parse->config.base; | ||
243 | link->conf.ConfigIndex = 0x5; | 225 | link->conf.ConfigIndex = 0x5; |
244 | 226 | ||
245 | CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); | 227 | CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); |
246 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); | 228 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
247 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); | 229 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
248 | 230 | ||
249 | kfree(parse); | ||
250 | |||
251 | if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0) | 231 | if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq.AssignedIRQ) < 0) |
252 | goto failed; | 232 | goto failed; |
253 | 233 | ||
@@ -255,7 +235,6 @@ static int pdacf_config(struct pcmcia_device *link) | |||
255 | return 0; | 235 | return 0; |
256 | 236 | ||
257 | cs_failed: | 237 | cs_failed: |
258 | kfree(parse); | ||
259 | cs_error(link, last_fn, last_ret); | 238 | cs_error(link, last_fn, last_ret); |
260 | failed: | 239 | failed: |
261 | pcmcia_disable_device(link); | 240 | pcmcia_disable_device(link); |
@@ -299,7 +278,8 @@ static int pdacf_resume(struct pcmcia_device *link) | |||
299 | * Module entry points | 278 | * Module entry points |
300 | */ | 279 | */ |
301 | static struct pcmcia_device_id snd_pdacf_ids[] = { | 280 | static struct pcmcia_device_id snd_pdacf_ids[] = { |
302 | PCMCIA_DEVICE_MANF_CARD(0x015d, 0x4c45), | 281 | /* this is too general PCMCIA_DEVICE_MANF_CARD(0x015d, 0x4c45), */ |
282 | PCMCIA_DEVICE_PROD_ID12("Core Sound","PDAudio-CF",0x396d19d2,0x71717b49), | ||
303 | PCMCIA_DEVICE_NULL | 283 | PCMCIA_DEVICE_NULL |
304 | }; | 284 | }; |
305 | MODULE_DEVICE_TABLE(pcmcia, snd_pdacf_ids); | 285 | MODULE_DEVICE_TABLE(pcmcia, snd_pdacf_ids); |
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 3089fcca800e..d7df59e9c647 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c | |||
@@ -217,34 +217,12 @@ static int vxpocket_config(struct pcmcia_device *link) | |||
217 | { | 217 | { |
218 | struct vx_core *chip = link->priv; | 218 | struct vx_core *chip = link->priv; |
219 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; | 219 | struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; |
220 | tuple_t tuple; | ||
221 | cisparse_t *parse; | ||
222 | u_short buf[32]; | ||
223 | int last_fn, last_ret; | 220 | int last_fn, last_ret; |
224 | 221 | ||
225 | snd_printdd(KERN_DEBUG "vxpocket_config called\n"); | 222 | snd_printdd(KERN_DEBUG "vxpocket_config called\n"); |
226 | parse = kmalloc(sizeof(*parse), GFP_KERNEL); | ||
227 | if (! parse) { | ||
228 | snd_printk(KERN_ERR "vx: cannot allocate\n"); | ||
229 | return -ENOMEM; | ||
230 | } | ||
231 | tuple.Attributes = 0; | ||
232 | tuple.TupleData = (cisdata_t *)buf; | ||
233 | tuple.TupleDataMax = sizeof(buf); | ||
234 | tuple.TupleOffset = 0; | ||
235 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
236 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
237 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
238 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse)); | ||
239 | link->conf.ConfigBase = parse->config.base; | ||
240 | link->conf.Present = parse->config.rmask[0]; | ||
241 | 223 | ||
242 | /* redefine hardware record according to the VERSION1 string */ | 224 | /* redefine hardware record according to the VERSION1 string */ |
243 | tuple.DesiredTuple = CISTPL_VERS_1; | 225 | if (!strcmp(link->prod_id[1], "VX-POCKET")) { |
244 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | ||
245 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | ||
246 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse)); | ||
247 | if (! strcmp(parse->version_1.str + parse->version_1.ofs[1], "VX-POCKET")) { | ||
248 | snd_printdd("VX-pocket is detected\n"); | 226 | snd_printdd("VX-pocket is detected\n"); |
249 | } else { | 227 | } else { |
250 | snd_printdd("VX-pocket 440 is detected\n"); | 228 | snd_printdd("VX-pocket 440 is detected\n"); |
@@ -265,14 +243,12 @@ static int vxpocket_config(struct pcmcia_device *link) | |||
265 | goto failed; | 243 | goto failed; |
266 | 244 | ||
267 | link->dev_node = &vxp->node; | 245 | link->dev_node = &vxp->node; |
268 | kfree(parse); | ||
269 | return 0; | 246 | return 0; |
270 | 247 | ||
271 | cs_failed: | 248 | cs_failed: |
272 | cs_error(link, last_fn, last_ret); | 249 | cs_error(link, last_fn, last_ret); |
273 | failed: | 250 | failed: |
274 | pcmcia_disable_device(link); | 251 | pcmcia_disable_device(link); |
275 | kfree(parse); | ||
276 | return -ENODEV; | 252 | return -ENODEV; |
277 | } | 253 | } |
278 | 254 | ||