diff options
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; |
