diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-14 08:19:08 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-14 08:19:08 -0400 |
commit | 905ec87e93bc9e01b15c60035cd6a50c636cbaef (patch) | |
tree | 46fd7618d6511611ffc19eb0dd4d7bc6b90a41c2 /drivers/scsi | |
parent | 1d6ae775d7a948c9575658eb41184fd2e506c0df (diff) | |
parent | 2f4ba45a75d6383b4a1201169a808ffea416ffa0 (diff) |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/3w-9xxx.c | 30 | ||||
-rw-r--r-- | drivers/scsi/53c7xx.c | 4 | ||||
-rw-r--r-- | drivers/scsi/Kconfig | 7 | ||||
-rw-r--r-- | drivers/scsi/Makefile | 1 | ||||
-rw-r--r-- | drivers/scsi/ahci.c | 16 | ||||
-rw-r--r-- | drivers/scsi/ata_piix.c | 24 | ||||
-rw-r--r-- | drivers/scsi/ch.c | 29 | ||||
-rw-r--r-- | drivers/scsi/cpqfcTSinit.c | 3 | ||||
-rw-r--r-- | drivers/scsi/ibmmca.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 22 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 7 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hw.h | 17 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 7 | ||||
-rw-r--r-- | drivers/scsi/osst.c | 13 | ||||
-rw-r--r-- | drivers/scsi/pluto.c | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 18 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 4 | ||||
-rw-r--r-- | drivers/scsi/sata_mv.c | 16 | ||||
-rw-r--r-- | drivers/scsi/sata_sis.c | 96 | ||||
-rw-r--r-- | drivers/scsi/sata_uli.c | 14 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 138 | ||||
-rw-r--r-- | drivers/scsi/scsi_priv.h | 1 | ||||
-rw-r--r-- | drivers/scsi/scsi_scan.c | 88 | ||||
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 28 | ||||
-rw-r--r-- | drivers/scsi/scsi_transport_sas.c | 820 | ||||
-rw-r--r-- | drivers/scsi/sg.c | 4 |
27 files changed, 1159 insertions, 254 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index bc6e4627c7a1..a6ac61611f35 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c | |||
@@ -59,6 +59,7 @@ | |||
59 | Fix 'handled=1' ISR usage, remove bogus IRQ check. | 59 | Fix 'handled=1' ISR usage, remove bogus IRQ check. |
60 | Remove un-needed eh_abort handler. | 60 | Remove un-needed eh_abort handler. |
61 | Add support for embedded firmware error strings. | 61 | Add support for embedded firmware error strings. |
62 | 2.26.02.003 - Correctly handle single sgl's with use_sg=1. | ||
62 | */ | 63 | */ |
63 | 64 | ||
64 | #include <linux/module.h> | 65 | #include <linux/module.h> |
@@ -81,7 +82,7 @@ | |||
81 | #include "3w-9xxx.h" | 82 | #include "3w-9xxx.h" |
82 | 83 | ||
83 | /* Globals */ | 84 | /* Globals */ |
84 | #define TW_DRIVER_VERSION "2.26.02.002" | 85 | #define TW_DRIVER_VERSION "2.26.02.003" |
85 | static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; | 86 | static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; |
86 | static unsigned int twa_device_extension_count; | 87 | static unsigned int twa_device_extension_count; |
87 | static int twa_major = -1; | 88 | static int twa_major = -1; |
@@ -1805,6 +1806,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, | |||
1805 | if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) { | 1806 | if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) { |
1806 | command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id]; | 1807 | command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id]; |
1807 | command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH; | 1808 | command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH; |
1809 | if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) | ||
1810 | memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen); | ||
1808 | } else { | 1811 | } else { |
1809 | buffaddr = twa_map_scsi_single_data(tw_dev, request_id); | 1812 | buffaddr = twa_map_scsi_single_data(tw_dev, request_id); |
1810 | if (buffaddr == 0) | 1813 | if (buffaddr == 0) |
@@ -1823,6 +1826,12 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, | |||
1823 | 1826 | ||
1824 | if (tw_dev->srb[request_id]->use_sg > 0) { | 1827 | if (tw_dev->srb[request_id]->use_sg > 0) { |
1825 | if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) { | 1828 | if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) { |
1829 | if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) { | ||
1830 | struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; | ||
1831 | char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | ||
1832 | memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length); | ||
1833 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | ||
1834 | } | ||
1826 | command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id]; | 1835 | command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id]; |
1827 | command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH; | 1836 | command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH; |
1828 | } else { | 1837 | } else { |
@@ -1888,11 +1897,20 @@ out: | |||
1888 | /* This function completes an execute scsi operation */ | 1897 | /* This function completes an execute scsi operation */ |
1889 | static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id) | 1898 | static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id) |
1890 | { | 1899 | { |
1891 | /* Copy the response if too small */ | 1900 | if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH && |
1892 | if ((tw_dev->srb[request_id]->request_buffer) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) { | 1901 | (tw_dev->srb[request_id]->sc_data_direction == DMA_FROM_DEVICE || |
1893 | memcpy(tw_dev->srb[request_id]->request_buffer, | 1902 | tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)) { |
1894 | tw_dev->generic_buffer_virt[request_id], | 1903 | if (tw_dev->srb[request_id]->use_sg == 0) { |
1895 | tw_dev->srb[request_id]->request_bufflen); | 1904 | memcpy(tw_dev->srb[request_id]->request_buffer, |
1905 | tw_dev->generic_buffer_virt[request_id], | ||
1906 | tw_dev->srb[request_id]->request_bufflen); | ||
1907 | } | ||
1908 | if (tw_dev->srb[request_id]->use_sg == 1) { | ||
1909 | struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; | ||
1910 | char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | ||
1911 | memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length); | ||
1912 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | ||
1913 | } | ||
1896 | } | 1914 | } |
1897 | } /* End twa_scsiop_execute_scsi_complete() */ | 1915 | } /* End twa_scsiop_execute_scsi_complete() */ |
1898 | 1916 | ||
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c index 2341d27ceed7..7a33c708f5b3 100644 --- a/drivers/scsi/53c7xx.c +++ b/drivers/scsi/53c7xx.c | |||
@@ -6090,8 +6090,8 @@ NCR53c7x0_release(struct Scsi_Host *host) { | |||
6090 | if (hostdata->num_cmds) | 6090 | if (hostdata->num_cmds) |
6091 | printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n", | 6091 | printk ("scsi%d : leaked %d NCR53c7x0_cmd structures\n", |
6092 | host->host_no, hostdata->num_cmds); | 6092 | host->host_no, hostdata->num_cmds); |
6093 | if (hostdata->events) | 6093 | |
6094 | vfree ((void *)hostdata->events); | 6094 | vfree(hostdata->events); |
6095 | 6095 | ||
6096 | /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which | 6096 | /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING, which |
6097 | * XXX may be invalid (CONFIG_060_WRITETHROUGH) | 6097 | * XXX may be invalid (CONFIG_060_WRITETHROUGH) |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 10f3f4da68c5..be96cb78e3b5 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -235,6 +235,13 @@ config SCSI_ISCSI_ATTRS | |||
235 | each attached iSCSI device to sysfs, say Y. | 235 | each attached iSCSI device to sysfs, say Y. |
236 | Otherwise, say N. | 236 | Otherwise, say N. |
237 | 237 | ||
238 | config SCSI_SAS_ATTRS | ||
239 | tristate "SAS Transport Attributes" | ||
240 | depends on SCSI | ||
241 | help | ||
242 | If you wish to export transport-specific information about | ||
243 | each attached SAS device to sysfs, say Y. | ||
244 | |||
238 | endmenu | 245 | endmenu |
239 | 246 | ||
240 | menu "SCSI low-level drivers" | 247 | menu "SCSI low-level drivers" |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 370a560c6aef..1e491ae9a7c5 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -31,6 +31,7 @@ obj-$(CONFIG_RAID_ATTRS) += raid_class.o | |||
31 | obj-$(CONFIG_SCSI_SPI_ATTRS) += scsi_transport_spi.o | 31 | obj-$(CONFIG_SCSI_SPI_ATTRS) += scsi_transport_spi.o |
32 | obj-$(CONFIG_SCSI_FC_ATTRS) += scsi_transport_fc.o | 32 | obj-$(CONFIG_SCSI_FC_ATTRS) += scsi_transport_fc.o |
33 | obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o | 33 | obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o |
34 | obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o | ||
34 | 35 | ||
35 | obj-$(CONFIG_SCSI_AMIGA7XX) += amiga7xx.o 53c7xx.o | 36 | obj-$(CONFIG_SCSI_AMIGA7XX) += amiga7xx.o 53c7xx.o |
36 | obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o | 37 | obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o |
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 320df6cd3def..c2c8fa828e24 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c | |||
@@ -865,22 +865,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) | |||
865 | return 0; | 865 | return 0; |
866 | } | 866 | } |
867 | 867 | ||
868 | /* move to PCI layer, integrate w/ MSI stuff */ | ||
869 | static void pci_intx(struct pci_dev *pdev, int enable) | ||
870 | { | ||
871 | u16 pci_command, new; | ||
872 | |||
873 | pci_read_config_word(pdev, PCI_COMMAND, &pci_command); | ||
874 | |||
875 | if (enable) | ||
876 | new = pci_command & ~PCI_COMMAND_INTX_DISABLE; | ||
877 | else | ||
878 | new = pci_command | PCI_COMMAND_INTX_DISABLE; | ||
879 | |||
880 | if (new != pci_command) | ||
881 | pci_write_config_word(pdev, PCI_COMMAND, pci_command); | ||
882 | } | ||
883 | |||
884 | static void ahci_print_info(struct ata_probe_ent *probe_ent) | 868 | static void ahci_print_info(struct ata_probe_ent *probe_ent) |
885 | { | 869 | { |
886 | struct ahci_host_priv *hpriv = probe_ent->private_data; | 870 | struct ahci_host_priv *hpriv = probe_ent->private_data; |
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index deec0cef88d9..87e0c36f1554 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c | |||
@@ -68,8 +68,8 @@ enum { | |||
68 | PIIX_COMB_PATA_P0 = (1 << 1), | 68 | PIIX_COMB_PATA_P0 = (1 << 1), |
69 | PIIX_COMB = (1 << 2), /* combined mode enabled? */ | 69 | PIIX_COMB = (1 << 2), /* combined mode enabled? */ |
70 | 70 | ||
71 | PIIX_PORT_PRESENT = (1 << 0), | 71 | PIIX_PORT_ENABLED = (1 << 0), |
72 | PIIX_PORT_ENABLED = (1 << 4), | 72 | PIIX_PORT_PRESENT = (1 << 4), |
73 | 73 | ||
74 | PIIX_80C_PRI = (1 << 5) | (1 << 4), | 74 | PIIX_80C_PRI = (1 << 5) | (1 << 4), |
75 | PIIX_80C_SEC = (1 << 7) | (1 << 6), | 75 | PIIX_80C_SEC = (1 << 7) | (1 << 6), |
@@ -377,7 +377,9 @@ static void piix_pata_phy_reset(struct ata_port *ap) | |||
377 | * None (inherited from caller). | 377 | * None (inherited from caller). |
378 | * | 378 | * |
379 | * RETURNS: | 379 | * RETURNS: |
380 | * Non-zero if device detected, zero otherwise. | 380 | * Non-zero if port is enabled, it may or may not have a device |
381 | * attached in that case (PRESENT bit would only be set if BIOS probe | ||
382 | * was done). Zero is returned if port is disabled. | ||
381 | */ | 383 | */ |
382 | static int piix_sata_probe (struct ata_port *ap) | 384 | static int piix_sata_probe (struct ata_port *ap) |
383 | { | 385 | { |
@@ -401,7 +403,7 @@ static int piix_sata_probe (struct ata_port *ap) | |||
401 | */ | 403 | */ |
402 | 404 | ||
403 | for (i = 0; i < 4; i++) { | 405 | for (i = 0; i < 4; i++) { |
404 | mask = (PIIX_PORT_PRESENT << i) | (PIIX_PORT_ENABLED << i); | 406 | mask = (PIIX_PORT_ENABLED << i); |
405 | 407 | ||
406 | if ((orig_mask & mask) == mask) | 408 | if ((orig_mask & mask) == mask) |
407 | if (combined || (i == ap->hard_port_no)) | 409 | if (combined || (i == ap->hard_port_no)) |
@@ -566,18 +568,6 @@ static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev) | |||
566 | } | 568 | } |
567 | } | 569 | } |
568 | 570 | ||
569 | /* move to PCI layer, integrate w/ MSI stuff */ | ||
570 | static void pci_enable_intx(struct pci_dev *pdev) | ||
571 | { | ||
572 | u16 pci_command; | ||
573 | |||
574 | pci_read_config_word(pdev, PCI_COMMAND, &pci_command); | ||
575 | if (pci_command & PCI_COMMAND_INTX_DISABLE) { | ||
576 | pci_command &= ~PCI_COMMAND_INTX_DISABLE; | ||
577 | pci_write_config_word(pdev, PCI_COMMAND, pci_command); | ||
578 | } | ||
579 | } | ||
580 | |||
581 | #define AHCI_PCI_BAR 5 | 571 | #define AHCI_PCI_BAR 5 |
582 | #define AHCI_GLOBAL_CTL 0x04 | 572 | #define AHCI_GLOBAL_CTL 0x04 |
583 | #define AHCI_ENABLE (1 << 31) | 573 | #define AHCI_ENABLE (1 << 31) |
@@ -675,7 +665,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
675 | * message-signalled interrupts currently). | 665 | * message-signalled interrupts currently). |
676 | */ | 666 | */ |
677 | if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR) | 667 | if (port_info[0]->host_flags & PIIX_FLAG_CHECKINTR) |
678 | pci_enable_intx(pdev); | 668 | pci_intx(pdev, 1); |
679 | 669 | ||
680 | if (combined) { | 670 | if (combined) { |
681 | port_info[sata_chan] = &piix_port_info[ent->driver_data]; | 671 | port_info[sata_chan] = &piix_port_info[ent->driver_data]; |
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index bd0e1b6be1ea..da6e51c7fe69 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c | |||
@@ -116,7 +116,7 @@ typedef struct { | |||
116 | } scsi_changer; | 116 | } scsi_changer; |
117 | 117 | ||
118 | static LIST_HEAD(ch_devlist); | 118 | static LIST_HEAD(ch_devlist); |
119 | static spinlock_t ch_devlist_lock = SPIN_LOCK_UNLOCKED; | 119 | static DEFINE_SPINLOCK(ch_devlist_lock); |
120 | static int ch_devcount; | 120 | static int ch_devcount; |
121 | 121 | ||
122 | static struct scsi_driver ch_template = | 122 | static struct scsi_driver ch_template = |
@@ -560,7 +560,7 @@ ch_set_voltag(scsi_changer *ch, u_int elem, | |||
560 | return result; | 560 | return result; |
561 | } | 561 | } |
562 | 562 | ||
563 | static int ch_gstatus(scsi_changer *ch, int type, unsigned char *dest) | 563 | static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest) |
564 | { | 564 | { |
565 | int retval = 0; | 565 | int retval = 0; |
566 | u_char data[16]; | 566 | u_char data[16]; |
@@ -634,6 +634,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
634 | { | 634 | { |
635 | scsi_changer *ch = file->private_data; | 635 | scsi_changer *ch = file->private_data; |
636 | int retval; | 636 | int retval; |
637 | void __user *argp = (void __user *)arg; | ||
637 | 638 | ||
638 | switch (cmd) { | 639 | switch (cmd) { |
639 | case CHIOGPARAMS: | 640 | case CHIOGPARAMS: |
@@ -646,7 +647,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
646 | params.cp_nportals = ch->counts[CHET_IE]; | 647 | params.cp_nportals = ch->counts[CHET_IE]; |
647 | params.cp_ndrives = ch->counts[CHET_DT]; | 648 | params.cp_ndrives = ch->counts[CHET_DT]; |
648 | 649 | ||
649 | if (copy_to_user((void *) arg, ¶ms, sizeof(params))) | 650 | if (copy_to_user(argp, ¶ms, sizeof(params))) |
650 | return -EFAULT; | 651 | return -EFAULT; |
651 | return 0; | 652 | return 0; |
652 | } | 653 | } |
@@ -671,7 +672,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
671 | vparams.cvp_n4 = ch->counts[CHET_V4]; | 672 | vparams.cvp_n4 = ch->counts[CHET_V4]; |
672 | strncpy(vparams.cvp_label4,vendor_labels[3],16); | 673 | strncpy(vparams.cvp_label4,vendor_labels[3],16); |
673 | } | 674 | } |
674 | if (copy_to_user((void *) arg, &vparams, sizeof(vparams))) | 675 | if (copy_to_user(argp, &vparams, sizeof(vparams))) |
675 | return -EFAULT; | 676 | return -EFAULT; |
676 | return 0; | 677 | return 0; |
677 | } | 678 | } |
@@ -680,7 +681,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
680 | { | 681 | { |
681 | struct changer_position pos; | 682 | struct changer_position pos; |
682 | 683 | ||
683 | if (copy_from_user(&pos, (void*)arg, sizeof (pos))) | 684 | if (copy_from_user(&pos, argp, sizeof (pos))) |
684 | return -EFAULT; | 685 | return -EFAULT; |
685 | 686 | ||
686 | if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) { | 687 | if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) { |
@@ -699,7 +700,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
699 | { | 700 | { |
700 | struct changer_move mv; | 701 | struct changer_move mv; |
701 | 702 | ||
702 | if (copy_from_user(&mv, (void*)arg, sizeof (mv))) | 703 | if (copy_from_user(&mv, argp, sizeof (mv))) |
703 | return -EFAULT; | 704 | return -EFAULT; |
704 | 705 | ||
705 | if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) || | 706 | if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) || |
@@ -721,7 +722,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
721 | { | 722 | { |
722 | struct changer_exchange mv; | 723 | struct changer_exchange mv; |
723 | 724 | ||
724 | if (copy_from_user(&mv, (void*)arg, sizeof (mv))) | 725 | if (copy_from_user(&mv, argp, sizeof (mv))) |
725 | return -EFAULT; | 726 | return -EFAULT; |
726 | 727 | ||
727 | if (0 != ch_checkrange(ch, mv.ce_srctype, mv.ce_srcunit ) || | 728 | if (0 != ch_checkrange(ch, mv.ce_srctype, mv.ce_srcunit ) || |
@@ -746,7 +747,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
746 | { | 747 | { |
747 | struct changer_element_status ces; | 748 | struct changer_element_status ces; |
748 | 749 | ||
749 | if (copy_from_user(&ces, (void*)arg, sizeof (ces))) | 750 | if (copy_from_user(&ces, argp, sizeof (ces))) |
750 | return -EFAULT; | 751 | return -EFAULT; |
751 | if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES) | 752 | if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES) |
752 | return -EINVAL; | 753 | return -EINVAL; |
@@ -762,7 +763,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
762 | unsigned int elem; | 763 | unsigned int elem; |
763 | int result,i; | 764 | int result,i; |
764 | 765 | ||
765 | if (copy_from_user(&cge, (void*)arg, sizeof (cge))) | 766 | if (copy_from_user(&cge, argp, sizeof (cge))) |
766 | return -EFAULT; | 767 | return -EFAULT; |
767 | 768 | ||
768 | if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit)) | 769 | if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit)) |
@@ -825,7 +826,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
825 | kfree(buffer); | 826 | kfree(buffer); |
826 | up(&ch->lock); | 827 | up(&ch->lock); |
827 | 828 | ||
828 | if (copy_to_user((void*)arg, &cge, sizeof (cge))) | 829 | if (copy_to_user(argp, &cge, sizeof (cge))) |
829 | return -EFAULT; | 830 | return -EFAULT; |
830 | return result; | 831 | return result; |
831 | } | 832 | } |
@@ -843,7 +844,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
843 | struct changer_set_voltag csv; | 844 | struct changer_set_voltag csv; |
844 | int elem; | 845 | int elem; |
845 | 846 | ||
846 | if (copy_from_user(&csv, (void*)arg, sizeof(csv))) | 847 | if (copy_from_user(&csv, argp, sizeof(csv))) |
847 | return -EFAULT; | 848 | return -EFAULT; |
848 | 849 | ||
849 | if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) { | 850 | if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) { |
@@ -861,7 +862,7 @@ static int ch_ioctl(struct inode * inode, struct file * file, | |||
861 | } | 862 | } |
862 | 863 | ||
863 | default: | 864 | default: |
864 | return scsi_ioctl(ch->device, cmd, (void*)arg); | 865 | return scsi_ioctl(ch->device, cmd, argp); |
865 | 866 | ||
866 | } | 867 | } |
867 | } | 868 | } |
@@ -894,9 +895,9 @@ static long ch_ioctl_compat(struct file * file, | |||
894 | case CHIOGSTATUS32: | 895 | case CHIOGSTATUS32: |
895 | { | 896 | { |
896 | struct changer_element_status32 ces32; | 897 | struct changer_element_status32 ces32; |
897 | unsigned char *data; | 898 | unsigned char __user *data; |
898 | 899 | ||
899 | if (copy_from_user(&ces32, (void*)arg, sizeof (ces32))) | 900 | if (copy_from_user(&ces32, (void __user *)arg, sizeof (ces32))) |
900 | return -EFAULT; | 901 | return -EFAULT; |
901 | if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES) | 902 | if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES) |
902 | return -EINVAL; | 903 | return -EINVAL; |
diff --git a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c index d72be0ce89c8..3fda8d455c5b 100644 --- a/drivers/scsi/cpqfcTSinit.c +++ b/drivers/scsi/cpqfcTSinit.c | |||
@@ -691,8 +691,7 @@ int cpqfcTS_ioctl( struct scsi_device *ScsiDev, int Cmnd, void *arg) | |||
691 | if( copy_to_user( vendor_cmd->bufp, buf, vendor_cmd->len)) | 691 | if( copy_to_user( vendor_cmd->bufp, buf, vendor_cmd->len)) |
692 | result = -EFAULT; | 692 | result = -EFAULT; |
693 | 693 | ||
694 | if( buf) | 694 | kfree(buf); |
695 | kfree( buf); | ||
696 | 695 | ||
697 | return result; | 696 | return result; |
698 | } | 697 | } |
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index b5dc35355570..6e54c7d9b33c 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/proc_fs.h> | 36 | #include <linux/proc_fs.h> |
37 | #include <linux/stat.h> | 37 | #include <linux/stat.h> |
38 | #include <linux/mca.h> | 38 | #include <linux/mca.h> |
39 | #include <linux/string.h> | ||
40 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
41 | #include <linux/init.h> | 40 | #include <linux/init.h> |
42 | #include <linux/mca-legacy.h> | 41 | #include <linux/mca-legacy.h> |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 0e089a42c03a..86eaf6d408d5 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -966,21 +966,21 @@ static void | |||
966 | lpfc_get_host_fabric_name (struct Scsi_Host *shost) | 966 | lpfc_get_host_fabric_name (struct Scsi_Host *shost) |
967 | { | 967 | { |
968 | struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; | 968 | struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0]; |
969 | u64 nodename; | 969 | u64 node_name; |
970 | 970 | ||
971 | spin_lock_irq(shost->host_lock); | 971 | spin_lock_irq(shost->host_lock); |
972 | 972 | ||
973 | if ((phba->fc_flag & FC_FABRIC) || | 973 | if ((phba->fc_flag & FC_FABRIC) || |
974 | ((phba->fc_topology == TOPOLOGY_LOOP) && | 974 | ((phba->fc_topology == TOPOLOGY_LOOP) && |
975 | (phba->fc_flag & FC_PUBLIC_LOOP))) | 975 | (phba->fc_flag & FC_PUBLIC_LOOP))) |
976 | memcpy(&nodename, &phba->fc_fabparam.nodeName, sizeof(u64)); | 976 | node_name = wwn_to_u64(phba->fc_fabparam.nodeName.wwn); |
977 | else | 977 | else |
978 | /* fabric is local port if there is no F/FL_Port */ | 978 | /* fabric is local port if there is no F/FL_Port */ |
979 | memcpy(&nodename, &phba->fc_nodename, sizeof(u64)); | 979 | node_name = wwn_to_u64(phba->fc_nodename.wwn); |
980 | 980 | ||
981 | spin_unlock_irq(shost->host_lock); | 981 | spin_unlock_irq(shost->host_lock); |
982 | 982 | ||
983 | fc_host_fabric_name(shost) = be64_to_cpu(nodename); | 983 | fc_host_fabric_name(shost) = node_name; |
984 | } | 984 | } |
985 | 985 | ||
986 | 986 | ||
@@ -1103,21 +1103,20 @@ lpfc_get_starget_node_name(struct scsi_target *starget) | |||
1103 | { | 1103 | { |
1104 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 1104 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
1105 | struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0]; | 1105 | struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0]; |
1106 | uint64_t node_name = 0; | 1106 | u64 node_name = 0; |
1107 | struct lpfc_nodelist *ndlp = NULL; | 1107 | struct lpfc_nodelist *ndlp = NULL; |
1108 | 1108 | ||
1109 | spin_lock_irq(shost->host_lock); | 1109 | spin_lock_irq(shost->host_lock); |
1110 | /* Search the mapped list for this target ID */ | 1110 | /* Search the mapped list for this target ID */ |
1111 | list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { | 1111 | list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { |
1112 | if (starget->id == ndlp->nlp_sid) { | 1112 | if (starget->id == ndlp->nlp_sid) { |
1113 | memcpy(&node_name, &ndlp->nlp_nodename, | 1113 | node_name = wwn_to_u64(ndlp->nlp_nodename.wwn); |
1114 | sizeof(struct lpfc_name)); | ||
1115 | break; | 1114 | break; |
1116 | } | 1115 | } |
1117 | } | 1116 | } |
1118 | spin_unlock_irq(shost->host_lock); | 1117 | spin_unlock_irq(shost->host_lock); |
1119 | 1118 | ||
1120 | fc_starget_node_name(starget) = be64_to_cpu(node_name); | 1119 | fc_starget_node_name(starget) = node_name; |
1121 | } | 1120 | } |
1122 | 1121 | ||
1123 | static void | 1122 | static void |
@@ -1125,21 +1124,20 @@ lpfc_get_starget_port_name(struct scsi_target *starget) | |||
1125 | { | 1124 | { |
1126 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 1125 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
1127 | struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0]; | 1126 | struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0]; |
1128 | uint64_t port_name = 0; | 1127 | u64 port_name = 0; |
1129 | struct lpfc_nodelist *ndlp = NULL; | 1128 | struct lpfc_nodelist *ndlp = NULL; |
1130 | 1129 | ||
1131 | spin_lock_irq(shost->host_lock); | 1130 | spin_lock_irq(shost->host_lock); |
1132 | /* Search the mapped list for this target ID */ | 1131 | /* Search the mapped list for this target ID */ |
1133 | list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { | 1132 | list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) { |
1134 | if (starget->id == ndlp->nlp_sid) { | 1133 | if (starget->id == ndlp->nlp_sid) { |
1135 | memcpy(&port_name, &ndlp->nlp_portname, | 1134 | port_name = wwn_to_u64(ndlp->nlp_portname.wwn); |
1136 | sizeof(struct lpfc_name)); | ||
1137 | break; | 1135 | break; |
1138 | } | 1136 | } |
1139 | } | 1137 | } |
1140 | spin_unlock_irq(shost->host_lock); | 1138 | spin_unlock_irq(shost->host_lock); |
1141 | 1139 | ||
1142 | fc_starget_port_name(starget) = be64_to_cpu(port_name); | 1140 | fc_starget_port_name(starget) = port_name; |
1143 | } | 1141 | } |
1144 | 1142 | ||
1145 | static void | 1143 | static void |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 0a8269d6b130..4fb8eb0c84cf 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -1017,13 +1017,10 @@ lpfc_register_remote_port(struct lpfc_hba * phba, | |||
1017 | struct fc_rport *rport; | 1017 | struct fc_rport *rport; |
1018 | struct lpfc_rport_data *rdata; | 1018 | struct lpfc_rport_data *rdata; |
1019 | struct fc_rport_identifiers rport_ids; | 1019 | struct fc_rport_identifiers rport_ids; |
1020 | uint64_t wwn; | ||
1021 | 1020 | ||
1022 | /* Remote port has reappeared. Re-register w/ FC transport */ | 1021 | /* Remote port has reappeared. Re-register w/ FC transport */ |
1023 | memcpy(&wwn, &ndlp->nlp_nodename, sizeof(uint64_t)); | 1022 | rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.wwn); |
1024 | rport_ids.node_name = be64_to_cpu(wwn); | 1023 | rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.wwn); |
1025 | memcpy(&wwn, &ndlp->nlp_portname, sizeof(uint64_t)); | ||
1026 | rport_ids.port_name = be64_to_cpu(wwn); | ||
1027 | rport_ids.port_id = ndlp->nlp_DID; | 1024 | rport_ids.port_id = ndlp->nlp_DID; |
1028 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; | 1025 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; |
1029 | if (ndlp->nlp_type & NLP_FCP_TARGET) | 1026 | if (ndlp->nlp_type & NLP_FCP_TARGET) |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 21591cb9f551..047a87c26cc0 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -262,12 +262,14 @@ struct lpfc_sli_ct_request { | |||
262 | #define FF_FRAME_SIZE 2048 | 262 | #define FF_FRAME_SIZE 2048 |
263 | 263 | ||
264 | struct lpfc_name { | 264 | struct lpfc_name { |
265 | union { | ||
266 | struct { | ||
265 | #ifdef __BIG_ENDIAN_BITFIELD | 267 | #ifdef __BIG_ENDIAN_BITFIELD |
266 | uint8_t nameType:4; /* FC Word 0, bit 28:31 */ | 268 | uint8_t nameType:4; /* FC Word 0, bit 28:31 */ |
267 | uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */ | 269 | uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */ |
268 | #else /* __LITTLE_ENDIAN_BITFIELD */ | 270 | #else /* __LITTLE_ENDIAN_BITFIELD */ |
269 | uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */ | 271 | uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */ |
270 | uint8_t nameType:4; /* FC Word 0, bit 28:31 */ | 272 | uint8_t nameType:4; /* FC Word 0, bit 28:31 */ |
271 | #endif | 273 | #endif |
272 | 274 | ||
273 | #define NAME_IEEE 0x1 /* IEEE name - nameType */ | 275 | #define NAME_IEEE 0x1 /* IEEE name - nameType */ |
@@ -276,8 +278,11 @@ struct lpfc_name { | |||
276 | #define NAME_IP_TYPE 0x4 /* IP address */ | 278 | #define NAME_IP_TYPE 0x4 /* IP address */ |
277 | #define NAME_CCITT_TYPE 0xC | 279 | #define NAME_CCITT_TYPE 0xC |
278 | #define NAME_CCITT_GR_TYPE 0xE | 280 | #define NAME_CCITT_GR_TYPE 0xE |
279 | uint8_t IEEEextLsb; /* FC Word 0, bit 16:23, IEEE extended Lsb */ | 281 | uint8_t IEEEextLsb; /* FC Word 0, bit 16:23, IEEE extended Lsb */ |
280 | uint8_t IEEE[6]; /* FC IEEE address */ | 282 | uint8_t IEEE[6]; /* FC IEEE address */ |
283 | }; | ||
284 | uint8_t wwn[8]; | ||
285 | }; | ||
281 | }; | 286 | }; |
282 | 287 | ||
283 | struct csp { | 288 | struct csp { |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 6f3cb59bf9e0..454058f655db 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -1333,7 +1333,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1333 | unsigned long bar0map_len, bar2map_len; | 1333 | unsigned long bar0map_len, bar2map_len; |
1334 | int error = -ENODEV, retval; | 1334 | int error = -ENODEV, retval; |
1335 | int i; | 1335 | int i; |
1336 | u64 wwname; | ||
1337 | 1336 | ||
1338 | if (pci_enable_device(pdev)) | 1337 | if (pci_enable_device(pdev)) |
1339 | goto out; | 1338 | goto out; |
@@ -1524,10 +1523,8 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
1524 | * Must done after lpfc_sli_hba_setup() | 1523 | * Must done after lpfc_sli_hba_setup() |
1525 | */ | 1524 | */ |
1526 | 1525 | ||
1527 | memcpy(&wwname, &phba->fc_nodename, sizeof(u64)); | 1526 | fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.wwn); |
1528 | fc_host_node_name(host) = be64_to_cpu(wwname); | 1527 | fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.wwn); |
1529 | memcpy(&wwname, &phba->fc_portname, sizeof(u64)); | ||
1530 | fc_host_port_name(host) = be64_to_cpu(wwname); | ||
1531 | fc_host_supported_classes(host) = FC_COS_CLASS3; | 1528 | fc_host_supported_classes(host) = FC_COS_CLASS3; |
1532 | 1529 | ||
1533 | memset(fc_host_supported_fc4s(host), 0, | 1530 | memset(fc_host_supported_fc4s(host), 0, |
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 89a4a0615c22..3f2f2464fa63 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c | |||
@@ -1377,7 +1377,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi | |||
1377 | 1377 | ||
1378 | if ((STp->buffer)->syscall_result || !SRpnt) { | 1378 | if ((STp->buffer)->syscall_result || !SRpnt) { |
1379 | printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name); | 1379 | printk(KERN_ERR "%s:E: Failed to read frame back from OnStream buffer\n", name); |
1380 | vfree((void *)buffer); | 1380 | vfree(buffer); |
1381 | *aSRpnt = SRpnt; | 1381 | *aSRpnt = SRpnt; |
1382 | return (-EIO); | 1382 | return (-EIO); |
1383 | } | 1383 | } |
@@ -1419,7 +1419,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi | |||
1419 | 1419 | ||
1420 | if (new_frame > frame + 1000) { | 1420 | if (new_frame > frame + 1000) { |
1421 | printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name); | 1421 | printk(KERN_ERR "%s:E: Failed to find writable tape media\n", name); |
1422 | vfree((void *)buffer); | 1422 | vfree(buffer); |
1423 | return (-EIO); | 1423 | return (-EIO); |
1424 | } | 1424 | } |
1425 | if ( i >= nframes + pending ) break; | 1425 | if ( i >= nframes + pending ) break; |
@@ -1500,7 +1500,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi | |||
1500 | SRpnt->sr_sense_buffer[12] == 0 && | 1500 | SRpnt->sr_sense_buffer[12] == 0 && |
1501 | SRpnt->sr_sense_buffer[13] == 2) { | 1501 | SRpnt->sr_sense_buffer[13] == 2) { |
1502 | printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name); | 1502 | printk(KERN_ERR "%s:E: Volume overflow in write error recovery\n", name); |
1503 | vfree((void *)buffer); | 1503 | vfree(buffer); |
1504 | return (-EIO); /* hit end of tape = fail */ | 1504 | return (-EIO); /* hit end of tape = fail */ |
1505 | } | 1505 | } |
1506 | i = ((SRpnt->sr_sense_buffer[3] << 24) | | 1506 | i = ((SRpnt->sr_sense_buffer[3] << 24) | |
@@ -1525,7 +1525,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct scsi | |||
1525 | } | 1525 | } |
1526 | if (!pending) | 1526 | if (!pending) |
1527 | osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */ | 1527 | osst_copy_to_buffer(STp->buffer, p); /* so buffer content == at entry in all cases */ |
1528 | vfree((void *)buffer); | 1528 | vfree(buffer); |
1529 | return 0; | 1529 | return 0; |
1530 | } | 1530 | } |
1531 | 1531 | ||
@@ -5852,7 +5852,7 @@ static int osst_remove(struct device *dev) | |||
5852 | os_scsi_tapes[i] = NULL; | 5852 | os_scsi_tapes[i] = NULL; |
5853 | osst_nr_dev--; | 5853 | osst_nr_dev--; |
5854 | write_unlock(&os_scsi_tapes_lock); | 5854 | write_unlock(&os_scsi_tapes_lock); |
5855 | if (tpnt->header_cache != NULL) vfree(tpnt->header_cache); | 5855 | vfree(tpnt->header_cache); |
5856 | if (tpnt->buffer) { | 5856 | if (tpnt->buffer) { |
5857 | normalize_buffer(tpnt->buffer); | 5857 | normalize_buffer(tpnt->buffer); |
5858 | kfree(tpnt->buffer); | 5858 | kfree(tpnt->buffer); |
@@ -5896,8 +5896,7 @@ static void __exit exit_osst (void) | |||
5896 | for (i=0; i < osst_max_dev; ++i) { | 5896 | for (i=0; i < osst_max_dev; ++i) { |
5897 | if (!(STp = os_scsi_tapes[i])) continue; | 5897 | if (!(STp = os_scsi_tapes[i])) continue; |
5898 | /* This is defensive, supposed to happen during detach */ | 5898 | /* This is defensive, supposed to happen during detach */ |
5899 | if (STp->header_cache) | 5899 | vfree(STp->header_cache); |
5900 | vfree(STp->header_cache); | ||
5901 | if (STp->buffer) { | 5900 | if (STp->buffer) { |
5902 | normalize_buffer(STp->buffer); | 5901 | normalize_buffer(STp->buffer); |
5903 | kfree(STp->buffer); | 5902 | kfree(STp->buffer); |
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c index 623082d3a83f..c89da7d5b6df 100644 --- a/drivers/scsi/pluto.c +++ b/drivers/scsi/pluto.c | |||
@@ -95,8 +95,7 @@ int __init pluto_detect(Scsi_Host_Template *tpnt) | |||
95 | int i, retry, nplutos; | 95 | int i, retry, nplutos; |
96 | fc_channel *fc; | 96 | fc_channel *fc; |
97 | Scsi_Device dev; | 97 | Scsi_Device dev; |
98 | struct timer_list fc_timer = | 98 | DEFINE_TIMER(fc_timer, pluto_detect_timeout, 0, 0); |
99 | TIMER_INITIALIZER(pluto_detect_timeout, 0, 0); | ||
100 | 99 | ||
101 | tpnt->proc_name = "pluto"; | 100 | tpnt->proc_name = "pluto"; |
102 | fcscount = 0; | 101 | fcscount = 0; |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index fe0fce71adc7..fc25cd834668 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -360,16 +360,16 @@ qla2x00_get_starget_node_name(struct scsi_target *starget) | |||
360 | struct Scsi_Host *host = dev_to_shost(starget->dev.parent); | 360 | struct Scsi_Host *host = dev_to_shost(starget->dev.parent); |
361 | scsi_qla_host_t *ha = to_qla_host(host); | 361 | scsi_qla_host_t *ha = to_qla_host(host); |
362 | fc_port_t *fcport; | 362 | fc_port_t *fcport; |
363 | uint64_t node_name = 0; | 363 | u64 node_name = 0; |
364 | 364 | ||
365 | list_for_each_entry(fcport, &ha->fcports, list) { | 365 | list_for_each_entry(fcport, &ha->fcports, list) { |
366 | if (starget->id == fcport->os_target_id) { | 366 | if (starget->id == fcport->os_target_id) { |
367 | node_name = *(uint64_t *)fcport->node_name; | 367 | node_name = wwn_to_u64(fcport->node_name); |
368 | break; | 368 | break; |
369 | } | 369 | } |
370 | } | 370 | } |
371 | 371 | ||
372 | fc_starget_node_name(starget) = be64_to_cpu(node_name); | 372 | fc_starget_node_name(starget) = node_name; |
373 | } | 373 | } |
374 | 374 | ||
375 | static void | 375 | static void |
@@ -378,16 +378,16 @@ qla2x00_get_starget_port_name(struct scsi_target *starget) | |||
378 | struct Scsi_Host *host = dev_to_shost(starget->dev.parent); | 378 | struct Scsi_Host *host = dev_to_shost(starget->dev.parent); |
379 | scsi_qla_host_t *ha = to_qla_host(host); | 379 | scsi_qla_host_t *ha = to_qla_host(host); |
380 | fc_port_t *fcport; | 380 | fc_port_t *fcport; |
381 | uint64_t port_name = 0; | 381 | u64 port_name = 0; |
382 | 382 | ||
383 | list_for_each_entry(fcport, &ha->fcports, list) { | 383 | list_for_each_entry(fcport, &ha->fcports, list) { |
384 | if (starget->id == fcport->os_target_id) { | 384 | if (starget->id == fcport->os_target_id) { |
385 | port_name = *(uint64_t *)fcport->port_name; | 385 | port_name = wwn_to_u64(fcport->port_name); |
386 | break; | 386 | break; |
387 | } | 387 | } |
388 | } | 388 | } |
389 | 389 | ||
390 | fc_starget_port_name(starget) = be64_to_cpu(port_name); | 390 | fc_starget_port_name(starget) = port_name; |
391 | } | 391 | } |
392 | 392 | ||
393 | static void | 393 | static void |
@@ -460,9 +460,7 @@ struct fc_function_template qla2xxx_transport_functions = { | |||
460 | void | 460 | void |
461 | qla2x00_init_host_attr(scsi_qla_host_t *ha) | 461 | qla2x00_init_host_attr(scsi_qla_host_t *ha) |
462 | { | 462 | { |
463 | fc_host_node_name(ha->host) = | 463 | fc_host_node_name(ha->host) = wwn_to_u64(ha->init_cb->node_name); |
464 | be64_to_cpu(*(uint64_t *)ha->init_cb->node_name); | 464 | fc_host_port_name(ha->host) = wwn_to_u64(ha->init_cb->port_name); |
465 | fc_host_port_name(ha->host) = | ||
466 | be64_to_cpu(*(uint64_t *)ha->init_cb->port_name); | ||
467 | fc_host_supported_classes(ha->host) = FC_COS_CLASS3; | 465 | fc_host_supported_classes(ha->host) = FC_COS_CLASS3; |
468 | } | 466 | } |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 72bbaa91dc77..9791496fa788 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
@@ -1334,7 +1334,7 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) | |||
1334 | 1334 | ||
1335 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | 1335 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); |
1336 | WRT_REG_DWORD(dmp_reg, 0xB0200000); | 1336 | WRT_REG_DWORD(dmp_reg, 0xB0200000); |
1337 | dmp_reg = (uint32_t *)((uint8_t *)reg + 0xFC); | 1337 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xFC); |
1338 | fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg); | 1338 | fw->shadow_reg[2] = RD_REG_DWORD(dmp_reg); |
1339 | 1339 | ||
1340 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); | 1340 | dmp_reg = (uint32_t __iomem *)((uint8_t __iomem *)reg + 0xF0); |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index c619583e646b..3e9b64137873 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -2066,8 +2066,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport) | |||
2066 | return; | 2066 | return; |
2067 | } | 2067 | } |
2068 | 2068 | ||
2069 | rport_ids.node_name = be64_to_cpu(*(uint64_t *)fcport->node_name); | 2069 | rport_ids.node_name = wwn_to_u64(fcport->node_name); |
2070 | rport_ids.port_name = be64_to_cpu(*(uint64_t *)fcport->port_name); | 2070 | rport_ids.port_name = wwn_to_u64(fcport->port_name); |
2071 | rport_ids.port_id = fcport->d_id.b.domain << 16 | | 2071 | rport_ids.port_id = fcport->d_id.b.domain << 16 | |
2072 | fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; | 2072 | fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; |
2073 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; | 2073 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; |
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index f97e3afa97d9..ea76fe44585e 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c | |||
@@ -699,22 +699,6 @@ static int mv_host_init(struct ata_probe_ent *probe_ent) | |||
699 | return rc; | 699 | return rc; |
700 | } | 700 | } |
701 | 701 | ||
702 | /* move to PCI layer, integrate w/ MSI stuff */ | ||
703 | static void pci_intx(struct pci_dev *pdev, int enable) | ||
704 | { | ||
705 | u16 pci_command, new; | ||
706 | |||
707 | pci_read_config_word(pdev, PCI_COMMAND, &pci_command); | ||
708 | |||
709 | if (enable) | ||
710 | new = pci_command & ~PCI_COMMAND_INTX_DISABLE; | ||
711 | else | ||
712 | new = pci_command | PCI_COMMAND_INTX_DISABLE; | ||
713 | |||
714 | if (new != pci_command) | ||
715 | pci_write_config_word(pdev, PCI_COMMAND, pci_command); | ||
716 | } | ||
717 | |||
718 | static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 702 | static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
719 | { | 703 | { |
720 | static int printed_version = 0; | 704 | static int printed_version = 0; |
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 43af445b3ad2..a63f93186e41 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c | |||
@@ -52,7 +52,10 @@ enum { | |||
52 | /* PCI configuration registers */ | 52 | /* PCI configuration registers */ |
53 | SIS_GENCTL = 0x54, /* IDE General Control register */ | 53 | SIS_GENCTL = 0x54, /* IDE General Control register */ |
54 | SIS_SCR_BASE = 0xc0, /* sata0 phy SCR registers */ | 54 | SIS_SCR_BASE = 0xc0, /* sata0 phy SCR registers */ |
55 | SIS_SATA1_OFS = 0x10, /* offset from sata0->sata1 phy regs */ | 55 | SIS180_SATA1_OFS = 0x10, /* offset from sata0->sata1 phy regs */ |
56 | SIS182_SATA1_OFS = 0x20, /* offset from sata0->sata1 phy regs */ | ||
57 | SIS_PMR = 0x90, /* port mapping register */ | ||
58 | SIS_PMR_COMBINED = 0x30, | ||
56 | 59 | ||
57 | /* random bits */ | 60 | /* random bits */ |
58 | SIS_FLAG_CFGSCR = (1 << 30), /* host flag: SCRs via PCI cfg */ | 61 | SIS_FLAG_CFGSCR = (1 << 30), /* host flag: SCRs via PCI cfg */ |
@@ -67,6 +70,7 @@ static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); | |||
67 | static struct pci_device_id sis_pci_tbl[] = { | 70 | static struct pci_device_id sis_pci_tbl[] = { |
68 | { PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, | 71 | { PCI_VENDOR_ID_SI, 0x180, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, |
69 | { PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, | 72 | { PCI_VENDOR_ID_SI, 0x181, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, |
73 | { PCI_VENDOR_ID_SI, 0x182, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sis_180 }, | ||
70 | { } /* terminate list */ | 74 | { } /* terminate list */ |
71 | }; | 75 | }; |
72 | 76 | ||
@@ -139,67 +143,95 @@ MODULE_LICENSE("GPL"); | |||
139 | MODULE_DEVICE_TABLE(pci, sis_pci_tbl); | 143 | MODULE_DEVICE_TABLE(pci, sis_pci_tbl); |
140 | MODULE_VERSION(DRV_VERSION); | 144 | MODULE_VERSION(DRV_VERSION); |
141 | 145 | ||
142 | static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg) | 146 | static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg, int device) |
143 | { | 147 | { |
144 | unsigned int addr = SIS_SCR_BASE + (4 * sc_reg); | 148 | unsigned int addr = SIS_SCR_BASE + (4 * sc_reg); |
145 | 149 | ||
146 | if (port_no) | 150 | if (port_no) { |
147 | addr += SIS_SATA1_OFS; | 151 | if (device == 0x182) |
152 | addr += SIS182_SATA1_OFS; | ||
153 | else | ||
154 | addr += SIS180_SATA1_OFS; | ||
155 | } | ||
156 | |||
148 | return addr; | 157 | return addr; |
149 | } | 158 | } |
150 | 159 | ||
151 | static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) | 160 | static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) |
152 | { | 161 | { |
153 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); | 162 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); |
154 | unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg); | 163 | unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device); |
155 | u32 val; | 164 | u32 val, val2; |
165 | u8 pmr; | ||
156 | 166 | ||
157 | if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ | 167 | if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ |
158 | return 0xffffffff; | 168 | return 0xffffffff; |
169 | |||
170 | pci_read_config_byte(pdev, SIS_PMR, &pmr); | ||
171 | |||
159 | pci_read_config_dword(pdev, cfg_addr, &val); | 172 | pci_read_config_dword(pdev, cfg_addr, &val); |
160 | return val; | 173 | |
174 | if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) | ||
175 | pci_read_config_dword(pdev, cfg_addr+0x10, &val2); | ||
176 | |||
177 | return val|val2; | ||
161 | } | 178 | } |
162 | 179 | ||
163 | static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) | 180 | static void sis_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val) |
164 | { | 181 | { |
165 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); | 182 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); |
166 | unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr); | 183 | unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr, pdev->device); |
184 | u8 pmr; | ||
167 | 185 | ||
168 | if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */ | 186 | if (scr == SCR_ERROR) /* doesn't exist in PCI cfg space */ |
169 | return; | 187 | return; |
188 | |||
189 | pci_read_config_byte(pdev, SIS_PMR, &pmr); | ||
190 | |||
170 | pci_write_config_dword(pdev, cfg_addr, val); | 191 | pci_write_config_dword(pdev, cfg_addr, val); |
192 | |||
193 | if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) | ||
194 | pci_write_config_dword(pdev, cfg_addr+0x10, val); | ||
171 | } | 195 | } |
172 | 196 | ||
173 | static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg) | 197 | static u32 sis_scr_read (struct ata_port *ap, unsigned int sc_reg) |
174 | { | 198 | { |
199 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); | ||
200 | u32 val, val2 = 0; | ||
201 | u8 pmr; | ||
202 | |||
175 | if (sc_reg > SCR_CONTROL) | 203 | if (sc_reg > SCR_CONTROL) |
176 | return 0xffffffffU; | 204 | return 0xffffffffU; |
177 | 205 | ||
178 | if (ap->flags & SIS_FLAG_CFGSCR) | 206 | if (ap->flags & SIS_FLAG_CFGSCR) |
179 | return sis_scr_cfg_read(ap, sc_reg); | 207 | return sis_scr_cfg_read(ap, sc_reg); |
180 | return inl(ap->ioaddr.scr_addr + (sc_reg * 4)); | 208 | |
209 | pci_read_config_byte(pdev, SIS_PMR, &pmr); | ||
210 | |||
211 | val = inl(ap->ioaddr.scr_addr + (sc_reg * 4)); | ||
212 | |||
213 | if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) | ||
214 | val2 = inl(ap->ioaddr.scr_addr + (sc_reg * 4) + 0x10); | ||
215 | |||
216 | return val | val2; | ||
181 | } | 217 | } |
182 | 218 | ||
183 | static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) | 219 | static void sis_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) |
184 | { | 220 | { |
221 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); | ||
222 | u8 pmr; | ||
223 | |||
185 | if (sc_reg > SCR_CONTROL) | 224 | if (sc_reg > SCR_CONTROL) |
186 | return; | 225 | return; |
187 | 226 | ||
227 | pci_read_config_byte(pdev, SIS_PMR, &pmr); | ||
228 | |||
188 | if (ap->flags & SIS_FLAG_CFGSCR) | 229 | if (ap->flags & SIS_FLAG_CFGSCR) |
189 | sis_scr_cfg_write(ap, sc_reg, val); | 230 | sis_scr_cfg_write(ap, sc_reg, val); |
190 | else | 231 | else { |
191 | outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)); | 232 | outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)); |
192 | } | 233 | if ((pdev->device == 0x182) || (pmr & SIS_PMR_COMBINED)) |
193 | 234 | outl(val, ap->ioaddr.scr_addr + (sc_reg * 4)+0x10); | |
194 | /* move to PCI layer, integrate w/ MSI stuff */ | ||
195 | static void pci_enable_intx(struct pci_dev *pdev) | ||
196 | { | ||
197 | u16 pci_command; | ||
198 | |||
199 | pci_read_config_word(pdev, PCI_COMMAND, &pci_command); | ||
200 | if (pci_command & PCI_COMMAND_INTX_DISABLE) { | ||
201 | pci_command &= ~PCI_COMMAND_INTX_DISABLE; | ||
202 | pci_write_config_word(pdev, PCI_COMMAND, pci_command); | ||
203 | } | 235 | } |
204 | } | 236 | } |
205 | 237 | ||
@@ -210,6 +242,8 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
210 | u32 genctl; | 242 | u32 genctl; |
211 | struct ata_port_info *ppi; | 243 | struct ata_port_info *ppi; |
212 | int pci_dev_busy = 0; | 244 | int pci_dev_busy = 0; |
245 | u8 pmr; | ||
246 | u8 port2_start; | ||
213 | 247 | ||
214 | rc = pci_enable_device(pdev); | 248 | rc = pci_enable_device(pdev); |
215 | if (rc) | 249 | if (rc) |
@@ -251,15 +285,31 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
251 | probe_ent->host_flags |= SIS_FLAG_CFGSCR; | 285 | probe_ent->host_flags |= SIS_FLAG_CFGSCR; |
252 | } | 286 | } |
253 | 287 | ||
288 | pci_read_config_byte(pdev, SIS_PMR, &pmr); | ||
289 | if (ent->device != 0x182) { | ||
290 | if ((pmr & SIS_PMR_COMBINED) == 0) { | ||
291 | printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n"); | ||
292 | port2_start=0x64; | ||
293 | } | ||
294 | else { | ||
295 | printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in combined mode\n"); | ||
296 | port2_start=0; | ||
297 | } | ||
298 | } | ||
299 | else { | ||
300 | printk(KERN_INFO "sata_sis: Detected SiS 182 chipset\n"); | ||
301 | port2_start = 0x20; | ||
302 | } | ||
303 | |||
254 | if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) { | 304 | if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) { |
255 | probe_ent->port[0].scr_addr = | 305 | probe_ent->port[0].scr_addr = |
256 | pci_resource_start(pdev, SIS_SCR_PCI_BAR); | 306 | pci_resource_start(pdev, SIS_SCR_PCI_BAR); |
257 | probe_ent->port[1].scr_addr = | 307 | probe_ent->port[1].scr_addr = |
258 | pci_resource_start(pdev, SIS_SCR_PCI_BAR) + 64; | 308 | pci_resource_start(pdev, SIS_SCR_PCI_BAR) + port2_start; |
259 | } | 309 | } |
260 | 310 | ||
261 | pci_set_master(pdev); | 311 | pci_set_master(pdev); |
262 | pci_enable_intx(pdev); | 312 | pci_intx(pdev, 1); |
263 | 313 | ||
264 | /* FIXME: check ata_device_add return value */ | 314 | /* FIXME: check ata_device_add return value */ |
265 | ata_device_add(probe_ent); | 315 | ata_device_add(probe_ent); |
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 42e13ed8eb5b..4c9fb8b71be1 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c | |||
@@ -176,18 +176,6 @@ static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) | |||
176 | uli_scr_cfg_write(ap, sc_reg, val); | 176 | uli_scr_cfg_write(ap, sc_reg, val); |
177 | } | 177 | } |
178 | 178 | ||
179 | /* move to PCI layer, integrate w/ MSI stuff */ | ||
180 | static void pci_enable_intx(struct pci_dev *pdev) | ||
181 | { | ||
182 | u16 pci_command; | ||
183 | |||
184 | pci_read_config_word(pdev, PCI_COMMAND, &pci_command); | ||
185 | if (pci_command & PCI_COMMAND_INTX_DISABLE) { | ||
186 | pci_command &= ~PCI_COMMAND_INTX_DISABLE; | ||
187 | pci_write_config_word(pdev, PCI_COMMAND, pci_command); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | 179 | static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) |
192 | { | 180 | { |
193 | struct ata_probe_ent *probe_ent; | 181 | struct ata_probe_ent *probe_ent; |
@@ -260,7 +248,7 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
260 | } | 248 | } |
261 | 249 | ||
262 | pci_set_master(pdev); | 250 | pci_set_master(pdev); |
263 | pci_enable_intx(pdev); | 251 | pci_intx(pdev, 1); |
264 | 252 | ||
265 | /* FIXME: check ata_device_add return value */ | 253 | /* FIXME: check ata_device_add return value */ |
266 | ata_device_add(probe_ent); | 254 | ata_device_add(probe_ent); |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 77f2d444f7e0..863bb6495daa 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -97,6 +97,30 @@ int scsi_insert_special_req(struct scsi_request *sreq, int at_head) | |||
97 | } | 97 | } |
98 | 98 | ||
99 | static void scsi_run_queue(struct request_queue *q); | 99 | static void scsi_run_queue(struct request_queue *q); |
100 | static void scsi_release_buffers(struct scsi_cmnd *cmd); | ||
101 | |||
102 | /* | ||
103 | * Function: scsi_unprep_request() | ||
104 | * | ||
105 | * Purpose: Remove all preparation done for a request, including its | ||
106 | * associated scsi_cmnd, so that it can be requeued. | ||
107 | * | ||
108 | * Arguments: req - request to unprepare | ||
109 | * | ||
110 | * Lock status: Assumed that no locks are held upon entry. | ||
111 | * | ||
112 | * Returns: Nothing. | ||
113 | */ | ||
114 | static void scsi_unprep_request(struct request *req) | ||
115 | { | ||
116 | struct scsi_cmnd *cmd = req->special; | ||
117 | |||
118 | req->flags &= ~REQ_DONTPREP; | ||
119 | req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL; | ||
120 | |||
121 | scsi_release_buffers(cmd); | ||
122 | scsi_put_command(cmd); | ||
123 | } | ||
100 | 124 | ||
101 | /* | 125 | /* |
102 | * Function: scsi_queue_insert() | 126 | * Function: scsi_queue_insert() |
@@ -116,12 +140,14 @@ static void scsi_run_queue(struct request_queue *q); | |||
116 | * commands. | 140 | * commands. |
117 | * Notes: This could be called either from an interrupt context or a | 141 | * Notes: This could be called either from an interrupt context or a |
118 | * normal process context. | 142 | * normal process context. |
143 | * Notes: Upon return, cmd is a stale pointer. | ||
119 | */ | 144 | */ |
120 | int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) | 145 | int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) |
121 | { | 146 | { |
122 | struct Scsi_Host *host = cmd->device->host; | 147 | struct Scsi_Host *host = cmd->device->host; |
123 | struct scsi_device *device = cmd->device; | 148 | struct scsi_device *device = cmd->device; |
124 | struct request_queue *q = device->request_queue; | 149 | struct request_queue *q = device->request_queue; |
150 | struct request *req = cmd->request; | ||
125 | unsigned long flags; | 151 | unsigned long flags; |
126 | 152 | ||
127 | SCSI_LOG_MLQUEUE(1, | 153 | SCSI_LOG_MLQUEUE(1, |
@@ -162,8 +188,9 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) | |||
162 | * function. The SCSI request function detects the blocked condition | 188 | * function. The SCSI request function detects the blocked condition |
163 | * and plugs the queue appropriately. | 189 | * and plugs the queue appropriately. |
164 | */ | 190 | */ |
191 | scsi_unprep_request(req); | ||
165 | spin_lock_irqsave(q->queue_lock, flags); | 192 | spin_lock_irqsave(q->queue_lock, flags); |
166 | blk_requeue_request(q, cmd->request); | 193 | blk_requeue_request(q, req); |
167 | spin_unlock_irqrestore(q->queue_lock, flags); | 194 | spin_unlock_irqrestore(q->queue_lock, flags); |
168 | 195 | ||
169 | scsi_run_queue(q); | 196 | scsi_run_queue(q); |
@@ -339,7 +366,7 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, | |||
339 | int result; | 366 | int result; |
340 | 367 | ||
341 | if (sshdr) { | 368 | if (sshdr) { |
342 | sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); | 369 | sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); |
343 | if (!sense) | 370 | if (!sense) |
344 | return DRIVER_ERROR << 24; | 371 | return DRIVER_ERROR << 24; |
345 | memset(sense, 0, SCSI_SENSE_BUFFERSIZE); | 372 | memset(sense, 0, SCSI_SENSE_BUFFERSIZE); |
@@ -552,15 +579,16 @@ static void scsi_run_queue(struct request_queue *q) | |||
552 | * I/O errors in the middle of the request, in which case | 579 | * I/O errors in the middle of the request, in which case |
553 | * we need to request the blocks that come after the bad | 580 | * we need to request the blocks that come after the bad |
554 | * sector. | 581 | * sector. |
582 | * Notes: Upon return, cmd is a stale pointer. | ||
555 | */ | 583 | */ |
556 | static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) | 584 | static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) |
557 | { | 585 | { |
586 | struct request *req = cmd->request; | ||
558 | unsigned long flags; | 587 | unsigned long flags; |
559 | 588 | ||
560 | cmd->request->flags &= ~REQ_DONTPREP; | 589 | scsi_unprep_request(req); |
561 | |||
562 | spin_lock_irqsave(q->queue_lock, flags); | 590 | spin_lock_irqsave(q->queue_lock, flags); |
563 | blk_requeue_request(q, cmd->request); | 591 | blk_requeue_request(q, req); |
564 | spin_unlock_irqrestore(q->queue_lock, flags); | 592 | spin_unlock_irqrestore(q->queue_lock, flags); |
565 | 593 | ||
566 | scsi_run_queue(q); | 594 | scsi_run_queue(q); |
@@ -595,13 +623,14 @@ void scsi_run_host_queues(struct Scsi_Host *shost) | |||
595 | * | 623 | * |
596 | * Lock status: Assumed that lock is not held upon entry. | 624 | * Lock status: Assumed that lock is not held upon entry. |
597 | * | 625 | * |
598 | * Returns: cmd if requeue done or required, NULL otherwise | 626 | * Returns: cmd if requeue required, NULL otherwise. |
599 | * | 627 | * |
600 | * Notes: This is called for block device requests in order to | 628 | * Notes: This is called for block device requests in order to |
601 | * mark some number of sectors as complete. | 629 | * mark some number of sectors as complete. |
602 | * | 630 | * |
603 | * We are guaranteeing that the request queue will be goosed | 631 | * We are guaranteeing that the request queue will be goosed |
604 | * at some point during this call. | 632 | * at some point during this call. |
633 | * Notes: If cmd was requeued, upon return it will be a stale pointer. | ||
605 | */ | 634 | */ |
606 | static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, | 635 | static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, |
607 | int bytes, int requeue) | 636 | int bytes, int requeue) |
@@ -624,14 +653,15 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate, | |||
624 | if (!uptodate && blk_noretry_request(req)) | 653 | if (!uptodate && blk_noretry_request(req)) |
625 | end_that_request_chunk(req, 0, leftover); | 654 | end_that_request_chunk(req, 0, leftover); |
626 | else { | 655 | else { |
627 | if (requeue) | 656 | if (requeue) { |
628 | /* | 657 | /* |
629 | * Bleah. Leftovers again. Stick the | 658 | * Bleah. Leftovers again. Stick the |
630 | * leftovers in the front of the | 659 | * leftovers in the front of the |
631 | * queue, and goose the queue again. | 660 | * queue, and goose the queue again. |
632 | */ | 661 | */ |
633 | scsi_requeue_command(q, cmd); | 662 | scsi_requeue_command(q, cmd); |
634 | 663 | cmd = NULL; | |
664 | } | ||
635 | return cmd; | 665 | return cmd; |
636 | } | 666 | } |
637 | } | 667 | } |
@@ -857,15 +887,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, | |||
857 | * requeueing right here - we will requeue down below | 887 | * requeueing right here - we will requeue down below |
858 | * when we handle the bad sectors. | 888 | * when we handle the bad sectors. |
859 | */ | 889 | */ |
860 | cmd = scsi_end_request(cmd, 1, good_bytes, result == 0); | ||
861 | 890 | ||
862 | /* | 891 | /* |
863 | * If the command completed without error, then either finish off the | 892 | * If the command completed without error, then either |
864 | * rest of the command, or start a new one. | 893 | * finish off the rest of the command, or start a new one. |
865 | */ | 894 | */ |
866 | if (result == 0 || cmd == NULL ) { | 895 | if (scsi_end_request(cmd, 1, good_bytes, result == 0) == NULL) |
867 | return; | 896 | return; |
868 | } | ||
869 | } | 897 | } |
870 | /* | 898 | /* |
871 | * Now, if we were good little boys and girls, Santa left us a request | 899 | * Now, if we were good little boys and girls, Santa left us a request |
@@ -880,7 +908,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, | |||
880 | * and quietly refuse further access. | 908 | * and quietly refuse further access. |
881 | */ | 909 | */ |
882 | cmd->device->changed = 1; | 910 | cmd->device->changed = 1; |
883 | cmd = scsi_end_request(cmd, 0, | 911 | scsi_end_request(cmd, 0, |
884 | this_count, 1); | 912 | this_count, 1); |
885 | return; | 913 | return; |
886 | } else { | 914 | } else { |
@@ -914,7 +942,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, | |||
914 | scsi_requeue_command(q, cmd); | 942 | scsi_requeue_command(q, cmd); |
915 | result = 0; | 943 | result = 0; |
916 | } else { | 944 | } else { |
917 | cmd = scsi_end_request(cmd, 0, this_count, 1); | 945 | scsi_end_request(cmd, 0, this_count, 1); |
918 | return; | 946 | return; |
919 | } | 947 | } |
920 | break; | 948 | break; |
@@ -931,7 +959,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, | |||
931 | dev_printk(KERN_INFO, | 959 | dev_printk(KERN_INFO, |
932 | &cmd->device->sdev_gendev, | 960 | &cmd->device->sdev_gendev, |
933 | "Device not ready.\n"); | 961 | "Device not ready.\n"); |
934 | cmd = scsi_end_request(cmd, 0, this_count, 1); | 962 | scsi_end_request(cmd, 0, this_count, 1); |
935 | return; | 963 | return; |
936 | case VOLUME_OVERFLOW: | 964 | case VOLUME_OVERFLOW: |
937 | if (!(req->flags & REQ_QUIET)) { | 965 | if (!(req->flags & REQ_QUIET)) { |
@@ -941,7 +969,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, | |||
941 | __scsi_print_command(cmd->data_cmnd); | 969 | __scsi_print_command(cmd->data_cmnd); |
942 | scsi_print_sense("", cmd); | 970 | scsi_print_sense("", cmd); |
943 | } | 971 | } |
944 | cmd = scsi_end_request(cmd, 0, block_bytes, 1); | 972 | scsi_end_request(cmd, 0, block_bytes, 1); |
945 | return; | 973 | return; |
946 | default: | 974 | default: |
947 | break; | 975 | break; |
@@ -972,7 +1000,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, | |||
972 | block_bytes = req->hard_cur_sectors << 9; | 1000 | block_bytes = req->hard_cur_sectors << 9; |
973 | if (!block_bytes) | 1001 | if (!block_bytes) |
974 | block_bytes = req->data_len; | 1002 | block_bytes = req->data_len; |
975 | cmd = scsi_end_request(cmd, 0, block_bytes, 1); | 1003 | scsi_end_request(cmd, 0, block_bytes, 1); |
976 | } | 1004 | } |
977 | } | 1005 | } |
978 | EXPORT_SYMBOL(scsi_io_completion); | 1006 | EXPORT_SYMBOL(scsi_io_completion); |
@@ -1118,7 +1146,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1118 | if (unlikely(!scsi_device_online(sdev))) { | 1146 | if (unlikely(!scsi_device_online(sdev))) { |
1119 | printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n", | 1147 | printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n", |
1120 | sdev->host->host_no, sdev->id, sdev->lun); | 1148 | sdev->host->host_no, sdev->id, sdev->lun); |
1121 | return BLKPREP_KILL; | 1149 | goto kill; |
1122 | } | 1150 | } |
1123 | if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { | 1151 | if (unlikely(sdev->sdev_state != SDEV_RUNNING)) { |
1124 | /* OK, we're not in a running state don't prep | 1152 | /* OK, we're not in a running state don't prep |
@@ -1128,7 +1156,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1128 | * at all allowed down */ | 1156 | * at all allowed down */ |
1129 | printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n", | 1157 | printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n", |
1130 | sdev->host->host_no, sdev->id, sdev->lun); | 1158 | sdev->host->host_no, sdev->id, sdev->lun); |
1131 | return BLKPREP_KILL; | 1159 | goto kill; |
1132 | } | 1160 | } |
1133 | /* OK, we only allow special commands (i.e. not | 1161 | /* OK, we only allow special commands (i.e. not |
1134 | * user initiated ones */ | 1162 | * user initiated ones */ |
@@ -1160,11 +1188,11 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1160 | if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) { | 1188 | if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) { |
1161 | if(specials_only == SDEV_QUIESCE || | 1189 | if(specials_only == SDEV_QUIESCE || |
1162 | specials_only == SDEV_BLOCK) | 1190 | specials_only == SDEV_BLOCK) |
1163 | return BLKPREP_DEFER; | 1191 | goto defer; |
1164 | 1192 | ||
1165 | printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n", | 1193 | printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n", |
1166 | sdev->host->host_no, sdev->id, sdev->lun); | 1194 | sdev->host->host_no, sdev->id, sdev->lun); |
1167 | return BLKPREP_KILL; | 1195 | goto kill; |
1168 | } | 1196 | } |
1169 | 1197 | ||
1170 | 1198 | ||
@@ -1182,7 +1210,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1182 | cmd->tag = req->tag; | 1210 | cmd->tag = req->tag; |
1183 | } else { | 1211 | } else { |
1184 | blk_dump_rq_flags(req, "SCSI bad req"); | 1212 | blk_dump_rq_flags(req, "SCSI bad req"); |
1185 | return BLKPREP_KILL; | 1213 | goto kill; |
1186 | } | 1214 | } |
1187 | 1215 | ||
1188 | /* note the overloading of req->special. When the tag | 1216 | /* note the overloading of req->special. When the tag |
@@ -1220,8 +1248,13 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1220 | * required). | 1248 | * required). |
1221 | */ | 1249 | */ |
1222 | ret = scsi_init_io(cmd); | 1250 | ret = scsi_init_io(cmd); |
1223 | if (ret) /* BLKPREP_KILL return also releases the command */ | 1251 | switch(ret) { |
1224 | return ret; | 1252 | case BLKPREP_KILL: |
1253 | /* BLKPREP_KILL return also releases the command */ | ||
1254 | goto kill; | ||
1255 | case BLKPREP_DEFER: | ||
1256 | goto defer; | ||
1257 | } | ||
1225 | 1258 | ||
1226 | /* | 1259 | /* |
1227 | * Initialize the actual SCSI command for this request. | 1260 | * Initialize the actual SCSI command for this request. |
@@ -1231,7 +1264,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1231 | if (unlikely(!drv->init_command(cmd))) { | 1264 | if (unlikely(!drv->init_command(cmd))) { |
1232 | scsi_release_buffers(cmd); | 1265 | scsi_release_buffers(cmd); |
1233 | scsi_put_command(cmd); | 1266 | scsi_put_command(cmd); |
1234 | return BLKPREP_KILL; | 1267 | goto kill; |
1235 | } | 1268 | } |
1236 | } else { | 1269 | } else { |
1237 | memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); | 1270 | memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); |
@@ -1262,6 +1295,9 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1262 | if (sdev->device_busy == 0) | 1295 | if (sdev->device_busy == 0) |
1263 | blk_plug_device(q); | 1296 | blk_plug_device(q); |
1264 | return BLKPREP_DEFER; | 1297 | return BLKPREP_DEFER; |
1298 | kill: | ||
1299 | req->errors = DID_NO_CONNECT << 16; | ||
1300 | return BLKPREP_KILL; | ||
1265 | } | 1301 | } |
1266 | 1302 | ||
1267 | /* | 1303 | /* |
@@ -1336,19 +1372,24 @@ static inline int scsi_host_queue_ready(struct request_queue *q, | |||
1336 | } | 1372 | } |
1337 | 1373 | ||
1338 | /* | 1374 | /* |
1339 | * Kill requests for a dead device | 1375 | * Kill a request for a dead device |
1340 | */ | 1376 | */ |
1341 | static void scsi_kill_requests(request_queue_t *q) | 1377 | static void scsi_kill_request(struct request *req, request_queue_t *q) |
1342 | { | 1378 | { |
1343 | struct request *req; | 1379 | struct scsi_cmnd *cmd = req->special; |
1380 | |||
1381 | blkdev_dequeue_request(req); | ||
1344 | 1382 | ||
1345 | while ((req = elv_next_request(q)) != NULL) { | 1383 | if (unlikely(cmd == NULL)) { |
1346 | blkdev_dequeue_request(req); | 1384 | printk(KERN_CRIT "impossible request in %s.\n", |
1347 | req->flags |= REQ_QUIET; | 1385 | __FUNCTION__); |
1348 | while (end_that_request_first(req, 0, req->nr_sectors)) | 1386 | BUG(); |
1349 | ; | ||
1350 | end_that_request_last(req); | ||
1351 | } | 1387 | } |
1388 | |||
1389 | scsi_init_cmd_errh(cmd); | ||
1390 | cmd->result = DID_NO_CONNECT << 16; | ||
1391 | atomic_inc(&cmd->device->iorequest_cnt); | ||
1392 | __scsi_done(cmd); | ||
1352 | } | 1393 | } |
1353 | 1394 | ||
1354 | /* | 1395 | /* |
@@ -1371,7 +1412,8 @@ static void scsi_request_fn(struct request_queue *q) | |||
1371 | 1412 | ||
1372 | if (!sdev) { | 1413 | if (!sdev) { |
1373 | printk("scsi: killing requests for dead queue\n"); | 1414 | printk("scsi: killing requests for dead queue\n"); |
1374 | scsi_kill_requests(q); | 1415 | while ((req = elv_next_request(q)) != NULL) |
1416 | scsi_kill_request(req, q); | ||
1375 | return; | 1417 | return; |
1376 | } | 1418 | } |
1377 | 1419 | ||
@@ -1398,11 +1440,7 @@ static void scsi_request_fn(struct request_queue *q) | |||
1398 | if (unlikely(!scsi_device_online(sdev))) { | 1440 | if (unlikely(!scsi_device_online(sdev))) { |
1399 | printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n", | 1441 | printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n", |
1400 | sdev->host->host_no, sdev->id, sdev->lun); | 1442 | sdev->host->host_no, sdev->id, sdev->lun); |
1401 | blkdev_dequeue_request(req); | 1443 | scsi_kill_request(req, q); |
1402 | req->flags |= REQ_QUIET; | ||
1403 | while (end_that_request_first(req, 0, req->nr_sectors)) | ||
1404 | ; | ||
1405 | end_that_request_last(req); | ||
1406 | continue; | 1444 | continue; |
1407 | } | 1445 | } |
1408 | 1446 | ||
@@ -1415,6 +1453,14 @@ static void scsi_request_fn(struct request_queue *q) | |||
1415 | sdev->device_busy++; | 1453 | sdev->device_busy++; |
1416 | 1454 | ||
1417 | spin_unlock(q->queue_lock); | 1455 | spin_unlock(q->queue_lock); |
1456 | cmd = req->special; | ||
1457 | if (unlikely(cmd == NULL)) { | ||
1458 | printk(KERN_CRIT "impossible request in %s.\n" | ||
1459 | "please mail a stack trace to " | ||
1460 | "linux-scsi@vger.kernel.org", | ||
1461 | __FUNCTION__); | ||
1462 | BUG(); | ||
1463 | } | ||
1418 | spin_lock(shost->host_lock); | 1464 | spin_lock(shost->host_lock); |
1419 | 1465 | ||
1420 | if (!scsi_host_queue_ready(q, shost, sdev)) | 1466 | if (!scsi_host_queue_ready(q, shost, sdev)) |
@@ -1433,15 +1479,6 @@ static void scsi_request_fn(struct request_queue *q) | |||
1433 | */ | 1479 | */ |
1434 | spin_unlock_irq(shost->host_lock); | 1480 | spin_unlock_irq(shost->host_lock); |
1435 | 1481 | ||
1436 | cmd = req->special; | ||
1437 | if (unlikely(cmd == NULL)) { | ||
1438 | printk(KERN_CRIT "impossible request in %s.\n" | ||
1439 | "please mail a stack trace to " | ||
1440 | "linux-scsi@vger.kernel.org", | ||
1441 | __FUNCTION__); | ||
1442 | BUG(); | ||
1443 | } | ||
1444 | |||
1445 | /* | 1482 | /* |
1446 | * Finally, initialize any error handling parameters, and set up | 1483 | * Finally, initialize any error handling parameters, and set up |
1447 | * the timers for timeouts. | 1484 | * the timers for timeouts. |
@@ -1477,6 +1514,7 @@ static void scsi_request_fn(struct request_queue *q) | |||
1477 | * cases (host limits or settings) should run the queue at some | 1514 | * cases (host limits or settings) should run the queue at some |
1478 | * later time. | 1515 | * later time. |
1479 | */ | 1516 | */ |
1517 | scsi_unprep_request(req); | ||
1480 | spin_lock_irq(q->queue_lock); | 1518 | spin_lock_irq(q->queue_lock); |
1481 | blk_requeue_request(q, req); | 1519 | blk_requeue_request(q, req); |
1482 | sdev->device_busy--; | 1520 | sdev->device_busy--; |
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index ee6de1768e53..d05f778d31a8 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h | |||
@@ -124,6 +124,7 @@ extern void scsi_sysfs_unregister(void); | |||
124 | extern void scsi_sysfs_device_initialize(struct scsi_device *); | 124 | extern void scsi_sysfs_device_initialize(struct scsi_device *); |
125 | extern int scsi_sysfs_target_initialize(struct scsi_device *); | 125 | extern int scsi_sysfs_target_initialize(struct scsi_device *); |
126 | extern struct scsi_transport_template blank_transport_template; | 126 | extern struct scsi_transport_template blank_transport_template; |
127 | extern void __scsi_remove_device(struct scsi_device *); | ||
127 | 128 | ||
128 | extern struct bus_type scsi_bus_type; | 129 | extern struct bus_type scsi_bus_type; |
129 | 130 | ||
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 19c9a232a754..b86f170fa8ed 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -870,8 +870,12 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
870 | out_free_sdev: | 870 | out_free_sdev: |
871 | if (res == SCSI_SCAN_LUN_PRESENT) { | 871 | if (res == SCSI_SCAN_LUN_PRESENT) { |
872 | if (sdevp) { | 872 | if (sdevp) { |
873 | scsi_device_get(sdev); | 873 | if (scsi_device_get(sdev) == 0) { |
874 | *sdevp = sdev; | 874 | *sdevp = sdev; |
875 | } else { | ||
876 | __scsi_remove_device(sdev); | ||
877 | res = SCSI_SCAN_NO_RESPONSE; | ||
878 | } | ||
875 | } | 879 | } |
876 | } else { | 880 | } else { |
877 | if (sdev->host->hostt->slave_destroy) | 881 | if (sdev->host->hostt->slave_destroy) |
@@ -1260,6 +1264,19 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, | |||
1260 | } | 1264 | } |
1261 | EXPORT_SYMBOL(__scsi_add_device); | 1265 | EXPORT_SYMBOL(__scsi_add_device); |
1262 | 1266 | ||
1267 | int scsi_add_device(struct Scsi_Host *host, uint channel, | ||
1268 | uint target, uint lun) | ||
1269 | { | ||
1270 | struct scsi_device *sdev = | ||
1271 | __scsi_add_device(host, channel, target, lun, NULL); | ||
1272 | if (IS_ERR(sdev)) | ||
1273 | return PTR_ERR(sdev); | ||
1274 | |||
1275 | scsi_device_put(sdev); | ||
1276 | return 0; | ||
1277 | } | ||
1278 | EXPORT_SYMBOL(scsi_add_device); | ||
1279 | |||
1263 | void scsi_rescan_device(struct device *dev) | 1280 | void scsi_rescan_device(struct device *dev) |
1264 | { | 1281 | { |
1265 | struct scsi_driver *drv; | 1282 | struct scsi_driver *drv; |
@@ -1276,27 +1293,8 @@ void scsi_rescan_device(struct device *dev) | |||
1276 | } | 1293 | } |
1277 | EXPORT_SYMBOL(scsi_rescan_device); | 1294 | EXPORT_SYMBOL(scsi_rescan_device); |
1278 | 1295 | ||
1279 | /** | 1296 | static void __scsi_scan_target(struct device *parent, unsigned int channel, |
1280 | * scsi_scan_target - scan a target id, possibly including all LUNs on the | 1297 | unsigned int id, unsigned int lun, int rescan) |
1281 | * target. | ||
1282 | * @sdevsca: Scsi_Device handle for scanning | ||
1283 | * @shost: host to scan | ||
1284 | * @channel: channel to scan | ||
1285 | * @id: target id to scan | ||
1286 | * | ||
1287 | * Description: | ||
1288 | * Scan the target id on @shost, @channel, and @id. Scan at least LUN | ||
1289 | * 0, and possibly all LUNs on the target id. | ||
1290 | * | ||
1291 | * Use the pre-allocated @sdevscan as a handle for the scanning. This | ||
1292 | * function sets sdevscan->host, sdevscan->id and sdevscan->lun; the | ||
1293 | * scanning functions modify sdevscan->lun. | ||
1294 | * | ||
1295 | * First try a REPORT LUN scan, if that does not scan the target, do a | ||
1296 | * sequential scan of LUNs on the target id. | ||
1297 | **/ | ||
1298 | void scsi_scan_target(struct device *parent, unsigned int channel, | ||
1299 | unsigned int id, unsigned int lun, int rescan) | ||
1300 | { | 1298 | { |
1301 | struct Scsi_Host *shost = dev_to_shost(parent); | 1299 | struct Scsi_Host *shost = dev_to_shost(parent); |
1302 | int bflags = 0; | 1300 | int bflags = 0; |
@@ -1310,9 +1308,7 @@ void scsi_scan_target(struct device *parent, unsigned int channel, | |||
1310 | */ | 1308 | */ |
1311 | return; | 1309 | return; |
1312 | 1310 | ||
1313 | |||
1314 | starget = scsi_alloc_target(parent, channel, id); | 1311 | starget = scsi_alloc_target(parent, channel, id); |
1315 | |||
1316 | if (!starget) | 1312 | if (!starget) |
1317 | return; | 1313 | return; |
1318 | 1314 | ||
@@ -1358,6 +1354,33 @@ void scsi_scan_target(struct device *parent, unsigned int channel, | |||
1358 | 1354 | ||
1359 | put_device(&starget->dev); | 1355 | put_device(&starget->dev); |
1360 | } | 1356 | } |
1357 | |||
1358 | /** | ||
1359 | * scsi_scan_target - scan a target id, possibly including all LUNs on the | ||
1360 | * target. | ||
1361 | * @parent: host to scan | ||
1362 | * @channel: channel to scan | ||
1363 | * @id: target id to scan | ||
1364 | * @lun: Specific LUN to scan or SCAN_WILD_CARD | ||
1365 | * @rescan: passed to LUN scanning routines | ||
1366 | * | ||
1367 | * Description: | ||
1368 | * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0, | ||
1369 | * and possibly all LUNs on the target id. | ||
1370 | * | ||
1371 | * First try a REPORT LUN scan, if that does not scan the target, do a | ||
1372 | * sequential scan of LUNs on the target id. | ||
1373 | **/ | ||
1374 | void scsi_scan_target(struct device *parent, unsigned int channel, | ||
1375 | unsigned int id, unsigned int lun, int rescan) | ||
1376 | { | ||
1377 | struct Scsi_Host *shost = dev_to_shost(parent); | ||
1378 | |||
1379 | down(&shost->scan_mutex); | ||
1380 | if (scsi_host_scan_allowed(shost)) | ||
1381 | __scsi_scan_target(parent, channel, id, lun, rescan); | ||
1382 | up(&shost->scan_mutex); | ||
1383 | } | ||
1361 | EXPORT_SYMBOL(scsi_scan_target); | 1384 | EXPORT_SYMBOL(scsi_scan_target); |
1362 | 1385 | ||
1363 | static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, | 1386 | static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, |
@@ -1383,10 +1406,12 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, | |||
1383 | order_id = shost->max_id - id - 1; | 1406 | order_id = shost->max_id - id - 1; |
1384 | else | 1407 | else |
1385 | order_id = id; | 1408 | order_id = id; |
1386 | scsi_scan_target(&shost->shost_gendev, channel, order_id, lun, rescan); | 1409 | __scsi_scan_target(&shost->shost_gendev, channel, |
1410 | order_id, lun, rescan); | ||
1387 | } | 1411 | } |
1388 | else | 1412 | else |
1389 | scsi_scan_target(&shost->shost_gendev, channel, id, lun, rescan); | 1413 | __scsi_scan_target(&shost->shost_gendev, channel, |
1414 | id, lun, rescan); | ||
1390 | } | 1415 | } |
1391 | 1416 | ||
1392 | int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, | 1417 | int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, |
@@ -1484,12 +1509,15 @@ void scsi_forget_host(struct Scsi_Host *shost) | |||
1484 | */ | 1509 | */ |
1485 | struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) | 1510 | struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) |
1486 | { | 1511 | { |
1487 | struct scsi_device *sdev; | 1512 | struct scsi_device *sdev = NULL; |
1488 | struct scsi_target *starget; | 1513 | struct scsi_target *starget; |
1489 | 1514 | ||
1515 | down(&shost->scan_mutex); | ||
1516 | if (!scsi_host_scan_allowed(shost)) | ||
1517 | goto out; | ||
1490 | starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); | 1518 | starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); |
1491 | if (!starget) | 1519 | if (!starget) |
1492 | return NULL; | 1520 | goto out; |
1493 | 1521 | ||
1494 | sdev = scsi_alloc_sdev(starget, 0, NULL); | 1522 | sdev = scsi_alloc_sdev(starget, 0, NULL); |
1495 | if (sdev) { | 1523 | if (sdev) { |
@@ -1497,6 +1525,8 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) | |||
1497 | sdev->borken = 0; | 1525 | sdev->borken = 0; |
1498 | } | 1526 | } |
1499 | put_device(&starget->dev); | 1527 | put_device(&starget->dev); |
1528 | out: | ||
1529 | up(&shost->scan_mutex); | ||
1500 | return sdev; | 1530 | return sdev; |
1501 | } | 1531 | } |
1502 | EXPORT_SYMBOL(scsi_get_host_dev); | 1532 | EXPORT_SYMBOL(scsi_get_host_dev); |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index dae59d1da07a..b8052d5206cc 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -653,7 +653,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) | |||
653 | error = attr_add(&sdev->sdev_gendev, | 653 | error = attr_add(&sdev->sdev_gendev, |
654 | sdev->host->hostt->sdev_attrs[i]); | 654 | sdev->host->hostt->sdev_attrs[i]); |
655 | if (error) { | 655 | if (error) { |
656 | scsi_remove_device(sdev); | 656 | __scsi_remove_device(sdev); |
657 | goto out; | 657 | goto out; |
658 | } | 658 | } |
659 | } | 659 | } |
@@ -667,7 +667,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) | |||
667 | scsi_sysfs_sdev_attrs[i]); | 667 | scsi_sysfs_sdev_attrs[i]); |
668 | error = device_create_file(&sdev->sdev_gendev, attr); | 668 | error = device_create_file(&sdev->sdev_gendev, attr); |
669 | if (error) { | 669 | if (error) { |
670 | scsi_remove_device(sdev); | 670 | __scsi_remove_device(sdev); |
671 | goto out; | 671 | goto out; |
672 | } | 672 | } |
673 | } | 673 | } |
@@ -687,17 +687,10 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) | |||
687 | return error; | 687 | return error; |
688 | } | 688 | } |
689 | 689 | ||
690 | /** | 690 | void __scsi_remove_device(struct scsi_device *sdev) |
691 | * scsi_remove_device - unregister a device from the scsi bus | ||
692 | * @sdev: scsi_device to unregister | ||
693 | **/ | ||
694 | void scsi_remove_device(struct scsi_device *sdev) | ||
695 | { | 691 | { |
696 | struct Scsi_Host *shost = sdev->host; | ||
697 | |||
698 | down(&shost->scan_mutex); | ||
699 | if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0) | 692 | if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0) |
700 | goto out; | 693 | return; |
701 | 694 | ||
702 | class_device_unregister(&sdev->sdev_classdev); | 695 | class_device_unregister(&sdev->sdev_classdev); |
703 | device_del(&sdev->sdev_gendev); | 696 | device_del(&sdev->sdev_gendev); |
@@ -706,8 +699,17 @@ void scsi_remove_device(struct scsi_device *sdev) | |||
706 | sdev->host->hostt->slave_destroy(sdev); | 699 | sdev->host->hostt->slave_destroy(sdev); |
707 | transport_unregister_device(&sdev->sdev_gendev); | 700 | transport_unregister_device(&sdev->sdev_gendev); |
708 | put_device(&sdev->sdev_gendev); | 701 | put_device(&sdev->sdev_gendev); |
709 | out: | 702 | } |
710 | up(&shost->scan_mutex); | 703 | |
704 | /** | ||
705 | * scsi_remove_device - unregister a device from the scsi bus | ||
706 | * @sdev: scsi_device to unregister | ||
707 | **/ | ||
708 | void scsi_remove_device(struct scsi_device *sdev) | ||
709 | { | ||
710 | down(&sdev->host->scan_mutex); | ||
711 | __scsi_remove_device(sdev); | ||
712 | up(&sdev->host->scan_mutex); | ||
711 | } | 713 | } |
712 | EXPORT_SYMBOL(scsi_remove_device); | 714 | EXPORT_SYMBOL(scsi_remove_device); |
713 | 715 | ||
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c new file mode 100644 index 000000000000..ff724bbe6611 --- /dev/null +++ b/drivers/scsi/scsi_transport_sas.c | |||
@@ -0,0 +1,820 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Dell Inc. | ||
3 | * Released under GPL v2. | ||
4 | * | ||
5 | * Serial Attached SCSI (SAS) transport class. | ||
6 | * | ||
7 | * The SAS transport class contains common code to deal with SAS HBAs, | ||
8 | * an aproximated representation of SAS topologies in the driver model, | ||
9 | * and various sysfs attributes to expose these topologies and managment | ||
10 | * interfaces to userspace. | ||
11 | * | ||
12 | * In addition to the basic SCSI core objects this transport class | ||
13 | * introduces two additional intermediate objects: The SAS PHY | ||
14 | * as represented by struct sas_phy defines an "outgoing" PHY on | ||
15 | * a SAS HBA or Expander, and the SAS remote PHY represented by | ||
16 | * struct sas_rphy defines an "incoming" PHY on a SAS Expander or | ||
17 | * end device. Note that this is purely a software concept, the | ||
18 | * underlying hardware for a PHY and a remote PHY is the exactly | ||
19 | * the same. | ||
20 | * | ||
21 | * There is no concept of a SAS port in this code, users can see | ||
22 | * what PHYs form a wide port based on the port_identifier attribute, | ||
23 | * which is the same for all PHYs in a port. | ||
24 | */ | ||
25 | |||
26 | #include <linux/init.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/err.h> | ||
29 | |||
30 | #include <scsi/scsi_device.h> | ||
31 | #include <scsi/scsi_host.h> | ||
32 | #include <scsi/scsi_transport.h> | ||
33 | #include <scsi/scsi_transport_sas.h> | ||
34 | |||
35 | |||
36 | #define SAS_HOST_ATTRS 0 | ||
37 | #define SAS_PORT_ATTRS 11 | ||
38 | #define SAS_RPORT_ATTRS 5 | ||
39 | |||
40 | struct sas_internal { | ||
41 | struct scsi_transport_template t; | ||
42 | struct sas_function_template *f; | ||
43 | |||
44 | struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS]; | ||
45 | struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS]; | ||
46 | struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS]; | ||
47 | |||
48 | struct transport_container phy_attr_cont; | ||
49 | struct transport_container rphy_attr_cont; | ||
50 | |||
51 | /* | ||
52 | * The array of null terminated pointers to attributes | ||
53 | * needed by scsi_sysfs.c | ||
54 | */ | ||
55 | struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1]; | ||
56 | struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1]; | ||
57 | struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1]; | ||
58 | }; | ||
59 | #define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t) | ||
60 | |||
61 | struct sas_host_attrs { | ||
62 | struct list_head rphy_list; | ||
63 | spinlock_t lock; | ||
64 | u32 next_target_id; | ||
65 | }; | ||
66 | #define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) | ||
67 | |||
68 | |||
69 | /* | ||
70 | * Hack to allow attributes of the same name in different objects. | ||
71 | */ | ||
72 | #define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \ | ||
73 | struct class_device_attribute class_device_attr_##_prefix##_##_name = \ | ||
74 | __ATTR(_name,_mode,_show,_store) | ||
75 | |||
76 | |||
77 | /* | ||
78 | * Pretty printing helpers | ||
79 | */ | ||
80 | |||
81 | #define sas_bitfield_name_match(title, table) \ | ||
82 | static ssize_t \ | ||
83 | get_sas_##title##_names(u32 table_key, char *buf) \ | ||
84 | { \ | ||
85 | char *prefix = ""; \ | ||
86 | ssize_t len = 0; \ | ||
87 | int i; \ | ||
88 | \ | ||
89 | for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ | ||
90 | if (table[i].value & table_key) { \ | ||
91 | len += sprintf(buf + len, "%s%s", \ | ||
92 | prefix, table[i].name); \ | ||
93 | prefix = ", "; \ | ||
94 | } \ | ||
95 | } \ | ||
96 | len += sprintf(buf + len, "\n"); \ | ||
97 | return len; \ | ||
98 | } | ||
99 | |||
100 | #define sas_bitfield_name_search(title, table) \ | ||
101 | static ssize_t \ | ||
102 | get_sas_##title##_names(u32 table_key, char *buf) \ | ||
103 | { \ | ||
104 | ssize_t len = 0; \ | ||
105 | int i; \ | ||
106 | \ | ||
107 | for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \ | ||
108 | if (table[i].value == table_key) { \ | ||
109 | len += sprintf(buf + len, "%s", \ | ||
110 | table[i].name); \ | ||
111 | break; \ | ||
112 | } \ | ||
113 | } \ | ||
114 | len += sprintf(buf + len, "\n"); \ | ||
115 | return len; \ | ||
116 | } | ||
117 | |||
118 | static struct { | ||
119 | u32 value; | ||
120 | char *name; | ||
121 | } sas_device_type_names[] = { | ||
122 | { SAS_PHY_UNUSED, "unused" }, | ||
123 | { SAS_END_DEVICE, "end device" }, | ||
124 | { SAS_EDGE_EXPANDER_DEVICE, "edge expander" }, | ||
125 | { SAS_FANOUT_EXPANDER_DEVICE, "fanout expander" }, | ||
126 | }; | ||
127 | sas_bitfield_name_search(device_type, sas_device_type_names) | ||
128 | |||
129 | |||
130 | static struct { | ||
131 | u32 value; | ||
132 | char *name; | ||
133 | } sas_protocol_names[] = { | ||
134 | { SAS_PROTOCOL_SATA, "sata" }, | ||
135 | { SAS_PROTOCOL_SMP, "smp" }, | ||
136 | { SAS_PROTOCOL_STP, "stp" }, | ||
137 | { SAS_PROTOCOL_SSP, "ssp" }, | ||
138 | }; | ||
139 | sas_bitfield_name_match(protocol, sas_protocol_names) | ||
140 | |||
141 | static struct { | ||
142 | u32 value; | ||
143 | char *name; | ||
144 | } sas_linkspeed_names[] = { | ||
145 | { SAS_LINK_RATE_UNKNOWN, "Unknown" }, | ||
146 | { SAS_PHY_DISABLED, "Phy disabled" }, | ||
147 | { SAS_LINK_RATE_FAILED, "Link Rate failed" }, | ||
148 | { SAS_SATA_SPINUP_HOLD, "Spin-up hold" }, | ||
149 | { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, | ||
150 | { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, | ||
151 | }; | ||
152 | sas_bitfield_name_search(linkspeed, sas_linkspeed_names) | ||
153 | |||
154 | |||
155 | /* | ||
156 | * SAS host attributes | ||
157 | */ | ||
158 | |||
159 | static int sas_host_setup(struct transport_container *tc, struct device *dev, | ||
160 | struct class_device *cdev) | ||
161 | { | ||
162 | struct Scsi_Host *shost = dev_to_shost(dev); | ||
163 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | ||
164 | |||
165 | INIT_LIST_HEAD(&sas_host->rphy_list); | ||
166 | spin_lock_init(&sas_host->lock); | ||
167 | sas_host->next_target_id = 0; | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static DECLARE_TRANSPORT_CLASS(sas_host_class, | ||
172 | "sas_host", sas_host_setup, NULL, NULL); | ||
173 | |||
174 | static int sas_host_match(struct attribute_container *cont, | ||
175 | struct device *dev) | ||
176 | { | ||
177 | struct Scsi_Host *shost; | ||
178 | struct sas_internal *i; | ||
179 | |||
180 | if (!scsi_is_host_device(dev)) | ||
181 | return 0; | ||
182 | shost = dev_to_shost(dev); | ||
183 | |||
184 | if (!shost->transportt) | ||
185 | return 0; | ||
186 | if (shost->transportt->host_attrs.ac.class != | ||
187 | &sas_host_class.class) | ||
188 | return 0; | ||
189 | |||
190 | i = to_sas_internal(shost->transportt); | ||
191 | return &i->t.host_attrs.ac == cont; | ||
192 | } | ||
193 | |||
194 | static int do_sas_phy_delete(struct device *dev, void *data) | ||
195 | { | ||
196 | if (scsi_is_sas_phy(dev)) | ||
197 | sas_phy_delete(dev_to_phy(dev)); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * sas_remove_host -- tear down a Scsi_Host's SAS data structures | ||
203 | * @shost: Scsi Host that is torn down | ||
204 | * | ||
205 | * Removes all SAS PHYs and remote PHYs for a given Scsi_Host. | ||
206 | * Must be called just before scsi_remove_host for SAS HBAs. | ||
207 | */ | ||
208 | void sas_remove_host(struct Scsi_Host *shost) | ||
209 | { | ||
210 | device_for_each_child(&shost->shost_gendev, NULL, do_sas_phy_delete); | ||
211 | } | ||
212 | EXPORT_SYMBOL(sas_remove_host); | ||
213 | |||
214 | |||
215 | /* | ||
216 | * SAS Port attributes | ||
217 | */ | ||
218 | |||
219 | #define sas_phy_show_simple(field, name, format_string, cast) \ | ||
220 | static ssize_t \ | ||
221 | show_sas_phy_##name(struct class_device *cdev, char *buf) \ | ||
222 | { \ | ||
223 | struct sas_phy *phy = transport_class_to_phy(cdev); \ | ||
224 | \ | ||
225 | return snprintf(buf, 20, format_string, cast phy->field); \ | ||
226 | } | ||
227 | |||
228 | #define sas_phy_simple_attr(field, name, format_string, type) \ | ||
229 | sas_phy_show_simple(field, name, format_string, (type)) \ | ||
230 | static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) | ||
231 | |||
232 | #define sas_phy_show_protocol(field, name) \ | ||
233 | static ssize_t \ | ||
234 | show_sas_phy_##name(struct class_device *cdev, char *buf) \ | ||
235 | { \ | ||
236 | struct sas_phy *phy = transport_class_to_phy(cdev); \ | ||
237 | \ | ||
238 | if (!phy->field) \ | ||
239 | return snprintf(buf, 20, "none\n"); \ | ||
240 | return get_sas_protocol_names(phy->field, buf); \ | ||
241 | } | ||
242 | |||
243 | #define sas_phy_protocol_attr(field, name) \ | ||
244 | sas_phy_show_protocol(field, name) \ | ||
245 | static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) | ||
246 | |||
247 | #define sas_phy_show_linkspeed(field) \ | ||
248 | static ssize_t \ | ||
249 | show_sas_phy_##field(struct class_device *cdev, char *buf) \ | ||
250 | { \ | ||
251 | struct sas_phy *phy = transport_class_to_phy(cdev); \ | ||
252 | \ | ||
253 | return get_sas_linkspeed_names(phy->field, buf); \ | ||
254 | } | ||
255 | |||
256 | #define sas_phy_linkspeed_attr(field) \ | ||
257 | sas_phy_show_linkspeed(field) \ | ||
258 | static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) | ||
259 | |||
260 | static ssize_t | ||
261 | show_sas_device_type(struct class_device *cdev, char *buf) | ||
262 | { | ||
263 | struct sas_phy *phy = transport_class_to_phy(cdev); | ||
264 | |||
265 | if (!phy->identify.device_type) | ||
266 | return snprintf(buf, 20, "none\n"); | ||
267 | return get_sas_device_type_names(phy->identify.device_type, buf); | ||
268 | } | ||
269 | |||
270 | static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); | ||
271 | |||
272 | sas_phy_protocol_attr(identify.initiator_port_protocols, | ||
273 | initiator_port_protocols); | ||
274 | sas_phy_protocol_attr(identify.target_port_protocols, | ||
275 | target_port_protocols); | ||
276 | sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", | ||
277 | unsigned long long); | ||
278 | sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); | ||
279 | sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8); | ||
280 | sas_phy_linkspeed_attr(negotiated_linkrate); | ||
281 | sas_phy_linkspeed_attr(minimum_linkrate_hw); | ||
282 | sas_phy_linkspeed_attr(minimum_linkrate); | ||
283 | sas_phy_linkspeed_attr(maximum_linkrate_hw); | ||
284 | sas_phy_linkspeed_attr(maximum_linkrate); | ||
285 | |||
286 | |||
287 | static DECLARE_TRANSPORT_CLASS(sas_phy_class, | ||
288 | "sas_phy", NULL, NULL, NULL); | ||
289 | |||
290 | static int sas_phy_match(struct attribute_container *cont, struct device *dev) | ||
291 | { | ||
292 | struct Scsi_Host *shost; | ||
293 | struct sas_internal *i; | ||
294 | |||
295 | if (!scsi_is_sas_phy(dev)) | ||
296 | return 0; | ||
297 | shost = dev_to_shost(dev->parent); | ||
298 | |||
299 | if (!shost->transportt) | ||
300 | return 0; | ||
301 | if (shost->transportt->host_attrs.ac.class != | ||
302 | &sas_host_class.class) | ||
303 | return 0; | ||
304 | |||
305 | i = to_sas_internal(shost->transportt); | ||
306 | return &i->phy_attr_cont.ac == cont; | ||
307 | } | ||
308 | |||
309 | static void sas_phy_release(struct device *dev) | ||
310 | { | ||
311 | struct sas_phy *phy = dev_to_phy(dev); | ||
312 | |||
313 | put_device(dev->parent); | ||
314 | kfree(phy); | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * sas_phy_alloc -- allocates and initialize a SAS PHY structure | ||
319 | * @parent: Parent device | ||
320 | * @number: Port number | ||
321 | * | ||
322 | * Allocates an SAS PHY structure. It will be added in the device tree | ||
323 | * below the device specified by @parent, which has to be either a Scsi_Host | ||
324 | * or sas_rphy. | ||
325 | * | ||
326 | * Returns: | ||
327 | * SAS PHY allocated or %NULL if the allocation failed. | ||
328 | */ | ||
329 | struct sas_phy *sas_phy_alloc(struct device *parent, int number) | ||
330 | { | ||
331 | struct Scsi_Host *shost = dev_to_shost(parent); | ||
332 | struct sas_phy *phy; | ||
333 | |||
334 | phy = kmalloc(sizeof(*phy), GFP_KERNEL); | ||
335 | if (!phy) | ||
336 | return NULL; | ||
337 | memset(phy, 0, sizeof(*phy)); | ||
338 | |||
339 | get_device(parent); | ||
340 | |||
341 | phy->number = number; | ||
342 | |||
343 | device_initialize(&phy->dev); | ||
344 | phy->dev.parent = get_device(parent); | ||
345 | phy->dev.release = sas_phy_release; | ||
346 | sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number); | ||
347 | |||
348 | transport_setup_device(&phy->dev); | ||
349 | |||
350 | return phy; | ||
351 | } | ||
352 | EXPORT_SYMBOL(sas_phy_alloc); | ||
353 | |||
354 | /** | ||
355 | * sas_phy_add -- add a SAS PHY to the device hierachy | ||
356 | * @phy: The PHY to be added | ||
357 | * | ||
358 | * Publishes a SAS PHY to the rest of the system. | ||
359 | */ | ||
360 | int sas_phy_add(struct sas_phy *phy) | ||
361 | { | ||
362 | int error; | ||
363 | |||
364 | error = device_add(&phy->dev); | ||
365 | if (!error) { | ||
366 | transport_add_device(&phy->dev); | ||
367 | transport_configure_device(&phy->dev); | ||
368 | } | ||
369 | |||
370 | return error; | ||
371 | } | ||
372 | EXPORT_SYMBOL(sas_phy_add); | ||
373 | |||
374 | /** | ||
375 | * sas_phy_free -- free a SAS PHY | ||
376 | * @phy: SAS PHY to free | ||
377 | * | ||
378 | * Frees the specified SAS PHY. | ||
379 | * | ||
380 | * Note: | ||
381 | * This function must only be called on a PHY that has not | ||
382 | * sucessfully been added using sas_phy_add(). | ||
383 | */ | ||
384 | void sas_phy_free(struct sas_phy *phy) | ||
385 | { | ||
386 | transport_destroy_device(&phy->dev); | ||
387 | put_device(phy->dev.parent); | ||
388 | put_device(phy->dev.parent); | ||
389 | put_device(phy->dev.parent); | ||
390 | kfree(phy); | ||
391 | } | ||
392 | EXPORT_SYMBOL(sas_phy_free); | ||
393 | |||
394 | /** | ||
395 | * sas_phy_delete -- remove SAS PHY | ||
396 | * @phy: SAS PHY to remove | ||
397 | * | ||
398 | * Removes the specified SAS PHY. If the SAS PHY has an | ||
399 | * associated remote PHY it is removed before. | ||
400 | */ | ||
401 | void | ||
402 | sas_phy_delete(struct sas_phy *phy) | ||
403 | { | ||
404 | struct device *dev = &phy->dev; | ||
405 | |||
406 | if (phy->rphy) | ||
407 | sas_rphy_delete(phy->rphy); | ||
408 | |||
409 | transport_remove_device(dev); | ||
410 | device_del(dev); | ||
411 | transport_destroy_device(dev); | ||
412 | put_device(dev->parent); | ||
413 | } | ||
414 | EXPORT_SYMBOL(sas_phy_delete); | ||
415 | |||
416 | /** | ||
417 | * scsi_is_sas_phy -- check if a struct device represents a SAS PHY | ||
418 | * @dev: device to check | ||
419 | * | ||
420 | * Returns: | ||
421 | * %1 if the device represents a SAS PHY, %0 else | ||
422 | */ | ||
423 | int scsi_is_sas_phy(const struct device *dev) | ||
424 | { | ||
425 | return dev->release == sas_phy_release; | ||
426 | } | ||
427 | EXPORT_SYMBOL(scsi_is_sas_phy); | ||
428 | |||
429 | /* | ||
430 | * SAS remote PHY attributes. | ||
431 | */ | ||
432 | |||
433 | #define sas_rphy_show_simple(field, name, format_string, cast) \ | ||
434 | static ssize_t \ | ||
435 | show_sas_rphy_##name(struct class_device *cdev, char *buf) \ | ||
436 | { \ | ||
437 | struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ | ||
438 | \ | ||
439 | return snprintf(buf, 20, format_string, cast rphy->field); \ | ||
440 | } | ||
441 | |||
442 | #define sas_rphy_simple_attr(field, name, format_string, type) \ | ||
443 | sas_rphy_show_simple(field, name, format_string, (type)) \ | ||
444 | static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ | ||
445 | show_sas_rphy_##name, NULL) | ||
446 | |||
447 | #define sas_rphy_show_protocol(field, name) \ | ||
448 | static ssize_t \ | ||
449 | show_sas_rphy_##name(struct class_device *cdev, char *buf) \ | ||
450 | { \ | ||
451 | struct sas_rphy *rphy = transport_class_to_rphy(cdev); \ | ||
452 | \ | ||
453 | if (!rphy->field) \ | ||
454 | return snprintf(buf, 20, "none\n"); \ | ||
455 | return get_sas_protocol_names(rphy->field, buf); \ | ||
456 | } | ||
457 | |||
458 | #define sas_rphy_protocol_attr(field, name) \ | ||
459 | sas_rphy_show_protocol(field, name) \ | ||
460 | static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \ | ||
461 | show_sas_rphy_##name, NULL) | ||
462 | |||
463 | static ssize_t | ||
464 | show_sas_rphy_device_type(struct class_device *cdev, char *buf) | ||
465 | { | ||
466 | struct sas_rphy *rphy = transport_class_to_rphy(cdev); | ||
467 | |||
468 | if (!rphy->identify.device_type) | ||
469 | return snprintf(buf, 20, "none\n"); | ||
470 | return get_sas_device_type_names( | ||
471 | rphy->identify.device_type, buf); | ||
472 | } | ||
473 | |||
474 | static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO, | ||
475 | show_sas_rphy_device_type, NULL); | ||
476 | |||
477 | sas_rphy_protocol_attr(identify.initiator_port_protocols, | ||
478 | initiator_port_protocols); | ||
479 | sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); | ||
480 | sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", | ||
481 | unsigned long long); | ||
482 | sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); | ||
483 | |||
484 | static DECLARE_TRANSPORT_CLASS(sas_rphy_class, | ||
485 | "sas_rphy", NULL, NULL, NULL); | ||
486 | |||
487 | static int sas_rphy_match(struct attribute_container *cont, struct device *dev) | ||
488 | { | ||
489 | struct Scsi_Host *shost; | ||
490 | struct sas_internal *i; | ||
491 | |||
492 | if (!scsi_is_sas_rphy(dev)) | ||
493 | return 0; | ||
494 | shost = dev_to_shost(dev->parent->parent); | ||
495 | |||
496 | if (!shost->transportt) | ||
497 | return 0; | ||
498 | if (shost->transportt->host_attrs.ac.class != | ||
499 | &sas_host_class.class) | ||
500 | return 0; | ||
501 | |||
502 | i = to_sas_internal(shost->transportt); | ||
503 | return &i->rphy_attr_cont.ac == cont; | ||
504 | } | ||
505 | |||
506 | static void sas_rphy_release(struct device *dev) | ||
507 | { | ||
508 | struct sas_rphy *rphy = dev_to_rphy(dev); | ||
509 | |||
510 | put_device(dev->parent); | ||
511 | kfree(rphy); | ||
512 | } | ||
513 | |||
514 | /** | ||
515 | * sas_rphy_alloc -- allocates and initialize a SAS remote PHY structure | ||
516 | * @parent: SAS PHY this remote PHY is conneted to | ||
517 | * | ||
518 | * Allocates an SAS remote PHY structure, connected to @parent. | ||
519 | * | ||
520 | * Returns: | ||
521 | * SAS PHY allocated or %NULL if the allocation failed. | ||
522 | */ | ||
523 | struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent) | ||
524 | { | ||
525 | struct Scsi_Host *shost = dev_to_shost(&parent->dev); | ||
526 | struct sas_rphy *rphy; | ||
527 | |||
528 | rphy = kmalloc(sizeof(*rphy), GFP_KERNEL); | ||
529 | if (!rphy) { | ||
530 | put_device(&parent->dev); | ||
531 | return NULL; | ||
532 | } | ||
533 | memset(rphy, 0, sizeof(*rphy)); | ||
534 | |||
535 | device_initialize(&rphy->dev); | ||
536 | rphy->dev.parent = get_device(&parent->dev); | ||
537 | rphy->dev.release = sas_rphy_release; | ||
538 | sprintf(rphy->dev.bus_id, "rphy-%d:%d", | ||
539 | shost->host_no, parent->number); | ||
540 | transport_setup_device(&rphy->dev); | ||
541 | |||
542 | return rphy; | ||
543 | } | ||
544 | EXPORT_SYMBOL(sas_rphy_alloc); | ||
545 | |||
546 | /** | ||
547 | * sas_rphy_add -- add a SAS remote PHY to the device hierachy | ||
548 | * @rphy: The remote PHY to be added | ||
549 | * | ||
550 | * Publishes a SAS remote PHY to the rest of the system. | ||
551 | */ | ||
552 | int sas_rphy_add(struct sas_rphy *rphy) | ||
553 | { | ||
554 | struct sas_phy *parent = dev_to_phy(rphy->dev.parent); | ||
555 | struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); | ||
556 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | ||
557 | struct sas_identify *identify = &rphy->identify; | ||
558 | int error; | ||
559 | |||
560 | if (parent->rphy) | ||
561 | return -ENXIO; | ||
562 | parent->rphy = rphy; | ||
563 | |||
564 | error = device_add(&rphy->dev); | ||
565 | if (error) | ||
566 | return error; | ||
567 | transport_add_device(&rphy->dev); | ||
568 | transport_configure_device(&rphy->dev); | ||
569 | |||
570 | spin_lock(&sas_host->lock); | ||
571 | list_add_tail(&rphy->list, &sas_host->rphy_list); | ||
572 | if (identify->device_type == SAS_END_DEVICE && | ||
573 | (identify->target_port_protocols & | ||
574 | (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) | ||
575 | rphy->scsi_target_id = sas_host->next_target_id++; | ||
576 | else | ||
577 | rphy->scsi_target_id = -1; | ||
578 | spin_unlock(&sas_host->lock); | ||
579 | |||
580 | if (rphy->scsi_target_id != -1) { | ||
581 | scsi_scan_target(&rphy->dev, parent->number, | ||
582 | rphy->scsi_target_id, ~0, 0); | ||
583 | } | ||
584 | |||
585 | return 0; | ||
586 | } | ||
587 | EXPORT_SYMBOL(sas_rphy_add); | ||
588 | |||
589 | /** | ||
590 | * sas_rphy_free -- free a SAS remote PHY | ||
591 | * @rphy SAS remote PHY to free | ||
592 | * | ||
593 | * Frees the specified SAS remote PHY. | ||
594 | * | ||
595 | * Note: | ||
596 | * This function must only be called on a remote | ||
597 | * PHY that has not sucessfully been added using | ||
598 | * sas_rphy_add(). | ||
599 | */ | ||
600 | void sas_rphy_free(struct sas_rphy *rphy) | ||
601 | { | ||
602 | struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); | ||
603 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | ||
604 | |||
605 | spin_lock(&sas_host->lock); | ||
606 | list_del(&rphy->list); | ||
607 | spin_unlock(&sas_host->lock); | ||
608 | |||
609 | transport_destroy_device(&rphy->dev); | ||
610 | put_device(rphy->dev.parent); | ||
611 | put_device(rphy->dev.parent); | ||
612 | put_device(rphy->dev.parent); | ||
613 | kfree(rphy); | ||
614 | } | ||
615 | EXPORT_SYMBOL(sas_rphy_free); | ||
616 | |||
617 | /** | ||
618 | * sas_rphy_delete -- remove SAS remote PHY | ||
619 | * @rphy: SAS remote PHY to remove | ||
620 | * | ||
621 | * Removes the specified SAS remote PHY. | ||
622 | */ | ||
623 | void | ||
624 | sas_rphy_delete(struct sas_rphy *rphy) | ||
625 | { | ||
626 | struct device *dev = &rphy->dev; | ||
627 | struct sas_phy *parent = dev_to_phy(dev->parent); | ||
628 | struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); | ||
629 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | ||
630 | |||
631 | transport_destroy_device(&rphy->dev); | ||
632 | |||
633 | scsi_remove_target(&rphy->dev); | ||
634 | |||
635 | spin_lock(&sas_host->lock); | ||
636 | list_del(&rphy->list); | ||
637 | spin_unlock(&sas_host->lock); | ||
638 | |||
639 | transport_remove_device(dev); | ||
640 | device_del(dev); | ||
641 | transport_destroy_device(dev); | ||
642 | put_device(&parent->dev); | ||
643 | } | ||
644 | EXPORT_SYMBOL(sas_rphy_delete); | ||
645 | |||
646 | /** | ||
647 | * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY | ||
648 | * @dev: device to check | ||
649 | * | ||
650 | * Returns: | ||
651 | * %1 if the device represents a SAS remote PHY, %0 else | ||
652 | */ | ||
653 | int scsi_is_sas_rphy(const struct device *dev) | ||
654 | { | ||
655 | return dev->release == sas_rphy_release; | ||
656 | } | ||
657 | EXPORT_SYMBOL(scsi_is_sas_rphy); | ||
658 | |||
659 | |||
660 | /* | ||
661 | * SCSI scan helper | ||
662 | */ | ||
663 | |||
664 | static struct device *sas_target_parent(struct Scsi_Host *shost, | ||
665 | int channel, uint id) | ||
666 | { | ||
667 | struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); | ||
668 | struct sas_rphy *rphy; | ||
669 | struct device *dev = NULL; | ||
670 | |||
671 | spin_lock(&sas_host->lock); | ||
672 | list_for_each_entry(rphy, &sas_host->rphy_list, list) { | ||
673 | struct sas_phy *parent = dev_to_phy(rphy->dev.parent); | ||
674 | if (parent->number == channel && | ||
675 | rphy->scsi_target_id == id) | ||
676 | dev = &rphy->dev; | ||
677 | } | ||
678 | spin_unlock(&sas_host->lock); | ||
679 | |||
680 | return dev; | ||
681 | } | ||
682 | |||
683 | |||
684 | /* | ||
685 | * Setup / Teardown code | ||
686 | */ | ||
687 | |||
688 | #define SETUP_RPORT_ATTRIBUTE(field) \ | ||
689 | i->private_rphy_attrs[count] = class_device_attr_##field; \ | ||
690 | i->private_rphy_attrs[count].attr.mode = S_IRUGO; \ | ||
691 | i->private_rphy_attrs[count].store = NULL; \ | ||
692 | i->rphy_attrs[count] = &i->private_rphy_attrs[count]; \ | ||
693 | count++ | ||
694 | |||
695 | #define SETUP_PORT_ATTRIBUTE(field) \ | ||
696 | i->private_phy_attrs[count] = class_device_attr_##field; \ | ||
697 | i->private_phy_attrs[count].attr.mode = S_IRUGO; \ | ||
698 | i->private_phy_attrs[count].store = NULL; \ | ||
699 | i->phy_attrs[count] = &i->private_phy_attrs[count]; \ | ||
700 | count++ | ||
701 | |||
702 | |||
703 | /** | ||
704 | * sas_attach_transport -- instantiate SAS transport template | ||
705 | * @ft: SAS transport class function template | ||
706 | */ | ||
707 | struct scsi_transport_template * | ||
708 | sas_attach_transport(struct sas_function_template *ft) | ||
709 | { | ||
710 | struct sas_internal *i; | ||
711 | int count; | ||
712 | |||
713 | i = kmalloc(sizeof(struct sas_internal), GFP_KERNEL); | ||
714 | if (!i) | ||
715 | return NULL; | ||
716 | memset(i, 0, sizeof(struct sas_internal)); | ||
717 | |||
718 | i->t.target_parent = sas_target_parent; | ||
719 | |||
720 | i->t.host_attrs.ac.attrs = &i->host_attrs[0]; | ||
721 | i->t.host_attrs.ac.class = &sas_host_class.class; | ||
722 | i->t.host_attrs.ac.match = sas_host_match; | ||
723 | transport_container_register(&i->t.host_attrs); | ||
724 | i->t.host_size = sizeof(struct sas_host_attrs); | ||
725 | |||
726 | i->phy_attr_cont.ac.class = &sas_phy_class.class; | ||
727 | i->phy_attr_cont.ac.attrs = &i->phy_attrs[0]; | ||
728 | i->phy_attr_cont.ac.match = sas_phy_match; | ||
729 | transport_container_register(&i->phy_attr_cont); | ||
730 | |||
731 | i->rphy_attr_cont.ac.class = &sas_rphy_class.class; | ||
732 | i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0]; | ||
733 | i->rphy_attr_cont.ac.match = sas_rphy_match; | ||
734 | transport_container_register(&i->rphy_attr_cont); | ||
735 | |||
736 | i->f = ft; | ||
737 | |||
738 | count = 0; | ||
739 | i->host_attrs[count] = NULL; | ||
740 | |||
741 | count = 0; | ||
742 | SETUP_PORT_ATTRIBUTE(initiator_port_protocols); | ||
743 | SETUP_PORT_ATTRIBUTE(target_port_protocols); | ||
744 | SETUP_PORT_ATTRIBUTE(device_type); | ||
745 | SETUP_PORT_ATTRIBUTE(sas_address); | ||
746 | SETUP_PORT_ATTRIBUTE(phy_identifier); | ||
747 | SETUP_PORT_ATTRIBUTE(port_identifier); | ||
748 | SETUP_PORT_ATTRIBUTE(negotiated_linkrate); | ||
749 | SETUP_PORT_ATTRIBUTE(minimum_linkrate_hw); | ||
750 | SETUP_PORT_ATTRIBUTE(minimum_linkrate); | ||
751 | SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw); | ||
752 | SETUP_PORT_ATTRIBUTE(maximum_linkrate); | ||
753 | i->phy_attrs[count] = NULL; | ||
754 | |||
755 | count = 0; | ||
756 | SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols); | ||
757 | SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols); | ||
758 | SETUP_RPORT_ATTRIBUTE(rphy_device_type); | ||
759 | SETUP_RPORT_ATTRIBUTE(rphy_sas_address); | ||
760 | SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); | ||
761 | i->rphy_attrs[count] = NULL; | ||
762 | |||
763 | return &i->t; | ||
764 | } | ||
765 | EXPORT_SYMBOL(sas_attach_transport); | ||
766 | |||
767 | /** | ||
768 | * sas_release_transport -- release SAS transport template instance | ||
769 | * @t: transport template instance | ||
770 | */ | ||
771 | void sas_release_transport(struct scsi_transport_template *t) | ||
772 | { | ||
773 | struct sas_internal *i = to_sas_internal(t); | ||
774 | |||
775 | transport_container_unregister(&i->t.host_attrs); | ||
776 | transport_container_unregister(&i->phy_attr_cont); | ||
777 | transport_container_unregister(&i->rphy_attr_cont); | ||
778 | |||
779 | kfree(i); | ||
780 | } | ||
781 | EXPORT_SYMBOL(sas_release_transport); | ||
782 | |||
783 | static __init int sas_transport_init(void) | ||
784 | { | ||
785 | int error; | ||
786 | |||
787 | error = transport_class_register(&sas_host_class); | ||
788 | if (error) | ||
789 | goto out; | ||
790 | error = transport_class_register(&sas_phy_class); | ||
791 | if (error) | ||
792 | goto out_unregister_transport; | ||
793 | error = transport_class_register(&sas_rphy_class); | ||
794 | if (error) | ||
795 | goto out_unregister_phy; | ||
796 | |||
797 | return 0; | ||
798 | |||
799 | out_unregister_phy: | ||
800 | transport_class_unregister(&sas_phy_class); | ||
801 | out_unregister_transport: | ||
802 | transport_class_unregister(&sas_host_class); | ||
803 | out: | ||
804 | return error; | ||
805 | |||
806 | } | ||
807 | |||
808 | static void __exit sas_transport_exit(void) | ||
809 | { | ||
810 | transport_class_unregister(&sas_host_class); | ||
811 | transport_class_unregister(&sas_phy_class); | ||
812 | transport_class_unregister(&sas_rphy_class); | ||
813 | } | ||
814 | |||
815 | MODULE_AUTHOR("Christoph Hellwig"); | ||
816 | MODULE_DESCRIPTION("SAS Transphy Attributes"); | ||
817 | MODULE_LICENSE("GPL"); | ||
818 | |||
819 | module_init(sas_transport_init); | ||
820 | module_exit(sas_transport_exit); | ||
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index b1b69d738d08..9ea4765d1d12 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -61,7 +61,7 @@ static int sg_version_num = 30533; /* 2 digits for each component */ | |||
61 | 61 | ||
62 | #ifdef CONFIG_SCSI_PROC_FS | 62 | #ifdef CONFIG_SCSI_PROC_FS |
63 | #include <linux/proc_fs.h> | 63 | #include <linux/proc_fs.h> |
64 | static char *sg_version_date = "20050901"; | 64 | static char *sg_version_date = "20050908"; |
65 | 65 | ||
66 | static int sg_proc_init(void); | 66 | static int sg_proc_init(void); |
67 | static void sg_proc_cleanup(void); | 67 | static void sg_proc_cleanup(void); |
@@ -1299,7 +1299,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) | |||
1299 | sg_rb_correct4mmap(rsv_schp, 1); /* do only once per fd lifetime */ | 1299 | sg_rb_correct4mmap(rsv_schp, 1); /* do only once per fd lifetime */ |
1300 | sfp->mmap_called = 1; | 1300 | sfp->mmap_called = 1; |
1301 | } | 1301 | } |
1302 | vma->vm_flags |= (VM_RESERVED | VM_IO); | 1302 | vma->vm_flags |= VM_RESERVED; |
1303 | vma->vm_private_data = sfp; | 1303 | vma->vm_private_data = sfp; |
1304 | vma->vm_ops = &sg_mmap_vm_ops; | 1304 | vma->vm_ops = &sg_mmap_vm_ops; |
1305 | return 0; | 1305 | return 0; |