[SCSI] qla2xxx: Add dev_loss_tmo_callbk/terminate_rport_io callback support.

Signed-off-by: Seokmann Ju <seokmann.ju@qlogic.com>
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

authored by

Seokmann Ju and committed by
James Bottomley
5f3a9a20 bbfb21da

+78 -25
+31
drivers/scsi/qla2xxx/qla_attr.c
··· 994 rport->dev_loss_tmo = ha->port_down_retry_count + 5; 995 } 996 997 static int 998 qla2x00_issue_lip(struct Scsi_Host *shost) 999 { ··· 1280 .show_rport_dev_loss_tmo = 1, 1281 1282 .issue_fc_host_lip = qla2x00_issue_lip, 1283 .get_fc_host_stats = qla2x00_get_fc_host_stats, 1284 1285 .vport_create = qla24xx_vport_create, ··· 1325 .show_rport_dev_loss_tmo = 1, 1326 1327 .issue_fc_host_lip = qla2x00_issue_lip, 1328 .get_fc_host_stats = qla2x00_get_fc_host_stats, 1329 }; 1330
··· 994 rport->dev_loss_tmo = ha->port_down_retry_count + 5; 995 } 996 997 + static void 998 + qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport) 999 + { 1000 + struct Scsi_Host *host = rport_to_shost(rport); 1001 + fc_port_t *fcport = *(fc_port_t **)rport->dd_data; 1002 + 1003 + qla2x00_abort_fcport_cmds(fcport); 1004 + 1005 + /* 1006 + * Transport has effectively 'deleted' the rport, clear 1007 + * all local references. 1008 + */ 1009 + spin_lock_irq(host->host_lock); 1010 + fcport->rport = NULL; 1011 + *((fc_port_t **)rport->dd_data) = NULL; 1012 + spin_unlock_irq(host->host_lock); 1013 + } 1014 + 1015 + static void 1016 + qla2x00_terminate_rport_io(struct fc_rport *rport) 1017 + { 1018 + fc_port_t *fcport = *(fc_port_t **)rport->dd_data; 1019 + 1020 + qla2x00_abort_fcport_cmds(fcport); 1021 + scsi_target_unblock(&rport->dev); 1022 + } 1023 + 1024 static int 1025 qla2x00_issue_lip(struct Scsi_Host *shost) 1026 { ··· 1253 .show_rport_dev_loss_tmo = 1, 1254 1255 .issue_fc_host_lip = qla2x00_issue_lip, 1256 + .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, 1257 + .terminate_rport_io = qla2x00_terminate_rport_io, 1258 .get_fc_host_stats = qla2x00_get_fc_host_stats, 1259 1260 .vport_create = qla24xx_vport_create, ··· 1296 .show_rport_dev_loss_tmo = 1, 1297 1298 .issue_fc_host_lip = qla2x00_issue_lip, 1299 + .dev_loss_tmo_callbk = qla2x00_dev_loss_tmo_callbk, 1300 + .terminate_rport_io = qla2x00_terminate_rport_io, 1301 .get_fc_host_stats = qla2x00_get_fc_host_stats, 1302 }; 1303
-1
drivers/scsi/qla2xxx/qla_def.h
··· 1544 int login_retry; 1545 atomic_t port_down_timer; 1546 1547 - spinlock_t rport_lock; 1548 struct fc_rport *rport, *drport; 1549 u32 supported_classes; 1550
··· 1544 int login_retry; 1545 atomic_t port_down_timer; 1546 1547 struct fc_rport *rport, *drport; 1548 u32 supported_classes; 1549
+2
drivers/scsi/qla2xxx/qla_gbl.h
··· 71 extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t, 72 uint16_t, uint16_t); 73 74 /* 75 * Global Functions in qla_mid.c source file. 76 */
··· 71 extern int qla2x00_post_hwe_work(struct scsi_qla_host *, uint16_t , uint16_t, 72 uint16_t, uint16_t); 73 74 + extern void qla2x00_abort_fcport_cmds(fc_port_t *); 75 + 76 /* 77 * Global Functions in qla_mid.c source file. 78 */
+5 -11
drivers/scsi/qla2xxx/qla_init.c
··· 1864 { 1865 fc_port_t *fcport = data; 1866 struct fc_rport *rport; 1867 - unsigned long flags; 1868 1869 - spin_lock_irqsave(&fcport->rport_lock, flags); 1870 rport = fcport->drport; 1871 fcport->drport = NULL; 1872 - spin_unlock_irqrestore(&fcport->rport_lock, flags); 1873 if (rport) 1874 fc_remote_port_delete(rport); 1875 } ··· 1897 atomic_set(&fcport->state, FCS_UNCONFIGURED); 1898 fcport->flags = FCF_RLC_SUPPORT; 1899 fcport->supported_classes = FC_COS_UNSPECIFIED; 1900 - spin_lock_init(&fcport->rport_lock); 1901 1902 return fcport; 1903 } ··· 2241 { 2242 struct fc_rport_identifiers rport_ids; 2243 struct fc_rport *rport; 2244 - unsigned long flags; 2245 2246 if (fcport->drport) 2247 qla2x00_rport_del(fcport); 2248 - if (fcport->rport) 2249 - return; 2250 2251 rport_ids.node_name = wwn_to_u64(fcport->node_name); 2252 rport_ids.port_name = wwn_to_u64(fcport->port_name); 2253 rport_ids.port_id = fcport->d_id.b.domain << 16 | 2254 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; 2255 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; 2256 - rport = fc_remote_port_add(ha->host, 0, &rport_ids); 2257 if (!rport) { 2258 qla_printk(KERN_WARNING, ha, 2259 "Unable to allocate fc remote port!\n"); 2260 return; 2261 } 2262 - spin_lock_irqsave(&fcport->rport_lock, flags); 2263 - fcport->rport = rport; 2264 *((fc_port_t **)rport->dd_data) = fcport; 2265 - spin_unlock_irqrestore(&fcport->rport_lock, flags); 2266 2267 rport->supported_classes = fcport->supported_classes; 2268
··· 1864 { 1865 fc_port_t *fcport = data; 1866 struct fc_rport *rport; 1867 1868 + spin_lock_irq(fcport->ha->host->host_lock); 1869 rport = fcport->drport; 1870 fcport->drport = NULL; 1871 + spin_unlock_irq(fcport->ha->host->host_lock); 1872 if (rport) 1873 fc_remote_port_delete(rport); 1874 } ··· 1898 atomic_set(&fcport->state, FCS_UNCONFIGURED); 1899 fcport->flags = FCF_RLC_SUPPORT; 1900 fcport->supported_classes = FC_COS_UNSPECIFIED; 1901 1902 return fcport; 1903 } ··· 2243 { 2244 struct fc_rport_identifiers rport_ids; 2245 struct fc_rport *rport; 2246 2247 if (fcport->drport) 2248 qla2x00_rport_del(fcport); 2249 2250 rport_ids.node_name = wwn_to_u64(fcport->node_name); 2251 rport_ids.port_name = wwn_to_u64(fcport->port_name); 2252 rport_ids.port_id = fcport->d_id.b.domain << 16 | 2253 fcport->d_id.b.area << 8 | fcport->d_id.b.al_pa; 2254 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; 2255 + fcport->rport = rport = fc_remote_port_add(ha->host, 0, &rport_ids); 2256 if (!rport) { 2257 qla_printk(KERN_WARNING, ha, 2258 "Unable to allocate fc remote port!\n"); 2259 return; 2260 } 2261 + spin_lock_irq(fcport->ha->host->host_lock); 2262 *((fc_port_t **)rport->dd_data) = fcport; 2263 + spin_unlock_irq(fcport->ha->host->host_lock); 2264 2265 rport->supported_classes = fcport->supported_classes; 2266
+40 -13
drivers/scsi/qla2xxx/qla_os.c
··· 388 } 389 390 /* Close window on fcport/rport state-transitioning. */ 391 - if (!*(fc_port_t **)rport->dd_data) { 392 cmd->result = DID_IMM_RETRY << 16; 393 goto qc_fail_command; 394 } ··· 455 } 456 457 /* Close window on fcport/rport state-transitioning. */ 458 - if (!*(fc_port_t **)rport->dd_data) { 459 cmd->result = DID_IMM_RETRY << 16; 460 goto qc24_fail_command; 461 } ··· 615 } 616 } 617 return (return_status); 618 } 619 620 static void ··· 1847 qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, 1848 int defer) 1849 { 1850 - unsigned long flags; 1851 struct fc_rport *rport; 1852 1853 if (!fcport->rport) ··· 1854 1855 rport = fcport->rport; 1856 if (defer) { 1857 - spin_lock_irqsave(&fcport->rport_lock, flags); 1858 fcport->drport = rport; 1859 - fcport->rport = NULL; 1860 - *(fc_port_t **)rport->dd_data = NULL; 1861 - spin_unlock_irqrestore(&fcport->rport_lock, flags); 1862 set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); 1863 - } else { 1864 - spin_lock_irqsave(&fcport->rport_lock, flags); 1865 - fcport->rport = NULL; 1866 - *(fc_port_t **)rport->dd_data = NULL; 1867 - spin_unlock_irqrestore(&fcport->rport_lock, flags); 1868 fc_remote_port_delete(rport); 1869 - } 1870 } 1871 1872 /*
··· 388 } 389 390 /* Close window on fcport/rport state-transitioning. */ 391 + if (fcport->drport) { 392 cmd->result = DID_IMM_RETRY << 16; 393 goto qc_fail_command; 394 } ··· 455 } 456 457 /* Close window on fcport/rport state-transitioning. */ 458 + if (fcport->drport) { 459 cmd->result = DID_IMM_RETRY << 16; 460 goto qc24_fail_command; 461 } ··· 615 } 616 } 617 return (return_status); 618 + } 619 + 620 + void 621 + qla2x00_abort_fcport_cmds(fc_port_t *fcport) 622 + { 623 + int cnt; 624 + unsigned long flags; 625 + srb_t *sp; 626 + scsi_qla_host_t *ha = fcport->ha; 627 + scsi_qla_host_t *pha = to_qla_parent(ha); 628 + 629 + spin_lock_irqsave(&pha->hardware_lock, flags); 630 + for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { 631 + sp = pha->outstanding_cmds[cnt]; 632 + if (!sp) 633 + continue; 634 + if (sp->fcport != fcport) 635 + continue; 636 + 637 + spin_unlock_irqrestore(&pha->hardware_lock, flags); 638 + if (ha->isp_ops->abort_command(ha, sp)) { 639 + DEBUG2(qla_printk(KERN_WARNING, ha, 640 + "Abort failed -- %lx\n", sp->cmd->serial_number)); 641 + } else { 642 + if (qla2x00_eh_wait_on_command(ha, sp->cmd) != 643 + QLA_SUCCESS) 644 + DEBUG2(qla_printk(KERN_WARNING, ha, 645 + "Abort failed while waiting -- %lx\n", 646 + sp->cmd->serial_number)); 647 + 648 + } 649 + spin_lock_irqsave(&pha->hardware_lock, flags); 650 + } 651 + spin_unlock_irqrestore(&pha->hardware_lock, flags); 652 } 653 654 static void ··· 1813 qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, 1814 int defer) 1815 { 1816 struct fc_rport *rport; 1817 1818 if (!fcport->rport) ··· 1821 1822 rport = fcport->rport; 1823 if (defer) { 1824 + spin_lock_irq(ha->host->host_lock); 1825 fcport->drport = rport; 1826 + spin_unlock_irq(ha->host->host_lock); 1827 set_bit(FCPORT_UPDATE_NEEDED, &ha->dpc_flags); 1828 + qla2xxx_wake_dpc(ha); 1829 + } else 1830 fc_remote_port_delete(rport); 1831 } 1832 1833 /*