diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-10 13:53:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-10 13:53:26 -0400 |
commit | ef5bef357cdf49f3a386c7102dbf3be5f7e5c913 (patch) | |
tree | 48d9dc86768e3e146267ea21d0c898f9008275a1 /drivers/scsi | |
parent | e26feff647ef34423b048b940540a0059001ddb0 (diff) | |
parent | 41bfcf90101601f9507240ff0435c1b73d28a132 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (37 commits)
[SCSI] zfcp: fix double dbf id usage
[SCSI] zfcp: wait on SCSI work to be finished before proceeding with init dev
[SCSI] zfcp: fix erp list usage without using locks
[SCSI] zfcp: prevent fc_remote_port_delete calls for unregistered rport
[SCSI] zfcp: fix deadlock caused by shared work queue tasks
[SCSI] zfcp: put threshold data in hba trace
[SCSI] zfcp: Simplify zfcp data structures
[SCSI] zfcp: Simplify get_adapter_by_busid
[SCSI] zfcp: remove all typedefs and replace them with standards
[SCSI] zfcp: attach and release SAN nameserver port on demand
[SCSI] zfcp: remove unused references, declarations and flags
[SCSI] zfcp: Update message with input from review
[SCSI] zfcp: add queue_full sysfs attribute
[SCSI] scsi_dh: suppress comparison warning
[SCSI] scsi_dh: add Dell product information into rdac device handler
[SCSI] qla2xxx: remove the unused SCSI_QLOGIC_FC_FIRMWARE option
[SCSI] qla2xxx: fix printk format warnings
[SCSI] qla2xxx: Update version number to 8.02.01-k8.
[SCSI] qla2xxx: Ignore payload reserved-bits during RSCN processing.
[SCSI] qla2xxx: Additional residual-count corrections during UNDERRUN handling.
...
Diffstat (limited to 'drivers/scsi')
29 files changed, 1069 insertions, 168 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 4e0322b1c1ea..d3b211af4e1c 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -1325,14 +1325,6 @@ config SCSI_QLOGIC_FAS | |||
1325 | To compile this driver as a module, choose M here: the | 1325 | To compile this driver as a module, choose M here: the |
1326 | module will be called qlogicfas. | 1326 | module will be called qlogicfas. |
1327 | 1327 | ||
1328 | config SCSI_QLOGIC_FC_FIRMWARE | ||
1329 | bool "Include loadable firmware in driver" | ||
1330 | depends on SCSI_QLOGIC_FC | ||
1331 | help | ||
1332 | Say Y to include ISP2X00 Fabric Initiator/Target Firmware, with | ||
1333 | expanded LUN addressing and FcTape (FCP-2) support, in the | ||
1334 | qlogicfc driver. This is required on some platforms. | ||
1335 | |||
1336 | config SCSI_QLOGIC_1280 | 1328 | config SCSI_QLOGIC_1280 |
1337 | tristate "Qlogic QLA 1240/1x80/1x160 SCSI support" | 1329 | tristate "Qlogic QLA 1240/1x80/1x160 SCSI support" |
1338 | depends on PCI && SCSI | 1330 | depends on PCI && SCSI |
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c index ef693e8412e9..8f45570a8a01 100644 --- a/drivers/scsi/device_handler/scsi_dh_emc.c +++ b/drivers/scsi/device_handler/scsi_dh_emc.c | |||
@@ -84,7 +84,7 @@ struct clariion_dh_data { | |||
84 | /* | 84 | /* |
85 | * I/O buffer for both MODE_SELECT and INQUIRY commands. | 85 | * I/O buffer for both MODE_SELECT and INQUIRY commands. |
86 | */ | 86 | */ |
87 | char buffer[CLARIION_BUFFER_SIZE]; | 87 | unsigned char buffer[CLARIION_BUFFER_SIZE]; |
88 | /* | 88 | /* |
89 | * SCSI sense buffer for commands -- assumes serial issuance | 89 | * SCSI sense buffer for commands -- assumes serial issuance |
90 | * and completion sequence of all commands for same multipath. | 90 | * and completion sequence of all commands for same multipath. |
@@ -176,7 +176,7 @@ static int parse_sp_info_reply(struct scsi_device *sdev, | |||
176 | err = SCSI_DH_DEV_TEMP_BUSY; | 176 | err = SCSI_DH_DEV_TEMP_BUSY; |
177 | goto out; | 177 | goto out; |
178 | } | 178 | } |
179 | if (csdev->buffer[4] < 0 || csdev->buffer[4] > 2) { | 179 | if (csdev->buffer[4] > 2) { |
180 | /* Invalid buffer format */ | 180 | /* Invalid buffer format */ |
181 | sdev_printk(KERN_NOTICE, sdev, | 181 | sdev_printk(KERN_NOTICE, sdev, |
182 | "%s: invalid VPD page 0xC0 format\n", | 182 | "%s: invalid VPD page 0xC0 format\n", |
@@ -278,7 +278,6 @@ static struct request *get_req(struct scsi_device *sdev, int cmd, | |||
278 | return NULL; | 278 | return NULL; |
279 | } | 279 | } |
280 | 280 | ||
281 | memset(rq->cmd, 0, BLK_MAX_CDB); | ||
282 | rq->cmd_len = COMMAND_SIZE(cmd); | 281 | rq->cmd_len = COMMAND_SIZE(cmd); |
283 | rq->cmd[0] = cmd; | 282 | rq->cmd[0] = cmd; |
284 | 283 | ||
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index a6a4ef3ad51c..5e93c88ad66b 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c | |||
@@ -114,7 +114,6 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h) | |||
114 | req->cmd_type = REQ_TYPE_BLOCK_PC; | 114 | req->cmd_type = REQ_TYPE_BLOCK_PC; |
115 | req->cmd_flags |= REQ_FAILFAST; | 115 | req->cmd_flags |= REQ_FAILFAST; |
116 | req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY); | 116 | req->cmd_len = COMMAND_SIZE(TEST_UNIT_READY); |
117 | memset(req->cmd, 0, MAX_COMMAND_SIZE); | ||
118 | req->cmd[0] = TEST_UNIT_READY; | 117 | req->cmd[0] = TEST_UNIT_READY; |
119 | req->timeout = HP_SW_TIMEOUT; | 118 | req->timeout = HP_SW_TIMEOUT; |
120 | req->sense = h->sense; | 119 | req->sense = h->sense; |
@@ -207,7 +206,6 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) | |||
207 | req->cmd_type = REQ_TYPE_BLOCK_PC; | 206 | req->cmd_type = REQ_TYPE_BLOCK_PC; |
208 | req->cmd_flags |= REQ_FAILFAST; | 207 | req->cmd_flags |= REQ_FAILFAST; |
209 | req->cmd_len = COMMAND_SIZE(START_STOP); | 208 | req->cmd_len = COMMAND_SIZE(START_STOP); |
210 | memset(req->cmd, 0, MAX_COMMAND_SIZE); | ||
211 | req->cmd[0] = START_STOP; | 209 | req->cmd[0] = START_STOP; |
212 | req->cmd[4] = 1; /* Start spin cycle */ | 210 | req->cmd[4] = 1; /* Start spin cycle */ |
213 | req->timeout = HP_SW_TIMEOUT; | 211 | req->timeout = HP_SW_TIMEOUT; |
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 6e2f130d56de..50bf95f3b5c4 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c | |||
@@ -225,8 +225,6 @@ static struct request *get_rdac_req(struct scsi_device *sdev, | |||
225 | return NULL; | 225 | return NULL; |
226 | } | 226 | } |
227 | 227 | ||
228 | memset(rq->cmd, 0, BLK_MAX_CDB); | ||
229 | |||
230 | rq->cmd_type = REQ_TYPE_BLOCK_PC; | 228 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
231 | rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE; | 229 | rq->cmd_flags |= REQ_FAILFAST | REQ_NOMERGE; |
232 | rq->retries = RDAC_RETRIES; | 230 | rq->retries = RDAC_RETRIES; |
@@ -590,6 +588,8 @@ static const struct scsi_dh_devlist rdac_dev_list[] = { | |||
590 | {"STK", "OPENstorage D280"}, | 588 | {"STK", "OPENstorage D280"}, |
591 | {"SUN", "CSM200_R"}, | 589 | {"SUN", "CSM200_R"}, |
592 | {"SUN", "LCSM100_F"}, | 590 | {"SUN", "LCSM100_F"}, |
591 | {"DELL", "MD3000"}, | ||
592 | {"DELL", "MD3000i"}, | ||
593 | {NULL, NULL}, | 593 | {NULL, NULL}, |
594 | }; | 594 | }; |
595 | 595 | ||
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index fed0b02ebc1d..3fdbb13e80a8 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -464,7 +464,7 @@ static int __scsi_host_match(struct device *dev, void *data) | |||
464 | struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) | 464 | struct Scsi_Host *scsi_host_lookup(unsigned short hostnum) |
465 | { | 465 | { |
466 | struct device *cdev; | 466 | struct device *cdev; |
467 | struct Scsi_Host *shost = ERR_PTR(-ENXIO); | 467 | struct Scsi_Host *shost = NULL; |
468 | 468 | ||
469 | cdev = class_find_device(&shost_class, NULL, &hostnum, | 469 | cdev = class_find_device(&shost_class, NULL, &hostnum, |
470 | __scsi_host_match); | 470 | __scsi_host_match); |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 1eca82420aab..da7b67d30d9a 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -1456,7 +1456,7 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun, | |||
1456 | if (lun == task->sc->device->lun || lun == -1) { | 1456 | if (lun == task->sc->device->lun || lun == -1) { |
1457 | debug_scsi("failing in progress sc %p itt 0x%x\n", | 1457 | debug_scsi("failing in progress sc %p itt 0x%x\n", |
1458 | task->sc, task->itt); | 1458 | task->sc, task->itt); |
1459 | fail_command(conn, task, DID_BUS_BUSY << 16); | 1459 | fail_command(conn, task, error << 16); |
1460 | } | 1460 | } |
1461 | } | 1461 | } |
1462 | } | 1462 | } |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 45e7dcb4b34d..0ddfe7106b3b 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -292,10 +292,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, | |||
292 | valid = 0; | 292 | valid = 0; |
293 | if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) | 293 | if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) |
294 | valid = 1; | 294 | valid = 1; |
295 | else if (start == (FA_BOOT_CODE_ADDR*4) || | 295 | else if (start == (ha->flt_region_boot * 4) || |
296 | start == (FA_RISC_CODE_ADDR*4)) | 296 | start == (ha->flt_region_fw * 4)) |
297 | valid = 1; | 297 | valid = 1; |
298 | else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4)) | 298 | else if (IS_QLA25XX(ha) && |
299 | start == (ha->flt_region_vpd_nvram * 4)) | ||
299 | valid = 1; | 300 | valid = 1; |
300 | if (!valid) { | 301 | if (!valid) { |
301 | qla_printk(KERN_WARNING, ha, | 302 | qla_printk(KERN_WARNING, ha, |
@@ -1065,6 +1066,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) | |||
1065 | pfc_host_stat->dumped_frames = stats->dumped_frames; | 1066 | pfc_host_stat->dumped_frames = stats->dumped_frames; |
1066 | pfc_host_stat->nos_count = stats->nos_rcvd; | 1067 | pfc_host_stat->nos_count = stats->nos_rcvd; |
1067 | } | 1068 | } |
1069 | pfc_host_stat->fcp_input_megabytes = ha->qla_stats.input_bytes >> 20; | ||
1070 | pfc_host_stat->fcp_output_megabytes = ha->qla_stats.output_bytes >> 20; | ||
1068 | 1071 | ||
1069 | done_free: | 1072 | done_free: |
1070 | dma_pool_free(ha->s_dma_pool, stats, stats_dma); | 1073 | dma_pool_free(ha->s_dma_pool, stats, stats_dma); |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 94a720eabfd8..83c819216771 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/firmware.h> | 25 | #include <linux/firmware.h> |
26 | #include <linux/aer.h> | 26 | #include <linux/aer.h> |
27 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
28 | #include <linux/semaphore.h> | ||
29 | 28 | ||
30 | #include <scsi/scsi.h> | 29 | #include <scsi/scsi.h> |
31 | #include <scsi/scsi_host.h> | 30 | #include <scsi/scsi_host.h> |
@@ -2157,6 +2156,8 @@ struct qla_chip_state_84xx { | |||
2157 | 2156 | ||
2158 | struct qla_statistics { | 2157 | struct qla_statistics { |
2159 | uint32_t total_isp_aborts; | 2158 | uint32_t total_isp_aborts; |
2159 | uint64_t input_bytes; | ||
2160 | uint64_t output_bytes; | ||
2160 | }; | 2161 | }; |
2161 | 2162 | ||
2162 | /* | 2163 | /* |
@@ -2238,6 +2239,7 @@ typedef struct scsi_qla_host { | |||
2238 | #define FCPORT_UPDATE_NEEDED 27 | 2239 | #define FCPORT_UPDATE_NEEDED 27 |
2239 | #define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */ | 2240 | #define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */ |
2240 | #define UNLOADING 29 | 2241 | #define UNLOADING 29 |
2242 | #define NPIV_CONFIG_NEEDED 30 | ||
2241 | 2243 | ||
2242 | uint32_t device_flags; | 2244 | uint32_t device_flags; |
2243 | #define DFLG_LOCAL_DEVICES BIT_0 | 2245 | #define DFLG_LOCAL_DEVICES BIT_0 |
@@ -2507,7 +2509,6 @@ typedef struct scsi_qla_host { | |||
2507 | uint64_t fce_wr, fce_rd; | 2509 | uint64_t fce_wr, fce_rd; |
2508 | struct mutex fce_mutex; | 2510 | struct mutex fce_mutex; |
2509 | 2511 | ||
2510 | uint32_t hw_event_start; | ||
2511 | uint32_t hw_event_ptr; | 2512 | uint32_t hw_event_ptr; |
2512 | uint32_t hw_event_pause_errors; | 2513 | uint32_t hw_event_pause_errors; |
2513 | 2514 | ||
@@ -2553,6 +2554,14 @@ typedef struct scsi_qla_host { | |||
2553 | uint32_t fdt_unprotect_sec_cmd; | 2554 | uint32_t fdt_unprotect_sec_cmd; |
2554 | uint32_t fdt_protect_sec_cmd; | 2555 | uint32_t fdt_protect_sec_cmd; |
2555 | 2556 | ||
2557 | uint32_t flt_region_flt; | ||
2558 | uint32_t flt_region_fdt; | ||
2559 | uint32_t flt_region_boot; | ||
2560 | uint32_t flt_region_fw; | ||
2561 | uint32_t flt_region_vpd_nvram; | ||
2562 | uint32_t flt_region_hw_event; | ||
2563 | uint32_t flt_region_npiv_conf; | ||
2564 | |||
2556 | /* Needed for BEACON */ | 2565 | /* Needed for BEACON */ |
2557 | uint16_t beacon_blink_led; | 2566 | uint16_t beacon_blink_led; |
2558 | uint8_t beacon_color_state; | 2567 | uint8_t beacon_color_state; |
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index cf194517400d..d1d14202575a 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h | |||
@@ -789,14 +789,23 @@ struct device_reg_24xx { | |||
789 | #define FA_RISC_CODE_ADDR 0x20000 | 789 | #define FA_RISC_CODE_ADDR 0x20000 |
790 | #define FA_RISC_CODE_SEGMENTS 2 | 790 | #define FA_RISC_CODE_SEGMENTS 2 |
791 | 791 | ||
792 | #define FA_FLASH_DESCR_ADDR_24 0x11000 | ||
793 | #define FA_FLASH_LAYOUT_ADDR_24 0x11400 | ||
794 | #define FA_NPIV_CONF0_ADDR_24 0x16000 | ||
795 | #define FA_NPIV_CONF1_ADDR_24 0x17000 | ||
796 | |||
792 | #define FA_FW_AREA_ADDR 0x40000 | 797 | #define FA_FW_AREA_ADDR 0x40000 |
793 | #define FA_VPD_NVRAM_ADDR 0x48000 | 798 | #define FA_VPD_NVRAM_ADDR 0x48000 |
794 | #define FA_FEATURE_ADDR 0x4C000 | 799 | #define FA_FEATURE_ADDR 0x4C000 |
795 | #define FA_FLASH_DESCR_ADDR 0x50000 | 800 | #define FA_FLASH_DESCR_ADDR 0x50000 |
801 | #define FA_FLASH_LAYOUT_ADDR 0x50400 | ||
796 | #define FA_HW_EVENT0_ADDR 0x54000 | 802 | #define FA_HW_EVENT0_ADDR 0x54000 |
797 | #define FA_HW_EVENT1_ADDR 0x54200 | 803 | #define FA_HW_EVENT1_ADDR 0x54400 |
798 | #define FA_HW_EVENT_SIZE 0x200 | 804 | #define FA_HW_EVENT_SIZE 0x200 |
799 | #define FA_HW_EVENT_ENTRY_SIZE 4 | 805 | #define FA_HW_EVENT_ENTRY_SIZE 4 |
806 | #define FA_NPIV_CONF0_ADDR 0x5C000 | ||
807 | #define FA_NPIV_CONF1_ADDR 0x5D000 | ||
808 | |||
800 | /* | 809 | /* |
801 | * Flash Error Log Event Codes. | 810 | * Flash Error Log Event Codes. |
802 | */ | 811 | */ |
@@ -806,10 +815,6 @@ struct device_reg_24xx { | |||
806 | #define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023 | 815 | #define HW_EVENT_NVRAM_CHKSUM_ERR 0xF023 |
807 | #define HW_EVENT_FLASH_FW_ERR 0xF024 | 816 | #define HW_EVENT_FLASH_FW_ERR 0xF024 |
808 | 817 | ||
809 | #define FA_BOOT_LOG_ADDR 0x58000 | ||
810 | #define FA_FW_DUMP0_ADDR 0x60000 | ||
811 | #define FA_FW_DUMP1_ADDR 0x70000 | ||
812 | |||
813 | uint32_t flash_data; /* Flash/NVRAM BIOS data. */ | 818 | uint32_t flash_data; /* Flash/NVRAM BIOS data. */ |
814 | 819 | ||
815 | uint32_t ctrl_status; /* Control/Status. */ | 820 | uint32_t ctrl_status; /* Control/Status. */ |
@@ -1203,6 +1208,62 @@ struct qla_fdt_layout { | |||
1203 | uint8_t unused2[65]; | 1208 | uint8_t unused2[65]; |
1204 | }; | 1209 | }; |
1205 | 1210 | ||
1211 | /* Flash Layout Table ********************************************************/ | ||
1212 | |||
1213 | struct qla_flt_location { | ||
1214 | uint8_t sig[4]; | ||
1215 | uint32_t start_lo; | ||
1216 | uint32_t start_hi; | ||
1217 | uint16_t unused; | ||
1218 | uint16_t checksum; | ||
1219 | }; | ||
1220 | |||
1221 | struct qla_flt_header { | ||
1222 | uint16_t version; | ||
1223 | uint16_t length; | ||
1224 | uint16_t checksum; | ||
1225 | uint16_t unused; | ||
1226 | }; | ||
1227 | |||
1228 | #define FLT_REG_FW 0x01 | ||
1229 | #define FLT_REG_BOOT_CODE 0x07 | ||
1230 | #define FLT_REG_VPD_0 0x14 | ||
1231 | #define FLT_REG_NVRAM_0 0x15 | ||
1232 | #define FLT_REG_VPD_1 0x16 | ||
1233 | #define FLT_REG_NVRAM_1 0x17 | ||
1234 | #define FLT_REG_FDT 0x1a | ||
1235 | #define FLT_REG_FLT 0x1c | ||
1236 | #define FLT_REG_HW_EVENT_0 0x1d | ||
1237 | #define FLT_REG_HW_EVENT_1 0x1f | ||
1238 | #define FLT_REG_NPIV_CONF_0 0x29 | ||
1239 | #define FLT_REG_NPIV_CONF_1 0x2a | ||
1240 | |||
1241 | struct qla_flt_region { | ||
1242 | uint32_t code; | ||
1243 | uint32_t size; | ||
1244 | uint32_t start; | ||
1245 | uint32_t end; | ||
1246 | }; | ||
1247 | |||
1248 | /* Flash NPIV Configuration Table ********************************************/ | ||
1249 | |||
1250 | struct qla_npiv_header { | ||
1251 | uint8_t sig[2]; | ||
1252 | uint16_t version; | ||
1253 | uint16_t entries; | ||
1254 | uint16_t unused[4]; | ||
1255 | uint16_t checksum; | ||
1256 | }; | ||
1257 | |||
1258 | struct qla_npiv_entry { | ||
1259 | uint16_t flags; | ||
1260 | uint16_t vf_id; | ||
1261 | uint16_t qos; | ||
1262 | uint16_t unused1; | ||
1263 | uint8_t port_name[WWN_SIZE]; | ||
1264 | uint8_t node_name[WWN_SIZE]; | ||
1265 | }; | ||
1266 | |||
1206 | /* 84XX Support **************************************************************/ | 1267 | /* 84XX Support **************************************************************/ |
1207 | 1268 | ||
1208 | #define MBA_ISP84XX_ALERT 0x800f /* Alert Notification. */ | 1269 | #define MBA_ISP84XX_ALERT 0x800f /* Alert Notification. */ |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 0b156735e9a6..753dbe6cce6e 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -313,9 +313,11 @@ extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); | |||
313 | extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t, | 313 | extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t, |
314 | uint16_t, uint16_t); | 314 | uint16_t, uint16_t); |
315 | 315 | ||
316 | extern void qla2xxx_get_flash_info(scsi_qla_host_t *); | 316 | extern int qla2xxx_get_flash_info(scsi_qla_host_t *); |
317 | extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); | 317 | extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t); |
318 | 318 | ||
319 | extern void qla2xxx_flash_npiv_conf(scsi_qla_host_t *); | ||
320 | |||
319 | /* | 321 | /* |
320 | * Global Function Prototypes in qla_dbg.c source file. | 322 | * Global Function Prototypes in qla_dbg.c source file. |
321 | */ | 323 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ee89ddd64aae..a470f2d3270d 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -83,6 +83,13 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
83 | 83 | ||
84 | ha->isp_ops->reset_chip(ha); | 84 | ha->isp_ops->reset_chip(ha); |
85 | 85 | ||
86 | rval = qla2xxx_get_flash_info(ha); | ||
87 | if (rval) { | ||
88 | DEBUG2(printk("scsi(%ld): Unable to validate FLASH data.\n", | ||
89 | ha->host_no)); | ||
90 | return (rval); | ||
91 | } | ||
92 | |||
86 | ha->isp_ops->get_flash_version(ha, ha->request_ring); | 93 | ha->isp_ops->get_flash_version(ha, ha->request_ring); |
87 | 94 | ||
88 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); | 95 | qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); |
@@ -109,7 +116,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) | |||
109 | rval = qla2x00_setup_chip(ha); | 116 | rval = qla2x00_setup_chip(ha); |
110 | if (rval) | 117 | if (rval) |
111 | return (rval); | 118 | return (rval); |
112 | qla2xxx_get_flash_info(ha); | ||
113 | } | 119 | } |
114 | if (IS_QLA84XX(ha)) { | 120 | if (IS_QLA84XX(ha)) { |
115 | ha->cs84xx = qla84xx_get_chip(ha); | 121 | ha->cs84xx = qla84xx_get_chip(ha); |
@@ -2016,7 +2022,7 @@ qla2x00_configure_loop(scsi_qla_host_t *ha) | |||
2016 | DEBUG3(printk("%s: exiting normally\n", __func__)); | 2022 | DEBUG3(printk("%s: exiting normally\n", __func__)); |
2017 | } | 2023 | } |
2018 | 2024 | ||
2019 | /* Restore state if a resync event occured during processing */ | 2025 | /* Restore state if a resync event occurred during processing */ |
2020 | if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { | 2026 | if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) { |
2021 | if (test_bit(LOCAL_LOOP_UPDATE, &save_flags)) | 2027 | if (test_bit(LOCAL_LOOP_UPDATE, &save_flags)) |
2022 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); | 2028 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); |
@@ -2561,7 +2567,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) | |||
2561 | rval = QLA_SUCCESS; | 2567 | rval = QLA_SUCCESS; |
2562 | 2568 | ||
2563 | /* Try GID_PT to get device list, else GAN. */ | 2569 | /* Try GID_PT to get device list, else GAN. */ |
2564 | swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_ATOMIC); | 2570 | swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_KERNEL); |
2565 | if (!swl) { | 2571 | if (!swl) { |
2566 | /*EMPTY*/ | 2572 | /*EMPTY*/ |
2567 | DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback " | 2573 | DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback " |
@@ -3751,7 +3757,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr) | |||
3751 | rval = QLA_SUCCESS; | 3757 | rval = QLA_SUCCESS; |
3752 | 3758 | ||
3753 | segments = FA_RISC_CODE_SEGMENTS; | 3759 | segments = FA_RISC_CODE_SEGMENTS; |
3754 | faddr = FA_RISC_CODE_ADDR; | 3760 | faddr = ha->flt_region_fw; |
3755 | dcode = (uint32_t *)ha->request_ring; | 3761 | dcode = (uint32_t *)ha->request_ring; |
3756 | *srisc_addr = 0; | 3762 | *srisc_addr = 0; |
3757 | 3763 | ||
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index 92fafbdbbaab..e90afad120ee 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h | |||
@@ -52,7 +52,7 @@ to_qla_parent(scsi_qla_host_t *ha) | |||
52 | * @ha: HA context | 52 | * @ha: HA context |
53 | * @ha_locked: is function called with the hardware lock | 53 | * @ha_locked: is function called with the hardware lock |
54 | * | 54 | * |
55 | * Returns non-zero if a failure occured, else zero. | 55 | * Returns non-zero if a failure occurred, else zero. |
56 | */ | 56 | */ |
57 | static inline int | 57 | static inline int |
58 | qla2x00_issue_marker(scsi_qla_host_t *ha, int ha_locked) | 58 | qla2x00_issue_marker(scsi_qla_host_t *ha, int ha_locked) |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index d57669aa4615..85bc0a48598b 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -21,17 +21,22 @@ static void qla2x00_isp_cmd(scsi_qla_host_t *ha); | |||
21 | * Returns the proper CF_* direction based on CDB. | 21 | * Returns the proper CF_* direction based on CDB. |
22 | */ | 22 | */ |
23 | static inline uint16_t | 23 | static inline uint16_t |
24 | qla2x00_get_cmd_direction(struct scsi_cmnd *cmd) | 24 | qla2x00_get_cmd_direction(srb_t *sp) |
25 | { | 25 | { |
26 | uint16_t cflags; | 26 | uint16_t cflags; |
27 | 27 | ||
28 | cflags = 0; | 28 | cflags = 0; |
29 | 29 | ||
30 | /* Set transfer direction */ | 30 | /* Set transfer direction */ |
31 | if (cmd->sc_data_direction == DMA_TO_DEVICE) | 31 | if (sp->cmd->sc_data_direction == DMA_TO_DEVICE) { |
32 | cflags = CF_WRITE; | 32 | cflags = CF_WRITE; |
33 | else if (cmd->sc_data_direction == DMA_FROM_DEVICE) | 33 | sp->fcport->ha->qla_stats.output_bytes += |
34 | scsi_bufflen(sp->cmd); | ||
35 | } else if (sp->cmd->sc_data_direction == DMA_FROM_DEVICE) { | ||
34 | cflags = CF_READ; | 36 | cflags = CF_READ; |
37 | sp->fcport->ha->qla_stats.input_bytes += | ||
38 | scsi_bufflen(sp->cmd); | ||
39 | } | ||
35 | return (cflags); | 40 | return (cflags); |
36 | } | 41 | } |
37 | 42 | ||
@@ -169,7 +174,7 @@ void qla2x00_build_scsi_iocbs_32(srb_t *sp, cmd_entry_t *cmd_pkt, | |||
169 | 174 | ||
170 | ha = sp->ha; | 175 | ha = sp->ha; |
171 | 176 | ||
172 | cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(cmd)); | 177 | cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp)); |
173 | 178 | ||
174 | /* Three DSDs are available in the Command Type 2 IOCB */ | 179 | /* Three DSDs are available in the Command Type 2 IOCB */ |
175 | avail_dsds = 3; | 180 | avail_dsds = 3; |
@@ -228,7 +233,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, | |||
228 | 233 | ||
229 | ha = sp->ha; | 234 | ha = sp->ha; |
230 | 235 | ||
231 | cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(cmd)); | 236 | cmd_pkt->control_flags |= cpu_to_le16(qla2x00_get_cmd_direction(sp)); |
232 | 237 | ||
233 | /* Two DSDs are available in the Command Type 3 IOCB */ | 238 | /* Two DSDs are available in the Command Type 3 IOCB */ |
234 | avail_dsds = 2; | 239 | avail_dsds = 2; |
@@ -262,7 +267,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, | |||
262 | * qla2x00_start_scsi() - Send a SCSI command to the ISP | 267 | * qla2x00_start_scsi() - Send a SCSI command to the ISP |
263 | * @sp: command to send to the ISP | 268 | * @sp: command to send to the ISP |
264 | * | 269 | * |
265 | * Returns non-zero if a failure occured, else zero. | 270 | * Returns non-zero if a failure occurred, else zero. |
266 | */ | 271 | */ |
267 | int | 272 | int |
268 | qla2x00_start_scsi(srb_t *sp) | 273 | qla2x00_start_scsi(srb_t *sp) |
@@ -407,7 +412,7 @@ queuing_error: | |||
407 | * | 412 | * |
408 | * Can be called from both normal and interrupt context. | 413 | * Can be called from both normal and interrupt context. |
409 | * | 414 | * |
410 | * Returns non-zero if a failure occured, else zero. | 415 | * Returns non-zero if a failure occurred, else zero. |
411 | */ | 416 | */ |
412 | int | 417 | int |
413 | __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, | 418 | __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, |
@@ -625,12 +630,17 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, | |||
625 | ha = sp->ha; | 630 | ha = sp->ha; |
626 | 631 | ||
627 | /* Set transfer direction */ | 632 | /* Set transfer direction */ |
628 | if (cmd->sc_data_direction == DMA_TO_DEVICE) | 633 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { |
629 | cmd_pkt->task_mgmt_flags = | 634 | cmd_pkt->task_mgmt_flags = |
630 | __constant_cpu_to_le16(TMF_WRITE_DATA); | 635 | __constant_cpu_to_le16(TMF_WRITE_DATA); |
631 | else if (cmd->sc_data_direction == DMA_FROM_DEVICE) | 636 | sp->fcport->ha->qla_stats.output_bytes += |
637 | scsi_bufflen(sp->cmd); | ||
638 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | ||
632 | cmd_pkt->task_mgmt_flags = | 639 | cmd_pkt->task_mgmt_flags = |
633 | __constant_cpu_to_le16(TMF_READ_DATA); | 640 | __constant_cpu_to_le16(TMF_READ_DATA); |
641 | sp->fcport->ha->qla_stats.input_bytes += | ||
642 | scsi_bufflen(sp->cmd); | ||
643 | } | ||
634 | 644 | ||
635 | /* One DSD is available in the Command Type 3 IOCB */ | 645 | /* One DSD is available in the Command Type 3 IOCB */ |
636 | avail_dsds = 1; | 646 | avail_dsds = 1; |
@@ -666,7 +676,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, | |||
666 | * qla24xx_start_scsi() - Send a SCSI command to the ISP | 676 | * qla24xx_start_scsi() - Send a SCSI command to the ISP |
667 | * @sp: command to send to the ISP | 677 | * @sp: command to send to the ISP |
668 | * | 678 | * |
669 | * Returns non-zero if a failure occured, else zero. | 679 | * Returns non-zero if a failure occurred, else zero. |
670 | */ | 680 | */ |
671 | int | 681 | int |
672 | qla24xx_start_scsi(srb_t *sp) | 682 | qla24xx_start_scsi(srb_t *sp) |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index bf41887cdd65..fc4bfa7f839c 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -391,9 +391,9 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
391 | break; | 391 | break; |
392 | 392 | ||
393 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ | 393 | case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ |
394 | DEBUG2(printk("scsi(%ld): LIP occured (%x).\n", ha->host_no, | 394 | DEBUG2(printk("scsi(%ld): LIP occurred (%x).\n", ha->host_no, |
395 | mb[1])); | 395 | mb[1])); |
396 | qla_printk(KERN_INFO, ha, "LIP occured (%x).\n", mb[1]); | 396 | qla_printk(KERN_INFO, ha, "LIP occurred (%x).\n", mb[1]); |
397 | 397 | ||
398 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { | 398 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { |
399 | atomic_set(&ha->loop_state, LOOP_DOWN); | 399 | atomic_set(&ha->loop_state, LOOP_DOWN); |
@@ -460,7 +460,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
460 | DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n", | 460 | DEBUG2(printk("scsi(%ld): Asynchronous LIP RESET (%x).\n", |
461 | ha->host_no, mb[1])); | 461 | ha->host_no, mb[1])); |
462 | qla_printk(KERN_INFO, ha, | 462 | qla_printk(KERN_INFO, ha, |
463 | "LIP reset occured (%x).\n", mb[1]); | 463 | "LIP reset occurred (%x).\n", mb[1]); |
464 | 464 | ||
465 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { | 465 | if (atomic_read(&ha->loop_state) != LOOP_DOWN) { |
466 | atomic_set(&ha->loop_state, LOOP_DOWN); | 466 | atomic_set(&ha->loop_state, LOOP_DOWN); |
@@ -543,7 +543,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
543 | 543 | ||
544 | case MBA_PORT_UPDATE: /* Port database update */ | 544 | case MBA_PORT_UPDATE: /* Port database update */ |
545 | /* | 545 | /* |
546 | * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET | 546 | * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET |
547 | * event etc. earlier indicating loop is down) then process | 547 | * event etc. earlier indicating loop is down) then process |
548 | * it. Otherwise ignore it and Wait for RSCN to come in. | 548 | * it. Otherwise ignore it and Wait for RSCN to come in. |
549 | */ | 549 | */ |
@@ -589,7 +589,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
589 | "scsi(%ld): RSCN database changed -- %04x %04x %04x.\n", | 589 | "scsi(%ld): RSCN database changed -- %04x %04x %04x.\n", |
590 | ha->host_no, mb[1], mb[2], mb[3])); | 590 | ha->host_no, mb[1], mb[2], mb[3])); |
591 | 591 | ||
592 | rscn_entry = (mb[1] << 16) | mb[2]; | 592 | rscn_entry = ((mb[1] & 0xff) << 16) | mb[2]; |
593 | host_pid = (ha->d_id.b.domain << 16) | (ha->d_id.b.area << 8) | | 593 | host_pid = (ha->d_id.b.domain << 16) | (ha->d_id.b.area << 8) | |
594 | ha->d_id.b.al_pa; | 594 | ha->d_id.b.al_pa; |
595 | if (rscn_entry == host_pid) { | 595 | if (rscn_entry == host_pid) { |
@@ -600,6 +600,8 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) | |||
600 | break; | 600 | break; |
601 | } | 601 | } |
602 | 602 | ||
603 | /* Ignore reserved bits from RSCN-payload. */ | ||
604 | rscn_entry = ((mb[1] & 0x3ff) << 16) | mb[2]; | ||
603 | rscn_queue_index = ha->rscn_in_ptr + 1; | 605 | rscn_queue_index = ha->rscn_in_ptr + 1; |
604 | if (rscn_queue_index == MAX_RSCN_COUNT) | 606 | if (rscn_queue_index == MAX_RSCN_COUNT) |
605 | rscn_queue_index = 0; | 607 | rscn_queue_index = 0; |
@@ -1060,8 +1062,9 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
1060 | resid = resid_len; | 1062 | resid = resid_len; |
1061 | /* Use F/W calculated residual length. */ | 1063 | /* Use F/W calculated residual length. */ |
1062 | if (IS_FWI2_CAPABLE(ha)) { | 1064 | if (IS_FWI2_CAPABLE(ha)) { |
1063 | if (scsi_status & SS_RESIDUAL_UNDER && | 1065 | if (!(scsi_status & SS_RESIDUAL_UNDER)) { |
1064 | resid != fw_resid_len) { | 1066 | lscsi_status = 0; |
1067 | } else if (resid != fw_resid_len) { | ||
1065 | scsi_status &= ~SS_RESIDUAL_UNDER; | 1068 | scsi_status &= ~SS_RESIDUAL_UNDER; |
1066 | lscsi_status = 0; | 1069 | lscsi_status = 0; |
1067 | } | 1070 | } |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 813bc7784c0a..36bc6851e23d 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -233,7 +233,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) | |||
233 | DEBUG2_3_11(printk("%s(%ld): timeout schedule " | 233 | DEBUG2_3_11(printk("%s(%ld): timeout schedule " |
234 | "isp_abort_needed.\n", __func__, ha->host_no)); | 234 | "isp_abort_needed.\n", __func__, ha->host_no)); |
235 | qla_printk(KERN_WARNING, ha, | 235 | qla_printk(KERN_WARNING, ha, |
236 | "Mailbox command timeout occured. Scheduling ISP " | 236 | "Mailbox command timeout occurred. Scheduling ISP " |
237 | "abort.\n"); | 237 | "abort.\n"); |
238 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); | 238 | set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); |
239 | qla2xxx_wake_dpc(ha); | 239 | qla2xxx_wake_dpc(ha); |
@@ -244,7 +244,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *pvha, mbx_cmd_t *mcp) | |||
244 | DEBUG2_3_11(printk("%s(%ld): timeout calling " | 244 | DEBUG2_3_11(printk("%s(%ld): timeout calling " |
245 | "abort_isp\n", __func__, ha->host_no)); | 245 | "abort_isp\n", __func__, ha->host_no)); |
246 | qla_printk(KERN_WARNING, ha, | 246 | qla_printk(KERN_WARNING, ha, |
247 | "Mailbox command timeout occured. Issuing ISP " | 247 | "Mailbox command timeout occurred. Issuing ISP " |
248 | "abort.\n"); | 248 | "abort.\n"); |
249 | 249 | ||
250 | set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); | 250 | set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); |
@@ -1995,7 +1995,7 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map) | |||
1995 | char *pmap; | 1995 | char *pmap; |
1996 | dma_addr_t pmap_dma; | 1996 | dma_addr_t pmap_dma; |
1997 | 1997 | ||
1998 | pmap = dma_pool_alloc(ha->s_dma_pool, GFP_ATOMIC, &pmap_dma); | 1998 | pmap = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &pmap_dma); |
1999 | if (pmap == NULL) { | 1999 | if (pmap == NULL) { |
2000 | DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****", | 2000 | DEBUG2_3_11(printk("%s(%ld): **** Mem Alloc Failed ****", |
2001 | __func__, ha->host_no)); | 2001 | __func__, ha->host_no)); |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 6d0f0e5f2827..3433441b956a 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -1517,6 +1517,7 @@ qla2xxx_scan_start(struct Scsi_Host *shost) | |||
1517 | set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); | 1517 | set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); |
1518 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); | 1518 | set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); |
1519 | set_bit(RSCN_UPDATE, &ha->dpc_flags); | 1519 | set_bit(RSCN_UPDATE, &ha->dpc_flags); |
1520 | set_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags); | ||
1520 | } | 1521 | } |
1521 | 1522 | ||
1522 | static int | 1523 | static int |
@@ -1663,8 +1664,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1663 | ha->gid_list_info_size = 8; | 1664 | ha->gid_list_info_size = 8; |
1664 | ha->optrom_size = OPTROM_SIZE_25XX; | 1665 | ha->optrom_size = OPTROM_SIZE_25XX; |
1665 | ha->isp_ops = &qla25xx_isp_ops; | 1666 | ha->isp_ops = &qla25xx_isp_ops; |
1666 | ha->hw_event_start = PCI_FUNC(pdev->devfn) ? | ||
1667 | FA_HW_EVENT1_ADDR: FA_HW_EVENT0_ADDR; | ||
1668 | } | 1667 | } |
1669 | host->can_queue = ha->request_q_length + 128; | 1668 | host->can_queue = ha->request_q_length + 128; |
1670 | 1669 | ||
@@ -2433,6 +2432,12 @@ qla2x00_do_dpc(void *data) | |||
2433 | ha->host_no)); | 2432 | ha->host_no)); |
2434 | } | 2433 | } |
2435 | 2434 | ||
2435 | if (test_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags) && | ||
2436 | atomic_read(&ha->loop_state) == LOOP_READY) { | ||
2437 | clear_bit(NPIV_CONFIG_NEEDED, &ha->dpc_flags); | ||
2438 | qla2xxx_flash_npiv_conf(ha); | ||
2439 | } | ||
2440 | |||
2436 | if (!ha->interrupts_on) | 2441 | if (!ha->interrupts_on) |
2437 | ha->isp_ops->enable_intrs(ha); | 2442 | ha->isp_ops->enable_intrs(ha); |
2438 | 2443 | ||
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 1bca74474935..90a13211717f 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -543,23 +543,198 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, | |||
543 | } | 543 | } |
544 | } | 544 | } |
545 | 545 | ||
546 | void | 546 | static int |
547 | qla2xxx_get_flash_info(scsi_qla_host_t *ha) | 547 | qla2xxx_find_flt_start(scsi_qla_host_t *ha, uint32_t *start) |
548 | { | ||
549 | const char *loc, *locations[] = { "DEF", "PCI" }; | ||
550 | uint32_t pcihdr, pcids; | ||
551 | uint32_t *dcode; | ||
552 | uint8_t *buf, *bcode, last_image; | ||
553 | uint16_t cnt, chksum, *wptr; | ||
554 | struct qla_flt_location *fltl; | ||
555 | |||
556 | /* | ||
557 | * FLT-location structure resides after the last PCI region. | ||
558 | */ | ||
559 | |||
560 | /* Begin with sane defaults. */ | ||
561 | loc = locations[0]; | ||
562 | *start = IS_QLA24XX_TYPE(ha) ? FA_FLASH_LAYOUT_ADDR_24: | ||
563 | FA_FLASH_LAYOUT_ADDR; | ||
564 | |||
565 | /* Begin with first PCI expansion ROM header. */ | ||
566 | buf = (uint8_t *)ha->request_ring; | ||
567 | dcode = (uint32_t *)ha->request_ring; | ||
568 | pcihdr = 0; | ||
569 | last_image = 1; | ||
570 | do { | ||
571 | /* Verify PCI expansion ROM header. */ | ||
572 | qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20); | ||
573 | bcode = buf + (pcihdr % 4); | ||
574 | if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) | ||
575 | goto end; | ||
576 | |||
577 | /* Locate PCI data structure. */ | ||
578 | pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); | ||
579 | qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20); | ||
580 | bcode = buf + (pcihdr % 4); | ||
581 | |||
582 | /* Validate signature of PCI data structure. */ | ||
583 | if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || | ||
584 | bcode[0x2] != 'I' || bcode[0x3] != 'R') | ||
585 | goto end; | ||
586 | |||
587 | last_image = bcode[0x15] & BIT_7; | ||
588 | |||
589 | /* Locate next PCI expansion ROM. */ | ||
590 | pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512; | ||
591 | } while (!last_image); | ||
592 | |||
593 | /* Now verify FLT-location structure. */ | ||
594 | fltl = (struct qla_flt_location *)ha->request_ring; | ||
595 | qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, | ||
596 | sizeof(struct qla_flt_location) >> 2); | ||
597 | if (fltl->sig[0] != 'Q' || fltl->sig[1] != 'F' || | ||
598 | fltl->sig[2] != 'L' || fltl->sig[3] != 'T') | ||
599 | goto end; | ||
600 | |||
601 | wptr = (uint16_t *)ha->request_ring; | ||
602 | cnt = sizeof(struct qla_flt_location) >> 1; | ||
603 | for (chksum = 0; cnt; cnt--) | ||
604 | chksum += le16_to_cpu(*wptr++); | ||
605 | if (chksum) { | ||
606 | qla_printk(KERN_ERR, ha, | ||
607 | "Inconsistent FLTL detected: checksum=0x%x.\n", chksum); | ||
608 | qla2x00_dump_buffer(buf, sizeof(struct qla_flt_location)); | ||
609 | return QLA_FUNCTION_FAILED; | ||
610 | } | ||
611 | |||
612 | /* Good data. Use specified location. */ | ||
613 | loc = locations[1]; | ||
614 | *start = le16_to_cpu(fltl->start_hi) << 16 | | ||
615 | le16_to_cpu(fltl->start_lo); | ||
616 | end: | ||
617 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FLTL[%s] = 0x%x.\n", loc, *start)); | ||
618 | return QLA_SUCCESS; | ||
619 | } | ||
620 | |||
621 | static void | ||
622 | qla2xxx_get_flt_info(scsi_qla_host_t *ha, uint32_t flt_addr) | ||
623 | { | ||
624 | const char *loc, *locations[] = { "DEF", "FLT" }; | ||
625 | uint16_t *wptr; | ||
626 | uint16_t cnt, chksum; | ||
627 | uint32_t start; | ||
628 | struct qla_flt_header *flt; | ||
629 | struct qla_flt_region *region; | ||
630 | |||
631 | ha->flt_region_flt = flt_addr; | ||
632 | wptr = (uint16_t *)ha->request_ring; | ||
633 | flt = (struct qla_flt_header *)ha->request_ring; | ||
634 | region = (struct qla_flt_region *)&flt[1]; | ||
635 | ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring, | ||
636 | flt_addr << 2, OPTROM_BURST_SIZE); | ||
637 | if (*wptr == __constant_cpu_to_le16(0xffff)) | ||
638 | goto no_flash_data; | ||
639 | if (flt->version != __constant_cpu_to_le16(1)) { | ||
640 | DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported FLT detected: " | ||
641 | "version=0x%x length=0x%x checksum=0x%x.\n", | ||
642 | le16_to_cpu(flt->version), le16_to_cpu(flt->length), | ||
643 | le16_to_cpu(flt->checksum))); | ||
644 | goto no_flash_data; | ||
645 | } | ||
646 | |||
647 | cnt = (sizeof(struct qla_flt_header) + le16_to_cpu(flt->length)) >> 1; | ||
648 | for (chksum = 0; cnt; cnt--) | ||
649 | chksum += le16_to_cpu(*wptr++); | ||
650 | if (chksum) { | ||
651 | DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent FLT detected: " | ||
652 | "version=0x%x length=0x%x checksum=0x%x.\n", | ||
653 | le16_to_cpu(flt->version), le16_to_cpu(flt->length), | ||
654 | chksum)); | ||
655 | goto no_flash_data; | ||
656 | } | ||
657 | |||
658 | loc = locations[1]; | ||
659 | cnt = le16_to_cpu(flt->length) / sizeof(struct qla_flt_region); | ||
660 | for ( ; cnt; cnt--, region++) { | ||
661 | /* Store addresses as DWORD offsets. */ | ||
662 | start = le32_to_cpu(region->start) >> 2; | ||
663 | |||
664 | DEBUG3(qla_printk(KERN_DEBUG, ha, "FLT[%02x]: start=0x%x " | ||
665 | "end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start, | ||
666 | le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size))); | ||
667 | |||
668 | switch (le32_to_cpu(region->code)) { | ||
669 | case FLT_REG_FW: | ||
670 | ha->flt_region_fw = start; | ||
671 | break; | ||
672 | case FLT_REG_BOOT_CODE: | ||
673 | ha->flt_region_boot = start; | ||
674 | break; | ||
675 | case FLT_REG_VPD_0: | ||
676 | ha->flt_region_vpd_nvram = start; | ||
677 | break; | ||
678 | case FLT_REG_FDT: | ||
679 | ha->flt_region_fdt = start; | ||
680 | break; | ||
681 | case FLT_REG_HW_EVENT_0: | ||
682 | if (!PCI_FUNC(ha->pdev->devfn)) | ||
683 | ha->flt_region_hw_event = start; | ||
684 | break; | ||
685 | case FLT_REG_HW_EVENT_1: | ||
686 | if (PCI_FUNC(ha->pdev->devfn)) | ||
687 | ha->flt_region_hw_event = start; | ||
688 | break; | ||
689 | case FLT_REG_NPIV_CONF_0: | ||
690 | if (!PCI_FUNC(ha->pdev->devfn)) | ||
691 | ha->flt_region_npiv_conf = start; | ||
692 | break; | ||
693 | case FLT_REG_NPIV_CONF_1: | ||
694 | if (PCI_FUNC(ha->pdev->devfn)) | ||
695 | ha->flt_region_npiv_conf = start; | ||
696 | break; | ||
697 | } | ||
698 | } | ||
699 | goto done; | ||
700 | |||
701 | no_flash_data: | ||
702 | /* Use hardcoded defaults. */ | ||
703 | loc = locations[0]; | ||
704 | ha->flt_region_fw = FA_RISC_CODE_ADDR; | ||
705 | ha->flt_region_boot = FA_BOOT_CODE_ADDR; | ||
706 | ha->flt_region_vpd_nvram = FA_VPD_NVRAM_ADDR; | ||
707 | ha->flt_region_fdt = IS_QLA24XX_TYPE(ha) ? FA_FLASH_DESCR_ADDR_24: | ||
708 | FA_FLASH_DESCR_ADDR; | ||
709 | ha->flt_region_hw_event = !PCI_FUNC(ha->pdev->devfn) ? | ||
710 | FA_HW_EVENT0_ADDR: FA_HW_EVENT1_ADDR; | ||
711 | ha->flt_region_npiv_conf = !PCI_FUNC(ha->pdev->devfn) ? | ||
712 | (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF0_ADDR_24: FA_NPIV_CONF0_ADDR): | ||
713 | (IS_QLA24XX_TYPE(ha) ? FA_NPIV_CONF1_ADDR_24: FA_NPIV_CONF1_ADDR); | ||
714 | done: | ||
715 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x " | ||
716 | "vpd_nvram=0x%x fdt=0x%x flt=0x%x hwe=0x%x npiv=0x%x.\n", loc, | ||
717 | ha->flt_region_boot, ha->flt_region_fw, ha->flt_region_vpd_nvram, | ||
718 | ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_hw_event, | ||
719 | ha->flt_region_npiv_conf)); | ||
720 | } | ||
721 | |||
722 | static void | ||
723 | qla2xxx_get_fdt_info(scsi_qla_host_t *ha) | ||
548 | { | 724 | { |
549 | #define FLASH_BLK_SIZE_32K 0x8000 | 725 | #define FLASH_BLK_SIZE_32K 0x8000 |
550 | #define FLASH_BLK_SIZE_64K 0x10000 | 726 | #define FLASH_BLK_SIZE_64K 0x10000 |
727 | const char *loc, *locations[] = { "MID", "FDT" }; | ||
551 | uint16_t cnt, chksum; | 728 | uint16_t cnt, chksum; |
552 | uint16_t *wptr; | 729 | uint16_t *wptr; |
553 | struct qla_fdt_layout *fdt; | 730 | struct qla_fdt_layout *fdt; |
554 | uint8_t man_id, flash_id; | 731 | uint8_t man_id, flash_id; |
555 | 732 | uint16_t mid, fid; | |
556 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) | ||
557 | return; | ||
558 | 733 | ||
559 | wptr = (uint16_t *)ha->request_ring; | 734 | wptr = (uint16_t *)ha->request_ring; |
560 | fdt = (struct qla_fdt_layout *)ha->request_ring; | 735 | fdt = (struct qla_fdt_layout *)ha->request_ring; |
561 | ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring, | 736 | ha->isp_ops->read_optrom(ha, (uint8_t *)ha->request_ring, |
562 | FA_FLASH_DESCR_ADDR << 2, OPTROM_BURST_SIZE); | 737 | ha->flt_region_fdt << 2, OPTROM_BURST_SIZE); |
563 | if (*wptr == __constant_cpu_to_le16(0xffff)) | 738 | if (*wptr == __constant_cpu_to_le16(0xffff)) |
564 | goto no_flash_data; | 739 | goto no_flash_data; |
565 | if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || | 740 | if (fdt->sig[0] != 'Q' || fdt->sig[1] != 'L' || fdt->sig[2] != 'I' || |
@@ -577,7 +752,10 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha) | |||
577 | goto no_flash_data; | 752 | goto no_flash_data; |
578 | } | 753 | } |
579 | 754 | ||
580 | ha->fdt_odd_index = le16_to_cpu(fdt->man_id) == 0x1f; | 755 | loc = locations[1]; |
756 | mid = le16_to_cpu(fdt->man_id); | ||
757 | fid = le16_to_cpu(fdt->id); | ||
758 | ha->fdt_odd_index = mid == 0x1f; | ||
581 | ha->fdt_wrt_disable = fdt->wrt_disable_bits; | 759 | ha->fdt_wrt_disable = fdt->wrt_disable_bits; |
582 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd); | 760 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x0300 | fdt->erase_cmd); |
583 | ha->fdt_block_size = le32_to_cpu(fdt->block_size); | 761 | ha->fdt_block_size = le32_to_cpu(fdt->block_size); |
@@ -588,16 +766,12 @@ qla2xxx_get_flash_info(scsi_qla_host_t *ha) | |||
588 | flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd): | 766 | flash_conf_to_access_addr(0x0300 | fdt->protect_sec_cmd): |
589 | flash_conf_to_access_addr(0x0336); | 767 | flash_conf_to_access_addr(0x0336); |
590 | } | 768 | } |
591 | 769 | goto done; | |
592 | DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[FDT]: (0x%x/0x%x) erase=0x%x " | ||
593 | "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", | ||
594 | le16_to_cpu(fdt->man_id), le16_to_cpu(fdt->id), ha->fdt_erase_cmd, | ||
595 | ha->fdt_protect_sec_cmd, ha->fdt_unprotect_sec_cmd, | ||
596 | ha->fdt_odd_index, ha->fdt_wrt_disable, ha->fdt_block_size)); | ||
597 | return; | ||
598 | |||
599 | no_flash_data: | 770 | no_flash_data: |
771 | loc = locations[0]; | ||
600 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); | 772 | qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); |
773 | mid = man_id; | ||
774 | fid = flash_id; | ||
601 | ha->fdt_wrt_disable = 0x9c; | 775 | ha->fdt_wrt_disable = 0x9c; |
602 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8); | 776 | ha->fdt_erase_cmd = flash_conf_to_access_addr(0x03d8); |
603 | switch (man_id) { | 777 | switch (man_id) { |
@@ -625,14 +799,117 @@ no_flash_data: | |||
625 | ha->fdt_block_size = FLASH_BLK_SIZE_64K; | 799 | ha->fdt_block_size = FLASH_BLK_SIZE_64K; |
626 | break; | 800 | break; |
627 | } | 801 | } |
628 | 802 | done: | |
629 | DEBUG2(qla_printk(KERN_DEBUG, ha, "Flash[MID]: (0x%x/0x%x) erase=0x%x " | 803 | DEBUG2(qla_printk(KERN_DEBUG, ha, "FDT[%s]: (0x%x/0x%x) erase=0x%x " |
630 | "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", man_id, flash_id, | 804 | "pro=%x upro=%x idx=%d wrtd=0x%x blk=0x%x.\n", loc, mid, fid, |
631 | ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd, | 805 | ha->fdt_erase_cmd, ha->fdt_protect_sec_cmd, |
632 | ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable, | 806 | ha->fdt_unprotect_sec_cmd, ha->fdt_odd_index, ha->fdt_wrt_disable, |
633 | ha->fdt_block_size)); | 807 | ha->fdt_block_size)); |
634 | } | 808 | } |
635 | 809 | ||
810 | int | ||
811 | qla2xxx_get_flash_info(scsi_qla_host_t *ha) | ||
812 | { | ||
813 | int ret; | ||
814 | uint32_t flt_addr; | ||
815 | |||
816 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) | ||
817 | return QLA_SUCCESS; | ||
818 | |||
819 | ret = qla2xxx_find_flt_start(ha, &flt_addr); | ||
820 | if (ret != QLA_SUCCESS) | ||
821 | return ret; | ||
822 | |||
823 | qla2xxx_get_flt_info(ha, flt_addr); | ||
824 | qla2xxx_get_fdt_info(ha); | ||
825 | |||
826 | return QLA_SUCCESS; | ||
827 | } | ||
828 | |||
829 | void | ||
830 | qla2xxx_flash_npiv_conf(scsi_qla_host_t *ha) | ||
831 | { | ||
832 | #define NPIV_CONFIG_SIZE (16*1024) | ||
833 | void *data; | ||
834 | uint16_t *wptr; | ||
835 | uint16_t cnt, chksum; | ||
836 | struct qla_npiv_header hdr; | ||
837 | struct qla_npiv_entry *entry; | ||
838 | |||
839 | if (!IS_QLA24XX_TYPE(ha) && !IS_QLA25XX(ha)) | ||
840 | return; | ||
841 | |||
842 | ha->isp_ops->read_optrom(ha, (uint8_t *)&hdr, | ||
843 | ha->flt_region_npiv_conf << 2, sizeof(struct qla_npiv_header)); | ||
844 | if (hdr.version == __constant_cpu_to_le16(0xffff)) | ||
845 | return; | ||
846 | if (hdr.version != __constant_cpu_to_le16(1)) { | ||
847 | DEBUG2(qla_printk(KERN_INFO, ha, "Unsupported NPIV-Config " | ||
848 | "detected: version=0x%x entries=0x%x checksum=0x%x.\n", | ||
849 | le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries), | ||
850 | le16_to_cpu(hdr.checksum))); | ||
851 | return; | ||
852 | } | ||
853 | |||
854 | data = kmalloc(NPIV_CONFIG_SIZE, GFP_KERNEL); | ||
855 | if (!data) { | ||
856 | DEBUG2(qla_printk(KERN_INFO, ha, "NPIV-Config: Unable to " | ||
857 | "allocate memory.\n")); | ||
858 | return; | ||
859 | } | ||
860 | |||
861 | ha->isp_ops->read_optrom(ha, (uint8_t *)data, | ||
862 | ha->flt_region_npiv_conf << 2, NPIV_CONFIG_SIZE); | ||
863 | |||
864 | cnt = (sizeof(struct qla_npiv_header) + le16_to_cpu(hdr.entries) * | ||
865 | sizeof(struct qla_npiv_entry)) >> 1; | ||
866 | for (wptr = data, chksum = 0; cnt; cnt--) | ||
867 | chksum += le16_to_cpu(*wptr++); | ||
868 | if (chksum) { | ||
869 | DEBUG2(qla_printk(KERN_INFO, ha, "Inconsistent NPIV-Config " | ||
870 | "detected: version=0x%x entries=0x%x checksum=0x%x.\n", | ||
871 | le16_to_cpu(hdr.version), le16_to_cpu(hdr.entries), | ||
872 | chksum)); | ||
873 | goto done; | ||
874 | } | ||
875 | |||
876 | entry = data + sizeof(struct qla_npiv_header); | ||
877 | cnt = le16_to_cpu(hdr.entries); | ||
878 | for ( ; cnt; cnt--, entry++) { | ||
879 | uint16_t flags; | ||
880 | struct fc_vport_identifiers vid; | ||
881 | struct fc_vport *vport; | ||
882 | |||
883 | flags = le16_to_cpu(entry->flags); | ||
884 | if (flags == 0xffff) | ||
885 | continue; | ||
886 | if ((flags & BIT_0) == 0) | ||
887 | continue; | ||
888 | |||
889 | memset(&vid, 0, sizeof(vid)); | ||
890 | vid.roles = FC_PORT_ROLE_FCP_INITIATOR; | ||
891 | vid.vport_type = FC_PORTTYPE_NPIV; | ||
892 | vid.disable = false; | ||
893 | vid.port_name = wwn_to_u64(entry->port_name); | ||
894 | vid.node_name = wwn_to_u64(entry->node_name); | ||
895 | |||
896 | DEBUG2(qla_printk(KERN_DEBUG, ha, "NPIV[%02x]: wwpn=%llx " | ||
897 | "wwnn=%llx vf_id=0x%x qos=0x%x.\n", cnt, | ||
898 | (unsigned long long)vid.port_name, | ||
899 | (unsigned long long)vid.node_name, | ||
900 | le16_to_cpu(entry->vf_id), le16_to_cpu(entry->qos))); | ||
901 | |||
902 | vport = fc_vport_create(ha->host, 0, &vid); | ||
903 | if (!vport) | ||
904 | qla_printk(KERN_INFO, ha, "NPIV-Config: Failed to " | ||
905 | "create vport [%02x]: wwpn=%llx wwnn=%llx.\n", cnt, | ||
906 | (unsigned long long)vid.port_name, | ||
907 | (unsigned long long)vid.node_name); | ||
908 | } | ||
909 | done: | ||
910 | kfree(data); | ||
911 | } | ||
912 | |||
636 | static void | 913 | static void |
637 | qla24xx_unprotect_flash(scsi_qla_host_t *ha) | 914 | qla24xx_unprotect_flash(scsi_qla_host_t *ha) |
638 | { | 915 | { |
@@ -920,7 +1197,8 @@ qla25xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
920 | dwptr = (uint32_t *)buf; | 1197 | dwptr = (uint32_t *)buf; |
921 | for (i = 0; i < bytes >> 2; i++, naddr++) | 1198 | for (i = 0; i < bytes >> 2; i++, naddr++) |
922 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, | 1199 | dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha, |
923 | flash_data_to_access_addr(FA_VPD_NVRAM_ADDR | naddr))); | 1200 | flash_data_to_access_addr(ha->flt_region_vpd_nvram | |
1201 | naddr))); | ||
924 | 1202 | ||
925 | return buf; | 1203 | return buf; |
926 | } | 1204 | } |
@@ -935,10 +1213,10 @@ qla25xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr, | |||
935 | dbuf = vmalloc(RMW_BUFFER_SIZE); | 1213 | dbuf = vmalloc(RMW_BUFFER_SIZE); |
936 | if (!dbuf) | 1214 | if (!dbuf) |
937 | return QLA_MEMORY_ALLOC_FAILED; | 1215 | return QLA_MEMORY_ALLOC_FAILED; |
938 | ha->isp_ops->read_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, | 1216 | ha->isp_ops->read_optrom(ha, dbuf, ha->flt_region_vpd_nvram << 2, |
939 | RMW_BUFFER_SIZE); | 1217 | RMW_BUFFER_SIZE); |
940 | memcpy(dbuf + (naddr << 2), buf, bytes); | 1218 | memcpy(dbuf + (naddr << 2), buf, bytes); |
941 | ha->isp_ops->write_optrom(ha, dbuf, FA_VPD_NVRAM_ADDR << 2, | 1219 | ha->isp_ops->write_optrom(ha, dbuf, ha->flt_region_vpd_nvram << 2, |
942 | RMW_BUFFER_SIZE); | 1220 | RMW_BUFFER_SIZE); |
943 | vfree(dbuf); | 1221 | vfree(dbuf); |
944 | 1222 | ||
@@ -2166,7 +2444,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2166 | memset(dbyte, 0, 8); | 2444 | memset(dbyte, 0, 8); |
2167 | dcode = (uint16_t *)dbyte; | 2445 | dcode = (uint16_t *)dbyte; |
2168 | 2446 | ||
2169 | qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10, | 2447 | qla2x00_read_flash_data(ha, dbyte, ha->flt_region_fw * 4 + 10, |
2170 | 8); | 2448 | 8); |
2171 | DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", | 2449 | DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", |
2172 | __func__, ha->host_no)); | 2450 | __func__, ha->host_no)); |
@@ -2177,7 +2455,7 @@ qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2177 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | 2455 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && |
2178 | dcode[3] == 0)) { | 2456 | dcode[3] == 0)) { |
2179 | DEBUG2(printk("%s(): Unrecognized fw revision at " | 2457 | DEBUG2(printk("%s(): Unrecognized fw revision at " |
2180 | "%x.\n", __func__, FA_RISC_CODE_ADDR * 4)); | 2458 | "%x.\n", __func__, ha->flt_region_fw * 4)); |
2181 | } else { | 2459 | } else { |
2182 | /* values are in big endian */ | 2460 | /* values are in big endian */ |
2183 | ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; | 2461 | ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; |
@@ -2212,7 +2490,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2212 | dcode = mbuf; | 2490 | dcode = mbuf; |
2213 | 2491 | ||
2214 | /* Begin with first PCI expansion ROM header. */ | 2492 | /* Begin with first PCI expansion ROM header. */ |
2215 | pcihdr = 0; | 2493 | pcihdr = ha->flt_region_boot; |
2216 | last_image = 1; | 2494 | last_image = 1; |
2217 | do { | 2495 | do { |
2218 | /* Verify PCI expansion ROM header. */ | 2496 | /* Verify PCI expansion ROM header. */ |
@@ -2282,7 +2560,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2282 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); | 2560 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); |
2283 | dcode = mbuf; | 2561 | dcode = mbuf; |
2284 | 2562 | ||
2285 | qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4); | 2563 | qla24xx_read_flash_data(ha, dcode, ha->flt_region_fw + 4, 4); |
2286 | for (i = 0; i < 4; i++) | 2564 | for (i = 0; i < 4; i++) |
2287 | dcode[i] = be32_to_cpu(dcode[i]); | 2565 | dcode[i] = be32_to_cpu(dcode[i]); |
2288 | 2566 | ||
@@ -2291,7 +2569,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | |||
2291 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | 2569 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && |
2292 | dcode[3] == 0)) { | 2570 | dcode[3] == 0)) { |
2293 | DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", | 2571 | DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", |
2294 | __func__, FA_RISC_CODE_ADDR)); | 2572 | __func__, ha->flt_region_fw)); |
2295 | } else { | 2573 | } else { |
2296 | ha->fw_revision[0] = dcode[0]; | 2574 | ha->fw_revision[0] = dcode[0]; |
2297 | ha->fw_revision[1] = dcode[1]; | 2575 | ha->fw_revision[1] = dcode[1]; |
@@ -2355,7 +2633,7 @@ qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata) | |||
2355 | /* Locate first empty entry. */ | 2633 | /* Locate first empty entry. */ |
2356 | for (;;) { | 2634 | for (;;) { |
2357 | if (ha->hw_event_ptr >= | 2635 | if (ha->hw_event_ptr >= |
2358 | ha->hw_event_start + FA_HW_EVENT_SIZE) { | 2636 | ha->flt_region_hw_event + FA_HW_EVENT_SIZE) { |
2359 | DEBUG2(qla_printk(KERN_WARNING, ha, | 2637 | DEBUG2(qla_printk(KERN_WARNING, ha, |
2360 | "HW event -- Log Full!\n")); | 2638 | "HW event -- Log Full!\n")); |
2361 | return QLA_MEMORY_ALLOC_FAILED; | 2639 | return QLA_MEMORY_ALLOC_FAILED; |
@@ -2391,7 +2669,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, | |||
2391 | int rval; | 2669 | int rval; |
2392 | uint32_t marker[2], fdata[4]; | 2670 | uint32_t marker[2], fdata[4]; |
2393 | 2671 | ||
2394 | if (ha->hw_event_start == 0) | 2672 | if (ha->flt_region_hw_event == 0) |
2395 | return QLA_FUNCTION_FAILED; | 2673 | return QLA_FUNCTION_FAILED; |
2396 | 2674 | ||
2397 | DEBUG2(qla_printk(KERN_WARNING, ha, | 2675 | DEBUG2(qla_printk(KERN_WARNING, ha, |
@@ -2406,7 +2684,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, | |||
2406 | QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER); | 2684 | QLA_DRIVER_PATCH_VER, QLA_DRIVER_BETA_VER); |
2407 | 2685 | ||
2408 | /* Locate marker. */ | 2686 | /* Locate marker. */ |
2409 | ha->hw_event_ptr = ha->hw_event_start; | 2687 | ha->hw_event_ptr = ha->flt_region_hw_event; |
2410 | for (;;) { | 2688 | for (;;) { |
2411 | qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr, | 2689 | qla24xx_read_flash_data(ha, fdata, ha->hw_event_ptr, |
2412 | 4); | 2690 | 4); |
@@ -2415,7 +2693,7 @@ qla2xxx_hw_event_log(scsi_qla_host_t *ha, uint16_t code, uint16_t d1, | |||
2415 | break; | 2693 | break; |
2416 | ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE; | 2694 | ha->hw_event_ptr += FA_HW_EVENT_ENTRY_SIZE; |
2417 | if (ha->hw_event_ptr >= | 2695 | if (ha->hw_event_ptr >= |
2418 | ha->hw_event_start + FA_HW_EVENT_SIZE) { | 2696 | ha->flt_region_hw_event + FA_HW_EVENT_SIZE) { |
2419 | DEBUG2(qla_printk(KERN_WARNING, ha, | 2697 | DEBUG2(qla_printk(KERN_WARNING, ha, |
2420 | "HW event -- Log Full!\n")); | 2698 | "HW event -- Log Full!\n")); |
2421 | return QLA_MEMORY_ALLOC_FAILED; | 2699 | return QLA_MEMORY_ALLOC_FAILED; |
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 4160e4caa7b9..be5e299df528 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
@@ -7,7 +7,7 @@ | |||
7 | /* | 7 | /* |
8 | * Driver version | 8 | * Driver version |
9 | */ | 9 | */ |
10 | #define QLA2XXX_VERSION "8.02.01-k7" | 10 | #define QLA2XXX_VERSION "8.02.01-k8" |
11 | 11 | ||
12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
13 | #define QLA_DRIVER_MINOR_VER 2 | 13 | #define QLA_DRIVER_MINOR_VER 2 |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index dbeb86cafc0d..2ac3cb2b9081 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -668,13 +668,14 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) | |||
668 | goto out; | 668 | goto out; |
669 | } | 669 | } |
670 | 670 | ||
671 | /* Check to see if the scsi lld put this device into state SDEV_BLOCK. */ | 671 | /* Check to see if the scsi lld made this device blocked. */ |
672 | if (unlikely(cmd->device->sdev_state == SDEV_BLOCK)) { | 672 | if (unlikely(scsi_device_blocked(cmd->device))) { |
673 | /* | 673 | /* |
674 | * in SDEV_BLOCK, the command is just put back on the device | 674 | * in blocked state, the command is just put back on |
675 | * queue. The suspend state has already blocked the queue so | 675 | * the device queue. The suspend state has already |
676 | * future requests should not occur until the device | 676 | * blocked the queue so future requests should not |
677 | * transitions out of the suspend state. | 677 | * occur until the device transitions out of the |
678 | * suspend state. | ||
678 | */ | 679 | */ |
679 | 680 | ||
680 | scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); | 681 | scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index e7686500e9dd..98ee55ced592 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -1250,6 +1250,7 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) | |||
1250 | break; | 1250 | break; |
1251 | case SDEV_QUIESCE: | 1251 | case SDEV_QUIESCE: |
1252 | case SDEV_BLOCK: | 1252 | case SDEV_BLOCK: |
1253 | case SDEV_CREATED_BLOCK: | ||
1253 | /* | 1254 | /* |
1254 | * If the devices is blocked we defer normal commands. | 1255 | * If the devices is blocked we defer normal commands. |
1255 | */ | 1256 | */ |
@@ -2073,10 +2074,13 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) | |||
2073 | 2074 | ||
2074 | switch (state) { | 2075 | switch (state) { |
2075 | case SDEV_CREATED: | 2076 | case SDEV_CREATED: |
2076 | /* There are no legal states that come back to | 2077 | switch (oldstate) { |
2077 | * created. This is the manually initialised start | 2078 | case SDEV_CREATED_BLOCK: |
2078 | * state */ | 2079 | break; |
2079 | goto illegal; | 2080 | default: |
2081 | goto illegal; | ||
2082 | } | ||
2083 | break; | ||
2080 | 2084 | ||
2081 | case SDEV_RUNNING: | 2085 | case SDEV_RUNNING: |
2082 | switch (oldstate) { | 2086 | switch (oldstate) { |
@@ -2114,8 +2118,17 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) | |||
2114 | 2118 | ||
2115 | case SDEV_BLOCK: | 2119 | case SDEV_BLOCK: |
2116 | switch (oldstate) { | 2120 | switch (oldstate) { |
2117 | case SDEV_CREATED: | ||
2118 | case SDEV_RUNNING: | 2121 | case SDEV_RUNNING: |
2122 | case SDEV_CREATED_BLOCK: | ||
2123 | break; | ||
2124 | default: | ||
2125 | goto illegal; | ||
2126 | } | ||
2127 | break; | ||
2128 | |||
2129 | case SDEV_CREATED_BLOCK: | ||
2130 | switch (oldstate) { | ||
2131 | case SDEV_CREATED: | ||
2119 | break; | 2132 | break; |
2120 | default: | 2133 | default: |
2121 | goto illegal; | 2134 | goto illegal; |
@@ -2403,8 +2416,12 @@ scsi_internal_device_block(struct scsi_device *sdev) | |||
2403 | int err = 0; | 2416 | int err = 0; |
2404 | 2417 | ||
2405 | err = scsi_device_set_state(sdev, SDEV_BLOCK); | 2418 | err = scsi_device_set_state(sdev, SDEV_BLOCK); |
2406 | if (err) | 2419 | if (err) { |
2407 | return err; | 2420 | err = scsi_device_set_state(sdev, SDEV_CREATED_BLOCK); |
2421 | |||
2422 | if (err) | ||
2423 | return err; | ||
2424 | } | ||
2408 | 2425 | ||
2409 | /* | 2426 | /* |
2410 | * The device has transitioned to SDEV_BLOCK. Stop the | 2427 | * The device has transitioned to SDEV_BLOCK. Stop the |
@@ -2447,8 +2464,12 @@ scsi_internal_device_unblock(struct scsi_device *sdev) | |||
2447 | * and goose the device queue if successful. | 2464 | * and goose the device queue if successful. |
2448 | */ | 2465 | */ |
2449 | err = scsi_device_set_state(sdev, SDEV_RUNNING); | 2466 | err = scsi_device_set_state(sdev, SDEV_RUNNING); |
2450 | if (err) | 2467 | if (err) { |
2451 | return err; | 2468 | err = scsi_device_set_state(sdev, SDEV_CREATED); |
2469 | |||
2470 | if (err) | ||
2471 | return err; | ||
2472 | } | ||
2452 | 2473 | ||
2453 | spin_lock_irqsave(q->queue_lock, flags); | 2474 | spin_lock_irqsave(q->queue_lock, flags); |
2454 | blk_start_queue(q); | 2475 | blk_start_queue(q); |
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index ae7ed9a22662..b37e133de805 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/time.h> | 21 | #include <linux/time.h> |
22 | #include <linux/jiffies.h> | 22 | #include <linux/jiffies.h> |
23 | #include <linux/security.h> | 23 | #include <linux/security.h> |
24 | #include <linux/delay.h> | ||
24 | #include <net/sock.h> | 25 | #include <net/sock.h> |
25 | #include <net/netlink.h> | 26 | #include <net/netlink.h> |
26 | 27 | ||
@@ -30,6 +31,39 @@ | |||
30 | struct sock *scsi_nl_sock = NULL; | 31 | struct sock *scsi_nl_sock = NULL; |
31 | EXPORT_SYMBOL_GPL(scsi_nl_sock); | 32 | EXPORT_SYMBOL_GPL(scsi_nl_sock); |
32 | 33 | ||
34 | static DEFINE_SPINLOCK(scsi_nl_lock); | ||
35 | static struct list_head scsi_nl_drivers; | ||
36 | |||
37 | static u32 scsi_nl_state; | ||
38 | #define STATE_EHANDLER_BSY 0x00000001 | ||
39 | |||
40 | struct scsi_nl_transport { | ||
41 | int (*msg_handler)(struct sk_buff *); | ||
42 | void (*event_handler)(struct notifier_block *, unsigned long, void *); | ||
43 | unsigned int refcnt; | ||
44 | int flags; | ||
45 | }; | ||
46 | |||
47 | /* flags values (bit flags) */ | ||
48 | #define HANDLER_DELETING 0x1 | ||
49 | |||
50 | static struct scsi_nl_transport transports[SCSI_NL_MAX_TRANSPORTS] = | ||
51 | { {NULL, }, }; | ||
52 | |||
53 | |||
54 | struct scsi_nl_drvr { | ||
55 | struct list_head next; | ||
56 | int (*dmsg_handler)(struct Scsi_Host *shost, void *payload, | ||
57 | u32 len, u32 pid); | ||
58 | void (*devt_handler)(struct notifier_block *nb, | ||
59 | unsigned long event, void *notify_ptr); | ||
60 | struct scsi_host_template *hostt; | ||
61 | u64 vendor_id; | ||
62 | unsigned int refcnt; | ||
63 | int flags; | ||
64 | }; | ||
65 | |||
66 | |||
33 | 67 | ||
34 | /** | 68 | /** |
35 | * scsi_nl_rcv_msg - Receive message handler. | 69 | * scsi_nl_rcv_msg - Receive message handler. |
@@ -45,8 +79,9 @@ scsi_nl_rcv_msg(struct sk_buff *skb) | |||
45 | { | 79 | { |
46 | struct nlmsghdr *nlh; | 80 | struct nlmsghdr *nlh; |
47 | struct scsi_nl_hdr *hdr; | 81 | struct scsi_nl_hdr *hdr; |
48 | uint32_t rlen; | 82 | unsigned long flags; |
49 | int err; | 83 | u32 rlen; |
84 | int err, tport; | ||
50 | 85 | ||
51 | while (skb->len >= NLMSG_SPACE(0)) { | 86 | while (skb->len >= NLMSG_SPACE(0)) { |
52 | err = 0; | 87 | err = 0; |
@@ -65,7 +100,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb) | |||
65 | 100 | ||
66 | if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { | 101 | if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { |
67 | err = -EBADMSG; | 102 | err = -EBADMSG; |
68 | return; | 103 | goto next_msg; |
69 | } | 104 | } |
70 | 105 | ||
71 | hdr = NLMSG_DATA(nlh); | 106 | hdr = NLMSG_DATA(nlh); |
@@ -83,12 +118,27 @@ scsi_nl_rcv_msg(struct sk_buff *skb) | |||
83 | if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) { | 118 | if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) { |
84 | printk(KERN_WARNING "%s: discarding partial message\n", | 119 | printk(KERN_WARNING "%s: discarding partial message\n", |
85 | __func__); | 120 | __func__); |
86 | return; | 121 | goto next_msg; |
87 | } | 122 | } |
88 | 123 | ||
89 | /* | 124 | /* |
90 | * We currently don't support anyone sending us a message | 125 | * Deliver message to the appropriate transport |
91 | */ | 126 | */ |
127 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
128 | |||
129 | tport = hdr->transport; | ||
130 | if ((tport < SCSI_NL_MAX_TRANSPORTS) && | ||
131 | !(transports[tport].flags & HANDLER_DELETING) && | ||
132 | (transports[tport].msg_handler)) { | ||
133 | transports[tport].refcnt++; | ||
134 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
135 | err = transports[tport].msg_handler(skb); | ||
136 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
137 | transports[tport].refcnt--; | ||
138 | } else | ||
139 | err = -ENOENT; | ||
140 | |||
141 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
92 | 142 | ||
93 | next_msg: | 143 | next_msg: |
94 | if ((err) || (nlh->nlmsg_flags & NLM_F_ACK)) | 144 | if ((err) || (nlh->nlmsg_flags & NLM_F_ACK)) |
@@ -110,14 +160,42 @@ static int | |||
110 | scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr) | 160 | scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr) |
111 | { | 161 | { |
112 | struct netlink_notify *n = ptr; | 162 | struct netlink_notify *n = ptr; |
163 | struct scsi_nl_drvr *driver; | ||
164 | unsigned long flags; | ||
165 | int tport; | ||
113 | 166 | ||
114 | if (n->protocol != NETLINK_SCSITRANSPORT) | 167 | if (n->protocol != NETLINK_SCSITRANSPORT) |
115 | return NOTIFY_DONE; | 168 | return NOTIFY_DONE; |
116 | 169 | ||
170 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
171 | scsi_nl_state |= STATE_EHANDLER_BSY; | ||
172 | |||
117 | /* | 173 | /* |
118 | * Currently, we are not tracking PID's, etc. There is nothing | 174 | * Pass event on to any transports that may be listening |
119 | * to handle. | ||
120 | */ | 175 | */ |
176 | for (tport = 0; tport < SCSI_NL_MAX_TRANSPORTS; tport++) { | ||
177 | if (!(transports[tport].flags & HANDLER_DELETING) && | ||
178 | (transports[tport].event_handler)) { | ||
179 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
180 | transports[tport].event_handler(this, event, ptr); | ||
181 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * Pass event on to any drivers that may be listening | ||
187 | */ | ||
188 | list_for_each_entry(driver, &scsi_nl_drivers, next) { | ||
189 | if (!(driver->flags & HANDLER_DELETING) && | ||
190 | (driver->devt_handler)) { | ||
191 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
192 | driver->devt_handler(this, event, ptr); | ||
193 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | scsi_nl_state &= ~STATE_EHANDLER_BSY; | ||
198 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
121 | 199 | ||
122 | return NOTIFY_DONE; | 200 | return NOTIFY_DONE; |
123 | } | 201 | } |
@@ -128,7 +206,281 @@ static struct notifier_block scsi_netlink_notifier = { | |||
128 | 206 | ||
129 | 207 | ||
130 | /** | 208 | /** |
131 | * scsi_netlink_init - Called by SCSI subsystem to intialize the SCSI transport netlink interface | 209 | * GENERIC SCSI transport receive and event handlers |
210 | **/ | ||
211 | |||
212 | /** | ||
213 | * scsi_generic_msg_handler - receive message handler for GENERIC transport | ||
214 | * messages | ||
215 | * | ||
216 | * @skb: socket receive buffer | ||
217 | * | ||
218 | **/ | ||
219 | static int | ||
220 | scsi_generic_msg_handler(struct sk_buff *skb) | ||
221 | { | ||
222 | struct nlmsghdr *nlh = nlmsg_hdr(skb); | ||
223 | struct scsi_nl_hdr *snlh = NLMSG_DATA(nlh); | ||
224 | struct scsi_nl_drvr *driver; | ||
225 | struct Scsi_Host *shost; | ||
226 | unsigned long flags; | ||
227 | int err = 0, match, pid; | ||
228 | |||
229 | pid = NETLINK_CREDS(skb)->pid; | ||
230 | |||
231 | switch (snlh->msgtype) { | ||
232 | case SCSI_NL_SHOST_VENDOR: | ||
233 | { | ||
234 | struct scsi_nl_host_vendor_msg *msg = NLMSG_DATA(nlh); | ||
235 | |||
236 | /* Locate the driver that corresponds to the message */ | ||
237 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
238 | match = 0; | ||
239 | list_for_each_entry(driver, &scsi_nl_drivers, next) { | ||
240 | if (driver->vendor_id == msg->vendor_id) { | ||
241 | match = 1; | ||
242 | break; | ||
243 | } | ||
244 | } | ||
245 | |||
246 | if ((!match) || (!driver->dmsg_handler)) { | ||
247 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
248 | err = -ESRCH; | ||
249 | goto rcv_exit; | ||
250 | } | ||
251 | |||
252 | if (driver->flags & HANDLER_DELETING) { | ||
253 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
254 | err = -ESHUTDOWN; | ||
255 | goto rcv_exit; | ||
256 | } | ||
257 | |||
258 | driver->refcnt++; | ||
259 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
260 | |||
261 | |||
262 | /* if successful, scsi_host_lookup takes a shost reference */ | ||
263 | shost = scsi_host_lookup(msg->host_no); | ||
264 | if (!shost) { | ||
265 | err = -ENODEV; | ||
266 | goto driver_exit; | ||
267 | } | ||
268 | |||
269 | /* is this host owned by the vendor ? */ | ||
270 | if (shost->hostt != driver->hostt) { | ||
271 | err = -EINVAL; | ||
272 | goto vendormsg_put; | ||
273 | } | ||
274 | |||
275 | /* pass message on to the driver */ | ||
276 | err = driver->dmsg_handler(shost, (void *)&msg[1], | ||
277 | msg->vmsg_datalen, pid); | ||
278 | |||
279 | vendormsg_put: | ||
280 | /* release reference by scsi_host_lookup */ | ||
281 | scsi_host_put(shost); | ||
282 | |||
283 | driver_exit: | ||
284 | /* release our own reference on the registration object */ | ||
285 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
286 | driver->refcnt--; | ||
287 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
288 | break; | ||
289 | } | ||
290 | |||
291 | default: | ||
292 | err = -EBADR; | ||
293 | break; | ||
294 | } | ||
295 | |||
296 | rcv_exit: | ||
297 | if (err) | ||
298 | printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n", | ||
299 | __func__, snlh->msgtype, err); | ||
300 | return err; | ||
301 | } | ||
302 | |||
303 | |||
304 | /** | ||
305 | * scsi_nl_add_transport - | ||
306 | * Registers message and event handlers for a transport. Enables | ||
307 | * receipt of netlink messages and events to a transport. | ||
308 | * | ||
309 | * @tport: transport registering handlers | ||
310 | * @msg_handler: receive message handler callback | ||
311 | * @event_handler: receive event handler callback | ||
312 | **/ | ||
313 | int | ||
314 | scsi_nl_add_transport(u8 tport, | ||
315 | int (*msg_handler)(struct sk_buff *), | ||
316 | void (*event_handler)(struct notifier_block *, unsigned long, void *)) | ||
317 | { | ||
318 | unsigned long flags; | ||
319 | int err = 0; | ||
320 | |||
321 | if (tport >= SCSI_NL_MAX_TRANSPORTS) | ||
322 | return -EINVAL; | ||
323 | |||
324 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
325 | |||
326 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | ||
327 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
328 | msleep(1); | ||
329 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
330 | } | ||
331 | |||
332 | if (transports[tport].msg_handler || transports[tport].event_handler) { | ||
333 | err = -EALREADY; | ||
334 | goto register_out; | ||
335 | } | ||
336 | |||
337 | transports[tport].msg_handler = msg_handler; | ||
338 | transports[tport].event_handler = event_handler; | ||
339 | transports[tport].flags = 0; | ||
340 | transports[tport].refcnt = 0; | ||
341 | |||
342 | register_out: | ||
343 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
344 | |||
345 | return err; | ||
346 | } | ||
347 | EXPORT_SYMBOL_GPL(scsi_nl_add_transport); | ||
348 | |||
349 | |||
350 | /** | ||
351 | * scsi_nl_remove_transport - | ||
352 | * Disable transport receiption of messages and events | ||
353 | * | ||
354 | * @tport: transport deregistering handlers | ||
355 | * | ||
356 | **/ | ||
357 | void | ||
358 | scsi_nl_remove_transport(u8 tport) | ||
359 | { | ||
360 | unsigned long flags; | ||
361 | |||
362 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
363 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | ||
364 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
365 | msleep(1); | ||
366 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
367 | } | ||
368 | |||
369 | if (tport < SCSI_NL_MAX_TRANSPORTS) { | ||
370 | transports[tport].flags |= HANDLER_DELETING; | ||
371 | |||
372 | while (transports[tport].refcnt != 0) { | ||
373 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
374 | schedule_timeout_uninterruptible(HZ/4); | ||
375 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
376 | } | ||
377 | transports[tport].msg_handler = NULL; | ||
378 | transports[tport].event_handler = NULL; | ||
379 | transports[tport].flags = 0; | ||
380 | } | ||
381 | |||
382 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
383 | |||
384 | return; | ||
385 | } | ||
386 | EXPORT_SYMBOL_GPL(scsi_nl_remove_transport); | ||
387 | |||
388 | |||
389 | /** | ||
390 | * scsi_nl_add_driver - | ||
391 | * A driver is registering its interfaces for SCSI netlink messages | ||
392 | * | ||
393 | * @vendor_id: A unique identification value for the driver. | ||
394 | * @hostt: address of the driver's host template. Used | ||
395 | * to verify an shost is bound to the driver | ||
396 | * @nlmsg_handler: receive message handler callback | ||
397 | * @nlevt_handler: receive event handler callback | ||
398 | * | ||
399 | * Returns: | ||
400 | * 0 on Success | ||
401 | * error result otherwise | ||
402 | **/ | ||
403 | int | ||
404 | scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt, | ||
405 | int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload, | ||
406 | u32 len, u32 pid), | ||
407 | void (*nlevt_handler)(struct notifier_block *nb, | ||
408 | unsigned long event, void *notify_ptr)) | ||
409 | { | ||
410 | struct scsi_nl_drvr *driver; | ||
411 | unsigned long flags; | ||
412 | |||
413 | driver = kzalloc(sizeof(*driver), GFP_KERNEL); | ||
414 | if (unlikely(!driver)) { | ||
415 | printk(KERN_ERR "%s: allocation failure\n", __func__); | ||
416 | return -ENOMEM; | ||
417 | } | ||
418 | |||
419 | driver->dmsg_handler = nlmsg_handler; | ||
420 | driver->devt_handler = nlevt_handler; | ||
421 | driver->hostt = hostt; | ||
422 | driver->vendor_id = vendor_id; | ||
423 | |||
424 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
425 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | ||
426 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
427 | msleep(1); | ||
428 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
429 | } | ||
430 | list_add_tail(&driver->next, &scsi_nl_drivers); | ||
431 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | EXPORT_SYMBOL_GPL(scsi_nl_add_driver); | ||
436 | |||
437 | |||
438 | /** | ||
439 | * scsi_nl_remove_driver - | ||
440 | * An driver is unregistering with the SCSI netlink messages | ||
441 | * | ||
442 | * @vendor_id: The unique identification value for the driver. | ||
443 | **/ | ||
444 | void | ||
445 | scsi_nl_remove_driver(u64 vendor_id) | ||
446 | { | ||
447 | struct scsi_nl_drvr *driver; | ||
448 | unsigned long flags; | ||
449 | |||
450 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
451 | if (scsi_nl_state & STATE_EHANDLER_BSY) { | ||
452 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
453 | msleep(1); | ||
454 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
455 | } | ||
456 | |||
457 | list_for_each_entry(driver, &scsi_nl_drivers, next) { | ||
458 | if (driver->vendor_id == vendor_id) { | ||
459 | driver->flags |= HANDLER_DELETING; | ||
460 | while (driver->refcnt != 0) { | ||
461 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
462 | schedule_timeout_uninterruptible(HZ/4); | ||
463 | spin_lock_irqsave(&scsi_nl_lock, flags); | ||
464 | } | ||
465 | list_del(&driver->next); | ||
466 | kfree(driver); | ||
467 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
468 | return; | ||
469 | } | ||
470 | } | ||
471 | |||
472 | spin_unlock_irqrestore(&scsi_nl_lock, flags); | ||
473 | |||
474 | printk(KERN_ERR "%s: removal of driver failed - vendor_id 0x%llx\n", | ||
475 | __func__, (unsigned long long)vendor_id); | ||
476 | return; | ||
477 | } | ||
478 | EXPORT_SYMBOL_GPL(scsi_nl_remove_driver); | ||
479 | |||
480 | |||
481 | /** | ||
482 | * scsi_netlink_init - Called by SCSI subsystem to intialize | ||
483 | * the SCSI transport netlink interface | ||
132 | * | 484 | * |
133 | **/ | 485 | **/ |
134 | void | 486 | void |
@@ -136,6 +488,8 @@ scsi_netlink_init(void) | |||
136 | { | 488 | { |
137 | int error; | 489 | int error; |
138 | 490 | ||
491 | INIT_LIST_HEAD(&scsi_nl_drivers); | ||
492 | |||
139 | error = netlink_register_notifier(&scsi_netlink_notifier); | 493 | error = netlink_register_notifier(&scsi_netlink_notifier); |
140 | if (error) { | 494 | if (error) { |
141 | printk(KERN_ERR "%s: register of event handler failed - %d\n", | 495 | printk(KERN_ERR "%s: register of event handler failed - %d\n", |
@@ -150,8 +504,15 @@ scsi_netlink_init(void) | |||
150 | printk(KERN_ERR "%s: register of recieve handler failed\n", | 504 | printk(KERN_ERR "%s: register of recieve handler failed\n", |
151 | __func__); | 505 | __func__); |
152 | netlink_unregister_notifier(&scsi_netlink_notifier); | 506 | netlink_unregister_notifier(&scsi_netlink_notifier); |
507 | return; | ||
153 | } | 508 | } |
154 | 509 | ||
510 | /* Register the entry points for the generic SCSI transport */ | ||
511 | error = scsi_nl_add_transport(SCSI_NL_TRANSPORT, | ||
512 | scsi_generic_msg_handler, NULL); | ||
513 | if (error) | ||
514 | printk(KERN_ERR "%s: register of GENERIC transport handler" | ||
515 | " failed - %d\n", __func__, error); | ||
155 | return; | 516 | return; |
156 | } | 517 | } |
157 | 518 | ||
@@ -163,6 +524,8 @@ scsi_netlink_init(void) | |||
163 | void | 524 | void |
164 | scsi_netlink_exit(void) | 525 | scsi_netlink_exit(void) |
165 | { | 526 | { |
527 | scsi_nl_remove_transport(SCSI_NL_TRANSPORT); | ||
528 | |||
166 | if (scsi_nl_sock) { | 529 | if (scsi_nl_sock) { |
167 | netlink_kernel_release(scsi_nl_sock); | 530 | netlink_kernel_release(scsi_nl_sock); |
168 | netlink_unregister_notifier(&scsi_netlink_notifier); | 531 | netlink_unregister_notifier(&scsi_netlink_notifier); |
@@ -172,3 +535,147 @@ scsi_netlink_exit(void) | |||
172 | } | 535 | } |
173 | 536 | ||
174 | 537 | ||
538 | /* | ||
539 | * Exported Interfaces | ||
540 | */ | ||
541 | |||
542 | /** | ||
543 | * scsi_nl_send_transport_msg - | ||
544 | * Generic function to send a single message from a SCSI transport to | ||
545 | * a single process | ||
546 | * | ||
547 | * @pid: receiving pid | ||
548 | * @hdr: message payload | ||
549 | * | ||
550 | **/ | ||
551 | void | ||
552 | scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr) | ||
553 | { | ||
554 | struct sk_buff *skb; | ||
555 | struct nlmsghdr *nlh; | ||
556 | const char *fn; | ||
557 | char *datab; | ||
558 | u32 len, skblen; | ||
559 | int err; | ||
560 | |||
561 | if (!scsi_nl_sock) { | ||
562 | err = -ENOENT; | ||
563 | fn = "netlink socket"; | ||
564 | goto msg_fail; | ||
565 | } | ||
566 | |||
567 | len = NLMSG_SPACE(hdr->msglen); | ||
568 | skblen = NLMSG_SPACE(len); | ||
569 | |||
570 | skb = alloc_skb(skblen, GFP_KERNEL); | ||
571 | if (!skb) { | ||
572 | err = -ENOBUFS; | ||
573 | fn = "alloc_skb"; | ||
574 | goto msg_fail; | ||
575 | } | ||
576 | |||
577 | nlh = nlmsg_put(skb, pid, 0, SCSI_TRANSPORT_MSG, len - sizeof(*nlh), 0); | ||
578 | if (!nlh) { | ||
579 | err = -ENOBUFS; | ||
580 | fn = "nlmsg_put"; | ||
581 | goto msg_fail_skb; | ||
582 | } | ||
583 | datab = NLMSG_DATA(nlh); | ||
584 | memcpy(datab, hdr, hdr->msglen); | ||
585 | |||
586 | err = nlmsg_unicast(scsi_nl_sock, skb, pid); | ||
587 | if (err < 0) { | ||
588 | fn = "nlmsg_unicast"; | ||
589 | /* nlmsg_unicast already kfree_skb'd */ | ||
590 | goto msg_fail; | ||
591 | } | ||
592 | |||
593 | return; | ||
594 | |||
595 | msg_fail_skb: | ||
596 | kfree_skb(skb); | ||
597 | msg_fail: | ||
598 | printk(KERN_WARNING | ||
599 | "%s: Dropped Message : pid %d Transport %d, msgtype x%x, " | ||
600 | "msglen %d: %s : err %d\n", | ||
601 | __func__, pid, hdr->transport, hdr->msgtype, hdr->msglen, | ||
602 | fn, err); | ||
603 | return; | ||
604 | } | ||
605 | EXPORT_SYMBOL_GPL(scsi_nl_send_transport_msg); | ||
606 | |||
607 | |||
608 | /** | ||
609 | * scsi_nl_send_vendor_msg - called to send a shost vendor unique message | ||
610 | * to a specific process id. | ||
611 | * | ||
612 | * @pid: process id of the receiver | ||
613 | * @host_no: host # sending the message | ||
614 | * @vendor_id: unique identifier for the driver's vendor | ||
615 | * @data_len: amount, in bytes, of vendor unique payload data | ||
616 | * @data_buf: pointer to vendor unique data buffer | ||
617 | * | ||
618 | * Returns: | ||
619 | * 0 on succesful return | ||
620 | * otherwise, failing error code | ||
621 | * | ||
622 | * Notes: | ||
623 | * This routine assumes no locks are held on entry. | ||
624 | */ | ||
625 | int | ||
626 | scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id, | ||
627 | char *data_buf, u32 data_len) | ||
628 | { | ||
629 | struct sk_buff *skb; | ||
630 | struct nlmsghdr *nlh; | ||
631 | struct scsi_nl_host_vendor_msg *msg; | ||
632 | u32 len, skblen; | ||
633 | int err; | ||
634 | |||
635 | if (!scsi_nl_sock) { | ||
636 | err = -ENOENT; | ||
637 | goto send_vendor_fail; | ||
638 | } | ||
639 | |||
640 | len = SCSI_NL_MSGALIGN(sizeof(*msg) + data_len); | ||
641 | skblen = NLMSG_SPACE(len); | ||
642 | |||
643 | skb = alloc_skb(skblen, GFP_KERNEL); | ||
644 | if (!skb) { | ||
645 | err = -ENOBUFS; | ||
646 | goto send_vendor_fail; | ||
647 | } | ||
648 | |||
649 | nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, | ||
650 | skblen - sizeof(*nlh), 0); | ||
651 | if (!nlh) { | ||
652 | err = -ENOBUFS; | ||
653 | goto send_vendor_fail_skb; | ||
654 | } | ||
655 | msg = NLMSG_DATA(nlh); | ||
656 | |||
657 | INIT_SCSI_NL_HDR(&msg->snlh, SCSI_NL_TRANSPORT, | ||
658 | SCSI_NL_SHOST_VENDOR, len); | ||
659 | msg->vendor_id = vendor_id; | ||
660 | msg->host_no = host_no; | ||
661 | msg->vmsg_datalen = data_len; /* bytes */ | ||
662 | memcpy(&msg[1], data_buf, data_len); | ||
663 | |||
664 | err = nlmsg_unicast(scsi_nl_sock, skb, pid); | ||
665 | if (err) | ||
666 | /* nlmsg_multicast already kfree_skb'd */ | ||
667 | goto send_vendor_fail; | ||
668 | |||
669 | return 0; | ||
670 | |||
671 | send_vendor_fail_skb: | ||
672 | kfree_skb(skb); | ||
673 | send_vendor_fail: | ||
674 | printk(KERN_WARNING | ||
675 | "%s: Dropped SCSI Msg : host %d vendor_unique - err %d\n", | ||
676 | __func__, host_no, err); | ||
677 | return err; | ||
678 | } | ||
679 | EXPORT_SYMBOL(scsi_nl_send_vendor_msg); | ||
680 | |||
681 | |||
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index c6a904a45bf9..82f7b2dd08a2 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c | |||
@@ -259,8 +259,8 @@ static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) | |||
259 | int error = -ENXIO; | 259 | int error = -ENXIO; |
260 | 260 | ||
261 | shost = scsi_host_lookup(host); | 261 | shost = scsi_host_lookup(host); |
262 | if (IS_ERR(shost)) | 262 | if (!shost) |
263 | return PTR_ERR(shost); | 263 | return error; |
264 | 264 | ||
265 | if (shost->transportt->user_scan) | 265 | if (shost->transportt->user_scan) |
266 | error = shost->transportt->user_scan(shost, channel, id, lun); | 266 | error = shost->transportt->user_scan(shost, channel, id, lun); |
@@ -287,8 +287,8 @@ static int scsi_remove_single_device(uint host, uint channel, uint id, uint lun) | |||
287 | int error = -ENXIO; | 287 | int error = -ENXIO; |
288 | 288 | ||
289 | shost = scsi_host_lookup(host); | 289 | shost = scsi_host_lookup(host); |
290 | if (IS_ERR(shost)) | 290 | if (!shost) |
291 | return PTR_ERR(shost); | 291 | return error; |
292 | sdev = scsi_device_lookup(shost, channel, id, lun); | 292 | sdev = scsi_device_lookup(shost, channel, id, lun); |
293 | if (sdev) { | 293 | if (sdev) { |
294 | scsi_remove_device(sdev); | 294 | scsi_remove_device(sdev); |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 34d0de6cd511..334862e26a1b 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -730,6 +730,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
730 | static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | 730 | static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, |
731 | int *bflags, int async) | 731 | int *bflags, int async) |
732 | { | 732 | { |
733 | int ret; | ||
734 | |||
733 | /* | 735 | /* |
734 | * XXX do not save the inquiry, since it can change underneath us, | 736 | * XXX do not save the inquiry, since it can change underneath us, |
735 | * save just vendor/model/rev. | 737 | * save just vendor/model/rev. |
@@ -885,7 +887,17 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
885 | 887 | ||
886 | /* set the device running here so that slave configure | 888 | /* set the device running here so that slave configure |
887 | * may do I/O */ | 889 | * may do I/O */ |
888 | scsi_device_set_state(sdev, SDEV_RUNNING); | 890 | ret = scsi_device_set_state(sdev, SDEV_RUNNING); |
891 | if (ret) { | ||
892 | ret = scsi_device_set_state(sdev, SDEV_BLOCK); | ||
893 | |||
894 | if (ret) { | ||
895 | sdev_printk(KERN_ERR, sdev, | ||
896 | "in wrong state %s to complete scan\n", | ||
897 | scsi_device_state_name(sdev->sdev_state)); | ||
898 | return SCSI_SCAN_NO_RESPONSE; | ||
899 | } | ||
900 | } | ||
889 | 901 | ||
890 | if (*bflags & BLIST_MS_192_BYTES_FOR_3F) | 902 | if (*bflags & BLIST_MS_192_BYTES_FOR_3F) |
891 | sdev->use_192_bytes_for_3f = 1; | 903 | sdev->use_192_bytes_for_3f = 1; |
@@ -899,7 +911,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, | |||
899 | transport_configure_device(&sdev->sdev_gendev); | 911 | transport_configure_device(&sdev->sdev_gendev); |
900 | 912 | ||
901 | if (sdev->host->hostt->slave_configure) { | 913 | if (sdev->host->hostt->slave_configure) { |
902 | int ret = sdev->host->hostt->slave_configure(sdev); | 914 | ret = sdev->host->hostt->slave_configure(sdev); |
903 | if (ret) { | 915 | if (ret) { |
904 | /* | 916 | /* |
905 | * if LLDD reports slave not present, don't clutter | 917 | * if LLDD reports slave not present, don't clutter |
@@ -994,7 +1006,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, | |||
994 | */ | 1006 | */ |
995 | sdev = scsi_device_lookup_by_target(starget, lun); | 1007 | sdev = scsi_device_lookup_by_target(starget, lun); |
996 | if (sdev) { | 1008 | if (sdev) { |
997 | if (rescan || sdev->sdev_state != SDEV_CREATED) { | 1009 | if (rescan || !scsi_device_created(sdev)) { |
998 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO | 1010 | SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO |
999 | "scsi scan: device exists on %s\n", | 1011 | "scsi scan: device exists on %s\n", |
1000 | sdev->sdev_gendev.bus_id)); | 1012 | sdev->sdev_gendev.bus_id)); |
@@ -1467,7 +1479,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, | |||
1467 | kfree(lun_data); | 1479 | kfree(lun_data); |
1468 | out: | 1480 | out: |
1469 | scsi_device_put(sdev); | 1481 | scsi_device_put(sdev); |
1470 | if (sdev->sdev_state == SDEV_CREATED) | 1482 | if (scsi_device_created(sdev)) |
1471 | /* | 1483 | /* |
1472 | * the sdev we used didn't appear in the report luns scan | 1484 | * the sdev we used didn't appear in the report luns scan |
1473 | */ | 1485 | */ |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 7f618ee5ecea..93c28f30bbd7 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -34,6 +34,7 @@ static const struct { | |||
34 | { SDEV_QUIESCE, "quiesce" }, | 34 | { SDEV_QUIESCE, "quiesce" }, |
35 | { SDEV_OFFLINE, "offline" }, | 35 | { SDEV_OFFLINE, "offline" }, |
36 | { SDEV_BLOCK, "blocked" }, | 36 | { SDEV_BLOCK, "blocked" }, |
37 | { SDEV_CREATED_BLOCK, "created-blocked" }, | ||
37 | }; | 38 | }; |
38 | 39 | ||
39 | const char *scsi_device_state_name(enum scsi_device_state state) | 40 | const char *scsi_device_state_name(enum scsi_device_state state) |
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 3117bb106b5d..48ba413f7f6a 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c | |||
@@ -460,7 +460,7 @@ int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag, | |||
460 | 460 | ||
461 | /* TODO: replace with a O(1) alg */ | 461 | /* TODO: replace with a O(1) alg */ |
462 | shost = scsi_host_lookup(host_no); | 462 | shost = scsi_host_lookup(host_no); |
463 | if (IS_ERR(shost)) { | 463 | if (!shost) { |
464 | printk(KERN_ERR "Could not find host no %d\n", host_no); | 464 | printk(KERN_ERR "Could not find host no %d\n", host_no); |
465 | return -EINVAL; | 465 | return -EINVAL; |
466 | } | 466 | } |
@@ -550,7 +550,7 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result) | |||
550 | dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); | 550 | dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); |
551 | 551 | ||
552 | shost = scsi_host_lookup(host_no); | 552 | shost = scsi_host_lookup(host_no); |
553 | if (IS_ERR(shost)) { | 553 | if (!shost) { |
554 | printk(KERN_ERR "Could not find host no %d\n", host_no); | 554 | printk(KERN_ERR "Could not find host no %d\n", host_no); |
555 | return err; | 555 | return err; |
556 | } | 556 | } |
@@ -603,7 +603,7 @@ int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result) | |||
603 | dprintk("%d %d%llx\n", host_no, result, (unsigned long long)itn_id); | 603 | dprintk("%d %d%llx\n", host_no, result, (unsigned long long)itn_id); |
604 | 604 | ||
605 | shost = scsi_host_lookup(host_no); | 605 | shost = scsi_host_lookup(host_no); |
606 | if (IS_ERR(shost)) { | 606 | if (!shost) { |
607 | printk(KERN_ERR "Could not find host no %d\n", host_no); | 607 | printk(KERN_ERR "Could not find host no %d\n", host_no); |
608 | return err; | 608 | return err; |
609 | } | 609 | } |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 9168883d0dfe..d5f7653bb94b 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -40,31 +40,7 @@ | |||
40 | 40 | ||
41 | static int fc_queue_work(struct Scsi_Host *, struct work_struct *); | 41 | static int fc_queue_work(struct Scsi_Host *, struct work_struct *); |
42 | static void fc_vport_sched_delete(struct work_struct *work); | 42 | static void fc_vport_sched_delete(struct work_struct *work); |
43 | 43 | static int fc_vport_setup(struct Scsi_Host *shost, int channel, | |
44 | /* | ||
45 | * This is a temporary carrier for creating a vport. It will eventually | ||
46 | * be replaced by a real message definition for sgio or netlink. | ||
47 | * | ||
48 | * fc_vport_identifiers: This set of data contains all elements | ||
49 | * to uniquely identify and instantiate a FC virtual port. | ||
50 | * | ||
51 | * Notes: | ||
52 | * symbolic_name: The driver is to append the symbolic_name string data | ||
53 | * to the symbolic_node_name data that it generates by default. | ||
54 | * the resulting combination should then be registered with the switch. | ||
55 | * It is expected that things like Xen may stuff a VM title into | ||
56 | * this field. | ||
57 | */ | ||
58 | struct fc_vport_identifiers { | ||
59 | u64 node_name; | ||
60 | u64 port_name; | ||
61 | u32 roles; | ||
62 | bool disable; | ||
63 | enum fc_port_type vport_type; /* only FC_PORTTYPE_NPIV allowed */ | ||
64 | char symbolic_name[FC_VPORT_SYMBOLIC_NAMELEN]; | ||
65 | }; | ||
66 | |||
67 | static int fc_vport_create(struct Scsi_Host *shost, int channel, | ||
68 | struct device *pdev, struct fc_vport_identifiers *ids, | 44 | struct device *pdev, struct fc_vport_identifiers *ids, |
69 | struct fc_vport **vport); | 45 | struct fc_vport **vport); |
70 | 46 | ||
@@ -1760,7 +1736,7 @@ store_fc_host_vport_create(struct device *dev, struct device_attribute *attr, | |||
1760 | vid.disable = false; /* always enabled */ | 1736 | vid.disable = false; /* always enabled */ |
1761 | 1737 | ||
1762 | /* we only allow support on Channel 0 !!! */ | 1738 | /* we only allow support on Channel 0 !!! */ |
1763 | stat = fc_vport_create(shost, 0, &shost->shost_gendev, &vid, &vport); | 1739 | stat = fc_vport_setup(shost, 0, &shost->shost_gendev, &vid, &vport); |
1764 | return stat ? stat : count; | 1740 | return stat ? stat : count; |
1765 | } | 1741 | } |
1766 | static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL, | 1742 | static FC_DEVICE_ATTR(host, vport_create, S_IWUSR, NULL, |
@@ -3103,7 +3079,7 @@ fc_scsi_scan_rport(struct work_struct *work) | |||
3103 | 3079 | ||
3104 | 3080 | ||
3105 | /** | 3081 | /** |
3106 | * fc_vport_create - allocates and creates a FC virtual port. | 3082 | * fc_vport_setup - allocates and creates a FC virtual port. |
3107 | * @shost: scsi host the virtual port is connected to. | 3083 | * @shost: scsi host the virtual port is connected to. |
3108 | * @channel: Channel on shost port connected to. | 3084 | * @channel: Channel on shost port connected to. |
3109 | * @pdev: parent device for vport | 3085 | * @pdev: parent device for vport |
@@ -3118,7 +3094,7 @@ fc_scsi_scan_rport(struct work_struct *work) | |||
3118 | * This routine assumes no locks are held on entry. | 3094 | * This routine assumes no locks are held on entry. |
3119 | */ | 3095 | */ |
3120 | static int | 3096 | static int |
3121 | fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev, | 3097 | fc_vport_setup(struct Scsi_Host *shost, int channel, struct device *pdev, |
3122 | struct fc_vport_identifiers *ids, struct fc_vport **ret_vport) | 3098 | struct fc_vport_identifiers *ids, struct fc_vport **ret_vport) |
3123 | { | 3099 | { |
3124 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); | 3100 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); |
@@ -3231,6 +3207,28 @@ delete_vport: | |||
3231 | return error; | 3207 | return error; |
3232 | } | 3208 | } |
3233 | 3209 | ||
3210 | /** | ||
3211 | * fc_vport_create - Admin App or LLDD requests creation of a vport | ||
3212 | * @shost: scsi host the virtual port is connected to. | ||
3213 | * @channel: channel on shost port connected to. | ||
3214 | * @ids: The world wide names, FC4 port roles, etc for | ||
3215 | * the virtual port. | ||
3216 | * | ||
3217 | * Notes: | ||
3218 | * This routine assumes no locks are held on entry. | ||
3219 | */ | ||
3220 | struct fc_vport * | ||
3221 | fc_vport_create(struct Scsi_Host *shost, int channel, | ||
3222 | struct fc_vport_identifiers *ids) | ||
3223 | { | ||
3224 | int stat; | ||
3225 | struct fc_vport *vport; | ||
3226 | |||
3227 | stat = fc_vport_setup(shost, channel, &shost->shost_gendev, | ||
3228 | ids, &vport); | ||
3229 | return stat ? NULL : vport; | ||
3230 | } | ||
3231 | EXPORT_SYMBOL(fc_vport_create); | ||
3234 | 3232 | ||
3235 | /** | 3233 | /** |
3236 | * fc_vport_terminate - Admin App or LLDD requests termination of a vport | 3234 | * fc_vport_terminate - Admin App or LLDD requests termination of a vport |
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 043c3921164f..0ce5f7cdfe2a 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -1361,7 +1361,7 @@ iscsi_tgt_dscvr(struct iscsi_transport *transport, | |||
1361 | return -EINVAL; | 1361 | return -EINVAL; |
1362 | 1362 | ||
1363 | shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no); | 1363 | shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no); |
1364 | if (IS_ERR(shost)) { | 1364 | if (!shost) { |
1365 | printk(KERN_ERR "target discovery could not find host no %u\n", | 1365 | printk(KERN_ERR "target discovery could not find host no %u\n", |
1366 | ev->u.tgt_dscvr.host_no); | 1366 | ev->u.tgt_dscvr.host_no); |
1367 | return -ENODEV; | 1367 | return -ENODEV; |
@@ -1387,7 +1387,7 @@ iscsi_set_host_param(struct iscsi_transport *transport, | |||
1387 | return -ENOSYS; | 1387 | return -ENOSYS; |
1388 | 1388 | ||
1389 | shost = scsi_host_lookup(ev->u.set_host_param.host_no); | 1389 | shost = scsi_host_lookup(ev->u.set_host_param.host_no); |
1390 | if (IS_ERR(shost)) { | 1390 | if (!shost) { |
1391 | printk(KERN_ERR "set_host_param could not find host no %u\n", | 1391 | printk(KERN_ERR "set_host_param could not find host no %u\n", |
1392 | ev->u.set_host_param.host_no); | 1392 | ev->u.set_host_param.host_no); |
1393 | return -ENODEV; | 1393 | return -ENODEV; |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c0cf4acda7de..a7b53be63367 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/blkpg.h> | 47 | #include <linux/blkpg.h> |
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/mutex.h> | 49 | #include <linux/mutex.h> |
50 | #include <linux/string_helpers.h> | ||
50 | #include <asm/uaccess.h> | 51 | #include <asm/uaccess.h> |
51 | 52 | ||
52 | #include <scsi/scsi.h> | 53 | #include <scsi/scsi.h> |
@@ -1433,27 +1434,21 @@ got_data: | |||
1433 | */ | 1434 | */ |
1434 | sector_size = 512; | 1435 | sector_size = 512; |
1435 | } | 1436 | } |
1437 | blk_queue_hardsect_size(sdp->request_queue, sector_size); | ||
1438 | |||
1436 | { | 1439 | { |
1437 | /* | 1440 | char cap_str_2[10], cap_str_10[10]; |
1438 | * The msdos fs needs to know the hardware sector size | 1441 | u64 sz = sdkp->capacity << ffz(~sector_size); |
1439 | * So I have created this table. See ll_rw_blk.c | ||
1440 | * Jacques Gelinas (Jacques@solucorp.qc.ca) | ||
1441 | */ | ||
1442 | int hard_sector = sector_size; | ||
1443 | sector_t sz = (sdkp->capacity/2) * (hard_sector/256); | ||
1444 | struct request_queue *queue = sdp->request_queue; | ||
1445 | sector_t mb = sz; | ||
1446 | 1442 | ||
1447 | blk_queue_hardsect_size(queue, hard_sector); | 1443 | string_get_size(sz, STRING_UNITS_2, cap_str_2, |
1448 | /* avoid 64-bit division on 32-bit platforms */ | 1444 | sizeof(cap_str_2)); |
1449 | sector_div(sz, 625); | 1445 | string_get_size(sz, STRING_UNITS_10, cap_str_10, |
1450 | mb -= sz - 974; | 1446 | sizeof(cap_str_10)); |
1451 | sector_div(mb, 1950); | ||
1452 | 1447 | ||
1453 | sd_printk(KERN_NOTICE, sdkp, | 1448 | sd_printk(KERN_NOTICE, sdkp, |
1454 | "%llu %d-byte hardware sectors (%llu MB)\n", | 1449 | "%llu %d-byte hardware sectors: (%s/%s)\n", |
1455 | (unsigned long long)sdkp->capacity, | 1450 | (unsigned long long)sdkp->capacity, |
1456 | hard_sector, (unsigned long long)mb); | 1451 | sector_size, cap_str_10, cap_str_2); |
1457 | } | 1452 | } |
1458 | 1453 | ||
1459 | /* Rescale capacity to 512-byte units */ | 1454 | /* Rescale capacity to 512-byte units */ |
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 1723d71cbf3f..69ac6e590f1d 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c | |||
@@ -2573,8 +2573,8 @@ static struct pci_driver dc390_driver = { | |||
2573 | static int __init dc390_module_init(void) | 2573 | static int __init dc390_module_init(void) |
2574 | { | 2574 | { |
2575 | if (!disable_clustering) | 2575 | if (!disable_clustering) |
2576 | printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n" | 2576 | printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n"); |
2577 | "\twith \"disable_clustering=1\" and report to maintainers\n"); | 2577 | printk(KERN_INFO " with \"disable_clustering=1\" and report to maintainers\n"); |
2578 | 2578 | ||
2579 | if (tmscsim[0] == -1 || tmscsim[0] > 15) { | 2579 | if (tmscsim[0] == -1 || tmscsim[0] > 15) { |
2580 | tmscsim[0] = 7; | 2580 | tmscsim[0] = 7; |