diff options
Diffstat (limited to 'drivers/scsi')
79 files changed, 2355 insertions, 707 deletions
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 80dc3ac12cd..89fc1c8af86 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -309,9 +309,6 @@ NCR_700_detect(struct scsi_host_template *tpnt, hostdata->msgin = memory + MSGIN_OFFSET; hostdata->msgout = memory + MSGOUT_OFFSET; hostdata->status = memory + STATUS_OFFSET; - /* all of these offsets are L1_CACHE_BYTES separated. It is fatal - * if this isn't sufficient separation to avoid dma flushing issues */ - BUG_ON(!dma_is_consistent(hostdata->dev, pScript) && L1_CACHE_BYTES < dma_get_cache_alignment()); hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET); hostdata->dev = dev; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 158284f0573..bbf91aec64f 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -370,6 +370,14 @@ config ISCSI_TCP http://open-iscsi.org +config ISCSI_BOOT_SYSFS + tristate "iSCSI Boot Sysfs Interface" + default n + help + This option enables support for exposing iSCSI boot information + via sysfs to userspace. If you wish to export this information, + say Y. Otherwise, say N. + source "drivers/scsi/cxgb3i/Kconfig" source "drivers/scsi/bnx2i/Kconfig" source "drivers/scsi/be2iscsi/Kconfig" @@ -1853,7 +1861,7 @@ config ZFCP_DIF config SCSI_PMCRAID tristate "PMC SIERRA Linux MaxRAID adapter support" - depends on PCI && SCSI + depends on PCI && SCSI && NET ---help--- This driver supports the PMC SIERRA MaxRAID adapters. diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 2a3fca2eca6..2703c6ec5e3 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_FCOE) += fcoe/ obj-$(CONFIG_FCOE_FNIC) += fnic/ obj-$(CONFIG_ISCSI_TCP) += libiscsi.o libiscsi_tcp.o iscsi_tcp.o obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o +obj-$(CONFIG_ISCSI_BOOT_SYSFS) += iscsi_boot_sysfs.o obj-$(CONFIG_SCSI_A4000T) += 53c700.o a4000t.o obj-$(CONFIG_SCSI_ZORRO7XX) += 53c700.o zorro7xx.o obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index f92da9fd5f2..5d2f148889a 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1857,7 +1857,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase #endif /* KLL May need eop and parity in 53c400 */ if (hostdata->flags & FLAG_NCR53C400) - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_PAR_CHECK | MR_ENABLE_PAR_INTR | MR_ENABLE_EOP_INTR | MR_DMA_MODE | MR_MONITOR_BSY); + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | + MR_ENABLE_PAR_CHECK | MR_ENABLE_PAR_INTR | + MR_ENABLE_EOP_INTR | MR_MONITOR_BSY); else NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE); #endif /* def REAL_DMA */ diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 04057ab72a8..84d77fd86e5 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c @@ -352,9 +352,8 @@ static int aac_rx_check_health(struct aac_dev *dev) pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), post, paddr); if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) { - ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10); - ret <<= 4; - ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10); + ret = (hex_to_bin(buffer[2]) << 4) + + hex_to_bin(buffer[3]); } pci_free_consistent(dev->pdev, 512, buffer, baddr); return ret; diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 2a8cf137f60..4f785f254c1 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c @@ -52,22 +52,6 @@ #define SCSI_BUF_PA(address) isa_virt_to_bus(address) #define SCSI_SG_PA(sgent) (isa_page_to_bus(sg_page((sgent))) + (sgent)->offset) -static void BAD_SG_DMA(Scsi_Cmnd * SCpnt, - struct scatterlist *sgp, - int nseg, - int badseg) -{ - printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%llx length %u\n", - badseg, nseg, sg_virt(sgp), - (unsigned long long)SCSI_SG_PA(sgp), - sgp->length); - - /* - * Not safe to continue. - */ - panic("Buffer at physical address > 16Mb used for aha1542"); -} - #include<linux/stat.h> #ifdef DEBUG @@ -691,8 +675,6 @@ static int aha1542_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) } scsi_for_each_sg(SCpnt, sg, sg_count, i) { any2scsi(cptr[i].dataptr, SCSI_SG_PA(sg)); - if (SCSI_SG_PA(sg) + sg->length - 1 > ISA_DMA_THRESHOLD) - BAD_SG_DMA(SCpnt, scsi_sglist(SCpnt), sg_count, i); any2scsi(cptr[i].datalen, sg->length); }; any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain)); @@ -1133,16 +1115,9 @@ static int __init aha1542_detect(struct scsi_host_template * tpnt) release_region(bases[indx], 4); continue; } - /* For now we do this - until kmalloc is more intelligent - we are resigned to stupid hacks like this */ - if (SCSI_BUF_PA(shpnt) >= ISA_DMA_THRESHOLD) { - printk(KERN_ERR "Invalid address for shpnt with 1542.\n"); - goto unregister; - } if (!aha1542_test_port(bases[indx], shpnt)) goto unregister; - base_io = bases[indx]; /* Set the Bus on/off-times as not to ruin floppy performance */ diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 24ac2315c5c..3b7e83d2dab 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -688,9 +688,9 @@ static int asd_register_sas_ha(struct asd_ha_struct *asd_ha) { int i; struct asd_sas_phy **sas_phys = - kmalloc(ASD_MAX_PHYS * sizeof(struct asd_sas_phy), GFP_KERNEL); + kcalloc(ASD_MAX_PHYS, sizeof(*sas_phys), GFP_KERNEL); struct asd_sas_port **sas_ports = - kmalloc(ASD_MAX_PHYS * sizeof(struct asd_sas_port), GFP_KERNEL); + kcalloc(ASD_MAX_PHYS, sizeof(*sas_ports), GFP_KERNEL); if (!sas_phys || !sas_ports) { kfree(sas_phys); diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 07fdfe57e38..a4e04c50c43 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -192,7 +192,6 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { .attr = { .name = "mu_read", .mode = S_IRUSR , - .owner = THIS_MODULE, }, .size = 1032, .read = arcmsr_sysfs_iop_message_read, @@ -202,7 +201,6 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { .attr = { .name = "mu_write", .mode = S_IWUSR, - .owner = THIS_MODULE, }, .size = 1032, .write = arcmsr_sysfs_iop_message_write, @@ -212,7 +210,6 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = { .attr = { .name = "mu_clear", .mode = S_IWUSR, - .owner = THIS_MODULE, }, .size = 1, .write = arcmsr_sysfs_iop_message_clear, diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 95a895dd4f1..c8dc392edd5 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -56,6 +56,7 @@ #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/timer.h> +#include <linux/slab.h> #include <linux/pci.h> #include <linux/aer.h> #include <asm/dma.h> diff --git a/drivers/scsi/be2iscsi/Kconfig b/drivers/scsi/be2iscsi/Kconfig index 84c275fb9f6..ceaca32e788 100644 --- a/drivers/scsi/be2iscsi/Kconfig +++ b/drivers/scsi/be2iscsi/Kconfig @@ -2,6 +2,7 @@ config BE2ISCSI tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2" depends on PCI && SCSI && NET select SCSI_ISCSI_ATTRS + select ISCSI_BOOT_SYSFS help This driver implements the iSCSI functionality for ServerEngines' diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h index 40641d0845f..5218de4ab35 100644 --- a/drivers/scsi/be2iscsi/be_cmds.h +++ b/drivers/scsi/be2iscsi/be_cmds.h @@ -162,6 +162,13 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES 2 #define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3 #define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7 +#define OPCODE_COMMON_ISCSI_NTWK_SET_VLAN 14 +#define OPCODE_COMMON_ISCSI_NTWK_CONFIGURE_STATELESS_IP_ADDR 17 +#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_IP_ADDR 21 +#define OPCODE_COMMON_ISCSI_NTWK_GET_DEFAULT_GATEWAY 22 +#define OPCODE_COMMON_ISCSI_NTWK_MODIFY_DEFAULT_GATEWAY 23 +#define OPCODE_COMMON_ISCSI_NTWK_GET_ALL_IF_ID 24 +#define OPCODE_COMMON_ISCSI_NTWK_GET_IF_INFO 25 #define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61 #define OPCODE_COMMON_ISCSI_DEFQ_CREATE 64 #define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65 @@ -237,11 +244,109 @@ struct be_cmd_resp_eq_create { u16 rsvd0; /* sword */ } __packed; +struct mgmt_chap_format { + u32 flags; + u8 intr_chap_name[256]; + u8 intr_secret[16]; + u8 target_chap_name[256]; + u8 target_secret[16]; + u16 intr_chap_name_length; + u16 intr_secret_length; + u16 target_chap_name_length; + u16 target_secret_length; +} __packed; + +struct mgmt_auth_method_format { + u8 auth_method_type; + u8 padding[3]; + struct mgmt_chap_format chap; +} __packed; + +struct mgmt_conn_login_options { + u8 flags; + u8 header_digest; + u8 data_digest; + u8 rsvd0; + u32 max_recv_datasegment_len_ini; + u32 max_recv_datasegment_len_tgt; + u32 tcp_mss; + u32 tcp_window_size; + struct mgmt_auth_method_format auth_data; +} __packed; + +struct ip_address_format { + u16 size_of_structure; + u8 reserved; + u8 ip_type; + u8 ip_address[16]; + u32 rsvd0; +} __packed; + +struct mgmt_conn_info { + u32 connection_handle; + u32 connection_status; + u16 src_port; + u16 dest_port; + u16 dest_port_redirected; + u16 cid; + u32 estimated_throughput; + struct ip_address_format src_ipaddr; + struct ip_address_format dest_ipaddr; + struct ip_address_format dest_ipaddr_redirected; + struct mgmt_conn_login_options negotiated_login_options; +} __packed; + +struct mgmt_session_login_options { + u8 flags; + u8 error_recovery_level; + u16 rsvd0; + u32 first_burst_length; + u32 max_burst_length; + u16 max_connections; + u16 max_outstanding_r2t; + u16 default_time2wait; + u16 default_time2retain; +} __packed; + +struct mgmt_session_info { + u32 session_handle; + u32 status; + u8 isid[6]; + u16 tsih; + u32 session_flags; + u16 conn_count; + u16 pad; + u8 target_name[224]; + u8 initiator_iscsiname[224]; + struct mgmt_session_login_options negotiated_login_options; + struct mgmt_conn_info conn_list[1]; +} __packed; + +struct be_cmd_req_get_session { + struct be_cmd_req_hdr hdr; + u32 session_handle; +} __packed; + +struct be_cmd_resp_get_session { + struct be_cmd_resp_hdr hdr; + struct mgmt_session_info session_info; +} __packed; + struct mac_addr { u16 size_of_struct; u8 addr[ETH_ALEN]; } __packed; +struct be_cmd_req_get_boot_target { + struct be_cmd_req_hdr hdr; +} __packed; + +struct be_cmd_resp_get_boot_target { + struct be_cmd_resp_hdr hdr; + u32 boot_session_count; + int boot_session_handle; +}; + struct be_cmd_req_mac_query { struct be_cmd_req_hdr hdr; u8 type; @@ -426,6 +531,11 @@ int be_poll_mcc(struct be_ctrl_info *ctrl); int mgmt_check_supported_fw(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba); unsigned int be_cmd_get_mac_addr(struct beiscsi_hba *phba); +unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba); +unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba, + u32 boot_session_handle, + struct be_dma_mem *nonemb_cmd); + void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag); /*ISCSI Functuions */ int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); @@ -601,14 +711,6 @@ struct be_eq_delay_params_in { struct eq_delay delay[8]; } __packed; -struct ip_address_format { - u16 size_of_structure; - u8 reserved; - u8 ip_type; - u8 ip_address[16]; - u32 rsvd0; -} __packed; - struct tcp_connect_and_offload_in { struct be_cmd_req_hdr hdr; struct ip_address_format ip_address; @@ -688,18 +790,29 @@ struct be_fw_cfg { u32 function_caps; } __packed; -#define CMD_ISCSI_COMMAND_INVALIDATE 1 -#define ISCSI_OPCODE_SCSI_DATA_OUT 5 +struct be_all_if_id { + struct be_cmd_req_hdr hdr; + u32 if_count; + u32 if_hndl_list[1]; +} __packed; + +#define ISCSI_OPCODE_SCSI_DATA_OUT 5 +#define OPCODE_COMMON_MODIFY_EQ_DELAY 41 +#define OPCODE_COMMON_ISCSI_CLEANUP 59 +#define OPCODE_COMMON_TCP_UPLOAD 56 #define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70 -#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 -#define OPCODE_COMMON_MODIFY_EQ_DELAY 41 -#define OPCODE_COMMON_ISCSI_CLEANUP 59 -#define OPCODE_COMMON_TCP_UPLOAD 56 #define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1 -/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ -#define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001 -#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002 +#define OPCODE_ISCSI_INI_CFG_GET_HBA_NAME 6 +#define OPCODE_ISCSI_INI_CFG_SET_HBA_NAME 7 +#define OPCODE_ISCSI_INI_SESSION_GET_A_SESSION 14 +#define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 +#define OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET 52 + +/* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ +#define CMD_ISCSI_COMMAND_INVALIDATE 1 +#define CMD_ISCSI_CONNECTION_INVALIDATE 0x8001 +#define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 0x8002 #define INI_WR_CMD 1 /* Initiator write command */ #define INI_TMF_CMD 2 /* Initiator TMF command */ diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 6d63e7b312c..7d4d2275573 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -300,40 +300,16 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf) { struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); - struct be_cmd_resp_get_mac_addr *resp; - struct be_mcc_wrb *wrb; - unsigned int tag, wrb_num; int len = 0; - unsigned short status, extd_status; - struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + int status; SE_DEBUG(DBG_LVL_8, "In beiscsi_get_host_param, param= %d\n", param); switch (param) { case ISCSI_HOST_PARAM_HWADDRESS: - tag = be_cmd_get_mac_addr(phba); - if (!tag) { - SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); - return -EAGAIN; - } else - wait_event_interruptible(phba->ctrl.mcc_wait[tag], - phba->ctrl.mcc_numtag[tag]); - - wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; - extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; - status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; - if (status || extd_status) { - SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" - " status = %d extd_status = %d\n", - status, extd_status); - free_mcc_tag(&phba->ctrl, tag); - return -EAGAIN; - } else { - wrb = queue_get_wrb(mccq, wrb_num); - free_mcc_tag(&phba->ctrl, tag); - resp = embedded_payload(wrb); - memcpy(phba->mac_address, resp->mac_address, ETH_ALEN); - len = sysfs_format_mac(buf, phba->mac_address, - ETH_ALEN); + status = beiscsi_get_macaddr(buf, phba); + if (status < 0) { + SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n"); + return status; } break; default: @@ -342,6 +318,48 @@ int beiscsi_get_host_param(struct Scsi_Host *shost, return len; } +int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba) +{ + struct be_cmd_resp_get_mac_addr *resp; + struct be_mcc_wrb *wrb; + unsigned int tag, wrb_num; + unsigned short status, extd_status; + struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + int rc; + + if (phba->read_mac_address) + return sysfs_format_mac(buf, phba->mac_address, + ETH_ALEN); + + tag = be_cmd_get_mac_addr(phba); + if (!tag) { + SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); + return -EBUSY; + } else + wait_event_interruptible(phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag]); + + wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; + extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; + status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; + if (status || extd_status) { + SE_DEBUG(DBG_LVL_1, "Failed to get be_cmd_get_mac_addr" + " status = %d extd_status = %d\n", + status, extd_status); + free_mcc_tag(&phba->ctrl, tag); + return -EAGAIN; + } + wrb = queue_get_wrb(mccq, wrb_num); + free_mcc_tag(&phba->ctrl, tag); + resp = embedded_payload(wrb); + memcpy(phba->mac_address, resp->mac_address, ETH_ALEN); + rc = sysfs_format_mac(buf, phba->mac_address, + ETH_ALEN); + phba->read_mac_address = 1; + return rc; +} + + /** * beiscsi_conn_get_stats - get the iscsi stats * @cls_conn: pointer to iscsi cls conn diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h index 870cdb2a73e..8950a702b9f 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.h +++ b/drivers/scsi/be2iscsi/be_iscsi.h @@ -54,6 +54,8 @@ int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, int beiscsi_get_host_param(struct Scsi_Host *shost, enum iscsi_host_param param, char *buf); +int beiscsi_get_macaddr(char *buf, struct beiscsi_hba *phba); + int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf, int buflen); diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 7436c5ad569..8220bde6c04 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -26,6 +26,7 @@ #include <linux/string.h> #include <linux/kernel.h> #include <linux/semaphore.h> +#include <linux/iscsi_boot_sysfs.h> #include <scsi/libiscsi.h> #include <scsi/scsi_transport_iscsi.h> @@ -211,6 +212,218 @@ unlock: return rc; } +static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) +{ + struct beiscsi_hba *phba = data; + char *str = buf; + int rc; + + switch (type) { + case ISCSI_BOOT_TGT_NAME: + rc = sprintf(buf, "%.*s\n", + (int)strlen(phba->boot_sess.target_name), + (char *)&phba->boot_sess.target_name); + break; + case ISCSI_BOOT_TGT_IP_ADDR: + if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1) + rc = sprintf(buf, "%pI4\n", + (char *)&phba->boot_sess.conn_list[0]. + dest_ipaddr.ip_address); + else + rc = sprintf(str, "%pI6\n", + (char *)&phba->boot_sess.conn_list[0]. + dest_ipaddr.ip_address); + break; + case ISCSI_BOOT_TGT_PORT: + rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0]. + dest_port); + break; + + case ISCSI_BOOT_TGT_CHAP_NAME: + rc = sprintf(str, "%.*s\n", + phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + target_chap_name_length, + (char *)&phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + target_chap_name); + break; + case ISCSI_BOOT_TGT_CHAP_SECRET: + rc = sprintf(str, "%.*s\n", + phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + target_secret_length, + (char *)&phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + target_secret); + + break; + case ISCSI_BOOT_TGT_REV_CHAP_NAME: + rc = sprintf(str, "%.*s\n", + phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + intr_chap_name_length, + (char *)&phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + intr_chap_name); + + break; + case ISCSI_BOOT_TGT_REV_CHAP_SECRET: + rc = sprintf(str, "%.*s\n", + phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + intr_secret_length, + (char *)&phba->boot_sess.conn_list[0]. + negotiated_login_options.auth_data.chap. + intr_secret); + break; + case ISCSI_BOOT_TGT_FLAGS: + rc = sprintf(str, "2\n"); + break; + case ISCSI_BOOT_TGT_NIC_ASSOC: + rc = sprintf(str, "0\n"); + break; + default: + rc = -ENOSYS; + break; + } + return rc; +} + +static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf) +{ + struct beiscsi_hba *phba = data; + char *str = buf; + int rc; + + switch (type) { + case ISCSI_BOOT_INI_INITIATOR_NAME: + rc = sprintf(str, "%s\n", phba->boot_sess.initiator_iscsiname); + break; + default: + rc = -ENOSYS; + break; + } + return rc; +} + +static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf) +{ + struct beiscsi_hba *phba = data; + char *str = buf; + int rc; + + switch (type) { + case ISCSI_BOOT_ETH_FLAGS: + rc = sprintf(str, "2\n"); + break; + case ISCSI_BOOT_ETH_INDEX: + rc = sprintf(str, "0\n"); + break; + case ISCSI_BOOT_ETH_MAC: + rc = beiscsi_get_macaddr(buf, phba); + if (rc < 0) { + SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n"); + return rc; + } + break; + default: + rc = -ENOSYS; + break; + } + return rc; +} + + +static mode_t beiscsi_tgt_get_attr_visibility(void *data, int type) +{ + int rc; + + switch (type) { + case ISCSI_BOOT_TGT_NAME: + case ISCSI_BOOT_TGT_IP_ADDR: + case ISCSI_BOOT_TGT_PORT: + case ISCSI_BOOT_TGT_CHAP_NAME: + case ISCSI_BOOT_TGT_CHAP_SECRET: + case ISCSI_BOOT_TGT_REV_CHAP_NAME: + case ISCSI_BOOT_TGT_REV_CHAP_SECRET: + case ISCSI_BOOT_TGT_NIC_ASSOC: + case ISCSI_BOOT_TGT_FLAGS: + rc = S_IRUGO; + break; + default: + rc = 0; + break; + } + return rc; +} + +static mode_t beiscsi_ini_get_attr_visibility(void *data, int type) +{ + int rc; + + switch (type) { + case ISCSI_BOOT_INI_INITIATOR_NAME: + rc = S_IRUGO; + break; + default: + rc = 0; + break; + } + return rc; +} + + +static mode_t beiscsi_eth_get_attr_visibility(void *data, int type) +{ + int rc; + + switch (type) { + case ISCSI_BOOT_ETH_FLAGS: + case ISCSI_BOOT_ETH_MAC: + case ISCSI_BOOT_ETH_INDEX: + rc = S_IRUGO; + break; + default: + rc = 0; + break; + } + return rc; +} + +static int beiscsi_setup_boot_info(struct beiscsi_hba *phba) +{ + struct iscsi_boot_kobj *boot_kobj; + + phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no); + if (!phba->boot_kset) + return -ENOMEM; + + /* get boot info using mgmt cmd */ + boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba, + beiscsi_show_boot_tgt_info, + beiscsi_tgt_get_attr_visibility); + if (!boot_kobj) + goto free_kset; + + boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba, + beiscsi_show_boot_ini_info, + beiscsi_ini_get_attr_visibility); + if (!boot_kobj) + goto free_kset; + + boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba, + beiscsi_show_boot_eth_info, + beiscsi_eth_get_attr_visibility); + if (!boot_kobj) + goto free_kset; + return 0; + +free_kset: + iscsi_boot_destroy_kset(phba->boot_kset); + return -ENOMEM; +} + /*------------------- PCI Driver operations and data ----------------- */ static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, @@ -268,6 +481,15 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) if (iscsi_host_add(shost, &phba->pcidev->dev)) goto free_devices; + + if (beiscsi_setup_boot_info(phba)) + /* + * log error but continue, because we may not be using + * iscsi boot. + */ + shost_printk(KERN_ERR, phba->shost, "Could not set up " + "iSCSI boot info."); + return phba; free_devices: @@ -3279,6 +3501,89 @@ static void hwi_disable_intr(struct beiscsi_hba *phba) "In hwi_disable_intr, Already Disabled\n"); } +static int beiscsi_get_boot_info(struct beiscsi_hba *phba) +{ + struct be_cmd_resp_get_boot_target *boot_resp; + struct be_cmd_resp_get_session *session_resp; + struct be_mcc_wrb *wrb; + struct be_dma_mem nonemb_cmd; + unsigned int tag, wrb_num; + unsigned short status, extd_status; + struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; + + tag = beiscsi_get_boot_target(phba); + if (!tag) { + SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); + return -EAGAIN; + } else + wait_event_interruptible(phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag]); + + wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; + extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; + status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; + if (status || extd_status) { + SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" + " status = %d extd_status = %d\n", + status, extd_status); + free_mcc_tag(&phba->ctrl, tag); + return -EBUSY; + } + wrb = queue_get_wrb(mccq, wrb_num); + free_mcc_tag(&phba->ctrl, tag); + boot_resp = embedded_payload(wrb); + + if (boot_resp->boot_session_handle < 0) { + printk(KERN_ERR "No Boot Session for this pci_func," + "session Hndl = %d\n", boot_resp->boot_session_handle); + return -ENXIO; + } + + nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, + sizeof(*session_resp), + &nonemb_cmd.dma); + if (nonemb_cmd.va == NULL) { + SE_DEBUG(DBG_LVL_1, + "Failed to allocate memory for" + "beiscsi_get_session_info\n"); + return -ENOMEM; + } + + memset(nonemb_cmd.va, 0, sizeof(*session_resp)); + tag = beiscsi_get_session_info(phba, + boot_resp->boot_session_handle, &nonemb_cmd); + if (!tag) { + SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info" + " Failed\n"); + goto boot_freemem; + } else + wait_event_interruptible(phba->ctrl.mcc_wait[tag], + phba->ctrl.mcc_numtag[tag]); + + wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; + extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; + status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; + if (status || extd_status) { + SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info Failed" + " status = %d extd_status = %d\n", + status, extd_status); + free_mcc_tag(&phba->ctrl, tag); + goto boot_freemem; + } + wrb = queue_get_wrb(mccq, wrb_num); + free_mcc_tag(&phba->ctrl, tag); + session_resp = nonemb_cmd.va ; + memcpy(&phba->boot_sess, &session_resp->session_info, + sizeof(struct mgmt_session_info)); + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); + return 0; +boot_freemem: + pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, + nonemb_cmd.va, nonemb_cmd.dma); + return -ENOMEM; +} + static int beiscsi_init_port(struct beiscsi_hba *phba) { int ret; @@ -3841,6 +4146,7 @@ static void beiscsi_remove(struct pci_dev *pcidev) iscsi_host_remove(phba->shost); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); + iscsi_boot_destroy_kset(phba->boot_kset); } static void beiscsi_msix_enable(struct beiscsi_hba *phba) @@ -3996,6 +4302,11 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, goto free_blkenbld; } hwi_enable_intr(phba); + ret = beiscsi_get_boot_info(phba); + if (ret < 0) { + shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" + "No Boot Devices !!!!!\n"); + } SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); return 0; diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h index c643bb3736f..90eb74f6bca 100644 --- a/drivers/scsi/be2iscsi/be_main.h +++ b/drivers/scsi/be2iscsi/be_main.h @@ -35,7 +35,7 @@ #include "be.h" #define DRV_NAME "be2iscsi" -#define BUILD_STR "2.0.527.0" +#define BUILD_STR "2.0.549.0" #define BE_NAME "ServerEngines BladeEngine2" \ "Linux iSCSI Driver version" BUILD_STR #define DRV_DESC BE_NAME " " "Driver" @@ -63,7 +63,7 @@ #define BEISCSI_SGLIST_ELEMENTS 30 #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ -#define BEISCSI_MAX_SECTORS 256 /* scsi_host->max_sectors */ +#define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */ #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ @@ -312,6 +312,7 @@ struct beiscsi_hba { struct list_head hba_queue; unsigned short *cid_array; struct iscsi_endpoint **ep_array; + struct iscsi_boot_kset *boot_kset; struct Scsi_Host *shost; struct { /** @@ -342,6 +343,8 @@ struct beiscsi_hba { struct work_struct work_cqs; /* The work being queued */ struct be_ctrl_info ctrl; unsigned int generation; + unsigned int read_mac_address; + struct mgmt_session_info boot_sess; struct invalidate_command_table inv_tbl[128]; }; diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 3f3fab91a7d..26350e470bc 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -20,6 +20,77 @@ #include "be_mgmt.h" #include "be_iscsi.h" +#include <scsi/scsi_transport_iscsi.h> + +unsigned int beiscsi_get_boot_target(struct beiscsi_hba *phba) +{ + struct be_ctrl_info *ctrl = &phba->ctrl; + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_mac_addr *req; + unsigned int tag = 0; + + SE_DEBUG(DBG_LVL_8, "In bescsi_get_boot_target\n"); + spin_lock(&ctrl->mbox_lock); + tag = alloc_mcc_tag(phba); + if (!tag) { + spin_unlock(&ctrl->mbox_lock); + return tag; + } + + wrb = wrb_from_mccq(phba); + req = embedded_payload(wrb); + wrb->tag0 |= tag; + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, + OPCODE_ISCSI_INI_BOOT_GET_BOOT_TARGET, + sizeof(*req)); + + be_mcc_notify(phba); + spin_unlock(&ctrl->mbox_lock); + return tag; +} + +unsigned int beiscsi_get_session_info(struct beiscsi_hba *phba, + u32 boot_session_handle, + struct be_dma_mem *nonemb_cmd) +{ + struct be_ctrl_info *ctrl = &phba->ctrl; + struct be_mcc_wrb *wrb; + unsigned int tag = 0; + struct be_cmd_req_get_session *req; + struct be_cmd_resp_get_session *resp; + struct be_sge *sge; + + SE_DEBUG(DBG_LVL_8, "In beiscsi_get_session_info\n"); + spin_lock(&ctrl->mbox_lock); + tag = alloc_mcc_tag(phba); + if (!tag) { + spin_unlock(&ctrl->mbox_lock); + return tag; + } + + nonemb_cmd->size = sizeof(*resp); + req = nonemb_cmd->va; + memset(req, 0, sizeof(*req)); + wrb = wrb_from_mccq(phba); + sge = nonembedded_sgl(wrb); + wrb->tag0 |= tag; + + + wrb->tag0 |= tag; + be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, + OPCODE_ISCSI_INI_SESSION_GET_A_SESSION, + sizeof(*resp)); + req->session_handle = boot_session_handle; + sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); + sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(nonemb_cmd->size); + + be_mcc_notify(phba); + spin_unlock(&ctrl->mbox_lock); + return tag; +} int mgmt_get_fw_config(struct be_ctrl_info *ctrl, struct beiscsi_hba *phba) diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c index f0933d8d1ed..76867b5577f 100644 --- a/drivers/scsi/bfa/bfa_fcport.c +++ b/drivers/scsi/bfa/bfa_fcport.c @@ -1310,7 +1310,7 @@ bfa_fcport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) break; case BFI_FCPORT_I2H_DISABLE_RSP: - if (fcport->msgtag == i2hmsg.penable_rsp->msgtag) + if (fcport->msgtag == i2hmsg.pdisable_rsp->msgtag) bfa_sm_send_event(fcport, BFA_FCPORT_SM_FWRSP); break; diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 915a29d6c7a..ca04cc9d332 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -788,6 +788,7 @@ bfad_drv_init(struct bfad_s *bfad) memset(&driver_info, 0, sizeof(driver_info)); strncpy(driver_info.version, BFAD_DRIVER_VERSION, sizeof(driver_info.version) - 1); + __kernel_param_lock(); if (host_name) strncpy(driver_info.host_machine_name, host_name, sizeof(driver_info.host_machine_name) - 1); @@ -797,6 +798,7 @@ bfad_drv_init(struct bfad_s *bfad) if (os_patch) strncpy(driver_info.host_os_patch, os_patch, sizeof(driver_info.host_os_patch) - 1); + __kernel_param_unlock(); strncpy(driver_info.os_device_name, bfad->pci_name, sizeof(driver_info.os_device_name - 1)); diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c index 678120b7046..6ef87f6fcdb 100644 --- a/drivers/scsi/bfa/bfad_im.c +++ b/drivers/scsi/bfa/bfad_im.c @@ -291,7 +291,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd) struct bfa_tskim_s *tskim; struct bfad_itnim_s *itnim; struct bfa_itnim_s *bfa_itnim; - DECLARE_WAIT_QUEUE_HEAD(wq); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); int rc = SUCCESS; unsigned long flags; enum bfi_tskim_status task_status; @@ -353,7 +353,7 @@ bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd) struct bfad_itnim_s *itnim; unsigned long flags; u32 i, rc, err_cnt = 0; - DECLARE_WAIT_QUEUE_HEAD(wq); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); enum bfi_tskim_status task_status; spin_lock_irqsave(&bfad->bfad_lock, flags); diff --git a/drivers/scsi/bfa/include/protocol/fcp.h b/drivers/scsi/bfa/include/protocol/fcp.h index 9ade68ad285..74ea63ce84b 100644 --- a/drivers/scsi/bfa/include/protocol/fcp.h +++ b/drivers/scsi/bfa/include/protocol/fcp.h @@ -18,6 +18,7 @@ #ifndef __FCPPROTO_H__ #define __FCPPROTO_H__ +#include <linux/bitops.h> #include <protocol/scsi.h> #pragma pack(1) @@ -102,9 +103,6 @@ enum { /* * Task management flags field - only one bit shall be set */ -#ifndef BIT -#define BIT(_x) (1 << (_x)) -#endif enum fcp_tm_cmnd{ FCP_TM_ABORT_TASK_SET = BIT(1), FCP_TM_CLEAR_TASK_SET = BIT(2), diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig index 1e9f7141102..45a6154ce97 100644 --- a/drivers/scsi/bnx2i/Kconfig +++ b/drivers/scsi/bnx2i/Kconfig @@ -1,10 +1,11 @@ config SCSI_BNX2_ISCSI tristate "Broadcom NetXtreme II iSCSI support" + depends on NET + depends on PCI select SCSI_ISCSI_ATTRS select NETDEVICES select NETDEV_1000 select CNIC - depends on PCI ---help--- This driver supports iSCSI offload for the Broadcom NetXtreme II devices. diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 4799d439120..d6532187f61 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -84,10 +84,16 @@ static const char * vendor_labels[CH_TYPES-4] = { }; // module_param_string_array(vendor_labels, NULL, 0444); -#define dprintk(fmt, arg...) if (debug) \ - printk(KERN_DEBUG "%s: " fmt, ch->name , ## arg) -#define vprintk(fmt, arg...) if (verbose) \ - printk(KERN_INFO "%s: " fmt, ch->name , ## arg) +#define DPRINTK(fmt, arg...) \ +do { \ + if (debug) \ + printk(KERN_DEBUG "%s: " fmt, ch->name, ##arg); \ +} while (0) +#define VPRINTK(level, fmt, arg...) \ +do { \ + if (verbose) \ + printk(level "%s: " fmt, ch->name, ##arg); \ +} while (0) /* ------------------------------------------------------------------- */ @@ -186,7 +192,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, retry: errno = 0; if (debug) { - dprintk("command: "); + DPRINTK("command: "); __scsi_print_command(cmd); } @@ -194,7 +200,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, buflength, &sshdr, timeout * HZ, MAX_RETRIES, NULL); - dprintk("result: 0x%x\n",result); + DPRINTK("result: 0x%x\n",result); if (driver_byte(result) & DRIVER_SENSE) { if (debug) scsi_print_sense_hdr(ch->name, &sshdr); @@ -250,7 +256,7 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data) cmd[9] = 255; if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) { if (((buffer[16] << 8) | buffer[17]) != elem) { - dprintk("asked for element 0x%02x, got 0x%02x\n", + DPRINTK("asked for element 0x%02x, got 0x%02x\n", elem,(buffer[16] << 8) | buffer[17]); kfree(buffer); return -EIO; @@ -259,10 +265,10 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data) } else { if (ch->voltags) { ch->voltags = 0; - vprintk("device has no volume tag support\n"); + VPRINTK(KERN_INFO, "device has no volume tag support\n"); goto retry; } - dprintk("READ ELEMENT STATUS for element 0x%x failed\n",elem); + DPRINTK("READ ELEMENT STATUS for element 0x%x failed\n",elem); } kfree(buffer); return result; @@ -274,12 +280,12 @@ ch_init_elem(scsi_changer *ch) int err; u_char cmd[6]; - vprintk("INITIALIZE ELEMENT STATUS, may take some time ...\n"); + VPRINTK(KERN_INFO, "INITIALIZE ELEMENT STATUS, may take some time ...\n"); memset(cmd,0,sizeof(cmd)); cmd[0] = INITIALIZE_ELEMENT_STATUS; cmd[1] = ch->device->lun << 5; err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE); - vprintk("... finished\n"); + VPRINTK(KERN_INFO, "... finished\n"); return err; } @@ -322,20 +328,20 @@ ch_readconfig(scsi_changer *ch) (buffer[buffer[3]+18] << 8) | buffer[buffer[3]+19]; ch->counts[CHET_DT] = (buffer[buffer[3]+20] << 8) | buffer[buffer[3]+21]; - vprintk("type #1 (mt): 0x%x+%d [medium transport]\n", + VPRINTK(KERN_INFO, "type #1 (mt): 0x%x+%d [medium transport]\n", ch->firsts[CHET_MT], ch->counts[CHET_MT]); - vprintk("type #2 (st): 0x%x+%d [storage]\n", + VPRINTK(KERN_INFO, "type #2 (st): 0x%x+%d [storage]\n", ch->firsts[CHET_ST], ch->counts[CHET_ST]); - vprintk("type #3 (ie): 0x%x+%d [import/export]\n", + VPRINTK(KERN_INFO, "type #3 (ie): 0x%x+%d [import/export]\n", ch->firsts[CHET_IE], ch->counts[CHET_IE]); - vprintk("type #4 (dt): 0x%x+%d [data transfer]\n", + VPRINTK(KERN_INFO, "type #4 (dt): 0x%x+%d [data transfer]\n", ch->firsts[CHET_DT], ch->counts[CHET_DT]); } else { - vprintk("reading element address assigment page failed!\n"); + VPRINTK(KERN_INFO, "reading element address assigment page failed!\n"); } /* vendor specific element types */ @@ -346,13 +352,13 @@ ch_readconfig(scsi_changer *ch) continue; ch->firsts[CHET_V1+i] = vendor_firsts[i]; ch->counts[CHET_V1+i] = vendor_counts[i]; - vprintk("type #%d (v%d): 0x%x+%d [%s, vendor specific]\n", + VPRINTK(KERN_INFO, "type #%d (v%d): 0x%x+%d [%s, vendor specific]\n", i+5,i+1,vendor_firsts[i],vendor_counts[i], vendor_labels[i]); } /* look up the devices of the data transfer elements */ - ch->dt = kmalloc(ch->counts[CHET_DT]*sizeof(struct scsi_device), + ch->dt = kcalloc(ch->counts[CHET_DT], sizeof(*ch->dt), GFP_KERNEL); if (!ch->dt) { @@ -366,21 +372,19 @@ ch_readconfig(scsi_changer *ch) if (elem < CH_DT_MAX && -1 != dt_id[elem]) { id = dt_id[elem]; lun = dt_lun[elem]; - vprintk("dt 0x%x: [insmod option] ", + VPRINTK(KERN_INFO, "dt 0x%x: [insmod option] ", elem+ch->firsts[CHET_DT]); } else if (0 != ch_read_element_status (ch,elem+ch->firsts[CHET_DT],data)) { - vprintk("dt 0x%x: READ ELEMENT STATUS failed\n", + VPRINTK(KERN_INFO, "dt 0x%x: READ ELEMENT STATUS failed\n", elem+ch->firsts[CHET_DT]); } else { - vprintk("dt 0x%x: ",elem+ch->firsts[CHET_DT]); + VPRINTK(KERN_INFO, "dt 0x%x: ",elem+ch->firsts[CHET_DT]); if (data[6] & 0x80) { - if (verbose) - printk("not this SCSI bus\n"); + VPRINTK(KERN_CONT, "not this SCSI bus\n"); ch->dt[elem] = NULL; } else if (0 == (data[6] & 0x30)) { - if (verbose) - printk("ID/LUN unknown\n"); + VPRINTK(KERN_CONT, "ID/LUN unknown\n"); ch->dt[elem] = NULL; } else { id = ch->device->id; @@ -390,22 +394,19 @@ ch_readconfig(scsi_changer *ch) } } if (-1 != id) { - if (verbose) - printk("ID %i, LUN %i, ",id,lun); + VPRINTK(KERN_CONT, "ID %i, LUN %i, ",id,lun); ch->dt[elem] = scsi_device_lookup(ch->device->host, ch->device->channel, id,lun); if (!ch->dt[elem]) { /* should not happen */ - if (verbose) - printk("Huh? device not found!\n"); + VPRINTK(KERN_CONT, "Huh? device not found!\n"); } else { - if (verbose) - printk("name: %8.8s %16.16s %4.4s\n", - ch->dt[elem]->vendor, - ch->dt[elem]->model, - ch->dt[elem]->rev); + VPRINTK(KERN_CONT, "name: %8.8s %16.16s %4.4s\n", + ch->dt[elem]->vendor, + ch->dt[elem]->model, + ch->dt[elem]->rev); } } } @@ -422,7 +423,7 @@ ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate) { u_char cmd[10]; - dprintk("position: 0x%x\n",elem); + DPRINTK("position: 0x%x\n",elem); if (0 == trans) trans = ch->firsts[CHET_MT]; memset(cmd,0,sizeof(cmd)); @@ -441,7 +442,7 @@ ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate) { u_char cmd[12]; - dprintk("move: 0x%x => 0x%x\n",src,dest); + DPRINTK("move: 0x%x => 0x%x\n",src,dest); if (0 == trans) trans = ch->firsts[CHET_MT]; memset(cmd,0,sizeof(cmd)); @@ -463,7 +464,7 @@ ch_exchange(scsi_changer *ch, u_int trans, u_int src, { u_char cmd[12]; - dprintk("exchange: 0x%x => 0x%x => 0x%x\n", + DPRINTK("exchange: 0x%x => 0x%x => 0x%x\n", src,dest1,dest2); if (0 == trans) trans = ch->firsts[CHET_MT]; @@ -511,7 +512,7 @@ ch_set_voltag(scsi_changer *ch, u_int elem, if (!buffer) return -ENOMEM; - dprintk("%s %s voltag: 0x%x => \"%s\"\n", + DPRINTK("%s %s voltag: 0x%x => \"%s\"\n", clear ? "clear" : "set", alternate ? "alternate" : "primary", elem, tag); @@ -550,7 +551,7 @@ static int ch_gstatus(scsi_changer *ch, int type, unsigned char __user *dest) } put_user(data[2], dest+i); if (data[2] & CESTATUS_EXCEPT) - vprintk("element 0x%x: asc=0x%x, ascq=0x%x\n", + VPRINTK(KERN_INFO, "element 0x%x: asc=0x%x, ascq=0x%x\n", ch->firsts[type]+i, (int)data[4],(int)data[5]); retval = ch_read_element_status @@ -660,7 +661,7 @@ static long ch_ioctl(struct file *file, return -EFAULT; if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) { - dprintk("CHIOPOSITION: invalid parameter\n"); + DPRINTK("CHIOPOSITION: invalid parameter\n"); return -EBADSLT; } mutex_lock(&ch->lock); @@ -680,7 +681,7 @@ static long ch_ioctl(struct file *file, if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) || 0 != ch_checkrange(ch, mv.cm_totype, mv.cm_tounit )) { - dprintk("CHIOMOVE: invalid parameter\n"); + DPRINTK("CHIOMOVE: invalid parameter\n"); return -EBADSLT; } @@ -703,7 +704,7 @@ static long ch_ioctl(struct file *file, if (0 != ch_checkrange(ch, mv.ce_srctype, mv.ce_srcunit ) || 0 != ch_checkrange(ch, mv.ce_fdsttype, mv.ce_fdstunit) || 0 != ch_checkrange(ch, mv.ce_sdsttype, mv.ce_sdstunit)) { - dprintk("CHIOEXCHANGE: invalid parameter\n"); + DPRINTK("CHIOEXCHANGE: invalid parameter\n"); return -EBADSLT; } @@ -796,7 +797,7 @@ static long ch_ioctl(struct file *file, } } else if (ch->voltags) { ch->voltags = 0; - vprintk("device has no volume tag support\n"); + VPRINTK(KERN_INFO, "device has no volume tag support\n"); goto voltag_retry; } kfree(buffer); @@ -824,7 +825,7 @@ static long ch_ioctl(struct file *file, return -EFAULT; if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) { - dprintk("CHIOSVOLTAG: invalid parameter\n"); + DPRINTK("CHIOSVOLTAG: invalid parameter\n"); return -EBADSLT; } elem = ch->firsts[csv.csv_type] + csv.csv_unit; diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index bd977be7544..54f50b07dac 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -1597,7 +1597,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, u32 tag_mask = 1; u8 tag_number = 0; while (tag_mask & dcb->tag_mask - && tag_number <= dcb->max_command) { + && tag_number < dcb->max_command) { tag_mask = tag_mask << 1; tag_number++; } diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h index 19338e0ba2c..cbb20b13b22 100644 --- a/drivers/scsi/fnic/fnic.h +++ b/drivers/scsi/fnic/fnic.h @@ -21,6 +21,7 @@ #include <linux/interrupt.h> #include <linux/netdevice.h> #include <linux/workqueue.h> +#include <linux/bitops.h> #include <scsi/libfc.h> #include <scsi/libfcoe.h> #include "fnic_io.h" @@ -49,7 +50,6 @@ /* * Tag bits used for special requests. */ -#define BIT(nr) (1UL << (nr)) #define FNIC_TAG_ABORT BIT(30) /* tag bit indicating abort */ #define FNIC_TAG_DEV_RST BIT(29) /* indicates device reset */ #define FNIC_TAG_MASK (BIT(24) - 1) /* mask for lookup */ diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 75585a52c88..427a56d3117 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -285,9 +285,12 @@ static int __init do_DTC3181E_setup(char *str) int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) { static int current_override = 0; - int count, i; + int count; unsigned int *ports; +#ifndef SCSI_G_NCR5380_MEM + int i; unsigned long region_size = 16; +#endif static unsigned int __initdata ncr_53c400a_ports[] = { 0x280, 0x290, 0x300, 0x310, 0x330, 0x340, 0x348, 0x350, 0 }; @@ -296,7 +299,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) }; int flags = 0; struct Scsi_Host *instance; -#ifdef CONFIG_SCSI_G_NCR5380_MEM +#ifdef SCSI_G_NCR5380_MEM unsigned long base; void __iomem *iomem; #endif @@ -315,17 +318,15 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) overrides[0].board = BOARD_NCR53C400A; else if (dtc_3181e != NCR_NOT_SET) overrides[0].board = BOARD_DTC3181E; - +#ifndef SCSI_G_NCR5380_MEM if (!current_override && isapnp_present()) { struct pnp_dev *dev = NULL; count = 0; while ((dev = pnp_find_dev(NULL, ISAPNP_VENDOR('D', 'T', 'C'), ISAPNP_FUNCTION(0x436e), dev))) { if (count >= NO_OVERRIDES) break; - if (pnp_device_attach(dev) < 0) { - printk(KERN_ERR "dtc436e probe: attach failed\n"); + if (pnp_device_attach(dev) < 0) continue; - } if (pnp_activate_dev(dev) < 0) { printk(KERN_ERR "dtc436e probe: activate failed\n"); pnp_device_detach(dev); @@ -349,7 +350,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) count++; } } - +#endif tpnt->proc_name = "g_NCR5380"; for (count = 0; current_override < NO_OVERRIDES; ++current_override) { @@ -374,7 +375,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) break; } -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM if (ports) { /* wakeup sequence for the NCR53C400A and DTC3181E */ @@ -436,7 +437,7 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) #endif instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); if (instance == NULL) { -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM release_region(overrides[current_override].NCR5380_map_name, region_size); #else iounmap(iomem); @@ -446,10 +447,10 @@ int __init generic_NCR5380_detect(struct scsi_host_template * tpnt) } instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name; -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM instance->n_io_port = region_size; #else - ((struct NCR5380_hostdata *)instance->hostdata).iomem = iomem; + ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem; #endif NCR5380_init(instance, flags); @@ -517,10 +518,10 @@ int generic_NCR5380_release_resources(struct Scsi_Host *instance) free_irq(instance->irq, instance); NCR5380_exit(instance); -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM release_region(instance->NCR5380_instance_name, instance->n_io_port); #else - iounmap(((struct NCR5380_hostdata *)instance->hostdata).iomem); + iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem); release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size); #endif @@ -590,14 +591,14 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, } while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY); -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM { int i; for (i = 0; i < 128; i++) dst[start + i] = NCR5380_read(C400_HOST_BUFFER); } #else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ + /* implies SCSI_G_NCR5380_MEM */ memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); #endif start += 128; @@ -610,14 +611,14 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, // FIXME - no timeout } -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM { int i; for (i = 0; i < 128; i++) dst[start + i] = NCR5380_read(C400_HOST_BUFFER); } #else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ + /* implies SCSI_G_NCR5380_MEM */ memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); #endif start += 128; @@ -676,13 +677,13 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, } while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - timeout -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM { for (i = 0; i < 128; i++) NCR5380_write(C400_HOST_BUFFER, src[start + i]); } #else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ + /* implies SCSI_G_NCR5380_MEM */ memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); #endif start += 128; @@ -692,13 +693,13 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - no timeout -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM { for (i = 0; i < 128; i++) NCR5380_write(C400_HOST_BUFFER, src[start + i]); } #else - /* implies CONFIG_SCSI_G_NCR5380_MEM */ + /* implies SCSI_G_NCR5380_MEM */ memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); #endif start += 128; @@ -938,7 +939,7 @@ module_param(ncr_53c400a, int, 0); module_param(dtc_3181e, int, 0); MODULE_LICENSE("GPL"); - +#ifndef SCSI_G_NCR5380_MEM static struct isapnp_device_id id_table[] __devinitdata = { { ISAPNP_ANY_ID, ISAPNP_ANY_ID, @@ -948,7 +949,7 @@ static struct isapnp_device_id id_table[] __devinitdata = { }; MODULE_DEVICE_TABLE(isapnp, id_table); - +#endif __setup("ncr5380=", do_NCR5380_setup); __setup("ncr53c400=", do_NCR53C400_setup); diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index df0b3f69ef6..921764c9ab2 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -63,7 +63,7 @@ static const char* generic_NCR5380_info(struct Scsi_Host *); #define __STRVAL(x) #x #define STRVAL(x) __STRVAL(x) -#ifndef CONFIG_SCSI_G_NCR5380_MEM +#ifndef SCSI_G_NCR5380_MEM #define NCR5380_map_config port #define NCR5380_map_type int @@ -91,7 +91,7 @@ static const char* generic_NCR5380_info(struct Scsi_Host *); NCR5380_map_name = (NCR5380_map_type)((instance)->NCR5380_instance_name) #else -/* therefore CONFIG_SCSI_G_NCR5380_MEM */ +/* therefore SCSI_G_NCR5380_MEM */ #define NCR5380_map_config memory #define NCR5380_map_type unsigned long @@ -114,7 +114,7 @@ static const char* generic_NCR5380_info(struct Scsi_Host *); register void __iomem *iomem #define NCR5380_setup(instance) \ - iomem = (((struct NCR5380_hostdata *)(instance)->hostdata).iomem) + iomem = (((struct NCR5380_hostdata *)(instance)->hostdata)->iomem) #endif diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index f672d6213ee..b860d650a56 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4914,7 +4914,7 @@ static int __init gdth_eisa_probe_one(u16 eisa_slot) error = scsi_add_host(shp, NULL); if (error) - goto out_free_coal_stat; + goto out_free_ccb_phys; list_add_tail(&ha->list, &gdth_instances); gdth_timer_init(); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index bd96cecaa61..9f75a6d519a 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -433,6 +433,9 @@ static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt, { switch (tgt->action) { case IBMVFC_TGT_ACTION_DEL_RPORT: + if (action == IBMVFC_TGT_ACTION_DELETED_RPORT) + tgt->action = action; + case IBMVFC_TGT_ACTION_DELETED_RPORT: break; default: if (action == IBMVFC_TGT_ACTION_DEL_RPORT) @@ -2036,95 +2039,108 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) } /** - * ibmvfc_abort_task_set - Abort outstanding commands to the device - * @sdev: scsi device to abort commands - * - * This sends an Abort Task Set to the VIOS for the specified device. This does - * NOT send any cancel to the VIOS. That must be done separately. + * ibmvfc_match_rport - Match function for specified remote port + * @evt: ibmvfc event struct + * @device: device to match (rport) * * Returns: - * 0 on success / other on failure + * 1 if event matches rport / 0 if event does not match rport **/ -static int ibmvfc_abort_task_set(struct scsi_device *sdev) +static int ibmvfc_match_rport(struct ibmvfc_event *evt, void *rport) { - struct ibmvfc_host *vhost = shost_priv(sdev->host); - struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); - struct ibmvfc_cmd *tmf; - struct ibmvfc_event *evt, *found_evt; - union ibmvfc_iu rsp_iu; - struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; - int rsp_rc = -EBUSY; - unsigned long flags; - int rsp_code = 0; + struct fc_rport *cmd_rport; - spin_lock_irqsave(vhost->host->host_lock, flags); - found_evt = NULL; - list_for_each_entry(evt, &vhost->sent, queue) { - if (evt->cmnd && evt->cmnd->device == sdev) { - found_evt = evt; - break; - } - } - - if (!found_evt) { - if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) - sdev_printk(KERN_INFO, sdev, "No events found to abort\n"); - spin_unlock_irqrestore(vhost->host->host_lock, flags); - return 0; - } - - if (vhost->state == IBMVFC_ACTIVE) { - evt = ibmvfc_get_event(vhost); - ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); - - tmf = &evt->iu.cmd; - memset(tmf, 0, sizeof(*tmf)); - tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); - tmf->resp.len = sizeof(tmf->rsp); - tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; - tmf->payload_len = sizeof(tmf->iu); - tmf->resp_len = sizeof(tmf->rsp); - tmf->cancel_key = (unsigned long)sdev->hostdata; - tmf->tgt_scsi_id = rport->port_id; - int_to_scsilun(sdev->lun, &tmf->iu.lun); - tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); - tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; - evt->sync_iu = &rsp_iu; - - init_completion(&evt->comp); - rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); + if (evt->cmnd) { + cmd_rport = starget_to_rport(scsi_target(evt->cmnd->device)); + if (cmd_rport == rport) + return 1; } + return 0; +} - spin_unlock_irqrestore(vhost->host->host_lock, flags); +/** + * ibmvfc_match_target - Match function for specified target + * @evt: ibmvfc event struct + * @device: device to match (starget) + * + * Returns: + * 1 if event matches starget / 0 if event does not match starget + **/ +static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) +{ + if (evt->cmnd && scsi_target(evt->cmnd->device) == device) + return 1; + return 0; +} - if (rsp_rc != 0) { - sdev_printk(KERN_ERR, sdev, "Failed to send abort. rc=%d\n", rsp_rc); - return -EIO; - } +/** + * ibmvfc_match_lun - Match function for specified LUN + * @evt: ibmvfc event struct + * @device: device to match (sdev) + * + * Returns: + * 1 if event matches sdev / 0 if event does not match sdev + **/ +static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) +{ + if (evt->cmnd && evt->cmnd->device == device) + return 1; + return 0; +} - sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); - wait_for_completion(&evt->comp); +/** + * ibmvfc_wait_for_ops - Wait for ops to complete + * @vhost: ibmvfc host struct + * @device: device to match (starget or sdev) + * @match: match function + * + * Returns: + * SUCCESS / FAILED + **/ +static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, + int (*match) (struct ibmvfc_event *, void *)) +{ + struct ibmvfc_event *evt; + DECLARE_COMPLETION_ONSTACK(comp); + int wait; + unsigned long flags; + signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ; - if (rsp_iu.cmd.status) - rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); + ENTER; + do { + wait = 0; + spin_lock_irqsave(vhost->host->host_lock, flags); + list_for_each_entry(evt, &vhost->sent, queue) { + if (match(evt, device)) { + evt->eh_comp = ∁ + wait++; + } + } + spin_unlock_irqrestore(vhost->host->host_lock, flags); - if (rsp_code) { - if (fc_rsp->flags & FCP_RSP_LEN_VALID) - rsp_code = fc_rsp->data.info.rsp_code; + if (wait) { + timeout = wait_for_completion_timeout(&comp, timeout); - sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " - "flags: %x fcp_rsp: %x, scsi_status: %x\n", - ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), - rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, - fc_rsp->scsi_status); - rsp_rc = -EIO; - } else - sdev_printk(KERN_INFO, sdev, "Abort successful\n"); + if (!timeout) { + wait = 0; + spin_lock_irqsave(vhost->host->host_lock, flags); + list_for_each_entry(evt, &vhost->sent, queue) { + if (match(evt, device)) { + evt->eh_comp = NULL; + wait++; + } + } + spin_unlock_irqrestore(vhost->host->host_lock, flags); + if (wait) + dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); + LEAVE; + return wait ? FAILED : SUCCESS; + } + } + } while (wait); - spin_lock_irqsave(vhost->host->host_lock, flags); - ibmvfc_free_event(evt); - spin_unlock_irqrestore(vhost->host->host_lock, flags); - return rsp_rc; + LEAVE; + return SUCCESS; } /** @@ -2212,88 +2228,130 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) } /** - * ibmvfc_match_target - Match function for specified target + * ibmvfc_match_key - Match function for specified cancel key * @evt: ibmvfc event struct - * @device: device to match (starget) + * @key: cancel key to match * * Returns: - * 1 if event matches starget / 0 if event does not match starget + * 1 if event matches key / 0 if event does not match key **/ -static int ibmvfc_match_target(struct ibmvfc_event *evt, void *device) +static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key) { - if (evt->cmnd && scsi_target(evt->cmnd->device) == device) - return 1; - return 0; -} + unsigned long cancel_key = (unsigned long)key; -/** - * ibmvfc_match_lun - Match function for specified LUN - * @evt: ibmvfc event struct - * @device: device to match (sdev) - * - * Returns: - * 1 if event matches sdev / 0 if event does not match sdev - **/ -static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device) -{ - if (evt->cmnd && evt->cmnd->device == device) + if (evt->crq.format == IBMVFC_CMD_FORMAT && + evt->iu.cmd.cancel_key == cancel_key) return 1; return 0; } /** - * ibmvfc_wait_for_ops - Wait for ops to complete - * @vhost: ibmvfc host struct - * @device: device to match (starget or sdev) - * @match: match function + * ibmvfc_abort_task_set - Abort outstanding commands to the device + * @sdev: scsi device to abort commands + * + * This sends an Abort Task Set to the VIOS for the specified device. This does + * NOT send any cancel to the VIOS. That must be done separately. * * Returns: - * SUCCESS / FAILED + * 0 on success / other on failure **/ -static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device, - int (*match) (struct ibmvfc_event *, void *)) +static int ibmvfc_abort_task_set(struct scsi_device *sdev) { - struct ibmvfc_event *evt; - DECLARE_COMPLETION_ONSTACK(comp); - int wait; - unsigned long flags; - signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ; + struct ibmvfc_host *vhost = shost_priv(sdev->host); + struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); + struct ibmvfc_cmd *tmf; + struct ibmvfc_event *evt, *found_evt; + union ibmvfc_iu rsp_iu; + struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.rsp; + int rc, rsp_rc = -EBUSY; + unsigned long flags, timeout = IBMVFC_ABORT_TIMEOUT; + int rsp_code = 0; - ENTER; - do { - wait = 0; - spin_lock_irqsave(vhost->host->host_lock, flags); - list_for_each_entry(evt, &vhost->sent, queue) { - if (match(evt, device)) { - evt->eh_comp = ∁ - wait++; - } + spin_lock_irqsave(vhost->host->host_lock, flags); + found_evt = NULL; + list_for_each_entry(evt, &vhost->sent, queue) { + if (evt->cmnd && evt->cmnd->device == sdev) { + found_evt = evt; + break; } + } + + if (!found_evt) { + if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) + sdev_printk(KERN_INFO, sdev, "No events found to abort\n"); spin_unlock_irqrestore(vhost->host->host_lock, flags); + return 0; + } - if (wait) { - timeout = wait_for_completion_timeout(&comp, timeout); + if (vhost->state == IBMVFC_ACTIVE) { + evt = ibmvfc_get_event(vhost); + ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); - if (!timeout) { - wait = 0; - spin_lock_irqsave(vhost->host->host_lock, flags); - list_for_each_entry(evt, &vhost->sent, queue) { - if (match(evt, device)) { - evt->eh_comp = NULL; - wait++; - } - } - spin_unlock_irqrestore(vhost->host->host_lock, flags); - if (wait) - dev_err(vhost->dev, "Timed out waiting for aborted commands\n"); - LEAVE; - return wait ? FAILED : SUCCESS; - } + tmf = &evt->iu.cmd; + memset(tmf, 0, sizeof(*tmf)); + tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); + tmf->resp.len = sizeof(tmf->rsp); + tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; + tmf->payload_len = sizeof(tmf->iu); + tmf->resp_len = sizeof(tmf->rsp); + tmf->cancel_key = (unsigned long)sdev->hostdata; + tmf->tgt_scsi_id = rport->port_id; + int_to_scsilun(sdev->lun, &tmf->iu.lun); + tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); + tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; + evt->sync_iu = &rsp_iu; + + init_completion(&evt->comp); + rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); + } + + spin_unlock_irqrestore(vhost->host->host_lock, flags); + + if (rsp_rc != 0) { + sdev_printk(KERN_ERR, sdev, "Failed to send abort. rc=%d\n", rsp_rc); + return -EIO; + } + + sdev_printk(KERN_INFO, sdev, "Aborting outstanding commands\n"); + timeout = wait_for_completion_timeout(&evt->comp, timeout); + + if (!timeout) { + rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); + if (!rc) { + rc = ibmvfc_wait_for_ops(vhost, sdev->hostdata, ibmvfc_match_key); + if (rc == SUCCESS) + rc = 0; } - } while (wait); - LEAVE; - return SUCCESS; + if (rc) { + sdev_printk(KERN_INFO, sdev, "Cancel failed, resetting host\n"); + ibmvfc_reset_host(vhost); + rsp_rc = 0; + goto out; + } + } + + if (rsp_iu.cmd.status) + rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd); + + if (rsp_code) { + if (fc_rsp->flags & FCP_RSP_LEN_VALID) + rsp_code = fc_rsp->data.info.rsp_code; + + sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " + "flags: %x fcp_rsp: %x, scsi_status: %x\n", + ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), + rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, + fc_rsp->scsi_status); + rsp_rc = -EIO; + } else + sdev_printk(KERN_INFO, sdev, "Abort successful\n"); + +out: + spin_lock_irqsave(vhost->host->host_lock, flags); + ibmvfc_free_event(evt); + spin_unlock_irqrestore(vhost->host->host_lock, flags); + return rsp_rc; } /** @@ -2351,18 +2409,6 @@ static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) } /** - * ibmvfc_dev_cancel_all_abts - Device iterated cancel all function - * @sdev: scsi device struct - * @data: return code - * - **/ -static void ibmvfc_dev_cancel_all_abts(struct scsi_device *sdev, void *data) -{ - unsigned long *rc = data; - *rc |= ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); -} - -/** * ibmvfc_dev_cancel_all_reset - Device iterated cancel all function * @sdev: scsi device struct * @data: return code @@ -2375,18 +2421,6 @@ static void ibmvfc_dev_cancel_all_reset(struct scsi_device *sdev, void *data) } /** - * ibmvfc_dev_abort_all - Device iterated abort task set function - * @sdev: scsi device struct - * @data: return code - * - **/ -static void ibmvfc_dev_abort_all(struct scsi_device *sdev, void *data) -{ - unsigned long *rc = data; - *rc |= ibmvfc_abort_task_set(sdev); -} - -/** * ibmvfc_eh_target_reset_handler - Reset the target * @cmd: scsi command struct * @@ -2440,19 +2474,22 @@ static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) **/ static void ibmvfc_terminate_rport_io(struct fc_rport *rport) { - struct scsi_target *starget = to_scsi_target(&rport->dev); - struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); + struct Scsi_Host *shost = rport_to_shost(rport); struct ibmvfc_host *vhost = shost_priv(shost); - unsigned long cancel_rc = 0; - unsigned long abort_rc = 0; - int rc = FAILED; + struct fc_rport *dev_rport; + struct scsi_device *sdev; + unsigned long rc; ENTER; - starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_abts); - starget_for_each_device(starget, &abort_rc, ibmvfc_dev_abort_all); + shost_for_each_device(sdev, shost) { + dev_rport = starget_to_rport(scsi_target(sdev)); + if (dev_rport != rport) + continue; + ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); + ibmvfc_abort_task_set(sdev); + } - if (!cancel_rc && !abort_rc) - rc = ibmvfc_wait_for_ops(vhost, starget, ibmvfc_match_target); + rc = ibmvfc_wait_for_ops(vhost, rport, ibmvfc_match_rport); if (rc == FAILED) ibmvfc_issue_fc_host_lip(shost); @@ -4193,11 +4230,15 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) { tgt_dbg(tgt, "Deleting rport\n"); list_del(&tgt->queue); + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT); spin_unlock_irqrestore(vhost->host->host_lock, flags); fc_remote_port_delete(rport); del_timer_sync(&tgt->timer); kref_put(&tgt->kref, ibmvfc_release_tgt); return; + } else if (rport && tgt->action == IBMVFC_TGT_ACTION_DELETED_RPORT) { + spin_unlock_irqrestore(vhost->host->host_lock, flags); + return; } if (rport) { @@ -4297,6 +4338,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) rport = tgt->rport; tgt->rport = NULL; list_del(&tgt->queue); + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT); spin_unlock_irqrestore(vhost->host->host_lock, flags); if (rport) fc_remote_port_delete(rport); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index d7e8dcd9065..608af394c8c 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -29,8 +29,8 @@ #include "viosrp.h" #define IBMVFC_NAME "ibmvfc" -#define IBMVFC_DRIVER_VERSION "1.0.8" -#define IBMVFC_DRIVER_DATE "(June 17, 2010)" +#define IBMVFC_DRIVER_VERSION "1.0.9" +#define IBMVFC_DRIVER_DATE "(August 5, 2010)" #define IBMVFC_DEFAULT_TIMEOUT 60 #define IBMVFC_ADISC_CANCEL_TIMEOUT 45 @@ -38,6 +38,7 @@ #define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT \ (IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT) #define IBMVFC_INIT_TIMEOUT 120 +#define IBMVFC_ABORT_TIMEOUT 8 #define IBMVFC_ABORT_WAIT_TIMEOUT 40 #define IBMVFC_MAX_REQUESTS_DEFAULT 100 @@ -597,6 +598,7 @@ enum ibmvfc_target_action { IBMVFC_TGT_ACTION_INIT, IBMVFC_TGT_ACTION_INIT_WAIT, IBMVFC_TGT_ACTION_DEL_RPORT, + IBMVFC_TGT_ACTION_DELETED_RPORT, }; struct ibmvfc_target { diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index a7714160fbc..108797761b9 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -2817,7 +2817,6 @@ static void i91uSCBPost(u8 * host_mem, u8 * cblk_mem) } cmnd->result = cblk->tastat | (cblk->hastat << 16); - WARN_ON(cmnd == NULL); i91u_unmap_scb(host->pci_dev, cmnd); cmnd->scsi_done(cmnd); /* Notify system DONE */ initio_release_scb(host, cblk); /* Release SCB for current channel */ diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c new file mode 100644 index 00000000000..df6bff7366c --- /dev/null +++ b/drivers/scsi/iscsi_boot_sysfs.c @@ -0,0 +1,481 @@ +/* + * Export the iSCSI boot info to userland via sysfs. + * + * Copyright (C) 2010 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010 Mike Christie + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License v2.0 as published by + * the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/module.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/sysfs.h> +#include <linux/capability.h> +#include <linux/iscsi_boot_sysfs.h> + + +MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>"); +MODULE_DESCRIPTION("sysfs interface and helpers to export iSCSI boot information"); +MODULE_LICENSE("GPL"); +/* + * The kobject and attribute structures. + */ +struct iscsi_boot_attr { + struct attribute attr; + int type; + ssize_t (*show) (void *data, int type, char *buf); +}; + +/* + * The routine called for all sysfs attributes. + */ +static ssize_t iscsi_boot_show_attribute(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct iscsi_boot_kobj *boot_kobj = + container_of(kobj, struct iscsi_boot_kobj, kobj); + struct iscsi_boot_attr *boot_attr = + container_of(attr, struct iscsi_boot_attr, attr); + ssize_t ret = -EIO; + char *str = buf; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (boot_kobj->show) + ret = boot_kobj->show(boot_kobj->data, boot_attr->type, str); + return ret; +} + +static const struct sysfs_ops iscsi_boot_attr_ops = { + .show = iscsi_boot_show_attribute, +}; + +static void iscsi_boot_kobj_release(struct kobject *kobj) +{ + struct iscsi_boot_kobj *boot_kobj = + container_of(kobj, struct iscsi_boot_kobj, kobj); + + kfree(boot_kobj->data); + kfree(boot_kobj); +} + +static struct kobj_type iscsi_boot_ktype = { + .release = iscsi_boot_kobj_release, + .sysfs_ops = &iscsi_boot_attr_ops, +}; + +#define iscsi_boot_rd_attr(fnname, sysfs_name, attr_type) \ +static struct iscsi_boot_attr iscsi_boot_attr_##fnname = { \ + .attr = { .name = __stringify(sysfs_name), .mode = 0444 }, \ + .type = attr_type, \ +} + +/* Target attrs */ +iscsi_boot_rd_attr(tgt_index, index, ISCSI_BOOT_TGT_INDEX); +iscsi_boot_rd_attr(tgt_flags, flags, ISCSI_BOOT_TGT_FLAGS); +iscsi_boot_rd_attr(tgt_ip, ip-addr, ISCSI_BOOT_TGT_IP_ADDR); +iscsi_boot_rd_attr(tgt_port, port, ISCSI_BOOT_TGT_PORT); +iscsi_boot_rd_attr(tgt_lun, lun, ISCSI_BOOT_TGT_LUN); +iscsi_boot_rd_attr(tgt_chap, chap-type, ISCSI_BOOT_TGT_CHAP_TYPE); +iscsi_boot_rd_attr(tgt_nic, nic-assoc, ISCSI_BOOT_TGT_NIC_ASSOC); +iscsi_boot_rd_attr(tgt_name, target-name, ISCSI_BOOT_TGT_NAME); +iscsi_boot_rd_attr(tgt_chap_name, chap-name, ISCSI_BOOT_TGT_CHAP_NAME); +iscsi_boot_rd_attr(tgt_chap_secret, chap-secret, ISCSI_BOOT_TGT_CHAP_SECRET); +iscsi_boot_rd_attr(tgt_chap_rev_name, rev-chap-name, + ISCSI_BOOT_TGT_REV_CHAP_NAME); +iscsi_boot_rd_attr(tgt_chap_rev_secret, rev-chap-name-secret, + ISCSI_BOOT_TGT_REV_CHAP_SECRET); + +static struct attribute *target_attrs[] = { + &iscsi_boot_attr_tgt_index.attr, + &iscsi_boot_attr_tgt_flags.attr, + &iscsi_boot_attr_tgt_ip.attr, + &iscsi_boot_attr_tgt_port.attr, + &iscsi_boot_attr_tgt_lun.attr, + &iscsi_boot_attr_tgt_chap.attr, + &iscsi_boot_attr_tgt_nic.attr, + &iscsi_boot_attr_tgt_name.attr, + &iscsi_boot_attr_tgt_chap_name.attr, + &iscsi_boot_attr_tgt_chap_secret.attr, + &iscsi_boot_attr_tgt_chap_rev_name.attr, + &iscsi_boot_attr_tgt_chap_rev_secret.attr, + NULL +}; + +static mode_t iscsi_boot_tgt_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int i) +{ + struct iscsi_boot_kobj *boot_kobj = + container_of(kobj, struct iscsi_boot_kobj, kobj); + + if (attr == &iscsi_boot_attr_tgt_index.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_INDEX); + else if (attr == &iscsi_boot_attr_tgt_flags.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_FLAGS); + else if (attr == &iscsi_boot_attr_tgt_ip.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_IP_ADDR); + else if (attr == &iscsi_boot_attr_tgt_port.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_PORT); + else if (attr == &iscsi_boot_attr_tgt_lun.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_LUN); + else if (attr == &iscsi_boot_attr_tgt_chap.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_CHAP_TYPE); + else if (attr == &iscsi_boot_attr_tgt_nic.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_NIC_ASSOC); + else if (attr == &iscsi_boot_attr_tgt_name.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_NAME); + else if (attr == &iscsi_boot_attr_tgt_chap_name.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_CHAP_NAME); + else if (attr == &iscsi_boot_attr_tgt_chap_secret.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_CHAP_SECRET); + else if (attr == &iscsi_boot_attr_tgt_chap_rev_name.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_REV_CHAP_NAME); + else if (attr == &iscsi_boot_attr_tgt_chap_rev_secret.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_TGT_REV_CHAP_SECRET); + return 0; +} + +static struct attribute_group iscsi_boot_target_attr_group = { + .attrs = target_attrs, + .is_visible = iscsi_boot_tgt_attr_is_visible, +}; + +/* Ethernet attrs */ +iscsi_boot_rd_attr(eth_index, index, ISCSI_BOOT_ETH_INDEX); +iscsi_boot_rd_attr(eth_flags, flags, ISCSI_BOOT_ETH_FLAGS); +iscsi_boot_rd_attr(eth_ip, ip-addr, ISCSI_BOOT_ETH_IP_ADDR); +iscsi_boot_rd_attr(eth_subnet, subnet-mask, ISCSI_BOOT_ETH_SUBNET_MASK); +iscsi_boot_rd_attr(eth_origin, origin, ISCSI_BOOT_ETH_ORIGIN); +iscsi_boot_rd_attr(eth_gateway, gateway, ISCSI_BOOT_ETH_GATEWAY); +iscsi_boot_rd_attr(eth_primary_dns, primary-dns, ISCSI_BOOT_ETH_PRIMARY_DNS); +iscsi_boot_rd_attr(eth_secondary_dns, secondary-dns, + ISCSI_BOOT_ETH_SECONDARY_DNS); +iscsi_boot_rd_attr(eth_dhcp, dhcp, ISCSI_BOOT_ETH_DHCP); +iscsi_boot_rd_attr(eth_vlan, vlan, ISCSI_BOOT_ETH_VLAN); +iscsi_boot_rd_attr(eth_mac, mac, ISCSI_BOOT_ETH_MAC); +iscsi_boot_rd_attr(eth_hostname, hostname, ISCSI_BOOT_ETH_HOSTNAME); + +static struct attribute *ethernet_attrs[] = { + &iscsi_boot_attr_eth_index.attr, + &iscsi_boot_attr_eth_flags.attr, + &iscsi_boot_attr_eth_ip.attr, + &iscsi_boot_attr_eth_subnet.attr, + &iscsi_boot_attr_eth_origin.attr, + &iscsi_boot_attr_eth_gateway.attr, + &iscsi_boot_attr_eth_primary_dns.attr, + &iscsi_boot_attr_eth_secondary_dns.attr, + &iscsi_boot_attr_eth_dhcp.attr, + &iscsi_boot_attr_eth_vlan.attr, + &iscsi_boot_attr_eth_mac.attr, + &iscsi_boot_attr_eth_hostname.attr, + NULL +}; + +static mode_t iscsi_boot_eth_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int i) +{ + struct iscsi_boot_kobj *boot_kobj = + container_of(kobj, struct iscsi_boot_kobj, kobj); + + if (attr == &iscsi_boot_attr_eth_index.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_INDEX); + else if (attr == &iscsi_boot_attr_eth_flags.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_FLAGS); + else if (attr == &iscsi_boot_attr_eth_ip.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_IP_ADDR); + else if (attr == &iscsi_boot_attr_eth_subnet.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_SUBNET_MASK); + else if (attr == &iscsi_boot_attr_eth_origin.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_ORIGIN); + else if (attr == &iscsi_boot_attr_eth_gateway.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_GATEWAY); + else if (attr == &iscsi_boot_attr_eth_primary_dns.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_PRIMARY_DNS); + else if (attr == &iscsi_boot_attr_eth_secondary_dns.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_SECONDARY_DNS); + else if (attr == &iscsi_boot_attr_eth_dhcp.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_DHCP); + else if (attr == &iscsi_boot_attr_eth_vlan.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_VLAN); + else if (attr == &iscsi_boot_attr_eth_mac.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_MAC); + else if (attr == &iscsi_boot_attr_eth_hostname.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_ETH_HOSTNAME); + return 0; +} + +static struct attribute_group iscsi_boot_ethernet_attr_group = { + .attrs = ethernet_attrs, + .is_visible = iscsi_boot_eth_attr_is_visible, +}; + +/* Initiator attrs */ +iscsi_boot_rd_attr(ini_index, index, ISCSI_BOOT_INI_INDEX); +iscsi_boot_rd_attr(ini_flags, flags, ISCSI_BOOT_INI_FLAGS); +iscsi_boot_rd_attr(ini_isns, isns-server, ISCSI_BOOT_INI_ISNS_SERVER); +iscsi_boot_rd_attr(ini_slp, slp-server, ISCSI_BOOT_INI_SLP_SERVER); +iscsi_boot_rd_attr(ini_primary_radius, pri-radius-server, + ISCSI_BOOT_INI_PRI_RADIUS_SERVER); +iscsi_boot_rd_attr(ini_secondary_radius, sec-radius-server, + ISCSI_BOOT_INI_SEC_RADIUS_SERVER); +iscsi_boot_rd_attr(ini_name, initiator-name, ISCSI_BOOT_INI_INITIATOR_NAME); + +static struct attribute *initiator_attrs[] = { + &iscsi_boot_attr_ini_index.attr, + &iscsi_boot_attr_ini_flags.attr, + &iscsi_boot_attr_ini_isns.attr, + &iscsi_boot_attr_ini_slp.attr, + &iscsi_boot_attr_ini_primary_radius.attr, + &iscsi_boot_attr_ini_secondary_radius.attr, + &iscsi_boot_attr_ini_name.attr, + NULL +}; + +static mode_t iscsi_boot_ini_attr_is_visible(struct kobject *kobj, + struct attribute *attr, int i) +{ + struct iscsi_boot_kobj *boot_kobj = + container_of(kobj, struct iscsi_boot_kobj, kobj); + + if (attr == &iscsi_boot_attr_ini_index.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_INDEX); + if (attr == &iscsi_boot_attr_ini_flags.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_FLAGS); + if (attr == &iscsi_boot_attr_ini_isns.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_ISNS_SERVER); + if (attr == &iscsi_boot_attr_ini_slp.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_SLP_SERVER); + if (attr == &iscsi_boot_attr_ini_primary_radius.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_PRI_RADIUS_SERVER); + if (attr == &iscsi_boot_attr_ini_secondary_radius.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_SEC_RADIUS_SERVER); + if (attr == &iscsi_boot_attr_ini_name.attr) + return boot_kobj->is_visible(boot_kobj->data, + ISCSI_BOOT_INI_INITIATOR_NAME); + + return 0; +} + +static struct attribute_group iscsi_boot_initiator_attr_group = { + .attrs = initiator_attrs, + .is_visible = iscsi_boot_ini_attr_is_visible, +}; + +static struct iscsi_boot_kobj * +iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset, + struct attribute_group *attr_group, + const char *name, int index, void *data, + ssize_t (*show) (void *data, int type, char *buf), + mode_t (*is_visible) (void *data, int type)) +{ + struct iscsi_boot_kobj *boot_kobj; + + boot_kobj = kzalloc(sizeof(*boot_kobj), GFP_KERNEL); + if (!boot_kobj) + return NULL; + INIT_LIST_HEAD(&boot_kobj->list); + + boot_kobj->kobj.kset = boot_kset->kset; + if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype, + NULL, name, index)) { + kfree(boot_kobj); + return NULL; + } + boot_kobj->data = data; + boot_kobj->show = show; + boot_kobj->is_visible = is_visible; + + if (sysfs_create_group(&boot_kobj->kobj, attr_group)) { + /* + * We do not want to free this because the caller + * will assume that since the creation call failed + * the boot kobj was not setup and the normal release + * path is not being run. + */ + boot_kobj->data = NULL; + kobject_put(&boot_kobj->kobj); + return NULL; + } + boot_kobj->attr_group = attr_group; + + kobject_uevent(&boot_kobj->kobj, KOBJ_ADD); + /* Nothing broke so lets add it to the list. */ + list_add_tail(&boot_kobj->list, &boot_kset->kobj_list); + return boot_kobj; +} + +static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj) +{ + list_del(&boot_kobj->list); + sysfs_remove_group(&boot_kobj->kobj, boot_kobj->attr_group); + kobject_put(&boot_kobj->kobj); +} + +/** + * iscsi_boot_create_target() - create boot target sysfs dir + * @boot_kset: boot kset + * @index: the target id + * @data: driver specific data for target + * @show: attr show function + * @is_visible: attr visibility function + * + * Note: The boot sysfs lib will free the data passed in for the caller + * when all refs to the target kobject have been released. + */ +struct iscsi_boot_kobj * +iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, + void *data, + ssize_t (*show) (void *data, int type, char *buf), + mode_t (*is_visible) (void *data, int type)) +{ + return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group, + "target%d", index, data, show, is_visible); +} +EXPORT_SYMBOL_GPL(iscsi_boot_create_target); + +/** + * iscsi_boot_create_initiator() - create boot initiator sysfs dir + * @boot_kset: boot kset + * @index: the initiator id + * @data: driver specific data + * @show: attr show function + * @is_visible: attr visibility function + * + * Note: The boot sysfs lib will free the data passed in for the caller + * when all refs to the initiator kobject have been released. + */ +struct iscsi_boot_kobj * +iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, + void *data, + ssize_t (*show) (void *data, int type, char *buf), + mode_t (*is_visible) (void *data, int type)) +{ + return iscsi_boot_create_kobj(boot_kset, + &iscsi_boot_initiator_attr_group, + "initiator", index, data, show, + is_visible); +} +EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator); + +/** + * iscsi_boot_create_ethernet() - create boot ethernet sysfs dir + * @boot_kset: boot kset + * @index: the ethernet device id + * @data: driver specific data + * @show: attr show function + * @is_visible: attr visibility function + * + * Note: The boot sysfs lib will free the data passed in for the caller + * when all refs to the ethernet kobject have been released. + */ +struct iscsi_boot_kobj * +iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, + void *data, + ssize_t (*show) (void *data, int type, char *buf), + mode_t (*is_visible) (void *data, int type)) +{ + return iscsi_boot_create_kobj(boot_kset, + &iscsi_boot_ethernet_attr_group, + "ethernet%d", index, data, show, + is_visible); +} +EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet); + +/** + * iscsi_boot_create_kset() - creates root sysfs tree + * @set_name: name of root dir + */ +struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name) +{ + struct iscsi_boot_kset *boot_kset; + + boot_kset = kzalloc(sizeof(*boot_kset), GFP_KERNEL); + if (!boot_kset) + return NULL; + + boot_kset->kset = kset_create_and_add(set_name, NULL, firmware_kobj); + if (!boot_kset->kset) { + kfree(boot_kset); + return NULL; + } + + INIT_LIST_HEAD(&boot_kset->kobj_list); + return boot_kset; +} +EXPORT_SYMBOL_GPL(iscsi_boot_create_kset); + +/** + * iscsi_boot_create_host_kset() - creates root sysfs tree for a scsi host + * @hostno: host number of scsi host + */ +struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno) +{ + struct iscsi_boot_kset *boot_kset; + char *set_name; + + set_name = kasprintf(GFP_KERNEL, "iscsi_boot%u", hostno); + if (!set_name) + return NULL; + + boot_kset = iscsi_boot_create_kset(set_name); + kfree(set_name); + return boot_kset; +} +EXPORT_SYMBOL_GPL(iscsi_boot_create_host_kset); + +/** + * iscsi_boot_destroy_kset() - destroy kset and kobjects under it + * @boot_kset: boot kset + * + * This will remove the kset and kobjects and attrs under it. + */ +void iscsi_boot_destroy_kset(struct iscsi_boot_kset *boot_kset) +{ + struct iscsi_boot_kobj *boot_kobj, *tmp_kobj; + + list_for_each_entry_safe(boot_kobj, tmp_kobj, + &boot_kset->kobj_list, list) + iscsi_boot_remove_kobj(boot_kobj); + + kset_unregister(boot_kset->kset); +} +EXPORT_SYMBOL_GPL(iscsi_boot_destroy_kset); diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index eac4d09314e..c797f6b48f0 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1765,14 +1765,14 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *)) struct fcoe_dev_stats *stats; lport = shost_priv(sc_cmd->device->host); - spin_unlock_irq(lport->host->host_lock); rval = fc_remote_port_chkready(rport); if (rval) { sc_cmd->result = rval; done(sc_cmd); - goto out; + return 0; } + spin_unlock_irq(lport->host->host_lock); if (!*(struct fc_remote_port **)rport->dd_data) { /* diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 3482d5a5aed..a50aa03b8ac 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h @@ -775,6 +775,7 @@ struct lpfc_hba { uint8_t temp_sensor_support; /* Fields used for heart beat. */ unsigned long last_completion_time; + unsigned long skipped_hb; struct timer_list hb_tmofunc; uint8_t hb_outstanding; enum hba_temp_state over_temp_state; @@ -817,6 +818,8 @@ struct lpfc_hba { uint32_t iocb_cnt; uint32_t iocb_max; atomic_t sdev_cnt; + uint8_t fips_spec_rev; + uint8_t fips_level; }; static inline struct Scsi_Host * diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 868874c28f9..23ce4570833 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -25,6 +25,7 @@ #include <linux/interrupt.h> #include <linux/aer.h> #include <linux/gfp.h> +#include <linux/kernel.h> #include <scsi/scsi.h> #include <scsi/scsi_device.h> @@ -1239,6 +1240,44 @@ lpfc_poll_store(struct device *dev, struct device_attribute *attr, } /** + * lpfc_fips_level_show - Return the current FIPS level for the HBA + * @dev: class unused variable. + * @attr: device attribute, not used. + * @buf: on return contains the module description text. + * + * Returns: size of formatted string. + **/ +static ssize_t +lpfc_fips_level_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + + return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_level); +} + +/** + * lpfc_fips_rev_show - Return the FIPS Spec revision for the HBA + * @dev: class unused variable. + * @attr: device attribute, not used. + * @buf: on return contains the module description text. + * + * Returns: size of formatted string. + **/ +static ssize_t +lpfc_fips_rev_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; + struct lpfc_hba *phba = vport->phba; + + return snprintf(buf, PAGE_SIZE, "%d\n", phba->fips_spec_rev); +} + +/** * lpfc_param_show - Return a cfg attribute value in decimal * * Description: @@ -1676,6 +1715,8 @@ static DEVICE_ATTR(max_xri, S_IRUGO, lpfc_max_xri_show, NULL); static DEVICE_ATTR(used_xri, S_IRUGO, lpfc_used_xri_show, NULL); static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL); static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL); +static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL); +static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL); static char *lpfc_soft_wwn_key = "C99G71SL8032A"; @@ -1795,12 +1836,11 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr, /* Validate and store the new name */ for (i=0, j=0; i < 16; i++) { - if ((*buf >= 'a') && (*buf <= 'f')) - j = ((j << 4) | ((*buf++ -'a') + 10)); - else if ((*buf >= 'A') && (*buf <= 'F')) - j = ((j << 4) | ((*buf++ -'A') + 10)); - else if ((*buf >= '0') && (*buf <= '9')) - j = ((j << 4) | (*buf++ -'0')); + int value; + + value = hex_to_bin(*buf++); + if (value >= 0) + j = (j << 4) | value; else return -EINVAL; if (i % 2) { @@ -1888,12 +1928,11 @@ lpfc_soft_wwnn_store(struct device *dev, struct device_attribute *attr, /* Validate and store the new name */ for (i=0, j=0; i < 16; i++) { - if ((*buf >= 'a') && (*buf <= 'f')) - j = ((j << 4) | ((*buf++ -'a') + 10)); - else if ((*buf >= 'A') && (*buf <= 'F')) - j = ((j << 4) | ((*buf++ -'A') + 10)); - else if ((*buf >= '0') && (*buf <= '9')) - j = ((j << 4) | (*buf++ -'0')); + int value; + + value = hex_to_bin(*buf++); + if (value >= 0) + j = (j << 4) | value; else return -EINVAL; if (i % 2) { @@ -2778,7 +2817,6 @@ static struct bin_attribute sysfs_drvr_stat_data_attr = { .attr = { .name = "lpfc_drvr_stat_data", .mode = S_IRUSR, - .owner = THIS_MODULE, }, .size = LPFC_MAX_TARGET * MAX_STAT_DATA_SIZE_PER_TARGET, .read = sysfs_drvr_stat_data_read, @@ -3280,7 +3318,7 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support"); # - Default will result in registering capabilities for all profiles. # */ -unsigned int lpfc_prot_mask = SHOST_DIX_TYPE0_PROTECTION; +unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION; module_param(lpfc_prot_mask, uint, 0); MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); @@ -3385,6 +3423,8 @@ struct device_attribute *lpfc_hba_attrs[] = { &dev_attr_iocb_hw, &dev_attr_txq_hw, &dev_attr_txcmplq_hw, + &dev_attr_lpfc_fips_level, + &dev_attr_lpfc_fips_rev, NULL, }; @@ -3411,6 +3451,8 @@ struct device_attribute *lpfc_vport_attrs[] = { &dev_attr_lpfc_max_scsicmpl_time, &dev_attr_lpfc_stat_data_ctrl, &dev_attr_lpfc_static_vport, + &dev_attr_lpfc_fips_level, + &dev_attr_lpfc_fips_rev, NULL, }; diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index d521569e662..49d0cf99c24 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -2724,15 +2724,6 @@ lpfc_bsg_issue_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, pmboxq->context2 = ext; pmboxq->in_ext_byte_len = - mbox_req->inExtWLen * - sizeof(uint32_t); - pmboxq->out_ext_byte_len = - mbox_req->outExtWLen * - sizeof(uint32_t); - pmboxq->mbox_offset_word = - mbox_req->mbOffset; - pmboxq->context2 = ext; - pmboxq->in_ext_byte_len = mbox_req->inExtWLen * sizeof(uint32_t); pmboxq->out_ext_byte_len = mbox_req->outExtWLen * sizeof(uint32_t); diff --git a/drivers/scsi/lpfc/lpfc_compat.h b/drivers/scsi/lpfc/lpfc_compat.h index a11f1ae7b98..75e2e569ded 100644 --- a/drivers/scsi/lpfc/lpfc_compat.h +++ b/drivers/scsi/lpfc/lpfc_compat.h @@ -82,8 +82,7 @@ lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes) static inline void lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes) { - /* actually returns 1 byte past dest */ - memcpy_toio( dest, src, bytes); + __iowrite32_copy(dest, src, bytes); } static inline void diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index afbed6bc31f..8d09191c327 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -600,6 +600,14 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI; spin_unlock_irq(shost->host_lock); } + } else if ((phba->sli_rev == LPFC_SLI_REV4) && + !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { + /* + * Driver needs to re-reg VPI in order for f/w + * to update the MAC address. + */ + lpfc_register_new_vport(phba, vport, ndlp); + return 0; } if (phba->sli_rev < LPFC_SLI_REV4) { @@ -801,9 +809,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED)) { lpfc_printf_log(phba, KERN_WARNING, LOG_FIP | LOG_ELS, "2611 FLOGI failed on registered " - "FCF record fcf_index:%d, trying " - "to perform round robin failover\n", - phba->fcf.current_rec.fcf_indx); + "FCF record fcf_index(%d), status: " + "x%x/x%x, tmo:x%x, trying to perform " + "round robin failover\n", + phba->fcf.current_rec.fcf_indx, + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout); fcf_index = lpfc_sli4_fcf_rr_next_index_get(phba); if (fcf_index == LPFC_FCOE_FCF_NEXT_NONE) { /* @@ -841,6 +852,12 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, } } + /* FLOGI failure */ + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, + "2858 FLOGI failure Status:x%x/x%x TMO:x%x\n", + irsp->ulpStatus, irsp->un.ulpWord[4], + irsp->ulpTimeout); + /* Check for retry */ if (lpfc_els_retry(phba, cmdiocb, rspiocb)) goto out; @@ -1291,6 +1308,8 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, struct serv_parm *sp; uint8_t name[sizeof(struct lpfc_name)]; uint32_t rc, keepDID = 0; + int put_node; + int put_rport; /* Fabric nodes can have the same WWPN so we don't bother searching * by WWPN. Just return the ndlp that was given to us. @@ -1379,6 +1398,28 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, /* Two ndlps cannot have the same did */ ndlp->nlp_DID = keepDID; lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); + /* Since we are swapping the ndlp passed in with the new one + * and the did has already been swapped, copy over the + * state and names. + */ + memcpy(&new_ndlp->nlp_portname, &ndlp->nlp_portname, + sizeof(struct lpfc_name)); + memcpy(&new_ndlp->nlp_nodename, &ndlp->nlp_nodename, + sizeof(struct lpfc_name)); + new_ndlp->nlp_state = ndlp->nlp_state; + /* Fix up the rport accordingly */ + rport = ndlp->rport; + if (rport) { + rdata = rport->dd_data; + put_node = rdata->pnode != NULL; + put_rport = ndlp->rport != NULL; + rdata->pnode = NULL; + ndlp->rport = NULL; + if (put_node) + lpfc_nlp_put(ndlp); + if (put_rport) + put_device(&rport->dev); + } } return new_ndlp; } @@ -2880,6 +2921,17 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, retry = 0; if (retry) { + if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_FDISC)) { + /* Stop retrying PLOGI and FDISC if in FCF discovery */ + if (phba->fcf.fcf_flag & FCF_DISCOVERY) { + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, + "2849 Stop retry ELS command " + "x%x to remote NPORT x%x, " + "Data: x%x x%x\n", cmd, did, + cmdiocb->retry, delay); + return 0; + } + } /* Retry ELS command <elsCmd> to remote NPORT <did> */ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, @@ -6076,8 +6128,12 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) if (mb->mbxStatus) { lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, - "0915 Register VPI failed: 0x%x\n", - mb->mbxStatus); + "0915 Register VPI failed : Status: x%x" + " upd bit: x%x \n", mb->mbxStatus, + mb->un.varRegVpi.upd); + if (phba->sli_rev == LPFC_SLI_REV4 && + mb->un.varRegVpi.upd) + goto mbox_err_exit ; switch (mb->mbxStatus) { case 0x11: /* unsupported feature */ @@ -6142,7 +6198,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) } else lpfc_do_scr_ns_plogi(phba, vport); } - +mbox_err_exit: /* Now, we decrement the ndlp reference count held for this * callback function */ @@ -6387,6 +6443,14 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, else vport->fc_flag |= FC_LOGO_RCVD_DID_CHNG; spin_unlock_irq(shost->host_lock); + } else if ((phba->sli_rev == LPFC_SLI_REV4) && + !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) { + /* + * Driver needs to re-reg VPI in order for f/w + * to update the MAC address. + */ + lpfc_register_new_vport(phba, vport, ndlp); + return ; } if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 0639c994349..1f62ea8c165 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -588,7 +588,7 @@ lpfc_work_done(struct lpfc_hba *phba) (status & HA_RXMASK)); } - if (pring->txq_cnt) + if ((phba->sli_rev == LPFC_SLI_REV4) && pring->txq_cnt) lpfc_drain_txq(phba); /* * Turn on Ring interrupts @@ -1852,8 +1852,7 @@ lpfc_mbx_cmpl_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) __lpfc_sli4_stop_fcf_redisc_wait_timer(phba); else if (phba->fcf.fcf_flag & FCF_REDISC_FOV) /* If in fast failover, mark it's completed */ - phba->fcf.fcf_flag &= ~(FCF_REDISC_FOV | - FCF_DISCOVERY); + phba->fcf.fcf_flag &= ~FCF_REDISC_FOV; spin_unlock_irq(&phba->hbalock); lpfc_printf_log(phba, KERN_INFO, LOG_FIP, "2836 The new FCF record (x%x) " @@ -2651,7 +2650,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) spin_unlock_irq(&phba->hbalock); lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2778 Start FCF table scan at linkup\n"); - rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); if (rc) { @@ -2660,6 +2658,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la) spin_unlock_irq(&phba->hbalock); goto out; } + /* Reset FCF roundrobin bmask for new discovery */ + memset(phba->fcf.fcf_rr_bmask, 0, + sizeof(*phba->fcf.fcf_rr_bmask)); } return; @@ -5097,6 +5098,7 @@ static void lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) { struct lpfc_vport *vport = mboxq->vport; + struct Scsi_Host *shost = lpfc_shost_from_vport(vport); if (mboxq->u.mb.mbxStatus) { lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, @@ -5104,6 +5106,9 @@ lpfc_unregister_vfi_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) "HBA state x%x\n", mboxq->u.mb.mbxStatus, vport->port_state); } + spin_lock_irq(shost->host_lock); + phba->pport->fc_flag &= ~FC_VFI_REGISTERED; + spin_unlock_irq(shost->host_lock); mempool_free(mboxq, phba->mbox_mem_pool); return; } @@ -5285,6 +5290,10 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); phba->fcf.fcf_flag |= FCF_INIT_DISC; spin_unlock_irq(&phba->hbalock); + + /* Reset FCF roundrobin bmask for new discovery */ + memset(phba->fcf.fcf_rr_bmask, 0, sizeof(*phba->fcf.fcf_rr_bmask)); + rc = lpfc_sli4_fcf_scan_read_fcf_rec(phba, LPFC_FCOE_FCF_GET_FIRST); if (rc) { diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index f5dbf2be3ea..1676f61291e 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h @@ -2291,7 +2291,8 @@ typedef struct { typedef struct { #ifdef __BIG_ENDIAN_BITFIELD uint32_t rsvd1; - uint32_t rsvd2:8; + uint32_t rsvd2:7; + uint32_t upd:1; uint32_t sid:24; uint32_t wwn[2]; uint32_t rsvd5; @@ -2300,7 +2301,8 @@ typedef struct { #else /* __LITTLE_ENDIAN */ uint32_t rsvd1; uint32_t sid:24; - uint32_t rsvd2:8; + uint32_t upd:1; + uint32_t rsvd2:7; uint32_t wwn[2]; uint32_t rsvd5; uint16_t vpi; @@ -2806,11 +2808,15 @@ typedef struct { uint32_t rsvd6; /* Reserved */ #ifdef __BIG_ENDIAN_BITFIELD - uint32_t rsvd7 : 16; /* Reserved */ + uint32_t fips_rev : 3; /* FIPS Spec Revision */ + uint32_t fips_level : 4; /* FIPS Level */ + uint32_t sec_err : 9; /* security crypto error */ uint32_t max_vpi : 16; /* Max number of virt N-Ports */ #else /* __LITTLE_ENDIAN */ uint32_t max_vpi : 16; /* Max number of virt N-Ports */ - uint32_t rsvd7 : 16; /* Reserved */ + uint32_t sec_err : 9; /* security crypto error */ + uint32_t fips_level : 4; /* FIPS Level */ + uint32_t fips_rev : 3; /* FIPS Spec Revision */ #endif } CONFIG_PORT_VAR; @@ -3441,63 +3447,63 @@ struct sli3_bg_fields { static inline uint32_t lpfc_bgs_get_bidir_bg_prof(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_BIDIR_BG_PROF_MASK) >> + return (bgstat & BGS_BIDIR_BG_PROF_MASK) >> BGS_BIDIR_BG_PROF_SHIFT; } static inline uint32_t lpfc_bgs_get_bidir_err_cond(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_BIDIR_ERR_COND_FLAGS_MASK) >> + return (bgstat & BGS_BIDIR_ERR_COND_FLAGS_MASK) >> BGS_BIDIR_ERR_COND_SHIFT; } static inline uint32_t lpfc_bgs_get_bg_prof(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_BG_PROFILE_MASK) >> + return (bgstat & BGS_BG_PROFILE_MASK) >> BGS_BG_PROFILE_SHIFT; } static inline uint32_t lpfc_bgs_get_invalid_prof(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_INVALID_PROF_MASK) >> + return (bgstat & BGS_INVALID_PROF_MASK) >> BGS_INVALID_PROF_SHIFT; } static inline uint32_t lpfc_bgs_get_uninit_dif_block(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_UNINIT_DIF_BLOCK_MASK) >> + return (bgstat & BGS_UNINIT_DIF_BLOCK_MASK) >> BGS_UNINIT_DIF_BLOCK_SHIFT; } static inline uint32_t lpfc_bgs_get_hi_water_mark_present(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_HI_WATER_MARK_PRESENT_MASK) >> + return (bgstat & BGS_HI_WATER_MARK_PRESENT_MASK) >> BGS_HI_WATER_MARK_PRESENT_SHIFT; } static inline uint32_t lpfc_bgs_get_reftag_err(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_REFTAG_ERR_MASK) >> + return (bgstat & BGS_REFTAG_ERR_MASK) >> BGS_REFTAG_ERR_SHIFT; } static inline uint32_t lpfc_bgs_get_apptag_err(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_APPTAG_ERR_MASK) >> + return (bgstat & BGS_APPTAG_ERR_MASK) >> BGS_APPTAG_ERR_SHIFT; } static inline uint32_t lpfc_bgs_get_guard_err(uint32_t bgstat) { - return (le32_to_cpu(bgstat) & BGS_GUARD_ERR_MASK) >> + return (bgstat & BGS_GUARD_ERR_MASK) >> BGS_GUARD_ERR_SHIFT; } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 2786ee3b605..da9ba06ad58 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -1032,27 +1032,46 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) /* If there is no heart beat outstanding, issue a heartbeat command */ if (phba->cfg_enable_hba_heartbeat) { if (!phba->hb_outstanding) { - pmboxq = mempool_alloc(phba->mbox_mem_pool,GFP_KERNEL); - if (!pmboxq) { - mod_timer(&phba->hb_tmofunc, - jiffies + HZ * LPFC_HB_MBOX_INTERVAL); - return; - } + if ((!(psli->sli_flag & LPFC_SLI_MBOX_ACTIVE)) && + (list_empty(&psli->mboxq))) { + pmboxq = mempool_alloc(phba->mbox_mem_pool, + GFP_KERNEL); + if (!pmboxq) { + mod_timer(&phba->hb_tmofunc, + jiffies + + HZ * LPFC_HB_MBOX_INTERVAL); + return; + } - lpfc_heart_beat(phba, pmboxq); - pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; - pmboxq->vport = phba->pport; - retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); + lpfc_heart_beat(phba, pmboxq); + pmboxq->mbox_cmpl = lpfc_hb_mbox_cmpl; + pmboxq->vport = phba->pport; + retval = lpfc_sli_issue_mbox(phba, pmboxq, + MBX_NOWAIT); + + if (retval != MBX_BUSY && + retval != MBX_SUCCESS) { + mempool_free(pmboxq, + phba->mbox_mem_pool); + mod_timer(&phba->hb_tmofunc, + jiffies + + HZ * LPFC_HB_MBOX_INTERVAL); + return; + } + phba->skipped_hb = 0; + phba->hb_outstanding = 1; + } else if (time_before_eq(phba->last_completion_time, + phba->skipped_hb)) { + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "2857 Last completion time not " + " updated in %d ms\n", + jiffies_to_msecs(jiffies + - phba->last_completion_time)); + } else + phba->skipped_hb = jiffies; - if (retval != MBX_BUSY && retval != MBX_SUCCESS) { - mempool_free(pmboxq, phba->mbox_mem_pool); - mod_timer(&phba->hb_tmofunc, - jiffies + HZ * LPFC_HB_MBOX_INTERVAL); - return; - } mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_TIMEOUT); - phba->hb_outstanding = 1; return; } else { /* @@ -3281,10 +3300,10 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport) if (!ndlp) return 0; } - if (phba->pport->port_state <= LPFC_FLOGI) + if (phba->pport->port_state < LPFC_FLOGI) return NULL; /* If virtual link is not yet instantiated ignore CVL */ - if (vport->port_state <= LPFC_FDISC) + if ((vport != phba->pport) && (vport->port_state < LPFC_FDISC)) return NULL; shost = lpfc_shost_from_vport(vport); if (!shost) @@ -3357,21 +3376,7 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, "evt_tag:x%x, fcf_index:x%x\n", acqe_fcoe->event_tag, acqe_fcoe->index); - /* If the FCF discovery is in progress, do nothing. */ - spin_lock_irq(&phba->hbalock); - if (phba->hba_flag & FCF_DISC_INPROGRESS) { - spin_unlock_irq(&phba->hbalock); - break; - } - /* If fast FCF failover rescan event is pending, do nothing */ - if (phba->fcf.fcf_flag & FCF_REDISC_EVT) { - spin_unlock_irq(&phba->hbalock); - break; - } - spin_unlock_irq(&phba->hbalock); - - if ((phba->fcf.fcf_flag & FCF_DISCOVERY) && - !(phba->fcf.fcf_flag & FCF_REDISC_FOV)) { + if (phba->fcf.fcf_flag & FCF_DISCOVERY) { /* * During period of FCF discovery, read the FCF * table record indexed by the event to update @@ -3385,13 +3390,26 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, acqe_fcoe->index); rc = lpfc_sli4_read_fcf_rec(phba, acqe_fcoe->index); } - /* If the FCF has been in discovered state, do nothing. */ + + /* If the FCF discovery is in progress, do nothing. */ spin_lock_irq(&phba->hbalock); + if (phba->hba_flag & FCF_DISC_INPROGRESS) { + spin_unlock_irq(&phba->hbalock); + break; + } + /* If fast FCF failover rescan event is pending, do nothing */ + if (phba->fcf.fcf_flag & FCF_REDISC_EVT) { + spin_unlock_irq(&phba->hbalock); + break; + } + + /* If the FCF has been in discovered state, do nothing. */ if (phba->fcf.fcf_flag & FCF_SCAN_DONE) { spin_unlock_irq(&phba->hbalock); break; } spin_unlock_irq(&phba->hbalock); + /* Otherwise, scan the entire FCF table and re-discover SAN */ lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2770 Start FCF table scan due to new FCF " @@ -3417,13 +3435,9 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, "2549 FCF disconnected from network index 0x%x" " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag); - /* If the event is not for currently used fcf do nothing */ - if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index) - break; - /* We request port to rediscover the entire FCF table for - * a fast recovery from case that the current FCF record - * is no longer valid if we are not in the middle of FCF - * failover process already. + /* + * If we are in the middle of FCF failover process, clear + * the corresponding FCF bit in the roundrobin bitmap. */ spin_lock_irq(&phba->hbalock); if (phba->fcf.fcf_flag & FCF_DISCOVERY) { @@ -3432,9 +3446,23 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, lpfc_sli4_fcf_rr_index_clear(phba, acqe_fcoe->index); break; } + spin_unlock_irq(&phba->hbalock); + + /* If the event is not for currently used fcf do nothing */ + if (phba->fcf.current_rec.fcf_indx != acqe_fcoe->index) + break; + + /* + * Otherwise, request the port to rediscover the entire FCF + * table for a fast recovery from case that the current FCF + * is no longer valid as we are not in the middle of FCF + * failover process already. + */ + spin_lock_irq(&phba->hbalock); /* Mark the fast failover process in progress */ phba->fcf.fcf_flag |= FCF_DEAD_DISC; spin_unlock_irq(&phba->hbalock); + lpfc_printf_log(phba, KERN_INFO, LOG_FIP | LOG_DISCOVERY, "2771 Start FCF fast failover process due to " "FCF DEAD event: evt_tag:x%x, fcf_index:x%x " @@ -3454,12 +3482,16 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, * as a link down to FCF registration. */ lpfc_sli4_fcf_dead_failthrough(phba); - } else - /* Handling fast FCF failover to a DEAD FCF event - * is considered equalivant to receiving CVL to all - * vports. + } else { + /* Reset FCF roundrobin bmask for new discovery */ + memset(phba->fcf.fcf_rr_bmask, 0, + sizeof(*phba->fcf.fcf_rr_bmask)); + /* + * Handling fast FCF failover to a DEAD FCF event is + * considered equalivant to receiving CVL to all vports. */ lpfc_sli4_perform_all_vport_cvl(phba); + } break; case LPFC_FCOE_EVENT_TYPE_CVL: lpfc_printf_log(phba, KERN_ERR, LOG_FIP | LOG_DISCOVERY, @@ -3534,7 +3566,13 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba, * the current registered FCF entry. */ lpfc_retry_pport_discovery(phba); - } + } else + /* + * Reset FCF roundrobin bmask for new + * discovery. + */ + memset(phba->fcf.fcf_rr_bmask, 0, + sizeof(*phba->fcf.fcf_rr_bmask)); } break; default: diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 9c2c7c7140c..0dfa310cd60 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c @@ -815,9 +815,15 @@ void lpfc_reg_vpi(struct lpfc_vport *vport, LPFC_MBOXQ_t *pmb) { MAILBOX_t *mb = &pmb->u.mb; + struct lpfc_hba *phba = vport->phba; memset(pmb, 0, sizeof (LPFC_MBOXQ_t)); - + /* + * Set the re-reg VPI bit for f/w to update the MAC address. + */ + if ((phba->sli_rev == LPFC_SLI_REV4) && + !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) + mb->un.varRegVpi.upd = 1; mb->un.varRegVpi.vpi = vport->vpi + vport->phba->vpi_base; mb->un.varRegVpi.sid = vport->fc_myDID; mb->un.varRegVpi.vfi = vport->vfi + vport->phba->vfi_base; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index c818a725596..2e51aa6b45b 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1325,7 +1325,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); pde5->reftag = reftag; - /* Endian convertion if necessary for PDE5 */ + /* Endianness conversion if necessary for PDE5 */ pde5->word0 = cpu_to_le32(pde5->word0); pde5->reftag = cpu_to_le32(pde5->reftag); @@ -1347,7 +1347,7 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde6_ai, pde6, 1); bf_set(pde6_apptagval, pde6, apptagval); - /* Endian convertion if necessary for PDE6 */ + /* Endianness conversion if necessary for PDE6 */ pde6->word0 = cpu_to_le32(pde6->word0); pde6->word1 = cpu_to_le32(pde6->word1); pde6->word2 = cpu_to_le32(pde6->word2); @@ -1459,7 +1459,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); pde5->reftag = reftag; - /* Endian convertion if necessary for PDE5 */ + /* Endianness conversion if necessary for PDE5 */ pde5->word0 = cpu_to_le32(pde5->word0); pde5->reftag = cpu_to_le32(pde5->reftag); @@ -1479,7 +1479,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde6_ai, pde6, 1); bf_set(pde6_apptagval, pde6, apptagval); - /* Endian convertion if necessary for PDE6 */ + /* Endianness conversion if necessary for PDE6 */ pde6->word0 = cpu_to_le32(pde6->word0); pde6->word1 = cpu_to_le32(pde6->word1); pde6->word2 = cpu_to_le32(pde6->word2); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index e758eae0d0f..fb8905f893f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1046,7 +1046,7 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) } else spin_unlock_irq(&phba->hbalock); - lpfc_printf_log(phba, KERN_ERR,LOG_SLI, + lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, "0318 Failed to allocate IOTAG.last IOTAG is %d\n", psli->last_iotag); @@ -3914,7 +3914,8 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED | LPFC_SLI3_HBQ_ENABLED | LPFC_SLI3_CRP_ENABLED | - LPFC_SLI3_BG_ENABLED); + LPFC_SLI3_BG_ENABLED | + LPFC_SLI3_DSS_ENABLED); if (rc != MBX_SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0442 Adapter failed to init, mbxCmd x%x " @@ -3949,8 +3950,23 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) } else phba->max_vpi = 0; - if (pmb->u.mb.un.varCfgPort.gdss) + phba->fips_level = 0; + phba->fips_spec_rev = 0; + if (pmb->u.mb.un.varCfgPort.gdss) { phba->sli3_options |= LPFC_SLI3_DSS_ENABLED; + phba->fips_level = pmb->u.mb.un.varCfgPort.fips_level; + phba->fips_spec_rev = pmb->u.mb.un.varCfgPort.fips_rev; + lpfc_printf_log(phba, KERN_INFO, LOG_INIT, + "2850 Security Crypto Active. FIPS x%d " + "(Spec Rev: x%d)", + phba->fips_level, phba->fips_spec_rev); + } + if (pmb->u.mb.un.varCfgPort.sec_err) { + lpfc_printf_log(phba, KERN_ERR, LOG_INIT, + "2856 Config Port Security Crypto " + "Error: x%x ", + pmb->u.mb.un.varCfgPort.sec_err); + } if (pmb->u.mb.un.varCfgPort.gerbm) phba->sli3_options |= LPFC_SLI3_HBQ_ENABLED; if (pmb->u.mb.un.varCfgPort.gcrp) @@ -9040,6 +9056,7 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, switch (bf_get(lpfc_cqe_code, &cqevt)) { case CQE_CODE_COMPL_WQE: /* Process the WQ/RQ complete event */ + phba->last_completion_time = jiffies; workposted = lpfc_sli4_sp_handle_els_wcqe(phba, (struct lpfc_wcqe_complete *)&cqevt); break; @@ -9050,11 +9067,13 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq, break; case CQE_CODE_XRI_ABORTED: /* Process the WQ XRI abort event */ + phba->last_completion_time = jiffies; workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, (struct sli4_wcqe_xri_aborted *)&cqevt); break; case CQE_CODE_RECEIVE: /* Process the RQ event */ + phba->last_completion_time = jiffies; workposted = lpfc_sli4_sp_handle_rcqe(phba, (struct lpfc_rcqe *)&cqevt); break; @@ -9276,7 +9295,6 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, { struct lpfc_wcqe_release wcqe; bool workposted = false; - unsigned long iflag; /* Copy the work queue CQE and convert endian order if needed */ lpfc_sli_pcimem_bcopy(cqe, &wcqe, sizeof(struct lpfc_cqe)); @@ -9285,9 +9303,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, switch (bf_get(lpfc_wcqe_c_code, &wcqe)) { case CQE_CODE_COMPL_WQE: /* Process the WQ complete event */ - spin_lock_irqsave(&phba->hbalock, iflag); phba->last_completion_time = jiffies; - spin_unlock_irqrestore(&phba->hbalock, iflag); lpfc_sli4_fp_handle_fcp_wcqe(phba, (struct lpfc_wcqe_complete *)&wcqe); break; @@ -9298,6 +9314,7 @@ lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, break; case CQE_CODE_XRI_ABORTED: /* Process the WQ XRI abort event */ + phba->last_completion_time = jiffies; workposted = lpfc_sli4_sp_handle_abort_xri_wcqe(phba, cq, (struct sli4_wcqe_xri_aborted *)&wcqe); break; @@ -12278,12 +12295,9 @@ lpfc_sli4_fcf_scan_read_fcf_rec(struct lpfc_hba *phba, uint16_t fcf_index) spin_lock_irq(&phba->hbalock); phba->hba_flag |= FCF_DISC_INPROGRESS; spin_unlock_irq(&phba->hbalock); - /* Reset FCF round robin index bmask for new scan */ - if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) { - memset(phba->fcf.fcf_rr_bmask, 0, - sizeof(*phba->fcf.fcf_rr_bmask)); + /* Reset eligible FCF count for new scan */ + if (fcf_index == LPFC_FCOE_FCF_GET_FIRST) phba->fcf.eligible_fcf_cnt = 0; - } error = 0; } fail_fcf_scan: diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index d28830af71d..61afb3420a9 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.3.15" +#define LPFC_DRIVER_VERSION "8.3.16" #define LPFC_DRIVER_NAME "lpfc" #define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp" #define LPFC_FP_DRIVER_HANDLER_NAME "lpfc:fp" diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index ee4b6914667..fda4de3440c 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -716,7 +716,7 @@ static int _osd_req_list_objects(struct osd_request *or, return PTR_ERR(bio); } - bio->bi_rw &= ~(1 << BIO_RW); + bio->bi_rw &= ~REQ_WRITE; or->in.bio = bio; or->in.total_bytes = bio->bi_size; return 0; @@ -814,7 +814,7 @@ void osd_req_write(struct osd_request *or, { _osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, len); WARN_ON(or->out.bio || or->out.total_bytes); - WARN_ON(0 == bio_rw_flagged(bio, BIO_RW)); + WARN_ON(0 == (bio->bi_rw & REQ_WRITE)); or->out.bio = bio; or->out.total_bytes = len; } @@ -829,7 +829,7 @@ int osd_req_write_kern(struct osd_request *or, if (IS_ERR(bio)) return PTR_ERR(bio); - bio->bi_rw |= (1 << BIO_RW); /* FIXME: bio_set_dir() */ + bio->bi_rw |= REQ_WRITE; /* FIXME: bio_set_dir() */ osd_req_write(or, obj, offset, bio, len); return 0; } @@ -865,7 +865,7 @@ void osd_req_read(struct osd_request *or, { _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, len); WARN_ON(or->in.bio || or->in.total_bytes); - WARN_ON(1 == bio_rw_flagged(bio, BIO_RW)); + WARN_ON(1 == (bio->bi_rw & REQ_WRITE)); or->in.bio = bio; or->in.total_bytes = len; } diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index d64b7178fa0..278b352ae78 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5868,7 +5868,8 @@ static int osst_probe(struct device *dev) } /* find a free minor number */ - for (i=0; os_scsi_tapes[i] && i<osst_max_dev; i++); + for (i = 0; i < osst_max_dev && os_scsi_tapes[i]; i++) + ; if(i >= osst_max_dev) panic ("Scsi_devices corrupt (osst)"); dev_num = i; diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 9d70aef9922..61f49bdcc0c 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -49,7 +49,6 @@ #include <scsi/scsi_host.h> #include "aha152x.h" -#include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/ds.h> @@ -101,9 +100,8 @@ static int aha152x_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->io.NumPorts1 = 0x20; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; + link->resource[0]->end = 0x20; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; @@ -131,15 +129,16 @@ static int aha152x_config_check(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { + p_dev->io_lines = 10; /* For New Media T&J, look for a SCSI window */ if (cfg->io.win[0].len >= 0x20) - p_dev->io.BasePort1 = cfg->io.win[0].base; + p_dev->resource[0]->start = cfg->io.win[0].base; else if ((cfg->io.nwin > 1) && (cfg->io.win[1].len >= 0x20)) - p_dev->io.BasePort1 = cfg->io.win[1].base; + p_dev->resource[0]->start = cfg->io.win[1].base; if ((cfg->io.nwin > 0) && - (p_dev->io.BasePort1 < 0xffff)) { - if (!pcmcia_request_io(p_dev, &p_dev->io)) + (p_dev->resource[0]->start < 0xffff)) { + if (!pcmcia_request_io(p_dev)) return 0; } return -EINVAL; @@ -168,7 +167,7 @@ static int aha152x_config_cs(struct pcmcia_device *link) /* Set configuration options for the aha152x driver */ memset(&s, 0, sizeof(s)); s.conf = "PCMCIA setup"; - s.io_port = link->io.BasePort1; + s.io_port = link->resource[0]->start; s.irq = link->irq; s.scsiid = host_id; s.reconnect = reconnect; diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 21b141151df..13dbe5c4849 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -46,7 +46,6 @@ #include <scsi/scsi_host.h> #include "fdomain.h" -#include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/ds.h> @@ -84,9 +83,8 @@ static int fdomain_probe(struct pcmcia_device *link) info->p_dev = link; link->priv = info; - link->io.NumPorts1 = 0x10; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; + link->resource[0]->end = 0x10; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; @@ -113,8 +111,9 @@ static int fdomain_config_check(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - p_dev->io.BasePort1 = cfg->io.win[0].base; - return pcmcia_request_io(p_dev, &p_dev->io); + p_dev->io_lines = 10; + p_dev->resource[0]->start = cfg->io.win[0].base; + return pcmcia_request_io(p_dev); } @@ -138,10 +137,10 @@ static int fdomain_config(struct pcmcia_device *link) goto failed; /* A bad hack... */ - release_region(link->io.BasePort1, link->io.NumPorts1); + release_region(link->resource[0]->start, resource_size(link->resource[0])); /* Set configuration options for the fdomain driver */ - sprintf(str, "%d,%d", link->io.BasePort1, link->irq); + sprintf(str, "%d,%d", (unsigned int) link->resource[0]->start, link->irq); fdomain_setup(str); host = __fdomain_16x0_detect(&fdomain_driver_template); diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 0f0e112c3f8..dd9b40306f3 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -47,7 +47,6 @@ #include <scsi/scsi.h> #include <scsi/scsi_ioctl.h> -#include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/cisreg.h> @@ -1559,9 +1558,8 @@ static int nsp_cs_probe(struct pcmcia_device *link) nsp_dbg(NSP_DEBUG_INIT, "info=0x%p", info); /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 0x10; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; /* not used */ + link->resource[0]->end = 0x10; + link->resource[0]->flags = IO_DATA_PATH_WIDTH_AUTO; /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; @@ -1642,29 +1640,27 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev, p_dev->conf.Attributes |= CONF_ENABLE_IRQ; /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + p_dev->resource[0]->end = p_dev->resource[1]->end = 0; if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; + p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK; + p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; + p_dev->resource[0]->flags |= + pcmcia_io_cfg_data_width(io->flags); + p_dev->resource[0]->start = io->win[0].base; + p_dev->resource[0]->end = io->win[0].len; if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; + p_dev->resource[1]->flags = + p_dev->resource[0]->flags; + p_dev->resource[1]->start = io->win[1].base; + p_dev->resource[1]->end = io->win[1].len; } /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) + if (pcmcia_request_io(p_dev) != 0) goto next_entry; } if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { - memreq_t map; cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem; cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; @@ -1676,8 +1672,8 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev, cfg_mem->req.AccessSpeed = 0; if (pcmcia_request_window(p_dev, &cfg_mem->req, &p_dev->win) != 0) goto next_entry; - map.Page = 0; map.CardOffset = mem->win[0].card_addr; - if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0) + if (pcmcia_map_mem_page(p_dev, p_dev->win, + mem->win[0].card_addr) != 0) goto next_entry; cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size); @@ -1720,17 +1716,19 @@ static int nsp_cs_config(struct pcmcia_device *link) goto cs_failed; if (free_ports) { - if (link->io.BasePort1) { - release_region(link->io.BasePort1, link->io.NumPorts1); + if (link->resource[0]) { + release_region(link->resource[0]->start, + resource_size(link->resource[0])); } - if (link->io.BasePort2) { - release_region(link->io.BasePort2, link->io.NumPorts2); + if (link->resource[1]) { + release_region(link->resource[1]->start, + resource_size(link->resource[1])); } } /* Set port and IRQ */ - data->BaseAddress = link->io.BasePort1; - data->NumAddress = link->io.NumPorts1; + data->BaseAddress = link->resource[0]->start; + data->NumAddress = resource_size(link->resource[0]); data->IrqNumber = link->irq; nsp_dbg(NSP_DEBUG_INIT, "I/O[0x%x+0x%x] IRQ %d", @@ -1765,13 +1763,10 @@ static int nsp_cs_config(struct pcmcia_device *link) if (link->conf.Attributes & CONF_ENABLE_IRQ) { printk(", irq %d", link->irq); } - if (link->io.NumPorts1) { - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - } - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2+link->io.NumPorts2-1); + if (link->resource[0]) + printk(", io %pR", link->resource[0]); + if (link->resource[1]) + printk(" & %pR", link->resource[1]); if (link->win) printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base, cfg_mem->req.Base+cfg_mem->req.Size-1); diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index f0fc6baed9f..eb775f1a523 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -48,7 +48,6 @@ #include <scsi/scsi_host.h> #include "../qlogicfas408.h" -#include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/ds.h> @@ -157,9 +156,8 @@ static int qlogic_probe(struct pcmcia_device *link) return -ENOMEM; info->p_dev = link; link->priv = info; - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; + link->resource[0]->end = 16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.Present = PRESENT_OPTION; @@ -186,13 +184,14 @@ static int qlogic_config_check(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - p_dev->io.BasePort1 = cfg->io.win[0].base; - p_dev->io.NumPorts1 = cfg->io.win[0].len; + p_dev->io_lines = 10; + p_dev->resource[0]->start = cfg->io.win[0].base; + p_dev->resource[0]->end = cfg->io.win[0].len; - if (p_dev->io.BasePort1 == 0) + if (p_dev->resource[0]->start == 0) return -ENODEV; - return pcmcia_request_io(p_dev, &p_dev->io); + return pcmcia_request_io(p_dev); } static int qlogic_config(struct pcmcia_device * link) @@ -216,18 +215,18 @@ static int qlogic_config(struct pcmcia_device * link) if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { /* set ATAcmd */ - outb(0xb4, link->io.BasePort1 + 0xd); - outb(0x24, link->io.BasePort1 + 0x9); - outb(0x04, link->io.BasePort1 + 0xd); + outb(0xb4, link->resource[0]->start + 0xd); + outb(0x24, link->resource[0]->start + 0x9); + outb(0x04, link->resource[0]->start + 0xd); } /* The KXL-810AN has a bigger IO port window */ - if (link->io.NumPorts1 == 32) + if (resource_size(link->resource[0]) == 32) host = qlogic_detect(&qlogicfas_driver_template, link, - link->io.BasePort1 + 16, link->irq); + link->resource[0]->start + 16, link->irq); else host = qlogic_detect(&qlogicfas_driver_template, link, - link->io.BasePort1, link->irq); + link->resource[0]->start, link->irq); if (!host) { printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name); @@ -269,9 +268,9 @@ static int qlogic_resume(struct pcmcia_device *link) if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { - outb(0x80, link->io.BasePort1 + 0xd); - outb(0x24, link->io.BasePort1 + 0x9); - outb(0x04, link->io.BasePort1 + 0xd); + outb(0x80, link->resource[0]->start + 0xd); + outb(0x24, link->resource[0]->start + 0x9); + outb(0x04, link->resource[0]->start + 0xd); } /* Ugggglllyyyy!!! */ qlogicfas408_bus_reset(NULL); diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index a5116417117..321e390c912 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -71,7 +71,6 @@ #include <scsi/scsi.h> #include <scsi/scsi_host.h> -#include <pcmcia/cs_types.h> #include <pcmcia/cs.h> #include <pcmcia/cistpl.h> #include <pcmcia/ds.h> @@ -691,13 +690,14 @@ static int SYM53C500_config_check(struct pcmcia_device *p_dev, unsigned int vcc, void *priv_data) { - p_dev->io.BasePort1 = cfg->io.win[0].base; - p_dev->io.NumPorts1 = cfg->io.win[0].len; + p_dev->io_lines = 10; + p_dev->resource[0]->start = cfg->io.win[0].base; + p_dev->resource[0]->end = cfg->io.win[0].len; - if (p_dev->io.BasePort1 == 0) + if (p_dev->resource[0]->start == 0) return -ENODEV; - return pcmcia_request_io(p_dev, &p_dev->io); + return pcmcia_request_io(p_dev); } static int @@ -734,9 +734,9 @@ SYM53C500_config(struct pcmcia_device *link) (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { /* set ATAcmd */ - outb(0xb4, link->io.BasePort1 + 0xd); - outb(0x24, link->io.BasePort1 + 0x9); - outb(0x04, link->io.BasePort1 + 0xd); + outb(0xb4, link->resource[0]->start + 0xd); + outb(0x24, link->resource[0]->start + 0x9); + outb(0x04, link->resource[0]->start + 0xd); } /* @@ -749,7 +749,7 @@ SYM53C500_config(struct pcmcia_device *link) * 0x130, 0x230, 0x280, 0x290, * 0x320, 0x330, 0x340, 0x350 */ - port_base = link->io.BasePort1; + port_base = link->resource[0]->start; irq_level = link->irq; DEB(printk("SYM53C500: port_base=0x%x, irq=%d, fast_pio=%d\n", @@ -822,15 +822,15 @@ static int sym53c500_resume(struct pcmcia_device *link) if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) { - outb(0x80, link->io.BasePort1 + 0xd); - outb(0x24, link->io.BasePort1 + 0x9); - outb(0x04, link->io.BasePort1 + 0xd); + outb(0x80, link->resource[0]->start + 0xd); + outb(0x24, link->resource[0]->start + 0x9); + outb(0x04, link->resource[0]->start + 0xd); } /* * If things don't work after a "resume", * this is a good place to start looking. */ - SYM53C500_int_host_reset(link->io.BasePort1); + SYM53C500_int_host_reset(link->resource[0]->start); return 0; } @@ -859,9 +859,8 @@ SYM53C500_probe(struct pcmcia_device *link) return -ENOMEM; info->p_dev = link; link->priv = info; - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - link->io.IOAddrLines = 10; + link->resource[0]->end = 16; + link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 58d1134935e..9793aa6afb1 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -4199,8 +4199,10 @@ static int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, circularQ = &pm8001_ha->inbnd_q_tbl[0]; memset(&nvmd_req, 0, sizeof(nvmd_req)); rc = pm8001_tag_alloc(pm8001_ha, &tag); - if (rc) + if (rc) { + kfree(fw_control_context); return rc; + } ccb = &pm8001_ha->ccb_info[tag]; ccb->ccb_tag = tag; ccb->fw_control_context = fw_control_context; @@ -4276,8 +4278,10 @@ static int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, ioctl_payload->length); memset(&nvmd_req, 0, sizeof(nvmd_req)); rc = pm8001_tag_alloc(pm8001_ha, &tag); - if (rc) + if (rc) { + kfree(fw_control_context); return rc; + } ccb = &pm8001_ha->ccb_info[tag]; ccb->fw_control_context = fw_control_context; ccb->ccb_tag = tag; @@ -4387,6 +4391,7 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, fw_control->len, 0) != 0) { PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Mem alloc failure\n")); + kfree(fw_control_context); return -ENOMEM; } } @@ -4401,8 +4406,10 @@ pm8001_chip_fw_flash_update_req(struct pm8001_hba_info *pm8001_ha, fw_control_context->virtAddr = buffer; fw_control_context->len = fw_control->len; rc = pm8001_tag_alloc(pm8001_ha, &tag); - if (rc) + if (rc) { + kfree(fw_control_context); return rc; + } ccb = &pm8001_ha->ccb_info[tag]; ccb->fw_control_context = fw_control_context; ccb->ccb_tag = tag; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index ff2172da7c1..8c80b49ac1c 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -115,8 +115,8 @@ int ql2xmaxqueues = 1; module_param(ql2xmaxqueues, int, S_IRUGO|S_IRUSR); MODULE_PARM_DESC(ql2xmaxqueues, "Enables MQ settings " - "Default is 1 for single queue. Set it to number \ - of queues in MQ mode."); + "Default is 1 for single queue. Set it to number " + "of queues in MQ mode."); int ql2xmultique_tag; module_param(ql2xmultique_tag, int, S_IRUGO|S_IRUSR); diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index a79da8dd206..9dc0a6616ed 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -36,6 +36,24 @@ #include "ql4_dbg.h" #include "ql4_nx.h" +#if defined(CONFIG_PCIEAER) +#include <linux/aer.h> +#else +/* AER releated */ +static inline int pci_enable_pcie_error_reporting(struct pci_dev *dev) +{ + return -EINVAL; +} +static inline int pci_disable_pcie_error_reporting(struct pci_dev *dev) +{ + return -EINVAL; +} +static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev) +{ + return -EINVAL; +} +#endif + #ifndef PCI_DEVICE_ID_QLOGIC_ISP4010 #define PCI_DEVICE_ID_QLOGIC_ISP4010 0x4010 #endif @@ -137,6 +155,9 @@ #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alias name size */ #define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */ +#define QL4_SESS_RECOVERY_TMO 30 /* iSCSI session */ + /* recovery timeout */ + #define LSDW(x) ((u32)((u64)(x))) #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) @@ -249,7 +270,6 @@ struct ddb_entry { uint32_t default_time2wait; /* Default Min time between * relogins (+aens) */ - atomic_t port_down_timer; /* Device connection timer */ atomic_t retry_relogin_timer; /* Min Time between relogins * (4000 only) */ atomic_t relogin_timer; /* Max Time to wait for relogin to complete */ @@ -378,7 +398,9 @@ struct scsi_qla_host { #define AF_MSI_ENABLED 16 /* 0x00010000 */ #define AF_MSIX_ENABLED 17 /* 0x00020000 */ #define AF_MBOX_COMMAND_NOPOLL 18 /* 0x00040000 */ - +#define AF_FW_RECOVERY 19 /* 0x00080000 */ +#define AF_EEH_BUSY 20 /* 0x00100000 */ +#define AF_PCI_CHANNEL_IO_PERM_FAILURE 21 /* 0x00200000 */ unsigned long dpc_flags; @@ -474,7 +496,6 @@ struct scsi_qla_host { uint32_t timer_active; /* Recovery Timers */ - uint32_t port_down_retry_count; uint32_t discovery_wait; atomic_t check_relogin_timeouts; uint32_t retry_reset_ha_cnt; @@ -615,6 +636,15 @@ static inline int is_qla8022(struct scsi_qla_host *ha) return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; } +/* Note: Currently AER/EEH is now supported only for 8022 cards + * This function needs to be updated when AER/EEH is enabled + * for other cards. + */ +static inline int is_aer_supported(struct scsi_qla_host *ha) +{ + return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8022; +} + static inline int adapter_up(struct scsi_qla_host *ha) { return (test_bit(AF_ONLINE, &ha->flags) != 0) && diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index c94c9ddfb3a..0336c6db8cb 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h @@ -673,17 +673,17 @@ struct flash_sys_info { }; /* 200 */ struct mbx_sys_info { - uint8_t board_id_str[16]; /* Keep board ID string first */ - /* in this structure for GUI. */ - uint16_t board_id; /* board ID code */ - uint16_t phys_port_cnt; /* number of physical network ports */ - uint16_t port_num; /* network port for this PCI function */ + uint8_t board_id_str[16]; /* 0-f Keep board ID string first */ + /* in this structure for GUI. */ + uint16_t board_id; /* 10-11 board ID code */ + uint16_t phys_port_cnt; /* 12-13 number of physical network ports */ + uint16_t port_num; /* 14-15 network port for this PCI function */ /* (port 0 is first port) */ - uint8_t mac_addr[6]; /* MAC address for this PCI function */ - uint32_t iscsi_pci_func_cnt; /* number of iSCSI PCI functions */ - uint32_t pci_func; /* this PCI function */ - unsigned char serial_number[16]; /* serial number string */ - uint8_t reserved[16]; + uint8_t mac_addr[6]; /* 16-1b MAC address for this PCI function */ + uint32_t iscsi_pci_func_cnt; /* 1c-1f number of iSCSI PCI functions */ + uint32_t pci_func; /* 20-23 this PCI function */ + unsigned char serial_number[16]; /* 24-33 serial number string */ + uint8_t reserved[12]; /* 34-3f */ }; struct crash_record { diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index c9cd5d6db98..95a26fb1626 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -93,6 +93,7 @@ void qla4xxx_free_irqs(struct scsi_qla_host *ha); void qla4xxx_process_response_queue(struct scsi_qla_host *ha); void qla4xxx_wake_dpc(struct scsi_qla_host *ha); void qla4xxx_get_conn_event_log(struct scsi_qla_host *ha); +void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha); void qla4_8xxx_pci_config(struct scsi_qla_host *); int qla4_8xxx_iospace_config(struct scsi_qla_host *ha); @@ -131,6 +132,7 @@ void qla4_8xxx_idc_unlock(struct scsi_qla_host *ha); int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha); void qla4_8xxx_need_qsnt_handler(struct scsi_qla_host *ha); void qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha); +void qla4_8xxx_set_drv_active(struct scsi_qla_host *ha); extern int ql4xextended_error_logging; extern int ql4xdiscoverywait; diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 30073577c3a..4c9be77ee70 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -308,7 +308,6 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) DEBUG2(printk("scsi%ld: %s: unable to get firmware " "state\n", ha->host_no, __func__)); break; - } if (ha->firmware_state & FW_STATE_ERROR) { @@ -445,6 +444,16 @@ static int qla4xxx_init_firmware(struct scsi_qla_host *ha) { int status = QLA_ERROR; + if (is_aer_supported(ha) && + test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags)) + return status; + + /* For 82xx, stop firmware before initializing because if BIOS + * has previously initialized firmware, then driver's initialize + * firmware will fail. */ + if (is_qla8022(ha)) + qla4_8xxx_stop_firmware(ha); + ql4_printk(KERN_INFO, ha, "Initializing firmware..\n"); if (qla4xxx_initialize_fw_cb(ha) == QLA_ERROR) { DEBUG2(printk("scsi%ld: %s: Failed to initialize firmware " @@ -669,7 +678,6 @@ static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, } ddb_entry->fw_ddb_index = fw_ddb_index; - atomic_set(&ddb_entry->port_down_timer, ha->port_down_retry_count); atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); atomic_set(&ddb_entry->relogin_timer, 0); atomic_set(&ddb_entry->relogin_retry_count, 0); @@ -1556,8 +1564,6 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, /* Device is back online. */ if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); - atomic_set(&ddb_entry->port_down_timer, - ha->port_down_retry_count); atomic_set(&ddb_entry->relogin_retry_count, 0); atomic_set(&ddb_entry->relogin_timer, 0); clear_bit(DF_RELOGIN, &ddb_entry->flags); diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index f89973deac5..4ef9ba112ee 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -19,7 +19,7 @@ qla4xxx_space_in_req_ring(struct scsi_qla_host *ha, uint16_t req_cnt) /* Calculate number of free request entries. */ if ((req_cnt + 2) >= ha->req_q_count) { - cnt = (uint16_t) le32_to_cpu(ha->shadow_regs->req_q_out); + cnt = (uint16_t) ha->isp_ops->rd_shdw_req_q_out(ha); if (ha->request_in < cnt) ha->req_q_count = cnt - ha->request_in; else diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index aa65697a86b..2a1ab63f3eb 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -816,6 +816,9 @@ irqreturn_t qla4_8xxx_intr_handler(int irq, void *dev_id) unsigned long flags = 0; uint8_t reqs_count = 0; + if (unlikely(pci_channel_offline(ha->pdev))) + return IRQ_HANDLED; + ha->isr_count++; status = qla4_8xxx_rd_32(ha, ISR_INT_VECTOR); if (!(status & ha->nx_legacy_intr.int_vec_bit)) diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 940ee561ee0..90021704d8c 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -39,6 +39,22 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, "pointer\n", ha->host_no, __func__)); return status; } + + if (is_qla8022(ha) && + test_bit(AF_FW_RECOVERY, &ha->flags)) { + DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: prematurely " + "completing mbx cmd as firmware recovery detected\n", + ha->host_no, __func__)); + return status; + } + + if ((is_aer_supported(ha)) && + (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags))) { + DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Perm failure on EEH, " + "timeout MBX Exiting.\n", ha->host_no, __func__)); + return status; + } + /* Mailbox code active */ wait_count = MBOX_TOV * 100; @@ -150,6 +166,7 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) { if (time_after_eq(jiffies, wait_count)) break; + /* * Service the interrupt. * The ISR will save the mailbox status registers @@ -196,6 +213,14 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, /* Check for mailbox timeout. */ if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) { + if (is_qla8022(ha) && + test_bit(AF_FW_RECOVERY, &ha->flags)) { + DEBUG2(ql4_printk(KERN_INFO, ha, + "scsi%ld: %s: prematurely completing mbx cmd as " + "firmware recovery detected\n", + ha->host_no, __func__)); + goto mbox_exit; + } DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...," " Scheduling Adapter Reset\n", ha->host_no, mbx_cmd[0])); @@ -246,6 +271,28 @@ mbox_exit: return status; } +void qla4xxx_mailbox_premature_completion(struct scsi_qla_host *ha) +{ + set_bit(AF_FW_RECOVERY, &ha->flags); + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: set FW RECOVERY!\n", + ha->host_no, __func__); + + if (test_bit(AF_MBOX_COMMAND, &ha->flags)) { + if (test_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags)) { + complete(&ha->mbx_intr_comp); + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " + "recovery, doing premature completion of " + "mbx cmd\n", ha->host_no, __func__); + + } else { + set_bit(AF_MBOX_COMMAND_DONE, &ha->flags); + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Due to fw " + "recovery, doing premature completion of " + "polling mbx cmd\n", ha->host_no, __func__); + } + } +} + static uint8_t qla4xxx_set_ifcb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, uint32_t *mbox_sts, dma_addr_t init_fw_cb_dma) @@ -361,7 +408,6 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha, min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ /* Save Command Line Paramater info */ - ha->port_down_retry_count = le16_to_cpu(init_fw_cb->conn_ka_timeout); ha->discovery_wait = ql4xdiscoverywait; if (ha->acb_version == ACB_SUPPORTED) { diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 3e119ae7839..5d4a3822382 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c @@ -1418,7 +1418,7 @@ static int qla4_8xxx_rcvpeg_ready(struct scsi_qla_host *ha) return QLA_SUCCESS; } -static inline void +void qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) { uint32_t drv_active; @@ -1441,11 +1441,15 @@ qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha) static inline int qla4_8xxx_need_reset(struct scsi_qla_host *ha) { - uint32_t drv_state; + uint32_t drv_state, drv_active; int rval; + drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); rval = drv_state & (1 << (ha->func_num * 4)); + if ((test_bit(AF_EEH_BUSY, &ha->flags)) && drv_active) + rval = 1; + return rval; } @@ -1949,7 +1953,8 @@ qla4_8xxx_get_fdt_info(struct scsi_qla_host *ha) uint16_t cnt, chksum; uint16_t *wptr; struct qla_fdt_layout *fdt; - uint16_t mid, fid; + uint16_t mid = 0; + uint16_t fid = 0; struct ql82xx_hw_data *hw = &ha->hw; hw->flash_conf_off = FARX_ACCESS_FLASH_CONF; @@ -2105,6 +2110,9 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha) qla4_8xxx_clear_rst_ready(ha); qla4_8xxx_idc_unlock(ha); + if (rval == QLA_SUCCESS) + clear_bit(AF_FW_RECOVERY, &ha->flags); + return rval; } @@ -2145,7 +2153,8 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha) goto exit_validate_mac82; } - if (mbox_sts[4] < sizeof(*sys_info)) { + /* Make sure we receive the minimum required data to cache internally */ + if (mbox_sts[4] < offsetof(struct mbx_sys_info, reserved)) { DEBUG2(printk("scsi%ld: %s: GET_SYS_INFO data receive" " error (%x)\n", ha->host_no, __func__, mbox_sts[4])); goto exit_validate_mac82; diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 5529b2a3974..370d40ff152 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -163,10 +163,10 @@ static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session) if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { atomic_set(&ddb_entry->state, DDB_STATE_DEAD); - DEBUG2(printk("scsi%ld: %s: ddb [%d] port down retry count " + DEBUG2(printk("scsi%ld: %s: ddb [%d] session recovery timeout " "of (%d) secs exhausted, marking device DEAD.\n", ha->host_no, __func__, ddb_entry->fw_ddb_index, - ha->port_down_retry_count)); + QL4_SESS_RECOVERY_TMO)); qla4xxx_wake_dpc(ha); } @@ -298,7 +298,8 @@ int qla4xxx_add_sess(struct ddb_entry *ddb_entry) { int err; - ddb_entry->sess->recovery_tmo = ddb_entry->ha->port_down_retry_count; + ddb_entry->sess->recovery_tmo = QL4_SESS_RECOVERY_TMO; + err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index); if (err) { DEBUG2(printk(KERN_ERR "Could not add session.\n")); @@ -474,6 +475,14 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, struct srb *srb; int rval; + if (test_bit(AF_EEH_BUSY, &ha->flags)) { + if (test_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags)) + cmd->result = DID_NO_CONNECT << 16; + else + cmd->result = DID_REQUEUE << 16; + goto qc_fail_command; + } + if (!sess) { cmd->result = DID_IMM_RETRY << 16; goto qc_fail_command; @@ -654,6 +663,13 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) uint32_t fw_heartbeat_counter, halt_status; fw_heartbeat_counter = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); + /* If PEG_ALIVE_COUNTER is 0xffffffff, AER/EEH is in progress, ignore */ + if (fw_heartbeat_counter == 0xffffffff) { + DEBUG2(printk(KERN_WARNING "scsi%ld: %s: Device in frozen " + "state, QLA82XX_PEG_ALIVE_COUNTER is 0xffffffff\n", + ha->host_no, __func__)); + return; + } if (ha->fw_heartbeat_counter == fw_heartbeat_counter) { ha->seconds_since_last_heartbeat++; @@ -662,6 +678,7 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) ha->seconds_since_last_heartbeat = 0; halt_status = qla4_8xxx_rd_32(ha, QLA82XX_PEG_HALT_STATUS1); + /* Since we cannot change dev_state in interrupt * context, set appropriate DPC flag then wakeup * DPC */ @@ -673,6 +690,7 @@ static void qla4_8xxx_check_fw_alive(struct scsi_qla_host *ha) set_bit(DPC_RESET_HA, &ha->dpc_flags); } qla4xxx_wake_dpc(ha); + qla4xxx_mailbox_premature_completion(ha); } } ha->fw_heartbeat_counter = fw_heartbeat_counter; @@ -698,6 +716,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) ha->host_no, __func__); set_bit(DPC_RESET_HA, &ha->dpc_flags); qla4xxx_wake_dpc(ha); + qla4xxx_mailbox_premature_completion(ha); } else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT && !test_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) { printk("scsi%ld: %s: HW State: NEED QUIES!\n", @@ -719,6 +738,19 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) { struct ddb_entry *ddb_entry, *dtemp; int start_dpc = 0; + uint16_t w; + + /* If we are in the middle of AER/EEH processing + * skip any processing and reschedule the timer + */ + if (test_bit(AF_EEH_BUSY, &ha->flags)) { + mod_timer(&ha->timer, jiffies + HZ); + return; + } + + /* Hardware read to trigger an EEH error during mailbox waits. */ + if (!pci_channel_offline(ha->pdev)) + pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w); if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) { DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n", @@ -1207,7 +1239,13 @@ static void qla4xxx_do_dpc(struct work_struct *work) /* Initialization not yet finished. Don't do anything yet. */ if (!test_bit(AF_INIT_DONE, &ha->flags)) - return; + goto do_dpc_exit; + + if (test_bit(AF_EEH_BUSY, &ha->flags)) { + DEBUG2(printk(KERN_INFO "scsi%ld: %s: flags = %lx\n", + ha->host_no, __func__, ha->flags)); + goto do_dpc_exit; + } /* HBA is in the process of being permanently disabled. * Don't process anything */ @@ -1346,6 +1384,8 @@ dpc_post_reset_ha: } } } + +do_dpc_exit: clear_bit(AF_DPC_SCHEDULED, &ha->flags); } @@ -1612,6 +1652,8 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, ha->host = host; ha->host_no = host->host_no; + pci_enable_pcie_error_reporting(pdev); + /* Setup Runtime configurable options */ if (is_qla8022(ha)) { ha->isp_ops = &qla4_8xxx_isp_ops; @@ -1630,6 +1672,10 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, ha->isp_ops = &qla4xxx_isp_ops; } + /* Set EEH reset type to fundamental if required by hba */ + if (is_qla8022(ha)) + pdev->needs_freset = 1; + /* Configure PCI I/O space. */ ret = ha->isp_ops->iospace_config(ha); if (ret) @@ -1726,6 +1772,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, } } + pci_save_state(ha->pdev); ha->isp_ops->enable_intrs(ha); /* Start timer thread. */ @@ -1752,6 +1799,7 @@ probe_failed: qla4xxx_free_adapter(ha); probe_failed_ioconfig: + pci_disable_pcie_error_reporting(pdev); scsi_host_put(ha->host); probe_disable_device: @@ -1781,6 +1829,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) scsi_host_put(ha->host); + pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); } @@ -1877,6 +1926,17 @@ static int qla4xxx_eh_wait_on_command(struct scsi_qla_host *ha, int done = 0; struct srb *rp; uint32_t max_wait_time = EH_WAIT_CMD_TOV; + int ret = SUCCESS; + + /* Dont wait on command if PCI error is being handled + * by PCI AER driver + */ + if (unlikely(pci_channel_offline(ha->pdev)) || + (test_bit(AF_EEH_BUSY, &ha->flags))) { + ql4_printk(KERN_WARNING, ha, "scsi%ld: Return from %s\n", + ha->host_no, __func__); + return ret; + } do { /* Checking to see if its returned to OS */ @@ -2172,6 +2232,252 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) return return_status; } +/* PCI AER driver recovers from all correctable errors w/o + * driver intervention. For uncorrectable errors PCI AER + * driver calls the following device driver's callbacks + * + * - Fatal Errors - link_reset + * - Non-Fatal Errors - driver's pci_error_detected() which + * returns CAN_RECOVER, NEED_RESET or DISCONNECT. + * + * PCI AER driver calls + * CAN_RECOVER - driver's pci_mmio_enabled(), mmio_enabled + * returns RECOVERED or NEED_RESET if fw_hung + * NEED_RESET - driver's slot_reset() + * DISCONNECT - device is dead & cannot recover + * RECOVERED - driver's pci_resume() + */ +static pci_ers_result_t +qla4xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) +{ + struct scsi_qla_host *ha = pci_get_drvdata(pdev); + + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: error detected:state %x\n", + ha->host_no, __func__, state); + + if (!is_aer_supported(ha)) + return PCI_ERS_RESULT_NONE; + + switch (state) { + case pci_channel_io_normal: + clear_bit(AF_EEH_BUSY, &ha->flags); + return PCI_ERS_RESULT_CAN_RECOVER; + case pci_channel_io_frozen: + set_bit(AF_EEH_BUSY, &ha->flags); + qla4xxx_mailbox_premature_completion(ha); + qla4xxx_free_irqs(ha); + pci_disable_device(pdev); + return PCI_ERS_RESULT_NEED_RESET; + case pci_channel_io_perm_failure: + set_bit(AF_EEH_BUSY, &ha->flags); + set_bit(AF_PCI_CHANNEL_IO_PERM_FAILURE, &ha->flags); + qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16); + return PCI_ERS_RESULT_DISCONNECT; + } + return PCI_ERS_RESULT_NEED_RESET; +} + +/** + * qla4xxx_pci_mmio_enabled() gets called if + * qla4xxx_pci_error_detected() returns PCI_ERS_RESULT_CAN_RECOVER + * and read/write to the device still works. + **/ +static pci_ers_result_t +qla4xxx_pci_mmio_enabled(struct pci_dev *pdev) +{ + struct scsi_qla_host *ha = pci_get_drvdata(pdev); + + if (!is_aer_supported(ha)) + return PCI_ERS_RESULT_NONE; + + if (test_bit(AF_FW_RECOVERY, &ha->flags)) { + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: firmware hang -- " + "mmio_enabled\n", ha->host_no, __func__); + return PCI_ERS_RESULT_NEED_RESET; + } else + return PCI_ERS_RESULT_RECOVERED; +} + +uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha) +{ + uint32_t rval = QLA_ERROR; + int fn; + struct pci_dev *other_pdev = NULL; + + ql4_printk(KERN_WARNING, ha, "scsi%ld: In %s\n", ha->host_no, __func__); + + set_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); + + if (test_bit(AF_ONLINE, &ha->flags)) { + clear_bit(AF_ONLINE, &ha->flags); + qla4xxx_mark_all_devices_missing(ha); + qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); + qla4xxx_abort_active_cmds(ha, DID_RESET << 16); + } + + fn = PCI_FUNC(ha->pdev->devfn); + while (fn > 0) { + fn--; + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Finding PCI device at " + "func %x\n", ha->host_no, __func__, fn); + /* Get the pci device given the domain, bus, + * slot/function number */ + other_pdev = + pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus), + ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn), + fn)); + + if (!other_pdev) + continue; + + if (atomic_read(&other_pdev->enable_cnt)) { + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: Found PCI " + "func in enabled state%x\n", ha->host_no, + __func__, fn); + pci_dev_put(other_pdev); + break; + } + pci_dev_put(other_pdev); + } + + /* The first function on the card, the reset owner will + * start & initialize the firmware. The other functions + * on the card will reset the firmware context + */ + if (!fn) { + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn being reset " + "0x%x is the owner\n", ha->host_no, __func__, + ha->pdev->devfn); + + qla4_8xxx_idc_lock(ha); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_COLD); + + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, + QLA82XX_IDC_VERSION); + + qla4_8xxx_idc_unlock(ha); + clear_bit(AF_FW_RECOVERY, &ha->flags); + rval = qla4xxx_initialize_adapter(ha, PRESERVE_DDB_LIST); + qla4_8xxx_idc_lock(ha); + + if (rval != QLA_SUCCESS) { + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: " + "FAILED\n", ha->host_no, __func__); + qla4_8xxx_clear_drv_active(ha); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_FAILED); + } else { + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: HW State: " + "READY\n", ha->host_no, __func__); + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, + QLA82XX_DEV_READY); + /* Clear driver state register */ + qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, 0); + qla4_8xxx_set_drv_active(ha); + ha->isp_ops->enable_intrs(ha); + } + qla4_8xxx_idc_unlock(ha); + } else { + ql4_printk(KERN_INFO, ha, "scsi%ld: %s: devfn 0x%x is not " + "the reset owner\n", ha->host_no, __func__, + ha->pdev->devfn); + if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) == + QLA82XX_DEV_READY)) { + clear_bit(AF_FW_RECOVERY, &ha->flags); + rval = qla4xxx_initialize_adapter(ha, + PRESERVE_DDB_LIST); + if (rval == QLA_SUCCESS) + ha->isp_ops->enable_intrs(ha); + qla4_8xxx_idc_lock(ha); + qla4_8xxx_set_drv_active(ha); + qla4_8xxx_idc_unlock(ha); + } + } + clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags); + return rval; +} + +static pci_ers_result_t +qla4xxx_pci_slot_reset(struct pci_dev *pdev) +{ + pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; + struct scsi_qla_host *ha = pci_get_drvdata(pdev); + int rc; + + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: slot_reset\n", + ha->host_no, __func__); + + if (!is_aer_supported(ha)) + return PCI_ERS_RESULT_NONE; + + /* Restore the saved state of PCIe device - + * BAR registers, PCI Config space, PCIX, MSI, + * IOV states + */ + pci_restore_state(pdev); + + /* pci_restore_state() clears the saved_state flag of the device + * save restored state which resets saved_state flag + */ + pci_save_state(pdev); + + /* Initialize device or resume if in suspended state */ + rc = pci_enable_device(pdev); + if (rc) { + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cant re-enable " + "device after reset\n", ha->host_no, __func__); + goto exit_slot_reset; + } + + ret = qla4xxx_request_irqs(ha); + if (ret) { + ql4_printk(KERN_WARNING, ha, "Failed to reserve interrupt %d" + " already in use.\n", pdev->irq); + goto exit_slot_reset; + } + + if (is_qla8022(ha)) { + if (qla4_8xxx_error_recovery(ha) == QLA_SUCCESS) { + ret = PCI_ERS_RESULT_RECOVERED; + goto exit_slot_reset; + } else + goto exit_slot_reset; + } + +exit_slot_reset: + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Return=%x\n" + "device after reset\n", ha->host_no, __func__, ret); + return ret; +} + +static void +qla4xxx_pci_resume(struct pci_dev *pdev) +{ + struct scsi_qla_host *ha = pci_get_drvdata(pdev); + int ret; + + ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: pci_resume\n", + ha->host_no, __func__); + + ret = qla4xxx_wait_for_hba_online(ha); + if (ret != QLA_SUCCESS) { + ql4_printk(KERN_ERR, ha, "scsi%ld: %s: the device failed to " + "resume I/O from slot/link_reset\n", ha->host_no, + __func__); + } + + pci_cleanup_aer_uncorrect_error_status(pdev); + clear_bit(AF_EEH_BUSY, &ha->flags); +} + +static struct pci_error_handlers qla4xxx_err_handler = { + .error_detected = qla4xxx_pci_error_detected, + .mmio_enabled = qla4xxx_pci_mmio_enabled, + .slot_reset = qla4xxx_pci_slot_reset, + .resume = qla4xxx_pci_resume, +}; + static struct pci_device_id qla4xxx_pci_tbl[] = { { .vendor = PCI_VENDOR_ID_QLOGIC, @@ -2206,6 +2512,7 @@ static struct pci_driver qla4xxx_pci_driver = { .id_table = qla4xxx_pci_tbl, .probe = qla4xxx_probe_adapter, .remove = qla4xxx_remove_adapter, + .err_handler = &qla4xxx_err_handler, }; static int __init qla4xxx_module_init(void) diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index c905dbd7533..a77b973f2cb 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,4 +5,4 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.02.00-k2" +#define QLA4XXX_DRIVER_VERSION "5.02.00-k3" diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index ca5c15c779c..f8c561cf751 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -704,7 +704,7 @@ static void __devexit qpti_chain_del(struct qlogicpti *qpti) static int __devinit qpti_map_regs(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; qpti->qregs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), @@ -727,9 +727,9 @@ static int __devinit qpti_map_regs(struct qlogicpti *qpti) static int __devinit qpti_register_irq(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; - qpti->qhost->irq = qpti->irq = op->irqs[0]; + qpti->qhost->irq = qpti->irq = op->archdata.irqs[0]; /* We used to try various overly-clever things to * reduce the interrupt processing overhead on @@ -752,7 +752,7 @@ fail: static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; struct device_node *dp; dp = op->dev.of_node; @@ -773,7 +773,7 @@ static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) static void qpti_get_bursts(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; u8 bursts, bmask; bursts = of_getintprop_default(op->dev.of_node, "burst-sizes", 0xff); @@ -806,7 +806,7 @@ static void qpti_get_clock(struct qlogicpti *qpti) */ static int __devinit qpti_map_queues(struct qlogicpti *qpti) { - struct of_device *op = qpti->op; + struct platform_device *op = qpti->op; #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) qpti->res_cpu = dma_alloc_coherent(&op->dev, @@ -1290,7 +1290,7 @@ static struct scsi_host_template qpti_template = { .use_clustering = ENABLE_CLUSTERING, }; -static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit qpti_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct scsi_host_template *tpnt = match->data; struct device_node *dp = op->dev.of_node; @@ -1302,7 +1302,7 @@ static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_devic /* Sometimes Antares cards come up not completely * setup, and we get a report of a zero IRQ. */ - if (op->irqs[0] == 0) + if (op->archdata.irqs[0] == 0) return -ENODEV; host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); @@ -1401,7 +1401,7 @@ fail_unlink: return -ENODEV; } -static int __devexit qpti_sbus_remove(struct of_device *op) +static int __devexit qpti_sbus_remove(struct platform_device *op) { struct qlogicpti *qpti = dev_get_drvdata(&op->dev); @@ -1467,12 +1467,12 @@ static struct of_platform_driver qpti_sbus_driver = { static int __init qpti_init(void) { - return of_register_driver(&qpti_sbus_driver, &of_bus_type); + return of_register_platform_driver(&qpti_sbus_driver); } static void __exit qpti_exit(void) { - of_unregister_driver(&qpti_sbus_driver); + of_unregister_platform_driver(&qpti_sbus_driver); } MODULE_DESCRIPTION("QlogicISP SBUS driver"); diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h index e3c74d1ee2d..4377e87ee79 100644 --- a/drivers/scsi/qlogicpti.h +++ b/drivers/scsi/qlogicpti.h @@ -342,7 +342,7 @@ struct qlogicpti { u_int req_in_ptr; /* index of next request slot */ u_int res_out_ptr; /* index of next result slot */ long send_marker; /* must we send a marker? */ - struct of_device *op; + struct platform_device *op; unsigned long __pad; int cmd_count[MAX_TARGETS]; diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2bf98469dc4..1de30eb83bb 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -320,7 +320,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) "changed. The Linux SCSI layer does not " "automatically adjust these parameters.\n"); - if (blk_barrier_rq(scmd->request)) + if (scmd->request->cmd_flags & REQ_HARDBARRIER) /* * barrier requests should always retry on UA * otherwise block will get a spurious error @@ -473,14 +473,17 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd) */ return SUCCESS; case RESERVATION_CONFLICT: - /* - * let issuer deal with this, it could be just fine - */ - return SUCCESS; + if (scmd->cmnd[0] == TEST_UNIT_READY) + /* it is a success, we probed the device and + * found it */ + return SUCCESS; + /* otherwise, we failed to send the command */ + return FAILED; case QUEUE_FULL: scsi_handle_queue_full(scmd->device); /* fall through */ case BUSY: + return NEEDS_RETRY; default: return FAILED; } @@ -1331,16 +1334,16 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd) case DID_OK: break; case DID_BUS_BUSY: - return blk_failfast_transport(scmd->request); + return (scmd->request->cmd_flags & REQ_FAILFAST_TRANSPORT); case DID_PARITY: - return blk_failfast_dev(scmd->request); + return (scmd->request->cmd_flags & REQ_FAILFAST_DEV); case DID_ERROR: if (msg_byte(scmd->result) == COMMAND_COMPLETE && status_byte(scmd->result) == RESERVATION_CONFLICT) return 0; /* fall through */ case DID_SOFT_ERROR: - return blk_failfast_driver(scmd->request); + return (scmd->request->cmd_flags & REQ_FAILFAST_DRIVER); } switch (status_byte(scmd->result)) { @@ -1349,7 +1352,9 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd) * assume caller has checked sense and determinted * the check condition was retryable. */ - return blk_failfast_dev(scmd->request); + if (scmd->request->cmd_flags & REQ_FAILFAST_DEV || + scmd->request->cmd_type == REQ_TYPE_BLOCK_PC) + return 1; } return 0; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 1646fe7cbd4..9ade720422c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -85,7 +85,7 @@ static void scsi_unprep_request(struct request *req) { struct scsi_cmnd *cmd = req->special; - req->cmd_flags &= ~REQ_DONTPREP; + blk_unprep_request(req); req->special = NULL; scsi_put_command(cmd); @@ -722,7 +722,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) sense_deferred = scsi_sense_is_deferred(&sshdr); } - if (blk_pc_request(req)) { /* SG_IO ioctl from block level */ + if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */ req->errors = result; if (result) { if (sense_valid && req->sense) { @@ -757,7 +757,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } } - BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */ + /* no bidi support for !REQ_TYPE_BLOCK_PC yet */ + BUG_ON(blk_bidi_rq(req)); /* * Next deal with any sectors which we were able to correctly @@ -1010,11 +1011,8 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) err_exit: scsi_release_buffers(cmd); - if (error == BLKPREP_KILL) - scsi_put_command(cmd); - else /* BLKPREP_DEFER */ - scsi_unprep_request(cmd->request); - + scsi_put_command(cmd); + cmd->request->special = NULL; return error; } EXPORT_SYMBOL(scsi_init_io); @@ -1372,12 +1370,6 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) blk_start_request(req); - if (unlikely(cmd == NULL)) { - printk(KERN_CRIT "impossible request in %s.\n", - __func__); - BUG(); - } - sdev = cmd->device; starget = scsi_target(sdev); shost = sdev->host; diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 026295e2c53..b4056d14f81 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -148,8 +148,6 @@ static inline void scsi_netlink_exit(void) {} /* scsi_pm.c */ #ifdef CONFIG_PM_OPS extern const struct dev_pm_ops scsi_bus_pm_ops; -#else /* CONFIG_PM_OPS */ -#define scsi_bus_pm_ops (*NULL) #endif #ifdef CONFIG_PM_RUNTIME extern void scsi_autopm_get_target(struct scsi_target *); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 562fb3bce26..c3f67373a4f 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -381,7 +381,9 @@ struct bus_type scsi_bus_type = { .name = "scsi", .match = scsi_bus_match, .uevent = scsi_bus_uevent, +#ifdef CONFIG_PM_OPS .pm = &scsi_bus_pm_ops, +#endif }; EXPORT_SYMBOL_GPL(scsi_bus_type); diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 66241dd525a..c399be97992 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -185,6 +185,7 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work) dprintk("cmd %p %d %u\n", cmd, cmd->sc_data_direction, rq_data_dir(cmd->request)); scsi_unmap_user_pages(tcmd); + tcmd->rq->bio = NULL; scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); } diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index edb6b362a8f..d7e470a0618 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -29,6 +29,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/kernel.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> #include <scsi/scsi_transport.h> @@ -1730,12 +1731,11 @@ fc_parse_wwn(const char *ns, u64 *nm) /* Validate and store the new name */ for (i=0, j=0; i < 16; i++) { - if ((*ns >= 'a') && (*ns <= 'f')) - j = ((j << 4) | ((*ns++ -'a') + 10)); - else if ((*ns >= 'A') && (*ns <= 'F')) - j = ((j << 4) | ((*ns++ -'A') + 10)); - else if ((*ns >= '0') && (*ns <= '9')) - j = ((j << 4) | (*ns++ -'0')); + int value; + + value = hex_to_bin(*ns++); + if (value >= 0) + j = (j << 4) | value; else return -EINVAL; if (i % 2) { diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index cc8a1d1d915..2714becc2ea 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -46,6 +46,7 @@ #include <linux/blkdev.h> #include <linux/blkpg.h> #include <linux/delay.h> +#include <linux/smp_lock.h> #include <linux/mutex.h> #include <linux/string_helpers.h> #include <linux/async.h> @@ -118,8 +119,8 @@ static DEFINE_IDA(sd_index_ida); * object after last put) */ static DEFINE_MUTEX(sd_ref_mutex); -struct kmem_cache *sd_cdb_cache; -mempool_t *sd_cdb_pool; +static struct kmem_cache *sd_cdb_cache; +static mempool_t *sd_cdb_pool; static const char *sd_cache_types[] = { "write through", "none", "write back", @@ -146,7 +147,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr, return -EINVAL; for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) { - const int len = strlen(sd_cache_types[i]); + len = strlen(sd_cache_types[i]); if (strncmp(sd_cache_types[i], buf, len) == 0 && buf[len] == '\n') { ct = i; @@ -411,54 +412,85 @@ static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif) } /** - * sd_prepare_discard - unmap blocks on thinly provisioned device + * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device + * @sdp: scsi device to operate one * @rq: Request to prepare * * Will issue either UNMAP or WRITE SAME(16) depending on preference * indicated by target device. **/ -static int sd_prepare_discard(struct request *rq) +static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) { struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); struct bio *bio = rq->bio; sector_t sector = bio->bi_sector; - unsigned int num = bio_sectors(bio); + unsigned int nr_sectors = bio_sectors(bio); + unsigned int len; + int ret; + struct page *page; if (sdkp->device->sector_size == 4096) { sector >>= 3; - num >>= 3; + nr_sectors >>= 3; } - rq->cmd_type = REQ_TYPE_BLOCK_PC; rq->timeout = SD_TIMEOUT; memset(rq->cmd, 0, rq->cmd_len); + page = alloc_page(GFP_ATOMIC | __GFP_ZERO); + if (!page) + return BLKPREP_DEFER; + if (sdkp->unmap) { - char *buf = kmap_atomic(bio_page(bio), KM_USER0); + char *buf = page_address(page); + rq->cmd_len = 10; rq->cmd[0] = UNMAP; rq->cmd[8] = 24; - rq->cmd_len = 10; - - /* Ensure that data length matches payload */ - rq->__data_len = bio->bi_size = bio->bi_io_vec->bv_len = 24; put_unaligned_be16(6 + 16, &buf[0]); put_unaligned_be16(16, &buf[2]); put_unaligned_be64(sector, &buf[8]); - put_unaligned_be32(num, &buf[16]); + put_unaligned_be32(nr_sectors, &buf[16]); - kunmap_atomic(buf, KM_USER0); + len = 24; } else { + rq->cmd_len = 16; rq->cmd[0] = WRITE_SAME_16; rq->cmd[1] = 0x8; /* UNMAP */ put_unaligned_be64(sector, &rq->cmd[2]); - put_unaligned_be32(num, &rq->cmd[10]); - rq->cmd_len = 16; + put_unaligned_be32(nr_sectors, &rq->cmd[10]); + + len = sdkp->device->sector_size; + } + + blk_add_request_payload(rq, page, len); + ret = scsi_setup_blk_pc_cmnd(sdp, rq); + rq->buffer = page_address(page); + if (ret != BLKPREP_OK) { + __free_page(page); + rq->buffer = NULL; } + return ret; +} - return BLKPREP_OK; +static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) +{ + rq->timeout = SD_TIMEOUT; + rq->retries = SD_MAX_RETRIES; + rq->cmd[0] = SYNCHRONIZE_CACHE; + rq->cmd_len = 10; + + return scsi_setup_blk_pc_cmnd(sdp, rq); +} + +static void sd_unprep_fn(struct request_queue *q, struct request *rq) +{ + if (rq->cmd_flags & REQ_DISCARD) { + free_page((unsigned long)rq->buffer); + rq->buffer = NULL; + } } /** @@ -485,10 +517,13 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * Discard request come in as REQ_TYPE_FS but we turn them into * block PC requests to make life easier. */ - if (blk_discard_rq(rq)) - ret = sd_prepare_discard(rq); - - if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { + if (rq->cmd_flags & REQ_DISCARD) { + ret = scsi_setup_discard_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_flags & REQ_FLUSH) { + ret = scsi_setup_flush_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { ret = scsi_setup_blk_pc_cmnd(sdp, rq); goto out; } else if (rq->cmd_type != REQ_TYPE_FS) { @@ -636,7 +671,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->cmnd[0] = VARIABLE_LENGTH_CMD; SCpnt->cmnd[7] = 0x18; SCpnt->cmnd[9] = (rq_data_dir(rq) == READ) ? READ_32 : WRITE_32; - SCpnt->cmnd[10] = protect | (blk_fua_rq(rq) ? 0x8 : 0); + SCpnt->cmnd[10] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); /* LBA */ SCpnt->cmnd[12] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; @@ -661,7 +696,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->cmnd[31] = (unsigned char) this_count & 0xff; } else if (block > 0xffffffff) { SCpnt->cmnd[0] += READ_16 - READ_6; - SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0); + SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0; SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0; @@ -682,7 +717,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) this_count = 0xffff; SCpnt->cmnd[0] += READ_10 - READ_6; - SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0); + SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; @@ -691,7 +726,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->cmnd[7] = (unsigned char) (this_count >> 8) & 0xff; SCpnt->cmnd[8] = (unsigned char) this_count & 0xff; } else { - if (unlikely(blk_fua_rq(rq))) { + if (unlikely(rq->cmd_flags & REQ_FUA)) { /* * This happens only if this drive failed * 10byte rw command with ILLEGAL_REQUEST @@ -745,6 +780,8 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * or from within the kernel (e.g. as a result of a mount(1) ). * In the latter case @inode and @filp carry an abridged amount * of information as noted above. + * + * Locking: called with bdev->bd_mutex held. **/ static int sd_open(struct block_device *bdev, fmode_t mode) { @@ -799,7 +836,7 @@ static int sd_open(struct block_device *bdev, fmode_t mode) if (!scsi_device_online(sdev)) goto error_out; - if (!sdkp->openers++ && sdev->removable) { + if ((atomic_inc_return(&sdkp->openers) == 1) && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) scsi_set_medium_removal(sdev, SCSI_REMOVAL_PREVENT); } @@ -823,6 +860,8 @@ error_autopm: * * Note: may block (uninterruptible) if error recovery is underway * on this disk. + * + * Locking: called with bdev->bd_mutex held. **/ static int sd_release(struct gendisk *disk, fmode_t mode) { @@ -831,7 +870,7 @@ static int sd_release(struct gendisk *disk, fmode_t mode) SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_release\n")); - if (!--sdkp->openers && sdev->removable) { + if (atomic_dec_return(&sdkp->openers) && sdev->removable) { if (scsi_block_when_processing_errors(sdev)) scsi_set_medium_removal(sdev, SCSI_REMOVAL_ALLOW); } @@ -904,7 +943,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, error = scsi_nonblockable_ioctl(sdp, cmd, p, (mode & FMODE_NDELAY) != 0); if (!scsi_block_when_processing_errors(sdp) || !error) - return error; + goto out; /* * Send SCSI addressing ioctls directly to mid level, send other @@ -914,13 +953,17 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode, switch (cmd) { case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: - return scsi_ioctl(sdp, cmd, p); + error = scsi_ioctl(sdp, cmd, p); + break; default: error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p); if (error != -ENOTTY) - return error; + break; + error = scsi_ioctl(sdp, cmd, p); + break; } - return scsi_ioctl(sdp, cmd, p); +out: + return error; } static void set_media_not_present(struct scsi_disk *sdkp) @@ -1045,15 +1088,6 @@ static int sd_sync_cache(struct scsi_disk *sdkp) return 0; } -static void sd_prepare_flush(struct request_queue *q, struct request *rq) -{ - rq->cmd_type = REQ_TYPE_BLOCK_PC; - rq->timeout = SD_TIMEOUT; - rq->retries = SD_MAX_RETRIES; - rq->cmd[0] = SYNCHRONIZE_CACHE; - rq->cmd_len = 10; -} - static void sd_rescan(struct device *dev) { struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); @@ -1103,7 +1137,7 @@ static const struct block_device_operations sd_fops = { .owner = THIS_MODULE, .open = sd_open, .release = sd_release, - .locked_ioctl = sd_ioctl, + .ioctl = sd_ioctl, .getgeo = sd_getgeo, #ifdef CONFIG_COMPAT .compat_ioctl = sd_compat_ioctl, @@ -1120,7 +1154,7 @@ static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) u64 bad_lba; int info_valid; - if (!blk_fs_request(scmd->request)) + if (scmd->request->cmd_type != REQ_TYPE_FS) return 0; info_valid = scsi_get_sense_info_fld(scmd->sense_buffer, @@ -1171,6 +1205,12 @@ static int sd_done(struct scsi_cmnd *SCpnt) int sense_valid = 0; int sense_deferred = 0; + if (SCpnt->request->cmd_flags & REQ_DISCARD) { + if (!result) + scsi_set_resid(SCpnt, 0); + return good_bytes; + } + if (result) { sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr); if (sense_valid) @@ -1383,7 +1423,7 @@ sd_spinup_disk(struct scsi_disk *sdkp) /* * Determine whether disk supports Data Integrity Field. */ -void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) +static void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) { struct scsi_device *sdp = sdkp->device; u8 type; @@ -1929,7 +1969,7 @@ defaults: * The ATO bit indicates whether the DIF application tag is available * for use by the operating system. */ -void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) +static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) { int res, offset; struct scsi_device *sdp = sdkp->device; @@ -2121,7 +2161,7 @@ static int sd_revalidate_disk(struct gendisk *disk) else ordered = QUEUE_ORDERED_DRAIN; - blk_queue_ordered(sdkp->disk->queue, ordered, sd_prepare_flush); + blk_queue_ordered(sdkp->disk->queue, ordered); set_capacity(disk, sdkp->capacity); kfree(buffer); @@ -2234,6 +2274,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) sd_revalidate_disk(gd); blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); + blk_queue_unprep_rq(sdp->request_queue, sd_unprep_fn); gd->driverfs_dev = &sdp->sdev_gendev; gd->flags = GENHD_FL_EXT_DEVT; @@ -2274,7 +2315,7 @@ static int sd_probe(struct device *dev) struct scsi_device *sdp = to_scsi_device(dev); struct scsi_disk *sdkp; struct gendisk *gd; - u32 index; + int index; int error; error = -ENODEV; @@ -2313,7 +2354,7 @@ static int sd_probe(struct device *dev) sdkp->driver = &sd_template; sdkp->disk = gd; sdkp->index = index; - sdkp->openers = 0; + atomic_set(&sdkp->openers, 0); sdkp->previous_state = 1; if (!sdp->request_queue->rq_timeout) { @@ -2372,6 +2413,7 @@ static int sd_remove(struct device *dev) async_synchronize_full(); blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn); + blk_queue_unprep_rq(sdkp->device->request_queue, NULL); device_del(&sdkp->dev); del_gendisk(sdkp->disk); sd_shutdown(dev); diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 43d3caf268e..f81a9309e6d 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -47,7 +47,7 @@ struct scsi_disk { struct scsi_device *device; struct device dev; struct gendisk *disk; - unsigned int openers; /* protected by BKL for now, yuck */ + atomic_t openers; sector_t capacity; /* size in 512-byte sectors */ u32 index; unsigned short hw_sector_size; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 2968c6b83dd..78d616315d8 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1686,14 +1686,9 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) int len, size = sizeof(struct sg_iovec) * iov_count; struct iovec *iov; - iov = kmalloc(size, GFP_ATOMIC); - if (!iov) - return -ENOMEM; - - if (copy_from_user(iov, hp->dxferp, size)) { - kfree(iov); - return -EFAULT; - } + iov = memdup_user(hp->dxferp, size); + if (IS_ERR(iov)) + return PTR_ERR(iov); len = iov_length(iov, iov_count); if (hp->dxfer_len < len) { diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 0a90abc7f14..ba9c3e0387c 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -44,6 +44,7 @@ #include <linux/init.h> #include <linux/blkdev.h> #include <linux/mutex.h> +#include <linux/smp_lock.h> #include <linux/slab.h> #include <asm/uaccess.h> @@ -466,22 +467,27 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) static int sr_block_open(struct block_device *bdev, fmode_t mode) { - struct scsi_cd *cd = scsi_cd_get(bdev->bd_disk); + struct scsi_cd *cd; int ret = -ENXIO; + lock_kernel(); + cd = scsi_cd_get(bdev->bd_disk); if (cd) { ret = cdrom_open(&cd->cdi, bdev, mode); if (ret) scsi_cd_put(cd); } + unlock_kernel(); return ret; } static int sr_block_release(struct gendisk *disk, fmode_t mode) { struct scsi_cd *cd = scsi_cd(disk); + lock_kernel(); cdrom_release(&cd->cdi, mode); scsi_cd_put(cd); + unlock_kernel(); return 0; } @@ -493,6 +499,8 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, void __user *argp = (void __user *)arg; int ret; + lock_kernel(); + /* * Send SCSI addressing ioctls directly to mid level, send other * ioctls to cdrom/block level. @@ -500,12 +508,13 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, switch (cmd) { case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_BUS_NUMBER: - return scsi_ioctl(sdev, cmd, argp); + ret = scsi_ioctl(sdev, cmd, argp); + goto out; } ret = cdrom_ioctl(&cd->cdi, bdev, mode, cmd, arg); if (ret != -ENOSYS) - return ret; + goto out; /* * ENODEV means that we didn't recognise the ioctl, or that we @@ -516,8 +525,12 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, ret = scsi_nonblockable_ioctl(sdev, cmd, argp, (mode & FMODE_NDELAY) != 0); if (ret != -ENODEV) - return ret; - return scsi_ioctl(sdev, cmd, argp); + goto out; + ret = scsi_ioctl(sdev, cmd, argp); + +out: + unlock_kernel(); + return ret; } static int sr_block_media_changed(struct gendisk *disk) @@ -531,7 +544,7 @@ static const struct block_device_operations sr_bdops = .owner = THIS_MODULE, .open = sr_block_open, .release = sr_block_release, - .locked_ioctl = sr_block_ioctl, + .ioctl = sr_block_ioctl, .media_changed = sr_block_media_changed, /* * No compat_ioctl for now because sr_block_ioctl never diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index b5838d547c6..713620ed70d 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -2022,7 +2022,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) if((count > SUN3_DMA_MINSIZE) && (sun3_dma_setup_done != cmd)) { - if(blk_fs_request(cmd->request)) { + if (cmd->request->cmd_type == REQ_TYPE_FS) { sun3scsi_dma_setup(d, count, rq_data_dir(cmd->request)); sun3_dma_setup_done = cmd; diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index e606cf0a2eb..613f5880d13 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -524,7 +524,7 @@ static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, struct scsi_cmnd *cmd, int write_flag) { - if(blk_fs_request(cmd->request)) + if (cmd->request->cmd_type == REQ_TYPE_FS) return wanted; else return 0; diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c index aaa4fd0dd1b..7c526b8e30a 100644 --- a/drivers/scsi/sun3_scsi_vme.c +++ b/drivers/scsi/sun3_scsi_vme.c @@ -458,7 +458,7 @@ static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, struct scsi_cmnd *cmd, int write_flag) { - if(blk_fs_request(cmd->request)) + if (cmd->request->cmd_type == REQ_TYPE_FS) return wanted; else return 0; diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index 386dd9d602b..193b37ba183 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c @@ -44,7 +44,7 @@ enum dvma_rev { }; static int __devinit esp_sbus_setup_dma(struct esp *esp, - struct of_device *dma_of) + struct platform_device *dma_of) { esp->dma = dma_of; @@ -81,7 +81,7 @@ static int __devinit esp_sbus_setup_dma(struct esp *esp, static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct resource *res; /* On HME, two reg sets exist, first is DVMA, @@ -101,7 +101,7 @@ static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) static int __devinit esp_sbus_map_command_block(struct esp *esp) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; esp->command_block = dma_alloc_coherent(&op->dev, 16, &esp->command_block_dma, @@ -114,15 +114,15 @@ static int __devinit esp_sbus_map_command_block(struct esp *esp) static int __devinit esp_sbus_register_irq(struct esp *esp) { struct Scsi_Host *host = esp->host; - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; - host->irq = op->irqs[0]; + host->irq = op->archdata.irqs[0]; return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); } -static void __devinit esp_get_scsi_id(struct esp *esp, struct of_device *espdma) +static void __devinit esp_get_scsi_id(struct esp *esp, struct platform_device *espdma) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *dp; dp = op->dev.of_node; @@ -144,7 +144,7 @@ done: static void __devinit esp_get_differential(struct esp *esp) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *dp; dp = op->dev.of_node; @@ -156,7 +156,7 @@ static void __devinit esp_get_differential(struct esp *esp) static void __devinit esp_get_clock_params(struct esp *esp) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *bus_dp, *dp; int fmhz; @@ -170,10 +170,10 @@ static void __devinit esp_get_clock_params(struct esp *esp) esp->cfreq = fmhz; } -static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) +static void __devinit esp_get_bursts(struct esp *esp, struct platform_device *dma_of) { struct device_node *dma_dp = dma_of->dev.of_node; - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; struct device_node *dp; u8 bursts, val; @@ -195,7 +195,7 @@ static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) esp->bursts = bursts; } -static void __devinit esp_sbus_get_props(struct esp *esp, struct of_device *espdma) +static void __devinit esp_sbus_get_props(struct esp *esp, struct platform_device *espdma) { esp_get_scsi_id(esp, espdma); esp_get_differential(esp); @@ -216,7 +216,7 @@ static u8 sbus_esp_read8(struct esp *esp, unsigned long reg) static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, size_t sz, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; return dma_map_single(&op->dev, buf, sz, dir); } @@ -224,7 +224,7 @@ static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, int num_sg, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; return dma_map_sg(&op->dev, sg, num_sg, dir); } @@ -232,7 +232,7 @@ static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, size_t sz, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; dma_unmap_single(&op->dev, addr, sz, dir); } @@ -240,7 +240,7 @@ static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, int num_sg, int dir) { - struct of_device *op = esp->dev; + struct platform_device *op = esp->dev; dma_unmap_sg(&op->dev, sg, num_sg, dir); } @@ -256,7 +256,7 @@ static void sbus_esp_reset_dma(struct esp *esp) { int can_do_burst16, can_do_burst32, can_do_burst64; int can_do_sbus64, lim; - struct of_device *op; + struct platform_device *op; u32 val; can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; @@ -487,8 +487,8 @@ static const struct esp_driver_ops sbus_esp_ops = { .dma_error = sbus_esp_dma_error, }; -static int __devinit esp_sbus_probe_one(struct of_device *op, - struct of_device *espdma, +static int __devinit esp_sbus_probe_one(struct platform_device *op, + struct platform_device *espdma, int hme) { struct scsi_host_template *tpnt = &scsi_esp_template; @@ -562,11 +562,11 @@ fail: return err; } -static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device_id *match) +static int __devinit esp_sbus_probe(struct platform_device *op, const struct of_device_id *match) { struct device_node *dma_node = NULL; struct device_node *dp = op->dev.of_node; - struct of_device *dma_of = NULL; + struct platform_device *dma_of = NULL; int hme = 0; if (dp->parent && @@ -585,10 +585,10 @@ static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device return esp_sbus_probe_one(op, dma_of, hme); } -static int __devexit esp_sbus_remove(struct of_device *op) +static int __devexit esp_sbus_remove(struct platform_device *op) { struct esp *esp = dev_get_drvdata(&op->dev); - struct of_device *dma_of = esp->dma; + struct platform_device *dma_of = esp->dma; unsigned int irq = esp->host->irq; bool is_hme; u32 val; @@ -644,12 +644,12 @@ static struct of_platform_driver esp_sbus_driver = { static int __init sunesp_init(void) { - return of_register_driver(&esp_sbus_driver, &of_bus_type); + return of_register_platform_driver(&esp_sbus_driver); } static void __exit sunesp_exit(void) { - of_unregister_driver(&esp_sbus_driver); + of_unregister_platform_driver(&esp_sbus_driver); } MODULE_DESCRIPTION("Sun ESP SCSI driver"); |