diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/bnx2i/bnx2i_hwi.c | 5 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 116 | ||||
-rw-r--r-- | drivers/scsi/fcoe/fcoe_ctlr.c | 4 | ||||
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_attr.c | 27 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_dbg.c | 8 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_gbl.h | 1 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 3 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 14 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 2 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_mbx.c | 25 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_nx.c | 42 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_nx.h | 4 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 86 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_version.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 55 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_fw.h | 8 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 16 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_init.c | 243 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_mbx.c | 11 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 1084 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_version.h | 2 |
22 files changed, 1547 insertions, 213 deletions
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index dba72a4e6a1..1ad0b822556 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c | |||
@@ -1906,18 +1906,19 @@ static int bnx2i_queue_scsi_cmd_resp(struct iscsi_session *session, | |||
1906 | spin_lock(&session->lock); | 1906 | spin_lock(&session->lock); |
1907 | task = iscsi_itt_to_task(bnx2i_conn->cls_conn->dd_data, | 1907 | task = iscsi_itt_to_task(bnx2i_conn->cls_conn->dd_data, |
1908 | cqe->itt & ISCSI_CMD_RESPONSE_INDEX); | 1908 | cqe->itt & ISCSI_CMD_RESPONSE_INDEX); |
1909 | if (!task) { | 1909 | if (!task || !task->sc) { |
1910 | spin_unlock(&session->lock); | 1910 | spin_unlock(&session->lock); |
1911 | return -EINVAL; | 1911 | return -EINVAL; |
1912 | } | 1912 | } |
1913 | sc = task->sc; | 1913 | sc = task->sc; |
1914 | spin_unlock(&session->lock); | ||
1915 | 1914 | ||
1916 | if (!blk_rq_cpu_valid(sc->request)) | 1915 | if (!blk_rq_cpu_valid(sc->request)) |
1917 | cpu = smp_processor_id(); | 1916 | cpu = smp_processor_id(); |
1918 | else | 1917 | else |
1919 | cpu = sc->request->cpu; | 1918 | cpu = sc->request->cpu; |
1920 | 1919 | ||
1920 | spin_unlock(&session->lock); | ||
1921 | |||
1921 | p = &per_cpu(bnx2i_percpu, cpu); | 1922 | p = &per_cpu(bnx2i_percpu, cpu); |
1922 | spin_lock(&p->p_work_lock); | 1923 | spin_lock(&p->p_work_lock); |
1923 | if (unlikely(!p->iothread)) { | 1924 | if (unlikely(!p->iothread)) { |
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index cefbe44bb84..8d67467dd9c 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/sysfs.h> | 31 | #include <linux/sysfs.h> |
32 | #include <linux/ctype.h> | 32 | #include <linux/ctype.h> |
33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
34 | #include <net/dcbnl.h> | ||
35 | #include <net/dcbevent.h> | ||
34 | #include <scsi/scsi_tcq.h> | 36 | #include <scsi/scsi_tcq.h> |
35 | #include <scsi/scsicam.h> | 37 | #include <scsi/scsicam.h> |
36 | #include <scsi/scsi_transport.h> | 38 | #include <scsi/scsi_transport.h> |
@@ -101,6 +103,8 @@ static int fcoe_ddp_done(struct fc_lport *, u16); | |||
101 | static int fcoe_ddp_target(struct fc_lport *, u16, struct scatterlist *, | 103 | static int fcoe_ddp_target(struct fc_lport *, u16, struct scatterlist *, |
102 | unsigned int); | 104 | unsigned int); |
103 | static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *); | 105 | static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *); |
106 | static int fcoe_dcb_app_notification(struct notifier_block *notifier, | ||
107 | ulong event, void *ptr); | ||
104 | 108 | ||
105 | static bool fcoe_match(struct net_device *netdev); | 109 | static bool fcoe_match(struct net_device *netdev); |
106 | static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode); | 110 | static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode); |
@@ -129,6 +133,11 @@ static struct notifier_block fcoe_cpu_notifier = { | |||
129 | .notifier_call = fcoe_cpu_callback, | 133 | .notifier_call = fcoe_cpu_callback, |
130 | }; | 134 | }; |
131 | 135 | ||
136 | /* notification function for DCB events */ | ||
137 | static struct notifier_block dcb_notifier = { | ||
138 | .notifier_call = fcoe_dcb_app_notification, | ||
139 | }; | ||
140 | |||
132 | static struct scsi_transport_template *fcoe_nport_scsi_transport; | 141 | static struct scsi_transport_template *fcoe_nport_scsi_transport; |
133 | static struct scsi_transport_template *fcoe_vport_scsi_transport; | 142 | static struct scsi_transport_template *fcoe_vport_scsi_transport; |
134 | 143 | ||
@@ -1522,6 +1531,8 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) | |||
1522 | skb_reset_network_header(skb); | 1531 | skb_reset_network_header(skb); |
1523 | skb->mac_len = elen; | 1532 | skb->mac_len = elen; |
1524 | skb->protocol = htons(ETH_P_FCOE); | 1533 | skb->protocol = htons(ETH_P_FCOE); |
1534 | skb->priority = port->priority; | ||
1535 | |||
1525 | if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN && | 1536 | if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN && |
1526 | fcoe->realdev->features & NETIF_F_HW_VLAN_TX) { | 1537 | fcoe->realdev->features & NETIF_F_HW_VLAN_TX) { |
1527 | skb->vlan_tci = VLAN_TAG_PRESENT | | 1538 | skb->vlan_tci = VLAN_TAG_PRESENT | |
@@ -1624,6 +1635,7 @@ static inline int fcoe_filter_frames(struct fc_lport *lport, | |||
1624 | stats->InvalidCRCCount++; | 1635 | stats->InvalidCRCCount++; |
1625 | if (stats->InvalidCRCCount < 5) | 1636 | if (stats->InvalidCRCCount < 5) |
1626 | printk(KERN_WARNING "fcoe: dropping frame with CRC error\n"); | 1637 | printk(KERN_WARNING "fcoe: dropping frame with CRC error\n"); |
1638 | put_cpu(); | ||
1627 | return -EINVAL; | 1639 | return -EINVAL; |
1628 | } | 1640 | } |
1629 | 1641 | ||
@@ -1746,6 +1758,7 @@ int fcoe_percpu_receive_thread(void *arg) | |||
1746 | */ | 1758 | */ |
1747 | static void fcoe_dev_setup(void) | 1759 | static void fcoe_dev_setup(void) |
1748 | { | 1760 | { |
1761 | register_dcbevent_notifier(&dcb_notifier); | ||
1749 | register_netdevice_notifier(&fcoe_notifier); | 1762 | register_netdevice_notifier(&fcoe_notifier); |
1750 | } | 1763 | } |
1751 | 1764 | ||
@@ -1754,9 +1767,69 @@ static void fcoe_dev_setup(void) | |||
1754 | */ | 1767 | */ |
1755 | static void fcoe_dev_cleanup(void) | 1768 | static void fcoe_dev_cleanup(void) |
1756 | { | 1769 | { |
1770 | unregister_dcbevent_notifier(&dcb_notifier); | ||
1757 | unregister_netdevice_notifier(&fcoe_notifier); | 1771 | unregister_netdevice_notifier(&fcoe_notifier); |
1758 | } | 1772 | } |
1759 | 1773 | ||
1774 | static struct fcoe_interface * | ||
1775 | fcoe_hostlist_lookup_realdev_port(struct net_device *netdev) | ||
1776 | { | ||
1777 | struct fcoe_interface *fcoe; | ||
1778 | struct net_device *real_dev; | ||
1779 | |||
1780 | list_for_each_entry(fcoe, &fcoe_hostlist, list) { | ||
1781 | if (fcoe->netdev->priv_flags & IFF_802_1Q_VLAN) | ||
1782 | real_dev = vlan_dev_real_dev(fcoe->netdev); | ||
1783 | else | ||
1784 | real_dev = fcoe->netdev; | ||
1785 | |||
1786 | if (netdev == real_dev) | ||
1787 | return fcoe; | ||
1788 | } | ||
1789 | return NULL; | ||
1790 | } | ||
1791 | |||
1792 | static int fcoe_dcb_app_notification(struct notifier_block *notifier, | ||
1793 | ulong event, void *ptr) | ||
1794 | { | ||
1795 | struct dcb_app_type *entry = ptr; | ||
1796 | struct fcoe_interface *fcoe; | ||
1797 | struct net_device *netdev; | ||
1798 | struct fcoe_port *port; | ||
1799 | int prio; | ||
1800 | |||
1801 | if (entry->app.selector != DCB_APP_IDTYPE_ETHTYPE) | ||
1802 | return NOTIFY_OK; | ||
1803 | |||
1804 | netdev = dev_get_by_index(&init_net, entry->ifindex); | ||
1805 | if (!netdev) | ||
1806 | return NOTIFY_OK; | ||
1807 | |||
1808 | fcoe = fcoe_hostlist_lookup_realdev_port(netdev); | ||
1809 | dev_put(netdev); | ||
1810 | if (!fcoe) | ||
1811 | return NOTIFY_OK; | ||
1812 | |||
1813 | if (entry->dcbx & DCB_CAP_DCBX_VER_CEE) | ||
1814 | prio = ffs(entry->app.priority) - 1; | ||
1815 | else | ||
1816 | prio = entry->app.priority; | ||
1817 | |||
1818 | if (prio < 0) | ||
1819 | return NOTIFY_OK; | ||
1820 | |||
1821 | if (entry->app.protocol == ETH_P_FIP || | ||
1822 | entry->app.protocol == ETH_P_FCOE) | ||
1823 | fcoe->ctlr.priority = prio; | ||
1824 | |||
1825 | if (entry->app.protocol == ETH_P_FCOE) { | ||
1826 | port = lport_priv(fcoe->ctlr.lp); | ||
1827 | port->priority = prio; | ||
1828 | } | ||
1829 | |||
1830 | return NOTIFY_OK; | ||
1831 | } | ||
1832 | |||
1760 | /** | 1833 | /** |
1761 | * fcoe_device_notification() - Handler for net device events | 1834 | * fcoe_device_notification() - Handler for net device events |
1762 | * @notifier: The context of the notification | 1835 | * @notifier: The context of the notification |
@@ -1965,6 +2038,46 @@ static bool fcoe_match(struct net_device *netdev) | |||
1965 | } | 2038 | } |
1966 | 2039 | ||
1967 | /** | 2040 | /** |
2041 | * fcoe_dcb_create() - Initialize DCB attributes and hooks | ||
2042 | * @netdev: The net_device object of the L2 link that should be queried | ||
2043 | * @port: The fcoe_port to bind FCoE APP priority with | ||
2044 | * @ | ||
2045 | */ | ||
2046 | static void fcoe_dcb_create(struct fcoe_interface *fcoe) | ||
2047 | { | ||
2048 | #ifdef CONFIG_DCB | ||
2049 | int dcbx; | ||
2050 | u8 fup, up; | ||
2051 | struct net_device *netdev = fcoe->realdev; | ||
2052 | struct fcoe_port *port = lport_priv(fcoe->ctlr.lp); | ||
2053 | struct dcb_app app = { | ||
2054 | .priority = 0, | ||
2055 | .protocol = ETH_P_FCOE | ||
2056 | }; | ||
2057 | |||
2058 | /* setup DCB priority attributes. */ | ||
2059 | if (netdev && netdev->dcbnl_ops && netdev->dcbnl_ops->getdcbx) { | ||
2060 | dcbx = netdev->dcbnl_ops->getdcbx(netdev); | ||
2061 | |||
2062 | if (dcbx & DCB_CAP_DCBX_VER_IEEE) { | ||
2063 | app.selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE; | ||
2064 | up = dcb_ieee_getapp_mask(netdev, &app); | ||
2065 | app.protocol = ETH_P_FIP; | ||
2066 | fup = dcb_ieee_getapp_mask(netdev, &app); | ||
2067 | } else { | ||
2068 | app.selector = DCB_APP_IDTYPE_ETHTYPE; | ||
2069 | up = dcb_getapp(netdev, &app); | ||
2070 | app.protocol = ETH_P_FIP; | ||
2071 | fup = dcb_getapp(netdev, &app); | ||
2072 | } | ||
2073 | |||
2074 | port->priority = ffs(up) ? ffs(up) - 1 : 0; | ||
2075 | fcoe->ctlr.priority = ffs(fup) ? ffs(fup) - 1 : port->priority; | ||
2076 | } | ||
2077 | #endif | ||
2078 | } | ||
2079 | |||
2080 | /** | ||
1968 | * fcoe_create() - Create a fcoe interface | 2081 | * fcoe_create() - Create a fcoe interface |
1969 | * @netdev : The net_device object the Ethernet interface to create on | 2082 | * @netdev : The net_device object the Ethernet interface to create on |
1970 | * @fip_mode: The FIP mode for this creation | 2083 | * @fip_mode: The FIP mode for this creation |
@@ -2007,6 +2120,9 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode) | |||
2007 | /* Make this the "master" N_Port */ | 2120 | /* Make this the "master" N_Port */ |
2008 | fcoe->ctlr.lp = lport; | 2121 | fcoe->ctlr.lp = lport; |
2009 | 2122 | ||
2123 | /* setup DCB priority attributes. */ | ||
2124 | fcoe_dcb_create(fcoe); | ||
2125 | |||
2010 | /* add to lports list */ | 2126 | /* add to lports list */ |
2011 | fcoe_hostlist_add(lport); | 2127 | fcoe_hostlist_add(lport); |
2012 | 2128 | ||
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index c74c4b8e71e..e7522dcc296 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c | |||
@@ -320,6 +320,7 @@ static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf) | |||
320 | 320 | ||
321 | skb_put(skb, sizeof(*sol)); | 321 | skb_put(skb, sizeof(*sol)); |
322 | skb->protocol = htons(ETH_P_FIP); | 322 | skb->protocol = htons(ETH_P_FIP); |
323 | skb->priority = fip->priority; | ||
323 | skb_reset_mac_header(skb); | 324 | skb_reset_mac_header(skb); |
324 | skb_reset_network_header(skb); | 325 | skb_reset_network_header(skb); |
325 | fip->send(fip, skb); | 326 | fip->send(fip, skb); |
@@ -474,6 +475,7 @@ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, | |||
474 | } | 475 | } |
475 | skb_put(skb, len); | 476 | skb_put(skb, len); |
476 | skb->protocol = htons(ETH_P_FIP); | 477 | skb->protocol = htons(ETH_P_FIP); |
478 | skb->priority = fip->priority; | ||
477 | skb_reset_mac_header(skb); | 479 | skb_reset_mac_header(skb); |
478 | skb_reset_network_header(skb); | 480 | skb_reset_network_header(skb); |
479 | fip->send(fip, skb); | 481 | fip->send(fip, skb); |
@@ -566,6 +568,7 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, | |||
566 | cap->fip.fip_dl_len = htons(dlen / FIP_BPW); | 568 | cap->fip.fip_dl_len = htons(dlen / FIP_BPW); |
567 | 569 | ||
568 | skb->protocol = htons(ETH_P_FIP); | 570 | skb->protocol = htons(ETH_P_FIP); |
571 | skb->priority = fip->priority; | ||
569 | skb_reset_mac_header(skb); | 572 | skb_reset_mac_header(skb); |
570 | skb_reset_network_header(skb); | 573 | skb_reset_network_header(skb); |
571 | return 0; | 574 | return 0; |
@@ -1911,6 +1914,7 @@ static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip, | |||
1911 | 1914 | ||
1912 | skb_put(skb, len); | 1915 | skb_put(skb, len); |
1913 | skb->protocol = htons(ETH_P_FIP); | 1916 | skb->protocol = htons(ETH_P_FIP); |
1917 | skb->priority = fip->priority; | ||
1914 | skb_reset_mac_header(skb); | 1918 | skb_reset_mac_header(skb); |
1915 | skb_reset_network_header(skb); | 1919 | skb_reset_network_header(skb); |
1916 | 1920 | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 4e041f6d808..d570573b796 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -4335,7 +4335,7 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
4335 | /* insert into event log */ | 4335 | /* insert into event log */ |
4336 | sz = offsetof(Mpi2EventNotificationReply_t, EventData) + | 4336 | sz = offsetof(Mpi2EventNotificationReply_t, EventData) + |
4337 | sizeof(Mpi2EventDataSasDeviceStatusChange_t); | 4337 | sizeof(Mpi2EventDataSasDeviceStatusChange_t); |
4338 | event_reply = kzalloc(sz, GFP_KERNEL); | 4338 | event_reply = kzalloc(sz, GFP_ATOMIC); |
4339 | if (!event_reply) { | 4339 | if (!event_reply) { |
4340 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 4340 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
4341 | ioc->name, __FILE__, __LINE__, __func__); | 4341 | ioc->name, __FILE__, __LINE__, __func__); |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index ac326c41e93..6465dae5883 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
@@ -1762,12 +1762,31 @@ qla2x00_get_host_port_state(struct Scsi_Host *shost) | |||
1762 | scsi_qla_host_t *vha = shost_priv(shost); | 1762 | scsi_qla_host_t *vha = shost_priv(shost); |
1763 | struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev); | 1763 | struct scsi_qla_host *base_vha = pci_get_drvdata(vha->hw->pdev); |
1764 | 1764 | ||
1765 | if (!base_vha->flags.online) | 1765 | if (!base_vha->flags.online) { |
1766 | fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; | 1766 | fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; |
1767 | else if (atomic_read(&base_vha->loop_state) == LOOP_TIMEOUT) | 1767 | return; |
1768 | fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; | 1768 | } |
1769 | else | 1769 | |
1770 | switch (atomic_read(&base_vha->loop_state)) { | ||
1771 | case LOOP_UPDATE: | ||
1772 | fc_host_port_state(shost) = FC_PORTSTATE_DIAGNOSTICS; | ||
1773 | break; | ||
1774 | case LOOP_DOWN: | ||
1775 | if (test_bit(LOOP_RESYNC_NEEDED, &base_vha->dpc_flags)) | ||
1776 | fc_host_port_state(shost) = FC_PORTSTATE_DIAGNOSTICS; | ||
1777 | else | ||
1778 | fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; | ||
1779 | break; | ||
1780 | case LOOP_DEAD: | ||
1781 | fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; | ||
1782 | break; | ||
1783 | case LOOP_READY: | ||
1770 | fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; | 1784 | fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; |
1785 | break; | ||
1786 | default: | ||
1787 | fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; | ||
1788 | break; | ||
1789 | } | ||
1771 | } | 1790 | } |
1772 | 1791 | ||
1773 | static int | 1792 | static int |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 9df4787715c..f3cddd5800c 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
@@ -12,17 +12,17 @@ | |||
12 | * | Level | Last Value Used | Holes | | 12 | * | Level | Last Value Used | Holes | |
13 | * ---------------------------------------------------------------------- | 13 | * ---------------------------------------------------------------------- |
14 | * | Module Init and Probe | 0x0116 | | | 14 | * | Module Init and Probe | 0x0116 | | |
15 | * | Mailbox commands | 0x1129 | | | 15 | * | Mailbox commands | 0x112b | | |
16 | * | Device Discovery | 0x2083 | | | 16 | * | Device Discovery | 0x2083 | | |
17 | * | Queue Command and IO tracing | 0x302e | 0x3008 | | 17 | * | Queue Command and IO tracing | 0x302e | 0x3008 | |
18 | * | DPC Thread | 0x401c | | | 18 | * | DPC Thread | 0x401c | | |
19 | * | Async Events | 0x5059 | | | 19 | * | Async Events | 0x5059 | | |
20 | * | Timer Routines | 0x600d | | | 20 | * | Timer Routines | 0x6010 | 0x600e,0x600f | |
21 | * | User Space Interactions | 0x709d | | | 21 | * | User Space Interactions | 0x709d | | |
22 | * | Task Management | 0x8041 | | | 22 | * | Task Management | 0x8041 | 0x800b | |
23 | * | AER/EEH | 0x900f | | | 23 | * | AER/EEH | 0x900f | | |
24 | * | Virtual Port | 0xa007 | | | 24 | * | Virtual Port | 0xa007 | | |
25 | * | ISP82XX Specific | 0xb051 | | | 25 | * | ISP82XX Specific | 0xb052 | | |
26 | * | MultiQ | 0xc00b | | | 26 | * | MultiQ | 0xc00b | | |
27 | * | Misc | 0xd00b | | | 27 | * | Misc | 0xd00b | | |
28 | * ---------------------------------------------------------------------- | 28 | * ---------------------------------------------------------------------- |
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index ce32d8135c9..c0c11afb685 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h | |||
@@ -578,6 +578,7 @@ extern int qla82xx_check_md_needed(scsi_qla_host_t *); | |||
578 | extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *); | 578 | extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *); |
579 | extern int qla82xx_mbx_beacon_ctl(scsi_qla_host_t *, int); | 579 | extern int qla82xx_mbx_beacon_ctl(scsi_qla_host_t *, int); |
580 | extern char *qdev_state(uint32_t); | 580 | extern char *qdev_state(uint32_t); |
581 | extern void qla82xx_clear_pending_mbx(scsi_qla_host_t *); | ||
581 | 582 | ||
582 | /* BSG related functions */ | 583 | /* BSG related functions */ |
583 | extern int qla24xx_bsg_request(struct fc_bsg_job *); | 584 | extern int qla24xx_bsg_request(struct fc_bsg_job *); |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index f03e915f187..54ea68cec4c 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -1509,7 +1509,8 @@ enable_82xx_npiv: | |||
1509 | &ha->fw_xcb_count, NULL, NULL, | 1509 | &ha->fw_xcb_count, NULL, NULL, |
1510 | &ha->max_npiv_vports, NULL); | 1510 | &ha->max_npiv_vports, NULL); |
1511 | 1511 | ||
1512 | if (!fw_major_version && ql2xallocfwdump) | 1512 | if (!fw_major_version && ql2xallocfwdump |
1513 | && !IS_QLA82XX(ha)) | ||
1513 | qla2x00_alloc_fw_dump(vha); | 1514 | qla2x00_alloc_fw_dump(vha); |
1514 | } | 1515 | } |
1515 | } else { | 1516 | } else { |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index dbec89622a0..a4b267e60a3 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -120,11 +120,10 @@ qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha) | |||
120 | * Returns a pointer to the continuation type 1 IOCB packet. | 120 | * Returns a pointer to the continuation type 1 IOCB packet. |
121 | */ | 121 | */ |
122 | static inline cont_a64_entry_t * | 122 | static inline cont_a64_entry_t * |
123 | qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha) | 123 | qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha, struct req_que *req) |
124 | { | 124 | { |
125 | cont_a64_entry_t *cont_pkt; | 125 | cont_a64_entry_t *cont_pkt; |
126 | 126 | ||
127 | struct req_que *req = vha->req; | ||
128 | /* Adjust ring index. */ | 127 | /* Adjust ring index. */ |
129 | req->ring_index++; | 128 | req->ring_index++; |
130 | if (req->ring_index == req->length) { | 129 | if (req->ring_index == req->length) { |
@@ -292,7 +291,7 @@ void qla2x00_build_scsi_iocbs_64(srb_t *sp, cmd_entry_t *cmd_pkt, | |||
292 | * Five DSDs are available in the Continuation | 291 | * Five DSDs are available in the Continuation |
293 | * Type 1 IOCB. | 292 | * Type 1 IOCB. |
294 | */ | 293 | */ |
295 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha); | 294 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req); |
296 | cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; | 295 | cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; |
297 | avail_dsds = 5; | 296 | avail_dsds = 5; |
298 | } | 297 | } |
@@ -684,7 +683,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, | |||
684 | * Five DSDs are available in the Continuation | 683 | * Five DSDs are available in the Continuation |
685 | * Type 1 IOCB. | 684 | * Type 1 IOCB. |
686 | */ | 685 | */ |
687 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha); | 686 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha, vha->req); |
688 | cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; | 687 | cur_dsd = (uint32_t *)cont_pkt->dseg_0_address; |
689 | avail_dsds = 5; | 688 | avail_dsds = 5; |
690 | } | 689 | } |
@@ -2070,7 +2069,8 @@ qla2x00_ct_iocb(srb_t *sp, ms_iocb_entry_t *ct_iocb) | |||
2070 | * Five DSDs are available in the Cont. | 2069 | * Five DSDs are available in the Cont. |
2071 | * Type 1 IOCB. | 2070 | * Type 1 IOCB. |
2072 | */ | 2071 | */ |
2073 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha); | 2072 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha, |
2073 | vha->hw->req_q_map[0]); | ||
2074 | cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; | 2074 | cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; |
2075 | avail_dsds = 5; | 2075 | avail_dsds = 5; |
2076 | cont_iocb_prsnt = 1; | 2076 | cont_iocb_prsnt = 1; |
@@ -2096,6 +2096,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) | |||
2096 | int index; | 2096 | int index; |
2097 | uint16_t tot_dsds; | 2097 | uint16_t tot_dsds; |
2098 | scsi_qla_host_t *vha = sp->fcport->vha; | 2098 | scsi_qla_host_t *vha = sp->fcport->vha; |
2099 | struct qla_hw_data *ha = vha->hw; | ||
2099 | struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job; | 2100 | struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job; |
2100 | int loop_iterartion = 0; | 2101 | int loop_iterartion = 0; |
2101 | int cont_iocb_prsnt = 0; | 2102 | int cont_iocb_prsnt = 0; |
@@ -2141,7 +2142,8 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) | |||
2141 | * Five DSDs are available in the Cont. | 2142 | * Five DSDs are available in the Cont. |
2142 | * Type 1 IOCB. | 2143 | * Type 1 IOCB. |
2143 | */ | 2144 | */ |
2144 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha); | 2145 | cont_pkt = qla2x00_prep_cont_type1_iocb(vha, |
2146 | ha->req_q_map[0]); | ||
2145 | cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; | 2147 | cur_dsd = (uint32_t *) cont_pkt->dseg_0_address; |
2146 | avail_dsds = 5; | 2148 | avail_dsds = 5; |
2147 | cont_iocb_prsnt = 1; | 2149 | cont_iocb_prsnt = 1; |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 2516adf1aee..7b91b290ffd 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -1741,7 +1741,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1741 | resid, scsi_bufflen(cp)); | 1741 | resid, scsi_bufflen(cp)); |
1742 | 1742 | ||
1743 | cp->result = DID_ERROR << 16 | lscsi_status; | 1743 | cp->result = DID_ERROR << 16 | lscsi_status; |
1744 | break; | 1744 | goto check_scsi_status; |
1745 | } | 1745 | } |
1746 | 1746 | ||
1747 | if (!lscsi_status && | 1747 | if (!lscsi_status && |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 3b3cec9f6ac..82a33533ed2 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -79,8 +79,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
79 | mcp->mb[0] = MBS_LINK_DOWN_ERROR; | 79 | mcp->mb[0] = MBS_LINK_DOWN_ERROR; |
80 | ql_log(ql_log_warn, base_vha, 0x1004, | 80 | ql_log(ql_log_warn, base_vha, 0x1004, |
81 | "FW hung = %d.\n", ha->flags.isp82xx_fw_hung); | 81 | "FW hung = %d.\n", ha->flags.isp82xx_fw_hung); |
82 | rval = QLA_FUNCTION_FAILED; | 82 | return QLA_FUNCTION_TIMEOUT; |
83 | goto premature_exit; | ||
84 | } | 83 | } |
85 | 84 | ||
86 | /* | 85 | /* |
@@ -163,6 +162,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
163 | HINT_MBX_INT_PENDING) { | 162 | HINT_MBX_INT_PENDING) { |
164 | spin_unlock_irqrestore(&ha->hardware_lock, | 163 | spin_unlock_irqrestore(&ha->hardware_lock, |
165 | flags); | 164 | flags); |
165 | ha->flags.mbox_busy = 0; | ||
166 | ql_dbg(ql_dbg_mbx, base_vha, 0x1010, | 166 | ql_dbg(ql_dbg_mbx, base_vha, 0x1010, |
167 | "Pending mailbox timeout, exiting.\n"); | 167 | "Pending mailbox timeout, exiting.\n"); |
168 | rval = QLA_FUNCTION_TIMEOUT; | 168 | rval = QLA_FUNCTION_TIMEOUT; |
@@ -188,6 +188,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
188 | HINT_MBX_INT_PENDING) { | 188 | HINT_MBX_INT_PENDING) { |
189 | spin_unlock_irqrestore(&ha->hardware_lock, | 189 | spin_unlock_irqrestore(&ha->hardware_lock, |
190 | flags); | 190 | flags); |
191 | ha->flags.mbox_busy = 0; | ||
191 | ql_dbg(ql_dbg_mbx, base_vha, 0x1012, | 192 | ql_dbg(ql_dbg_mbx, base_vha, 0x1012, |
192 | "Pending mailbox timeout, exiting.\n"); | 193 | "Pending mailbox timeout, exiting.\n"); |
193 | rval = QLA_FUNCTION_TIMEOUT; | 194 | rval = QLA_FUNCTION_TIMEOUT; |
@@ -302,7 +303,15 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
302 | if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && | 303 | if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && |
303 | !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && | 304 | !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && |
304 | !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { | 305 | !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { |
305 | 306 | if (IS_QLA82XX(ha)) { | |
307 | ql_dbg(ql_dbg_mbx, vha, 0x112a, | ||
308 | "disabling pause transmit on port " | ||
309 | "0 & 1.\n"); | ||
310 | qla82xx_wr_32(ha, | ||
311 | QLA82XX_CRB_NIU + 0x98, | ||
312 | CRB_NIU_XG_PAUSE_CTL_P0| | ||
313 | CRB_NIU_XG_PAUSE_CTL_P1); | ||
314 | } | ||
306 | ql_log(ql_log_info, base_vha, 0x101c, | 315 | ql_log(ql_log_info, base_vha, 0x101c, |
307 | "Mailbox cmd timeout occured. " | 316 | "Mailbox cmd timeout occured. " |
308 | "Scheduling ISP abort eeh_busy=0x%x.\n", | 317 | "Scheduling ISP abort eeh_busy=0x%x.\n", |
@@ -318,7 +327,15 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
318 | if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && | 327 | if (!test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) && |
319 | !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && | 328 | !test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) && |
320 | !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { | 329 | !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) { |
321 | 330 | if (IS_QLA82XX(ha)) { | |
331 | ql_dbg(ql_dbg_mbx, vha, 0x112b, | ||
332 | "disabling pause transmit on port " | ||
333 | "0 & 1.\n"); | ||
334 | qla82xx_wr_32(ha, | ||
335 | QLA82XX_CRB_NIU + 0x98, | ||
336 | CRB_NIU_XG_PAUSE_CTL_P0| | ||
337 | CRB_NIU_XG_PAUSE_CTL_P1); | ||
338 | } | ||
322 | ql_log(ql_log_info, base_vha, 0x101e, | 339 | ql_log(ql_log_info, base_vha, 0x101e, |
323 | "Mailbox cmd timeout occured. " | 340 | "Mailbox cmd timeout occured. " |
324 | "Scheduling ISP abort.\n"); | 341 | "Scheduling ISP abort.\n"); |
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 94bded5ddce..03554934b0a 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c | |||
@@ -3817,6 +3817,20 @@ exit: | |||
3817 | return rval; | 3817 | return rval; |
3818 | } | 3818 | } |
3819 | 3819 | ||
3820 | void qla82xx_clear_pending_mbx(scsi_qla_host_t *vha) | ||
3821 | { | ||
3822 | struct qla_hw_data *ha = vha->hw; | ||
3823 | |||
3824 | if (ha->flags.mbox_busy) { | ||
3825 | ha->flags.mbox_int = 1; | ||
3826 | ha->flags.mbox_busy = 0; | ||
3827 | ql_log(ql_log_warn, vha, 0x6010, | ||
3828 | "Doing premature completion of mbx command.\n"); | ||
3829 | if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags)) | ||
3830 | complete(&ha->mbx_intr_comp); | ||
3831 | } | ||
3832 | } | ||
3833 | |||
3820 | void qla82xx_watchdog(scsi_qla_host_t *vha) | 3834 | void qla82xx_watchdog(scsi_qla_host_t *vha) |
3821 | { | 3835 | { |
3822 | uint32_t dev_state, halt_status; | 3836 | uint32_t dev_state, halt_status; |
@@ -3839,9 +3853,13 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) | |||
3839 | qla2xxx_wake_dpc(vha); | 3853 | qla2xxx_wake_dpc(vha); |
3840 | } else { | 3854 | } else { |
3841 | if (qla82xx_check_fw_alive(vha)) { | 3855 | if (qla82xx_check_fw_alive(vha)) { |
3856 | ql_dbg(ql_dbg_timer, vha, 0x6011, | ||
3857 | "disabling pause transmit on port 0 & 1.\n"); | ||
3858 | qla82xx_wr_32(ha, QLA82XX_CRB_NIU + 0x98, | ||
3859 | CRB_NIU_XG_PAUSE_CTL_P0|CRB_NIU_XG_PAUSE_CTL_P1); | ||
3842 | halt_status = qla82xx_rd_32(ha, | 3860 | halt_status = qla82xx_rd_32(ha, |
3843 | QLA82XX_PEG_HALT_STATUS1); | 3861 | QLA82XX_PEG_HALT_STATUS1); |
3844 | ql_dbg(ql_dbg_timer, vha, 0x6005, | 3862 | ql_log(ql_log_info, vha, 0x6005, |
3845 | "dumping hw/fw registers:.\n " | 3863 | "dumping hw/fw registers:.\n " |
3846 | " PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,.\n " | 3864 | " PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,.\n " |
3847 | " PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,.\n " | 3865 | " PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,.\n " |
@@ -3858,6 +3876,11 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) | |||
3858 | QLA82XX_CRB_PEG_NET_3 + 0x3c), | 3876 | QLA82XX_CRB_PEG_NET_3 + 0x3c), |
3859 | qla82xx_rd_32(ha, | 3877 | qla82xx_rd_32(ha, |
3860 | QLA82XX_CRB_PEG_NET_4 + 0x3c)); | 3878 | QLA82XX_CRB_PEG_NET_4 + 0x3c)); |
3879 | if (LSW(MSB(halt_status)) == 0x67) | ||
3880 | ql_log(ql_log_warn, vha, 0xb052, | ||
3881 | "Firmware aborted with " | ||
3882 | "error code 0x00006700. Device is " | ||
3883 | "being reset.\n"); | ||
3861 | if (halt_status & HALT_STATUS_UNRECOVERABLE) { | 3884 | if (halt_status & HALT_STATUS_UNRECOVERABLE) { |
3862 | set_bit(ISP_UNRECOVERABLE, | 3885 | set_bit(ISP_UNRECOVERABLE, |
3863 | &vha->dpc_flags); | 3886 | &vha->dpc_flags); |
@@ -3869,16 +3892,8 @@ void qla82xx_watchdog(scsi_qla_host_t *vha) | |||
3869 | } | 3892 | } |
3870 | qla2xxx_wake_dpc(vha); | 3893 | qla2xxx_wake_dpc(vha); |
3871 | ha->flags.isp82xx_fw_hung = 1; | 3894 | ha->flags.isp82xx_fw_hung = 1; |
3872 | if (ha->flags.mbox_busy) { | 3895 | ql_log(ql_log_warn, vha, 0x6007, "Firmware hung.\n"); |
3873 | ha->flags.mbox_int = 1; | 3896 | qla82xx_clear_pending_mbx(vha); |
3874 | ql_log(ql_log_warn, vha, 0x6007, | ||
3875 | "Due to FW hung, doing " | ||
3876 | "premature completion of mbx " | ||
3877 | "command.\n"); | ||
3878 | if (test_bit(MBX_INTR_WAIT, | ||
3879 | &ha->mbx_cmd_flags)) | ||
3880 | complete(&ha->mbx_intr_comp); | ||
3881 | } | ||
3882 | } | 3897 | } |
3883 | } | 3898 | } |
3884 | } | 3899 | } |
@@ -4073,10 +4088,7 @@ qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha) | |||
4073 | msleep(1000); | 4088 | msleep(1000); |
4074 | if (qla82xx_check_fw_alive(vha)) { | 4089 | if (qla82xx_check_fw_alive(vha)) { |
4075 | ha->flags.isp82xx_fw_hung = 1; | 4090 | ha->flags.isp82xx_fw_hung = 1; |
4076 | if (ha->flags.mbox_busy) { | 4091 | qla82xx_clear_pending_mbx(vha); |
4077 | ha->flags.mbox_int = 1; | ||
4078 | complete(&ha->mbx_intr_comp); | ||
4079 | } | ||
4080 | break; | 4092 | break; |
4081 | } | 4093 | } |
4082 | } | 4094 | } |
diff --git a/drivers/scsi/qla2xxx/qla_nx.h b/drivers/scsi/qla2xxx/qla_nx.h index 57820c199bc..57a226be339 100644 --- a/drivers/scsi/qla2xxx/qla_nx.h +++ b/drivers/scsi/qla2xxx/qla_nx.h | |||
@@ -1173,4 +1173,8 @@ struct qla82xx_md_entry_queue { | |||
1173 | 1173 | ||
1174 | static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, 0x410000AC, | 1174 | static const int MD_MIU_TEST_AGT_RDDATA[] = { 0x410000A8, 0x410000AC, |
1175 | 0x410000B8, 0x410000BC }; | 1175 | 0x410000B8, 0x410000BC }; |
1176 | |||
1177 | #define CRB_NIU_XG_PAUSE_CTL_P0 0x1 | ||
1178 | #define CRB_NIU_XG_PAUSE_CTL_P1 0x8 | ||
1179 | |||
1176 | #endif | 1180 | #endif |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index fd14c7bfc62..f9e5b85e84d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -201,12 +201,12 @@ MODULE_PARM_DESC(ql2xmdcapmask, | |||
201 | "Set the Minidump driver capture mask level. " | 201 | "Set the Minidump driver capture mask level. " |
202 | "Default is 0x7F - Can be set to 0x3, 0x7, 0xF, 0x1F, 0x7F."); | 202 | "Default is 0x7F - Can be set to 0x3, 0x7, 0xF, 0x1F, 0x7F."); |
203 | 203 | ||
204 | int ql2xmdenable; | 204 | int ql2xmdenable = 1; |
205 | module_param(ql2xmdenable, int, S_IRUGO); | 205 | module_param(ql2xmdenable, int, S_IRUGO); |
206 | MODULE_PARM_DESC(ql2xmdenable, | 206 | MODULE_PARM_DESC(ql2xmdenable, |
207 | "Enable/disable MiniDump. " | 207 | "Enable/disable MiniDump. " |
208 | "0 (Default) - MiniDump disabled. " | 208 | "0 - MiniDump disabled. " |
209 | "1 - MiniDump enabled."); | 209 | "1 (Default) - MiniDump enabled."); |
210 | 210 | ||
211 | /* | 211 | /* |
212 | * SCSI host template entry points | 212 | * SCSI host template entry points |
@@ -423,6 +423,7 @@ fail2: | |||
423 | qla25xx_delete_queues(vha); | 423 | qla25xx_delete_queues(vha); |
424 | destroy_workqueue(ha->wq); | 424 | destroy_workqueue(ha->wq); |
425 | ha->wq = NULL; | 425 | ha->wq = NULL; |
426 | vha->req = ha->req_q_map[0]; | ||
426 | fail: | 427 | fail: |
427 | ha->mqenable = 0; | 428 | ha->mqenable = 0; |
428 | kfree(ha->req_q_map); | 429 | kfree(ha->req_q_map); |
@@ -814,49 +815,6 @@ qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha) | |||
814 | return return_status; | 815 | return return_status; |
815 | } | 816 | } |
816 | 817 | ||
817 | /* | ||
818 | * qla2x00_wait_for_loop_ready | ||
819 | * Wait for MAX_LOOP_TIMEOUT(5 min) value for loop | ||
820 | * to be in LOOP_READY state. | ||
821 | * Input: | ||
822 | * ha - pointer to host adapter structure | ||
823 | * | ||
824 | * Note: | ||
825 | * Does context switching-Release SPIN_LOCK | ||
826 | * (if any) before calling this routine. | ||
827 | * | ||
828 | * | ||
829 | * Return: | ||
830 | * Success (LOOP_READY) : 0 | ||
831 | * Failed (LOOP_NOT_READY) : 1 | ||
832 | */ | ||
833 | static inline int | ||
834 | qla2x00_wait_for_loop_ready(scsi_qla_host_t *vha) | ||
835 | { | ||
836 | int return_status = QLA_SUCCESS; | ||
837 | unsigned long loop_timeout ; | ||
838 | struct qla_hw_data *ha = vha->hw; | ||
839 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | ||
840 | |||
841 | /* wait for 5 min at the max for loop to be ready */ | ||
842 | loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ); | ||
843 | |||
844 | while ((!atomic_read(&base_vha->loop_down_timer) && | ||
845 | atomic_read(&base_vha->loop_state) == LOOP_DOWN) || | ||
846 | atomic_read(&base_vha->loop_state) != LOOP_READY) { | ||
847 | if (atomic_read(&base_vha->loop_state) == LOOP_DEAD) { | ||
848 | return_status = QLA_FUNCTION_FAILED; | ||
849 | break; | ||
850 | } | ||
851 | msleep(1000); | ||
852 | if (time_after_eq(jiffies, loop_timeout)) { | ||
853 | return_status = QLA_FUNCTION_FAILED; | ||
854 | break; | ||
855 | } | ||
856 | } | ||
857 | return (return_status); | ||
858 | } | ||
859 | |||
860 | static void | 818 | static void |
861 | sp_get(struct srb *sp) | 819 | sp_get(struct srb *sp) |
862 | { | 820 | { |
@@ -1035,12 +993,6 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, | |||
1035 | "Wait for hba online failed for cmd=%p.\n", cmd); | 993 | "Wait for hba online failed for cmd=%p.\n", cmd); |
1036 | goto eh_reset_failed; | 994 | goto eh_reset_failed; |
1037 | } | 995 | } |
1038 | err = 1; | ||
1039 | if (qla2x00_wait_for_loop_ready(vha) != QLA_SUCCESS) { | ||
1040 | ql_log(ql_log_warn, vha, 0x800b, | ||
1041 | "Wait for loop ready failed for cmd=%p.\n", cmd); | ||
1042 | goto eh_reset_failed; | ||
1043 | } | ||
1044 | err = 2; | 996 | err = 2; |
1045 | if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1) | 997 | if (do_reset(fcport, cmd->device->lun, cmd->request->cpu + 1) |
1046 | != QLA_SUCCESS) { | 998 | != QLA_SUCCESS) { |
@@ -1137,10 +1089,9 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) | |||
1137 | goto eh_bus_reset_done; | 1089 | goto eh_bus_reset_done; |
1138 | } | 1090 | } |
1139 | 1091 | ||
1140 | if (qla2x00_wait_for_loop_ready(vha) == QLA_SUCCESS) { | 1092 | if (qla2x00_loop_reset(vha) == QLA_SUCCESS) |
1141 | if (qla2x00_loop_reset(vha) == QLA_SUCCESS) | 1093 | ret = SUCCESS; |
1142 | ret = SUCCESS; | 1094 | |
1143 | } | ||
1144 | if (ret == FAILED) | 1095 | if (ret == FAILED) |
1145 | goto eh_bus_reset_done; | 1096 | goto eh_bus_reset_done; |
1146 | 1097 | ||
@@ -1206,15 +1157,6 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1206 | if (qla2x00_wait_for_reset_ready(vha) != QLA_SUCCESS) | 1157 | if (qla2x00_wait_for_reset_ready(vha) != QLA_SUCCESS) |
1207 | goto eh_host_reset_lock; | 1158 | goto eh_host_reset_lock; |
1208 | 1159 | ||
1209 | /* | ||
1210 | * Fixme-may be dpc thread is active and processing | ||
1211 | * loop_resync,so wait a while for it to | ||
1212 | * be completed and then issue big hammer.Otherwise | ||
1213 | * it may cause I/O failure as big hammer marks the | ||
1214 | * devices as lost kicking of the port_down_timer | ||
1215 | * while dpc is stuck for the mailbox to complete. | ||
1216 | */ | ||
1217 | qla2x00_wait_for_loop_ready(vha); | ||
1218 | if (vha != base_vha) { | 1160 | if (vha != base_vha) { |
1219 | if (qla2x00_vp_abort_isp(vha)) | 1161 | if (qla2x00_vp_abort_isp(vha)) |
1220 | goto eh_host_reset_lock; | 1162 | goto eh_host_reset_lock; |
@@ -1297,16 +1239,13 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) | |||
1297 | atomic_set(&vha->loop_state, LOOP_DOWN); | 1239 | atomic_set(&vha->loop_state, LOOP_DOWN); |
1298 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); | 1240 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); |
1299 | qla2x00_mark_all_devices_lost(vha, 0); | 1241 | qla2x00_mark_all_devices_lost(vha, 0); |
1300 | qla2x00_wait_for_loop_ready(vha); | ||
1301 | } | 1242 | } |
1302 | 1243 | ||
1303 | if (ha->flags.enable_lip_reset) { | 1244 | if (ha->flags.enable_lip_reset) { |
1304 | ret = qla2x00_lip_reset(vha); | 1245 | ret = qla2x00_lip_reset(vha); |
1305 | if (ret != QLA_SUCCESS) { | 1246 | if (ret != QLA_SUCCESS) |
1306 | ql_dbg(ql_dbg_taskm, vha, 0x802e, | 1247 | ql_dbg(ql_dbg_taskm, vha, 0x802e, |
1307 | "lip_reset failed (%d).\n", ret); | 1248 | "lip_reset failed (%d).\n", ret); |
1308 | } else | ||
1309 | qla2x00_wait_for_loop_ready(vha); | ||
1310 | } | 1249 | } |
1311 | 1250 | ||
1312 | /* Issue marker command only when we are going to start the I/O */ | 1251 | /* Issue marker command only when we are going to start the I/O */ |
@@ -4070,13 +4009,8 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) | |||
4070 | /* For ISP82XX complete any pending mailbox cmd */ | 4009 | /* For ISP82XX complete any pending mailbox cmd */ |
4071 | if (IS_QLA82XX(ha)) { | 4010 | if (IS_QLA82XX(ha)) { |
4072 | ha->flags.isp82xx_fw_hung = 1; | 4011 | ha->flags.isp82xx_fw_hung = 1; |
4073 | if (ha->flags.mbox_busy) { | 4012 | ql_dbg(ql_dbg_aer, vha, 0x9001, "Pci channel io frozen\n"); |
4074 | ha->flags.mbox_int = 1; | 4013 | qla82xx_clear_pending_mbx(vha); |
4075 | ql_dbg(ql_dbg_aer, vha, 0x9001, | ||
4076 | "Due to pci channel io frozen, doing premature " | ||
4077 | "completion of mbx command.\n"); | ||
4078 | complete(&ha->mbx_intr_comp); | ||
4079 | } | ||
4080 | } | 4014 | } |
4081 | qla2x00_free_irqs(vha); | 4015 | qla2x00_free_irqs(vha); |
4082 | pci_disable_device(pdev); | 4016 | pci_disable_device(pdev); |
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 13b6357c1fa..23f33a6d52d 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.03.07.07-k" | 10 | #define QLA2XXX_VERSION "8.03.07.12-k" |
11 | 11 | ||
12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
13 | #define QLA_DRIVER_MINOR_VER 3 | 13 | #define QLA_DRIVER_MINOR_VER 3 |
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index ace637bf254..fd5edc6e166 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -147,7 +147,7 @@ | |||
147 | #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alias name size */ | 147 | #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alias name size */ |
148 | #define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */ | 148 | #define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */ |
149 | 149 | ||
150 | #define QL4_SESS_RECOVERY_TMO 30 /* iSCSI session */ | 150 | #define QL4_SESS_RECOVERY_TMO 120 /* iSCSI session */ |
151 | /* recovery timeout */ | 151 | /* recovery timeout */ |
152 | 152 | ||
153 | #define LSDW(x) ((u32)((u64)(x))) | 153 | #define LSDW(x) ((u32)((u64)(x))) |
@@ -173,6 +173,8 @@ | |||
173 | #define ISNS_DEREG_TOV 5 | 173 | #define ISNS_DEREG_TOV 5 |
174 | #define HBA_ONLINE_TOV 30 | 174 | #define HBA_ONLINE_TOV 30 |
175 | #define DISABLE_ACB_TOV 30 | 175 | #define DISABLE_ACB_TOV 30 |
176 | #define IP_CONFIG_TOV 30 | ||
177 | #define LOGIN_TOV 12 | ||
176 | 178 | ||
177 | #define MAX_RESET_HA_RETRIES 2 | 179 | #define MAX_RESET_HA_RETRIES 2 |
178 | 180 | ||
@@ -240,6 +242,45 @@ struct ddb_entry { | |||
240 | 242 | ||
241 | uint16_t fw_ddb_index; /* DDB firmware index */ | 243 | uint16_t fw_ddb_index; /* DDB firmware index */ |
242 | uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */ | 244 | uint32_t fw_ddb_device_state; /* F/W Device State -- see ql4_fw.h */ |
245 | uint16_t ddb_type; | ||
246 | #define FLASH_DDB 0x01 | ||
247 | |||
248 | struct dev_db_entry fw_ddb_entry; | ||
249 | int (*unblock_sess)(struct iscsi_cls_session *cls_session); | ||
250 | int (*ddb_change)(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | ||
251 | struct ddb_entry *ddb_entry, uint32_t state); | ||
252 | |||
253 | /* Driver Re-login */ | ||
254 | unsigned long flags; /* DDB Flags */ | ||
255 | uint16_t default_relogin_timeout; /* Max time to wait for | ||
256 | * relogin to complete */ | ||
257 | atomic_t retry_relogin_timer; /* Min Time between relogins | ||
258 | * (4000 only) */ | ||
259 | atomic_t relogin_timer; /* Max Time to wait for | ||
260 | * relogin to complete */ | ||
261 | atomic_t relogin_retry_count; /* Num of times relogin has been | ||
262 | * retried */ | ||
263 | uint32_t default_time2wait; /* Default Min time between | ||
264 | * relogins (+aens) */ | ||
265 | |||
266 | }; | ||
267 | |||
268 | struct qla_ddb_index { | ||
269 | struct list_head list; | ||
270 | uint16_t fw_ddb_idx; | ||
271 | struct dev_db_entry fw_ddb; | ||
272 | }; | ||
273 | |||
274 | #define DDB_IPADDR_LEN 64 | ||
275 | |||
276 | struct ql4_tuple_ddb { | ||
277 | int port; | ||
278 | int tpgt; | ||
279 | char ip_addr[DDB_IPADDR_LEN]; | ||
280 | char iscsi_name[ISCSI_NAME_SIZE]; | ||
281 | uint16_t options; | ||
282 | #define DDB_OPT_IPV6 0x0e0e | ||
283 | #define DDB_OPT_IPV4 0x0f0f | ||
243 | }; | 284 | }; |
244 | 285 | ||
245 | /* | 286 | /* |
@@ -411,7 +452,7 @@ struct scsi_qla_host { | |||
411 | #define AF_FW_RECOVERY 19 /* 0x00080000 */ | 452 | #define AF_FW_RECOVERY 19 /* 0x00080000 */ |
412 | #define AF_EEH_BUSY 20 /* 0x00100000 */ | 453 | #define AF_EEH_BUSY 20 /* 0x00100000 */ |
413 | #define AF_PCI_CHANNEL_IO_PERM_FAILURE 21 /* 0x00200000 */ | 454 | #define AF_PCI_CHANNEL_IO_PERM_FAILURE 21 /* 0x00200000 */ |
414 | 455 | #define AF_BUILD_DDB_LIST 22 /* 0x00400000 */ | |
415 | unsigned long dpc_flags; | 456 | unsigned long dpc_flags; |
416 | 457 | ||
417 | #define DPC_RESET_HA 1 /* 0x00000002 */ | 458 | #define DPC_RESET_HA 1 /* 0x00000002 */ |
@@ -604,6 +645,7 @@ struct scsi_qla_host { | |||
604 | uint16_t bootload_minor; | 645 | uint16_t bootload_minor; |
605 | uint16_t bootload_patch; | 646 | uint16_t bootload_patch; |
606 | uint16_t bootload_build; | 647 | uint16_t bootload_build; |
648 | uint16_t def_timeout; /* Default login timeout */ | ||
607 | 649 | ||
608 | uint32_t flash_state; | 650 | uint32_t flash_state; |
609 | #define QLFLASH_WAITING 0 | 651 | #define QLFLASH_WAITING 0 |
@@ -623,6 +665,11 @@ struct scsi_qla_host { | |||
623 | uint16_t iscsi_pci_func_cnt; | 665 | uint16_t iscsi_pci_func_cnt; |
624 | uint8_t model_name[16]; | 666 | uint8_t model_name[16]; |
625 | struct completion disable_acb_comp; | 667 | struct completion disable_acb_comp; |
668 | struct dma_pool *fw_ddb_dma_pool; | ||
669 | #define DDB_DMA_BLOCK_SIZE 512 | ||
670 | uint16_t pri_ddb_idx; | ||
671 | uint16_t sec_ddb_idx; | ||
672 | int is_reset; | ||
626 | }; | 673 | }; |
627 | 674 | ||
628 | struct ql4_task_data { | 675 | struct ql4_task_data { |
@@ -835,6 +882,10 @@ static inline int ql4xxx_reset_active(struct scsi_qla_host *ha) | |||
835 | /*---------------------------------------------------------------------------*/ | 882 | /*---------------------------------------------------------------------------*/ |
836 | 883 | ||
837 | /* Defines for qla4xxx_initialize_adapter() and qla4xxx_recover_adapter() */ | 884 | /* Defines for qla4xxx_initialize_adapter() and qla4xxx_recover_adapter() */ |
885 | |||
886 | #define INIT_ADAPTER 0 | ||
887 | #define RESET_ADAPTER 1 | ||
888 | |||
838 | #define PRESERVE_DDB_LIST 0 | 889 | #define PRESERVE_DDB_LIST 0 |
839 | #define REBUILD_DDB_LIST 1 | 890 | #define REBUILD_DDB_LIST 1 |
840 | 891 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index cbd5a20dbbd..4ac07f88252 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #define MAX_PRST_DEV_DB_ENTRIES 64 | 12 | #define MAX_PRST_DEV_DB_ENTRIES 64 |
13 | #define MIN_DISC_DEV_DB_ENTRY MAX_PRST_DEV_DB_ENTRIES | 13 | #define MIN_DISC_DEV_DB_ENTRY MAX_PRST_DEV_DB_ENTRIES |
14 | #define MAX_DEV_DB_ENTRIES 512 | 14 | #define MAX_DEV_DB_ENTRIES 512 |
15 | #define MAX_DEV_DB_ENTRIES_40XX 256 | ||
15 | 16 | ||
16 | /************************************************************************* | 17 | /************************************************************************* |
17 | * | 18 | * |
@@ -604,6 +605,13 @@ struct addr_ctrl_blk { | |||
604 | uint8_t res14[140]; /* 274-2FF */ | 605 | uint8_t res14[140]; /* 274-2FF */ |
605 | }; | 606 | }; |
606 | 607 | ||
608 | #define IP_ADDR_COUNT 4 /* Total 4 IP address supported in one interface | ||
609 | * One IPv4, one IPv6 link local and 2 IPv6 | ||
610 | */ | ||
611 | |||
612 | #define IP_STATE_MASK 0x0F000000 | ||
613 | #define IP_STATE_SHIFT 24 | ||
614 | |||
607 | struct init_fw_ctrl_blk { | 615 | struct init_fw_ctrl_blk { |
608 | struct addr_ctrl_blk pri; | 616 | struct addr_ctrl_blk pri; |
609 | /* struct addr_ctrl_blk sec;*/ | 617 | /* struct addr_ctrl_blk sec;*/ |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 160db9d5ea2..d0dd4b33020 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -13,7 +13,7 @@ struct iscsi_cls_conn; | |||
13 | int qla4xxx_hw_reset(struct scsi_qla_host *ha); | 13 | int qla4xxx_hw_reset(struct scsi_qla_host *ha); |
14 | int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); | 14 | int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); |
15 | int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb *srb); | 15 | int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb *srb); |
16 | int qla4xxx_initialize_adapter(struct scsi_qla_host *ha); | 16 | int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset); |
17 | int qla4xxx_soft_reset(struct scsi_qla_host *ha); | 17 | int qla4xxx_soft_reset(struct scsi_qla_host *ha); |
18 | irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id); | 18 | irqreturn_t qla4xxx_intr_handler(int irq, void *dev_id); |
19 | 19 | ||
@@ -153,10 +153,13 @@ int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
153 | uint32_t *mbx_sts); | 153 | uint32_t *mbx_sts); |
154 | int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index); | 154 | int qla4xxx_clear_ddb_entry(struct scsi_qla_host *ha, uint32_t fw_ddb_index); |
155 | int qla4xxx_send_passthru0(struct iscsi_task *task); | 155 | int qla4xxx_send_passthru0(struct iscsi_task *task); |
156 | void qla4xxx_free_ddb_index(struct scsi_qla_host *ha); | ||
156 | int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index, | 157 | int qla4xxx_get_mgmt_data(struct scsi_qla_host *ha, uint16_t fw_ddb_index, |
157 | uint16_t stats_size, dma_addr_t stats_dma); | 158 | uint16_t stats_size, dma_addr_t stats_dma); |
158 | void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, | 159 | void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, |
159 | struct ddb_entry *ddb_entry); | 160 | struct ddb_entry *ddb_entry); |
161 | void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha, | ||
162 | struct ddb_entry *ddb_entry); | ||
160 | int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha, | 163 | int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha, |
161 | struct dev_db_entry *fw_ddb_entry, | 164 | struct dev_db_entry *fw_ddb_entry, |
162 | dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index); | 165 | dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index); |
@@ -169,11 +172,22 @@ int qla4xxx_set_nvram(struct scsi_qla_host *ha, dma_addr_t nvram_dma, | |||
169 | int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha, | 172 | int qla4xxx_restore_factory_defaults(struct scsi_qla_host *ha, |
170 | uint32_t region, uint32_t field0, | 173 | uint32_t region, uint32_t field0, |
171 | uint32_t field1); | 174 | uint32_t field1); |
175 | int qla4xxx_get_ddb_index(struct scsi_qla_host *ha, uint16_t *ddb_index); | ||
176 | void qla4xxx_login_flash_ddb(struct iscsi_cls_session *cls_session); | ||
177 | int qla4xxx_unblock_ddb(struct iscsi_cls_session *cls_session); | ||
178 | int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session); | ||
179 | int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | ||
180 | struct ddb_entry *ddb_entry, uint32_t state); | ||
181 | int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | ||
182 | struct ddb_entry *ddb_entry, uint32_t state); | ||
183 | void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset); | ||
172 | 184 | ||
173 | /* BSG Functions */ | 185 | /* BSG Functions */ |
174 | int qla4xxx_bsg_request(struct bsg_job *bsg_job); | 186 | int qla4xxx_bsg_request(struct bsg_job *bsg_job); |
175 | int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job); | 187 | int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job); |
176 | 188 | ||
189 | void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry); | ||
190 | |||
177 | extern int ql4xextended_error_logging; | 191 | extern int ql4xextended_error_logging; |
178 | extern int ql4xdontresethba; | 192 | extern int ql4xdontresethba; |
179 | extern int ql4xenablemsix; | 193 | extern int ql4xenablemsix; |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 3075fbaef55..1bdfa8120ac 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
@@ -773,22 +773,24 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha) | |||
773 | * be freed so that when login happens from user space there are free DDB | 773 | * be freed so that when login happens from user space there are free DDB |
774 | * indices available. | 774 | * indices available. |
775 | **/ | 775 | **/ |
776 | static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha) | 776 | void qla4xxx_free_ddb_index(struct scsi_qla_host *ha) |
777 | { | 777 | { |
778 | int max_ddbs; | 778 | int max_ddbs; |
779 | int ret; | 779 | int ret; |
780 | uint32_t idx = 0, next_idx = 0; | 780 | uint32_t idx = 0, next_idx = 0; |
781 | uint32_t state = 0, conn_err = 0; | 781 | uint32_t state = 0, conn_err = 0; |
782 | 782 | ||
783 | max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES : | 783 | max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : |
784 | MAX_DEV_DB_ENTRIES; | 784 | MAX_DEV_DB_ENTRIES; |
785 | 785 | ||
786 | for (idx = 0; idx < max_ddbs; idx = next_idx) { | 786 | for (idx = 0; idx < max_ddbs; idx = next_idx) { |
787 | ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL, | 787 | ret = qla4xxx_get_fwddb_entry(ha, idx, NULL, 0, NULL, |
788 | &next_idx, &state, &conn_err, | 788 | &next_idx, &state, &conn_err, |
789 | NULL, NULL); | 789 | NULL, NULL); |
790 | if (ret == QLA_ERROR) | 790 | if (ret == QLA_ERROR) { |
791 | next_idx++; | ||
791 | continue; | 792 | continue; |
793 | } | ||
792 | if (state == DDB_DS_NO_CONNECTION_ACTIVE || | 794 | if (state == DDB_DS_NO_CONNECTION_ACTIVE || |
793 | state == DDB_DS_SESSION_FAILED) { | 795 | state == DDB_DS_SESSION_FAILED) { |
794 | DEBUG2(ql4_printk(KERN_INFO, ha, | 796 | DEBUG2(ql4_printk(KERN_INFO, ha, |
@@ -804,7 +806,6 @@ static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha) | |||
804 | } | 806 | } |
805 | } | 807 | } |
806 | 808 | ||
807 | |||
808 | /** | 809 | /** |
809 | * qla4xxx_initialize_adapter - initiailizes hba | 810 | * qla4xxx_initialize_adapter - initiailizes hba |
810 | * @ha: Pointer to host adapter structure. | 811 | * @ha: Pointer to host adapter structure. |
@@ -812,7 +813,7 @@ static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha) | |||
812 | * This routine parforms all of the steps necessary to initialize the adapter. | 813 | * This routine parforms all of the steps necessary to initialize the adapter. |
813 | * | 814 | * |
814 | **/ | 815 | **/ |
815 | int qla4xxx_initialize_adapter(struct scsi_qla_host *ha) | 816 | int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset) |
816 | { | 817 | { |
817 | int status = QLA_ERROR; | 818 | int status = QLA_ERROR; |
818 | 819 | ||
@@ -840,7 +841,8 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha) | |||
840 | if (status == QLA_ERROR) | 841 | if (status == QLA_ERROR) |
841 | goto exit_init_hba; | 842 | goto exit_init_hba; |
842 | 843 | ||
843 | qla4xxx_free_ddb_index(ha); | 844 | if (is_reset == RESET_ADAPTER) |
845 | qla4xxx_build_ddb_list(ha, is_reset); | ||
844 | 846 | ||
845 | set_bit(AF_ONLINE, &ha->flags); | 847 | set_bit(AF_ONLINE, &ha->flags); |
846 | exit_init_hba: | 848 | exit_init_hba: |
@@ -855,38 +857,12 @@ exit_init_hba: | |||
855 | return status; | 857 | return status; |
856 | } | 858 | } |
857 | 859 | ||
858 | /** | 860 | int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, |
859 | * qla4xxx_process_ddb_changed - process ddb state change | 861 | struct ddb_entry *ddb_entry, uint32_t state) |
860 | * @ha - Pointer to host adapter structure. | ||
861 | * @fw_ddb_index - Firmware's device database index | ||
862 | * @state - Device state | ||
863 | * | ||
864 | * This routine processes a Decive Database Changed AEN Event. | ||
865 | **/ | ||
866 | int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | ||
867 | uint32_t state, uint32_t conn_err) | ||
868 | { | 862 | { |
869 | struct ddb_entry * ddb_entry; | ||
870 | uint32_t old_fw_ddb_device_state; | 863 | uint32_t old_fw_ddb_device_state; |
871 | int status = QLA_ERROR; | 864 | int status = QLA_ERROR; |
872 | 865 | ||
873 | /* check for out of range index */ | ||
874 | if (fw_ddb_index >= MAX_DDB_ENTRIES) | ||
875 | goto exit_ddb_event; | ||
876 | |||
877 | /* Get the corresponging ddb entry */ | ||
878 | ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index); | ||
879 | /* Device does not currently exist in our database. */ | ||
880 | if (ddb_entry == NULL) { | ||
881 | ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n", | ||
882 | __func__, fw_ddb_index); | ||
883 | |||
884 | if (state == DDB_DS_NO_CONNECTION_ACTIVE) | ||
885 | clear_bit(fw_ddb_index, ha->ddb_idx_map); | ||
886 | |||
887 | goto exit_ddb_event; | ||
888 | } | ||
889 | |||
890 | old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state; | 866 | old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state; |
891 | DEBUG2(ql4_printk(KERN_INFO, ha, | 867 | DEBUG2(ql4_printk(KERN_INFO, ha, |
892 | "%s: DDB - old state = 0x%x, new state = 0x%x for " | 868 | "%s: DDB - old state = 0x%x, new state = 0x%x for " |
@@ -900,9 +876,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
900 | switch (state) { | 876 | switch (state) { |
901 | case DDB_DS_SESSION_ACTIVE: | 877 | case DDB_DS_SESSION_ACTIVE: |
902 | case DDB_DS_DISCOVERY: | 878 | case DDB_DS_DISCOVERY: |
903 | iscsi_conn_start(ddb_entry->conn); | 879 | ddb_entry->unblock_sess(ddb_entry->sess); |
904 | iscsi_conn_login_event(ddb_entry->conn, | ||
905 | ISCSI_CONN_STATE_LOGGED_IN); | ||
906 | qla4xxx_update_session_conn_param(ha, ddb_entry); | 880 | qla4xxx_update_session_conn_param(ha, ddb_entry); |
907 | status = QLA_SUCCESS; | 881 | status = QLA_SUCCESS; |
908 | break; | 882 | break; |
@@ -936,9 +910,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
936 | switch (state) { | 910 | switch (state) { |
937 | case DDB_DS_SESSION_ACTIVE: | 911 | case DDB_DS_SESSION_ACTIVE: |
938 | case DDB_DS_DISCOVERY: | 912 | case DDB_DS_DISCOVERY: |
939 | iscsi_conn_start(ddb_entry->conn); | 913 | ddb_entry->unblock_sess(ddb_entry->sess); |
940 | iscsi_conn_login_event(ddb_entry->conn, | ||
941 | ISCSI_CONN_STATE_LOGGED_IN); | ||
942 | qla4xxx_update_session_conn_param(ha, ddb_entry); | 914 | qla4xxx_update_session_conn_param(ha, ddb_entry); |
943 | status = QLA_SUCCESS; | 915 | status = QLA_SUCCESS; |
944 | break; | 916 | break; |
@@ -954,7 +926,198 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
954 | __func__)); | 926 | __func__)); |
955 | break; | 927 | break; |
956 | } | 928 | } |
929 | return status; | ||
930 | } | ||
931 | |||
932 | void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry) | ||
933 | { | ||
934 | /* | ||
935 | * This triggers a relogin. After the relogin_timer | ||
936 | * expires, the relogin gets scheduled. We must wait a | ||
937 | * minimum amount of time since receiving an 0x8014 AEN | ||
938 | * with failed device_state or a logout response before | ||
939 | * we can issue another relogin. | ||
940 | * | ||
941 | * Firmware pads this timeout: (time2wait +1). | ||
942 | * Driver retry to login should be longer than F/W. | ||
943 | * Otherwise F/W will fail | ||
944 | * set_ddb() mbx cmd with 0x4005 since it still | ||
945 | * counting down its time2wait. | ||
946 | */ | ||
947 | atomic_set(&ddb_entry->relogin_timer, 0); | ||
948 | atomic_set(&ddb_entry->retry_relogin_timer, | ||
949 | ddb_entry->default_time2wait + 4); | ||
950 | |||
951 | } | ||
952 | |||
953 | int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | ||
954 | struct ddb_entry *ddb_entry, uint32_t state) | ||
955 | { | ||
956 | uint32_t old_fw_ddb_device_state; | ||
957 | int status = QLA_ERROR; | ||
958 | |||
959 | old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state; | ||
960 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
961 | "%s: DDB - old state = 0x%x, new state = 0x%x for " | ||
962 | "index [%d]\n", __func__, | ||
963 | ddb_entry->fw_ddb_device_state, state, fw_ddb_index)); | ||
964 | |||
965 | ddb_entry->fw_ddb_device_state = state; | ||
966 | |||
967 | switch (old_fw_ddb_device_state) { | ||
968 | case DDB_DS_LOGIN_IN_PROCESS: | ||
969 | case DDB_DS_NO_CONNECTION_ACTIVE: | ||
970 | switch (state) { | ||
971 | case DDB_DS_SESSION_ACTIVE: | ||
972 | ddb_entry->unblock_sess(ddb_entry->sess); | ||
973 | qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry); | ||
974 | status = QLA_SUCCESS; | ||
975 | break; | ||
976 | case DDB_DS_SESSION_FAILED: | ||
977 | iscsi_block_session(ddb_entry->sess); | ||
978 | if (!test_bit(DF_RELOGIN, &ddb_entry->flags)) | ||
979 | qla4xxx_arm_relogin_timer(ddb_entry); | ||
980 | status = QLA_SUCCESS; | ||
981 | break; | ||
982 | } | ||
983 | break; | ||
984 | case DDB_DS_SESSION_ACTIVE: | ||
985 | switch (state) { | ||
986 | case DDB_DS_SESSION_FAILED: | ||
987 | iscsi_block_session(ddb_entry->sess); | ||
988 | if (!test_bit(DF_RELOGIN, &ddb_entry->flags)) | ||
989 | qla4xxx_arm_relogin_timer(ddb_entry); | ||
990 | status = QLA_SUCCESS; | ||
991 | break; | ||
992 | } | ||
993 | break; | ||
994 | case DDB_DS_SESSION_FAILED: | ||
995 | switch (state) { | ||
996 | case DDB_DS_SESSION_ACTIVE: | ||
997 | ddb_entry->unblock_sess(ddb_entry->sess); | ||
998 | qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry); | ||
999 | status = QLA_SUCCESS; | ||
1000 | break; | ||
1001 | case DDB_DS_SESSION_FAILED: | ||
1002 | if (!test_bit(DF_RELOGIN, &ddb_entry->flags)) | ||
1003 | qla4xxx_arm_relogin_timer(ddb_entry); | ||
1004 | status = QLA_SUCCESS; | ||
1005 | break; | ||
1006 | } | ||
1007 | break; | ||
1008 | default: | ||
1009 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unknown Event\n", | ||
1010 | __func__)); | ||
1011 | break; | ||
1012 | } | ||
1013 | return status; | ||
1014 | } | ||
1015 | |||
1016 | /** | ||
1017 | * qla4xxx_process_ddb_changed - process ddb state change | ||
1018 | * @ha - Pointer to host adapter structure. | ||
1019 | * @fw_ddb_index - Firmware's device database index | ||
1020 | * @state - Device state | ||
1021 | * | ||
1022 | * This routine processes a Decive Database Changed AEN Event. | ||
1023 | **/ | ||
1024 | int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, | ||
1025 | uint32_t fw_ddb_index, | ||
1026 | uint32_t state, uint32_t conn_err) | ||
1027 | { | ||
1028 | struct ddb_entry *ddb_entry; | ||
1029 | int status = QLA_ERROR; | ||
1030 | |||
1031 | /* check for out of range index */ | ||
1032 | if (fw_ddb_index >= MAX_DDB_ENTRIES) | ||
1033 | goto exit_ddb_event; | ||
1034 | |||
1035 | /* Get the corresponging ddb entry */ | ||
1036 | ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index); | ||
1037 | /* Device does not currently exist in our database. */ | ||
1038 | if (ddb_entry == NULL) { | ||
1039 | ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n", | ||
1040 | __func__, fw_ddb_index); | ||
1041 | |||
1042 | if (state == DDB_DS_NO_CONNECTION_ACTIVE) | ||
1043 | clear_bit(fw_ddb_index, ha->ddb_idx_map); | ||
1044 | |||
1045 | goto exit_ddb_event; | ||
1046 | } | ||
1047 | |||
1048 | ddb_entry->ddb_change(ha, fw_ddb_index, ddb_entry, state); | ||
957 | 1049 | ||
958 | exit_ddb_event: | 1050 | exit_ddb_event: |
959 | return status; | 1051 | return status; |
960 | } | 1052 | } |
1053 | |||
1054 | /** | ||
1055 | * qla4xxx_login_flash_ddb - Login to target (DDB) | ||
1056 | * @cls_session: Pointer to the session to login | ||
1057 | * | ||
1058 | * This routine logins to the target. | ||
1059 | * Issues setddb and conn open mbx | ||
1060 | **/ | ||
1061 | void qla4xxx_login_flash_ddb(struct iscsi_cls_session *cls_session) | ||
1062 | { | ||
1063 | struct iscsi_session *sess; | ||
1064 | struct ddb_entry *ddb_entry; | ||
1065 | struct scsi_qla_host *ha; | ||
1066 | struct dev_db_entry *fw_ddb_entry = NULL; | ||
1067 | dma_addr_t fw_ddb_dma; | ||
1068 | uint32_t mbx_sts = 0; | ||
1069 | int ret; | ||
1070 | |||
1071 | sess = cls_session->dd_data; | ||
1072 | ddb_entry = sess->dd_data; | ||
1073 | ha = ddb_entry->ha; | ||
1074 | |||
1075 | if (!test_bit(AF_LINK_UP, &ha->flags)) | ||
1076 | return; | ||
1077 | |||
1078 | if (ddb_entry->ddb_type != FLASH_DDB) { | ||
1079 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1080 | "Skipping login to non FLASH DB")); | ||
1081 | goto exit_login; | ||
1082 | } | ||
1083 | |||
1084 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | ||
1085 | &fw_ddb_dma); | ||
1086 | if (fw_ddb_entry == NULL) { | ||
1087 | DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n")); | ||
1088 | goto exit_login; | ||
1089 | } | ||
1090 | |||
1091 | if (ddb_entry->fw_ddb_index == INVALID_ENTRY) { | ||
1092 | ret = qla4xxx_get_ddb_index(ha, &ddb_entry->fw_ddb_index); | ||
1093 | if (ret == QLA_ERROR) | ||
1094 | goto exit_login; | ||
1095 | |||
1096 | ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry; | ||
1097 | ha->tot_ddbs++; | ||
1098 | } | ||
1099 | |||
1100 | memcpy(fw_ddb_entry, &ddb_entry->fw_ddb_entry, | ||
1101 | sizeof(struct dev_db_entry)); | ||
1102 | ddb_entry->sess->target_id = ddb_entry->fw_ddb_index; | ||
1103 | |||
1104 | ret = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index, | ||
1105 | fw_ddb_dma, &mbx_sts); | ||
1106 | if (ret == QLA_ERROR) { | ||
1107 | DEBUG2(ql4_printk(KERN_ERR, ha, "Set DDB failed\n")); | ||
1108 | goto exit_login; | ||
1109 | } | ||
1110 | |||
1111 | ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS; | ||
1112 | ret = qla4xxx_conn_open(ha, ddb_entry->fw_ddb_index); | ||
1113 | if (ret == QLA_ERROR) { | ||
1114 | ql4_printk(KERN_ERR, ha, "%s: Login failed: %s\n", __func__, | ||
1115 | sess->targetname); | ||
1116 | goto exit_login; | ||
1117 | } | ||
1118 | |||
1119 | exit_login: | ||
1120 | if (fw_ddb_entry) | ||
1121 | dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); | ||
1122 | } | ||
1123 | |||
diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 4c2b8487039..c2593782fbb 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c | |||
@@ -41,6 +41,16 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, | |||
41 | return status; | 41 | return status; |
42 | } | 42 | } |
43 | 43 | ||
44 | if (is_qla40XX(ha)) { | ||
45 | if (test_bit(AF_HA_REMOVAL, &ha->flags)) { | ||
46 | DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " | ||
47 | "prematurely completing mbx cmd as " | ||
48 | "adapter removal detected\n", | ||
49 | ha->host_no, __func__)); | ||
50 | return status; | ||
51 | } | ||
52 | } | ||
53 | |||
44 | if (is_qla8022(ha)) { | 54 | if (is_qla8022(ha)) { |
45 | if (test_bit(AF_FW_RECOVERY, &ha->flags)) { | 55 | if (test_bit(AF_FW_RECOVERY, &ha->flags)) { |
46 | DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " | 56 | DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: " |
@@ -413,6 +423,7 @@ qla4xxx_update_local_ifcb(struct scsi_qla_host *ha, | |||
413 | memcpy(ha->name_string, init_fw_cb->iscsi_name, | 423 | memcpy(ha->name_string, init_fw_cb->iscsi_name, |
414 | min(sizeof(ha->name_string), | 424 | min(sizeof(ha->name_string), |
415 | sizeof(init_fw_cb->iscsi_name))); | 425 | sizeof(init_fw_cb->iscsi_name))); |
426 | ha->def_timeout = le16_to_cpu(init_fw_cb->def_timeout); | ||
416 | /*memcpy(ha->alias, init_fw_cb->Alias, | 427 | /*memcpy(ha->alias, init_fw_cb->Alias, |
417 | min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ | 428 | min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ |
418 | 429 | ||
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 30f31b127f3..4169c8baa11 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
9 | #include <linux/blkdev.h> | 9 | #include <linux/blkdev.h> |
10 | #include <linux/iscsi_boot_sysfs.h> | 10 | #include <linux/iscsi_boot_sysfs.h> |
11 | #include <linux/inet.h> | ||
11 | 12 | ||
12 | #include <scsi/scsi_tcq.h> | 13 | #include <scsi/scsi_tcq.h> |
13 | #include <scsi/scsicam.h> | 14 | #include <scsi/scsicam.h> |
@@ -31,6 +32,13 @@ static struct kmem_cache *srb_cachep; | |||
31 | /* | 32 | /* |
32 | * Module parameter information and variables | 33 | * Module parameter information and variables |
33 | */ | 34 | */ |
35 | int ql4xdisablesysfsboot = 1; | ||
36 | module_param(ql4xdisablesysfsboot, int, S_IRUGO | S_IWUSR); | ||
37 | MODULE_PARM_DESC(ql4xdisablesysfsboot, | ||
38 | "Set to disable exporting boot targets to sysfs\n" | ||
39 | " 0 - Export boot targets\n" | ||
40 | " 1 - Do not export boot targets (Default)"); | ||
41 | |||
34 | int ql4xdontresethba = 0; | 42 | int ql4xdontresethba = 0; |
35 | module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR); | 43 | module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR); |
36 | MODULE_PARM_DESC(ql4xdontresethba, | 44 | MODULE_PARM_DESC(ql4xdontresethba, |
@@ -63,7 +71,7 @@ static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO; | |||
63 | module_param(ql4xsess_recovery_tmo, int, S_IRUGO); | 71 | module_param(ql4xsess_recovery_tmo, int, S_IRUGO); |
64 | MODULE_PARM_DESC(ql4xsess_recovery_tmo, | 72 | MODULE_PARM_DESC(ql4xsess_recovery_tmo, |
65 | "Target Session Recovery Timeout.\n" | 73 | "Target Session Recovery Timeout.\n" |
66 | " Default: 30 sec."); | 74 | " Default: 120 sec."); |
67 | 75 | ||
68 | static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha); | 76 | static int qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha); |
69 | /* | 77 | /* |
@@ -415,7 +423,7 @@ static int qla4xxx_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) | |||
415 | qla_ep = ep->dd_data; | 423 | qla_ep = ep->dd_data; |
416 | ha = to_qla_host(qla_ep->host); | 424 | ha = to_qla_host(qla_ep->host); |
417 | 425 | ||
418 | if (adapter_up(ha)) | 426 | if (adapter_up(ha) && !test_bit(AF_BUILD_DDB_LIST, &ha->flags)) |
419 | ret = 1; | 427 | ret = 1; |
420 | 428 | ||
421 | return ret; | 429 | return ret; |
@@ -975,6 +983,150 @@ static int qla4xxx_conn_get_param(struct iscsi_cls_conn *cls_conn, | |||
975 | 983 | ||
976 | } | 984 | } |
977 | 985 | ||
986 | int qla4xxx_get_ddb_index(struct scsi_qla_host *ha, uint16_t *ddb_index) | ||
987 | { | ||
988 | uint32_t mbx_sts = 0; | ||
989 | uint16_t tmp_ddb_index; | ||
990 | int ret; | ||
991 | |||
992 | get_ddb_index: | ||
993 | tmp_ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES); | ||
994 | |||
995 | if (tmp_ddb_index >= MAX_DDB_ENTRIES) { | ||
996 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
997 | "Free DDB index not available\n")); | ||
998 | ret = QLA_ERROR; | ||
999 | goto exit_get_ddb_index; | ||
1000 | } | ||
1001 | |||
1002 | if (test_and_set_bit(tmp_ddb_index, ha->ddb_idx_map)) | ||
1003 | goto get_ddb_index; | ||
1004 | |||
1005 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1006 | "Found a free DDB index at %d\n", tmp_ddb_index)); | ||
1007 | ret = qla4xxx_req_ddb_entry(ha, tmp_ddb_index, &mbx_sts); | ||
1008 | if (ret == QLA_ERROR) { | ||
1009 | if (mbx_sts == MBOX_STS_COMMAND_ERROR) { | ||
1010 | ql4_printk(KERN_INFO, ha, | ||
1011 | "DDB index = %d not available trying next\n", | ||
1012 | tmp_ddb_index); | ||
1013 | goto get_ddb_index; | ||
1014 | } | ||
1015 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1016 | "Free FW DDB not available\n")); | ||
1017 | } | ||
1018 | |||
1019 | *ddb_index = tmp_ddb_index; | ||
1020 | |||
1021 | exit_get_ddb_index: | ||
1022 | return ret; | ||
1023 | } | ||
1024 | |||
1025 | static int qla4xxx_match_ipaddress(struct scsi_qla_host *ha, | ||
1026 | struct ddb_entry *ddb_entry, | ||
1027 | char *existing_ipaddr, | ||
1028 | char *user_ipaddr) | ||
1029 | { | ||
1030 | uint8_t dst_ipaddr[IPv6_ADDR_LEN]; | ||
1031 | char formatted_ipaddr[DDB_IPADDR_LEN]; | ||
1032 | int status = QLA_SUCCESS, ret = 0; | ||
1033 | |||
1034 | if (ddb_entry->fw_ddb_entry.options & DDB_OPT_IPV6_DEVICE) { | ||
1035 | ret = in6_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr, | ||
1036 | '\0', NULL); | ||
1037 | if (ret == 0) { | ||
1038 | status = QLA_ERROR; | ||
1039 | goto out_match; | ||
1040 | } | ||
1041 | ret = sprintf(formatted_ipaddr, "%pI6", dst_ipaddr); | ||
1042 | } else { | ||
1043 | ret = in4_pton(user_ipaddr, strlen(user_ipaddr), dst_ipaddr, | ||
1044 | '\0', NULL); | ||
1045 | if (ret == 0) { | ||
1046 | status = QLA_ERROR; | ||
1047 | goto out_match; | ||
1048 | } | ||
1049 | ret = sprintf(formatted_ipaddr, "%pI4", dst_ipaddr); | ||
1050 | } | ||
1051 | |||
1052 | if (strcmp(existing_ipaddr, formatted_ipaddr)) | ||
1053 | status = QLA_ERROR; | ||
1054 | |||
1055 | out_match: | ||
1056 | return status; | ||
1057 | } | ||
1058 | |||
1059 | static int qla4xxx_match_fwdb_session(struct scsi_qla_host *ha, | ||
1060 | struct iscsi_cls_conn *cls_conn) | ||
1061 | { | ||
1062 | int idx = 0, max_ddbs, rval; | ||
1063 | struct iscsi_cls_session *cls_sess = iscsi_conn_to_session(cls_conn); | ||
1064 | struct iscsi_session *sess, *existing_sess; | ||
1065 | struct iscsi_conn *conn, *existing_conn; | ||
1066 | struct ddb_entry *ddb_entry; | ||
1067 | |||
1068 | sess = cls_sess->dd_data; | ||
1069 | conn = cls_conn->dd_data; | ||
1070 | |||
1071 | if (sess->targetname == NULL || | ||
1072 | conn->persistent_address == NULL || | ||
1073 | conn->persistent_port == 0) | ||
1074 | return QLA_ERROR; | ||
1075 | |||
1076 | max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : | ||
1077 | MAX_DEV_DB_ENTRIES; | ||
1078 | |||
1079 | for (idx = 0; idx < max_ddbs; idx++) { | ||
1080 | ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); | ||
1081 | if (ddb_entry == NULL) | ||
1082 | continue; | ||
1083 | |||
1084 | if (ddb_entry->ddb_type != FLASH_DDB) | ||
1085 | continue; | ||
1086 | |||
1087 | existing_sess = ddb_entry->sess->dd_data; | ||
1088 | existing_conn = ddb_entry->conn->dd_data; | ||
1089 | |||
1090 | if (existing_sess->targetname == NULL || | ||
1091 | existing_conn->persistent_address == NULL || | ||
1092 | existing_conn->persistent_port == 0) | ||
1093 | continue; | ||
1094 | |||
1095 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1096 | "IQN = %s User IQN = %s\n", | ||
1097 | existing_sess->targetname, | ||
1098 | sess->targetname)); | ||
1099 | |||
1100 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1101 | "IP = %s User IP = %s\n", | ||
1102 | existing_conn->persistent_address, | ||
1103 | conn->persistent_address)); | ||
1104 | |||
1105 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1106 | "Port = %d User Port = %d\n", | ||
1107 | existing_conn->persistent_port, | ||
1108 | conn->persistent_port)); | ||
1109 | |||
1110 | if (strcmp(existing_sess->targetname, sess->targetname)) | ||
1111 | continue; | ||
1112 | rval = qla4xxx_match_ipaddress(ha, ddb_entry, | ||
1113 | existing_conn->persistent_address, | ||
1114 | conn->persistent_address); | ||
1115 | if (rval == QLA_ERROR) | ||
1116 | continue; | ||
1117 | if (existing_conn->persistent_port != conn->persistent_port) | ||
1118 | continue; | ||
1119 | break; | ||
1120 | } | ||
1121 | |||
1122 | if (idx == max_ddbs) | ||
1123 | return QLA_ERROR; | ||
1124 | |||
1125 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1126 | "Match found in fwdb sessions\n")); | ||
1127 | return QLA_SUCCESS; | ||
1128 | } | ||
1129 | |||
978 | static struct iscsi_cls_session * | 1130 | static struct iscsi_cls_session * |
979 | qla4xxx_session_create(struct iscsi_endpoint *ep, | 1131 | qla4xxx_session_create(struct iscsi_endpoint *ep, |
980 | uint16_t cmds_max, uint16_t qdepth, | 1132 | uint16_t cmds_max, uint16_t qdepth, |
@@ -984,8 +1136,7 @@ qla4xxx_session_create(struct iscsi_endpoint *ep, | |||
984 | struct scsi_qla_host *ha; | 1136 | struct scsi_qla_host *ha; |
985 | struct qla_endpoint *qla_ep; | 1137 | struct qla_endpoint *qla_ep; |
986 | struct ddb_entry *ddb_entry; | 1138 | struct ddb_entry *ddb_entry; |
987 | uint32_t ddb_index; | 1139 | uint16_t ddb_index; |
988 | uint32_t mbx_sts = 0; | ||
989 | struct iscsi_session *sess; | 1140 | struct iscsi_session *sess; |
990 | struct sockaddr *dst_addr; | 1141 | struct sockaddr *dst_addr; |
991 | int ret; | 1142 | int ret; |
@@ -1000,32 +1151,9 @@ qla4xxx_session_create(struct iscsi_endpoint *ep, | |||
1000 | dst_addr = (struct sockaddr *)&qla_ep->dst_addr; | 1151 | dst_addr = (struct sockaddr *)&qla_ep->dst_addr; |
1001 | ha = to_qla_host(qla_ep->host); | 1152 | ha = to_qla_host(qla_ep->host); |
1002 | 1153 | ||
1003 | get_ddb_index: | 1154 | ret = qla4xxx_get_ddb_index(ha, &ddb_index); |
1004 | ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES); | 1155 | if (ret == QLA_ERROR) |
1005 | |||
1006 | if (ddb_index >= MAX_DDB_ENTRIES) { | ||
1007 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1008 | "Free DDB index not available\n")); | ||
1009 | return NULL; | ||
1010 | } | ||
1011 | |||
1012 | if (test_and_set_bit(ddb_index, ha->ddb_idx_map)) | ||
1013 | goto get_ddb_index; | ||
1014 | |||
1015 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1016 | "Found a free DDB index at %d\n", ddb_index)); | ||
1017 | ret = qla4xxx_req_ddb_entry(ha, ddb_index, &mbx_sts); | ||
1018 | if (ret == QLA_ERROR) { | ||
1019 | if (mbx_sts == MBOX_STS_COMMAND_ERROR) { | ||
1020 | ql4_printk(KERN_INFO, ha, | ||
1021 | "DDB index = %d not available trying next\n", | ||
1022 | ddb_index); | ||
1023 | goto get_ddb_index; | ||
1024 | } | ||
1025 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1026 | "Free FW DDB not available\n")); | ||
1027 | return NULL; | 1156 | return NULL; |
1028 | } | ||
1029 | 1157 | ||
1030 | cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, qla_ep->host, | 1158 | cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, qla_ep->host, |
1031 | cmds_max, sizeof(struct ddb_entry), | 1159 | cmds_max, sizeof(struct ddb_entry), |
@@ -1040,6 +1168,8 @@ get_ddb_index: | |||
1040 | ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE; | 1168 | ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE; |
1041 | ddb_entry->ha = ha; | 1169 | ddb_entry->ha = ha; |
1042 | ddb_entry->sess = cls_sess; | 1170 | ddb_entry->sess = cls_sess; |
1171 | ddb_entry->unblock_sess = qla4xxx_unblock_ddb; | ||
1172 | ddb_entry->ddb_change = qla4xxx_ddb_change; | ||
1043 | cls_sess->recovery_tmo = ql4xsess_recovery_tmo; | 1173 | cls_sess->recovery_tmo = ql4xsess_recovery_tmo; |
1044 | ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry; | 1174 | ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry; |
1045 | ha->tot_ddbs++; | 1175 | ha->tot_ddbs++; |
@@ -1077,6 +1207,9 @@ qla4xxx_conn_create(struct iscsi_cls_session *cls_sess, uint32_t conn_idx) | |||
1077 | DEBUG2(printk(KERN_INFO "Func: %s\n", __func__)); | 1207 | DEBUG2(printk(KERN_INFO "Func: %s\n", __func__)); |
1078 | cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), | 1208 | cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), |
1079 | conn_idx); | 1209 | conn_idx); |
1210 | if (!cls_conn) | ||
1211 | return NULL; | ||
1212 | |||
1080 | sess = cls_sess->dd_data; | 1213 | sess = cls_sess->dd_data; |
1081 | ddb_entry = sess->dd_data; | 1214 | ddb_entry = sess->dd_data; |
1082 | ddb_entry->conn = cls_conn; | 1215 | ddb_entry->conn = cls_conn; |
@@ -1109,7 +1242,7 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn) | |||
1109 | struct iscsi_session *sess; | 1242 | struct iscsi_session *sess; |
1110 | struct ddb_entry *ddb_entry; | 1243 | struct ddb_entry *ddb_entry; |
1111 | struct scsi_qla_host *ha; | 1244 | struct scsi_qla_host *ha; |
1112 | struct dev_db_entry *fw_ddb_entry; | 1245 | struct dev_db_entry *fw_ddb_entry = NULL; |
1113 | dma_addr_t fw_ddb_entry_dma; | 1246 | dma_addr_t fw_ddb_entry_dma; |
1114 | uint32_t mbx_sts = 0; | 1247 | uint32_t mbx_sts = 0; |
1115 | int ret = 0; | 1248 | int ret = 0; |
@@ -1120,12 +1253,25 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn) | |||
1120 | ddb_entry = sess->dd_data; | 1253 | ddb_entry = sess->dd_data; |
1121 | ha = ddb_entry->ha; | 1254 | ha = ddb_entry->ha; |
1122 | 1255 | ||
1256 | /* Check if we have matching FW DDB, if yes then do not | ||
1257 | * login to this target. This could cause target to logout previous | ||
1258 | * connection | ||
1259 | */ | ||
1260 | ret = qla4xxx_match_fwdb_session(ha, cls_conn); | ||
1261 | if (ret == QLA_SUCCESS) { | ||
1262 | ql4_printk(KERN_INFO, ha, | ||
1263 | "Session already exist in FW.\n"); | ||
1264 | ret = -EEXIST; | ||
1265 | goto exit_conn_start; | ||
1266 | } | ||
1267 | |||
1123 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | 1268 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), |
1124 | &fw_ddb_entry_dma, GFP_KERNEL); | 1269 | &fw_ddb_entry_dma, GFP_KERNEL); |
1125 | if (!fw_ddb_entry) { | 1270 | if (!fw_ddb_entry) { |
1126 | ql4_printk(KERN_ERR, ha, | 1271 | ql4_printk(KERN_ERR, ha, |
1127 | "%s: Unable to allocate dma buffer\n", __func__); | 1272 | "%s: Unable to allocate dma buffer\n", __func__); |
1128 | return -ENOMEM; | 1273 | ret = -ENOMEM; |
1274 | goto exit_conn_start; | ||
1129 | } | 1275 | } |
1130 | 1276 | ||
1131 | ret = qla4xxx_set_param_ddbentry(ha, ddb_entry, cls_conn, &mbx_sts); | 1277 | ret = qla4xxx_set_param_ddbentry(ha, ddb_entry, cls_conn, &mbx_sts); |
@@ -1138,9 +1284,7 @@ static int qla4xxx_conn_start(struct iscsi_cls_conn *cls_conn) | |||
1138 | if (mbx_sts) | 1284 | if (mbx_sts) |
1139 | if (ddb_entry->fw_ddb_device_state == | 1285 | if (ddb_entry->fw_ddb_device_state == |
1140 | DDB_DS_SESSION_ACTIVE) { | 1286 | DDB_DS_SESSION_ACTIVE) { |
1141 | iscsi_conn_start(ddb_entry->conn); | 1287 | ddb_entry->unblock_sess(ddb_entry->sess); |
1142 | iscsi_conn_login_event(ddb_entry->conn, | ||
1143 | ISCSI_CONN_STATE_LOGGED_IN); | ||
1144 | goto exit_set_param; | 1288 | goto exit_set_param; |
1145 | } | 1289 | } |
1146 | 1290 | ||
@@ -1167,8 +1311,9 @@ exit_set_param: | |||
1167 | ret = 0; | 1311 | ret = 0; |
1168 | 1312 | ||
1169 | exit_conn_start: | 1313 | exit_conn_start: |
1170 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | 1314 | if (fw_ddb_entry) |
1171 | fw_ddb_entry, fw_ddb_entry_dma); | 1315 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), |
1316 | fw_ddb_entry, fw_ddb_entry_dma); | ||
1172 | return ret; | 1317 | return ret; |
1173 | } | 1318 | } |
1174 | 1319 | ||
@@ -1344,6 +1489,101 @@ static int qla4xxx_task_xmit(struct iscsi_task *task) | |||
1344 | return -ENOSYS; | 1489 | return -ENOSYS; |
1345 | } | 1490 | } |
1346 | 1491 | ||
1492 | static void qla4xxx_copy_fwddb_param(struct scsi_qla_host *ha, | ||
1493 | struct dev_db_entry *fw_ddb_entry, | ||
1494 | struct iscsi_cls_session *cls_sess, | ||
1495 | struct iscsi_cls_conn *cls_conn) | ||
1496 | { | ||
1497 | int buflen = 0; | ||
1498 | struct iscsi_session *sess; | ||
1499 | struct iscsi_conn *conn; | ||
1500 | char ip_addr[DDB_IPADDR_LEN]; | ||
1501 | uint16_t options = 0; | ||
1502 | |||
1503 | sess = cls_sess->dd_data; | ||
1504 | conn = cls_conn->dd_data; | ||
1505 | |||
1506 | conn->max_recv_dlength = BYTE_UNITS * | ||
1507 | le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len); | ||
1508 | |||
1509 | conn->max_xmit_dlength = BYTE_UNITS * | ||
1510 | le16_to_cpu(fw_ddb_entry->iscsi_max_snd_data_seg_len); | ||
1511 | |||
1512 | sess->initial_r2t_en = | ||
1513 | (BIT_10 & le16_to_cpu(fw_ddb_entry->iscsi_options)); | ||
1514 | |||
1515 | sess->max_r2t = le16_to_cpu(fw_ddb_entry->iscsi_max_outsnd_r2t); | ||
1516 | |||
1517 | sess->imm_data_en = (BIT_11 & le16_to_cpu(fw_ddb_entry->iscsi_options)); | ||
1518 | |||
1519 | sess->first_burst = BYTE_UNITS * | ||
1520 | le16_to_cpu(fw_ddb_entry->iscsi_first_burst_len); | ||
1521 | |||
1522 | sess->max_burst = BYTE_UNITS * | ||
1523 | le16_to_cpu(fw_ddb_entry->iscsi_max_burst_len); | ||
1524 | |||
1525 | sess->time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); | ||
1526 | |||
1527 | sess->time2retain = le16_to_cpu(fw_ddb_entry->iscsi_def_time2retain); | ||
1528 | |||
1529 | conn->persistent_port = le16_to_cpu(fw_ddb_entry->port); | ||
1530 | |||
1531 | sess->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); | ||
1532 | |||
1533 | options = le16_to_cpu(fw_ddb_entry->options); | ||
1534 | if (options & DDB_OPT_IPV6_DEVICE) | ||
1535 | sprintf(ip_addr, "%pI6", fw_ddb_entry->ip_addr); | ||
1536 | else | ||
1537 | sprintf(ip_addr, "%pI4", fw_ddb_entry->ip_addr); | ||
1538 | |||
1539 | iscsi_set_param(cls_conn, ISCSI_PARAM_TARGET_NAME, | ||
1540 | (char *)fw_ddb_entry->iscsi_name, buflen); | ||
1541 | iscsi_set_param(cls_conn, ISCSI_PARAM_INITIATOR_NAME, | ||
1542 | (char *)ha->name_string, buflen); | ||
1543 | iscsi_set_param(cls_conn, ISCSI_PARAM_PERSISTENT_ADDRESS, | ||
1544 | (char *)ip_addr, buflen); | ||
1545 | } | ||
1546 | |||
1547 | void qla4xxx_update_session_conn_fwddb_param(struct scsi_qla_host *ha, | ||
1548 | struct ddb_entry *ddb_entry) | ||
1549 | { | ||
1550 | struct iscsi_cls_session *cls_sess; | ||
1551 | struct iscsi_cls_conn *cls_conn; | ||
1552 | uint32_t ddb_state; | ||
1553 | dma_addr_t fw_ddb_entry_dma; | ||
1554 | struct dev_db_entry *fw_ddb_entry; | ||
1555 | |||
1556 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
1557 | &fw_ddb_entry_dma, GFP_KERNEL); | ||
1558 | if (!fw_ddb_entry) { | ||
1559 | ql4_printk(KERN_ERR, ha, | ||
1560 | "%s: Unable to allocate dma buffer\n", __func__); | ||
1561 | goto exit_session_conn_fwddb_param; | ||
1562 | } | ||
1563 | |||
1564 | if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry, | ||
1565 | fw_ddb_entry_dma, NULL, NULL, &ddb_state, | ||
1566 | NULL, NULL, NULL) == QLA_ERROR) { | ||
1567 | DEBUG2(ql4_printk(KERN_ERR, ha, "scsi%ld: %s: failed " | ||
1568 | "get_ddb_entry for fw_ddb_index %d\n", | ||
1569 | ha->host_no, __func__, | ||
1570 | ddb_entry->fw_ddb_index)); | ||
1571 | goto exit_session_conn_fwddb_param; | ||
1572 | } | ||
1573 | |||
1574 | cls_sess = ddb_entry->sess; | ||
1575 | |||
1576 | cls_conn = ddb_entry->conn; | ||
1577 | |||
1578 | /* Update params */ | ||
1579 | qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn); | ||
1580 | |||
1581 | exit_session_conn_fwddb_param: | ||
1582 | if (fw_ddb_entry) | ||
1583 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
1584 | fw_ddb_entry, fw_ddb_entry_dma); | ||
1585 | } | ||
1586 | |||
1347 | void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, | 1587 | void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, |
1348 | struct ddb_entry *ddb_entry) | 1588 | struct ddb_entry *ddb_entry) |
1349 | { | 1589 | { |
@@ -1360,7 +1600,7 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, | |||
1360 | if (!fw_ddb_entry) { | 1600 | if (!fw_ddb_entry) { |
1361 | ql4_printk(KERN_ERR, ha, | 1601 | ql4_printk(KERN_ERR, ha, |
1362 | "%s: Unable to allocate dma buffer\n", __func__); | 1602 | "%s: Unable to allocate dma buffer\n", __func__); |
1363 | return; | 1603 | goto exit_session_conn_param; |
1364 | } | 1604 | } |
1365 | 1605 | ||
1366 | if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry, | 1606 | if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, fw_ddb_entry, |
@@ -1370,7 +1610,7 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, | |||
1370 | "get_ddb_entry for fw_ddb_index %d\n", | 1610 | "get_ddb_entry for fw_ddb_index %d\n", |
1371 | ha->host_no, __func__, | 1611 | ha->host_no, __func__, |
1372 | ddb_entry->fw_ddb_index)); | 1612 | ddb_entry->fw_ddb_index)); |
1373 | return; | 1613 | goto exit_session_conn_param; |
1374 | } | 1614 | } |
1375 | 1615 | ||
1376 | cls_sess = ddb_entry->sess; | 1616 | cls_sess = ddb_entry->sess; |
@@ -1379,6 +1619,12 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, | |||
1379 | cls_conn = ddb_entry->conn; | 1619 | cls_conn = ddb_entry->conn; |
1380 | conn = cls_conn->dd_data; | 1620 | conn = cls_conn->dd_data; |
1381 | 1621 | ||
1622 | /* Update timers after login */ | ||
1623 | ddb_entry->default_relogin_timeout = | ||
1624 | le16_to_cpu(fw_ddb_entry->def_timeout); | ||
1625 | ddb_entry->default_time2wait = | ||
1626 | le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); | ||
1627 | |||
1382 | /* Update params */ | 1628 | /* Update params */ |
1383 | conn->max_recv_dlength = BYTE_UNITS * | 1629 | conn->max_recv_dlength = BYTE_UNITS * |
1384 | le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len); | 1630 | le16_to_cpu(fw_ddb_entry->iscsi_max_rcv_data_seg_len); |
@@ -1407,6 +1653,11 @@ void qla4xxx_update_session_conn_param(struct scsi_qla_host *ha, | |||
1407 | 1653 | ||
1408 | memcpy(sess->initiatorname, ha->name_string, | 1654 | memcpy(sess->initiatorname, ha->name_string, |
1409 | min(sizeof(ha->name_string), sizeof(sess->initiatorname))); | 1655 | min(sizeof(ha->name_string), sizeof(sess->initiatorname))); |
1656 | |||
1657 | exit_session_conn_param: | ||
1658 | if (fw_ddb_entry) | ||
1659 | dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | ||
1660 | fw_ddb_entry, fw_ddb_entry_dma); | ||
1410 | } | 1661 | } |
1411 | 1662 | ||
1412 | /* | 1663 | /* |
@@ -1607,6 +1858,9 @@ static void qla4xxx_mem_free(struct scsi_qla_host *ha) | |||
1607 | vfree(ha->chap_list); | 1858 | vfree(ha->chap_list); |
1608 | ha->chap_list = NULL; | 1859 | ha->chap_list = NULL; |
1609 | 1860 | ||
1861 | if (ha->fw_ddb_dma_pool) | ||
1862 | dma_pool_destroy(ha->fw_ddb_dma_pool); | ||
1863 | |||
1610 | /* release io space registers */ | 1864 | /* release io space registers */ |
1611 | if (is_qla8022(ha)) { | 1865 | if (is_qla8022(ha)) { |
1612 | if (ha->nx_pcibase) | 1866 | if (ha->nx_pcibase) |
@@ -1689,6 +1943,16 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha) | |||
1689 | goto mem_alloc_error_exit; | 1943 | goto mem_alloc_error_exit; |
1690 | } | 1944 | } |
1691 | 1945 | ||
1946 | ha->fw_ddb_dma_pool = dma_pool_create("ql4_fw_ddb", &ha->pdev->dev, | ||
1947 | DDB_DMA_BLOCK_SIZE, 8, 0); | ||
1948 | |||
1949 | if (ha->fw_ddb_dma_pool == NULL) { | ||
1950 | ql4_printk(KERN_WARNING, ha, | ||
1951 | "%s: fw_ddb_dma_pool allocation failed..\n", | ||
1952 | __func__); | ||
1953 | goto mem_alloc_error_exit; | ||
1954 | } | ||
1955 | |||
1692 | return QLA_SUCCESS; | 1956 | return QLA_SUCCESS; |
1693 | 1957 | ||
1694 | mem_alloc_error_exit: | 1958 | mem_alloc_error_exit: |
@@ -1800,6 +2064,60 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha) | |||
1800 | } | 2064 | } |
1801 | } | 2065 | } |
1802 | 2066 | ||
2067 | void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess) | ||
2068 | { | ||
2069 | struct iscsi_session *sess; | ||
2070 | struct ddb_entry *ddb_entry; | ||
2071 | struct scsi_qla_host *ha; | ||
2072 | |||
2073 | sess = cls_sess->dd_data; | ||
2074 | ddb_entry = sess->dd_data; | ||
2075 | ha = ddb_entry->ha; | ||
2076 | |||
2077 | if (!(ddb_entry->ddb_type == FLASH_DDB)) | ||
2078 | return; | ||
2079 | |||
2080 | if (adapter_up(ha) && !test_bit(DF_RELOGIN, &ddb_entry->flags) && | ||
2081 | !iscsi_is_session_online(cls_sess)) { | ||
2082 | if (atomic_read(&ddb_entry->retry_relogin_timer) != | ||
2083 | INVALID_ENTRY) { | ||
2084 | if (atomic_read(&ddb_entry->retry_relogin_timer) == | ||
2085 | 0) { | ||
2086 | atomic_set(&ddb_entry->retry_relogin_timer, | ||
2087 | INVALID_ENTRY); | ||
2088 | set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); | ||
2089 | set_bit(DF_RELOGIN, &ddb_entry->flags); | ||
2090 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2091 | "%s: index [%d] login device\n", | ||
2092 | __func__, ddb_entry->fw_ddb_index)); | ||
2093 | } else | ||
2094 | atomic_dec(&ddb_entry->retry_relogin_timer); | ||
2095 | } | ||
2096 | } | ||
2097 | |||
2098 | /* Wait for relogin to timeout */ | ||
2099 | if (atomic_read(&ddb_entry->relogin_timer) && | ||
2100 | (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) { | ||
2101 | /* | ||
2102 | * If the relogin times out and the device is | ||
2103 | * still NOT ONLINE then try and relogin again. | ||
2104 | */ | ||
2105 | if (!iscsi_is_session_online(cls_sess)) { | ||
2106 | /* Reset retry relogin timer */ | ||
2107 | atomic_inc(&ddb_entry->relogin_retry_count); | ||
2108 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2109 | "%s: index[%d] relogin timed out-retrying" | ||
2110 | " relogin (%d), retry (%d)\n", __func__, | ||
2111 | ddb_entry->fw_ddb_index, | ||
2112 | atomic_read(&ddb_entry->relogin_retry_count), | ||
2113 | ddb_entry->default_time2wait + 4)); | ||
2114 | set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); | ||
2115 | atomic_set(&ddb_entry->retry_relogin_timer, | ||
2116 | ddb_entry->default_time2wait + 4); | ||
2117 | } | ||
2118 | } | ||
2119 | } | ||
2120 | |||
1803 | /** | 2121 | /** |
1804 | * qla4xxx_timer - checks every second for work to do. | 2122 | * qla4xxx_timer - checks every second for work to do. |
1805 | * @ha: Pointer to host adapter structure. | 2123 | * @ha: Pointer to host adapter structure. |
@@ -1809,6 +2127,8 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) | |||
1809 | int start_dpc = 0; | 2127 | int start_dpc = 0; |
1810 | uint16_t w; | 2128 | uint16_t w; |
1811 | 2129 | ||
2130 | iscsi_host_for_each_session(ha->host, qla4xxx_check_relogin_flash_ddb); | ||
2131 | |||
1812 | /* If we are in the middle of AER/EEH processing | 2132 | /* If we are in the middle of AER/EEH processing |
1813 | * skip any processing and reschedule the timer | 2133 | * skip any processing and reschedule the timer |
1814 | */ | 2134 | */ |
@@ -2078,7 +2398,12 @@ static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session) | |||
2078 | sess = cls_session->dd_data; | 2398 | sess = cls_session->dd_data; |
2079 | ddb_entry = sess->dd_data; | 2399 | ddb_entry = sess->dd_data; |
2080 | ddb_entry->fw_ddb_device_state = DDB_DS_SESSION_FAILED; | 2400 | ddb_entry->fw_ddb_device_state = DDB_DS_SESSION_FAILED; |
2081 | iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); | 2401 | |
2402 | if (ddb_entry->ddb_type == FLASH_DDB) | ||
2403 | iscsi_block_session(ddb_entry->sess); | ||
2404 | else | ||
2405 | iscsi_session_failure(cls_session->dd_data, | ||
2406 | ISCSI_ERR_CONN_FAILED); | ||
2082 | } | 2407 | } |
2083 | 2408 | ||
2084 | /** | 2409 | /** |
@@ -2163,7 +2488,7 @@ recover_ha_init_adapter: | |||
2163 | 2488 | ||
2164 | /* NOTE: AF_ONLINE flag set upon successful completion of | 2489 | /* NOTE: AF_ONLINE flag set upon successful completion of |
2165 | * qla4xxx_initialize_adapter */ | 2490 | * qla4xxx_initialize_adapter */ |
2166 | status = qla4xxx_initialize_adapter(ha); | 2491 | status = qla4xxx_initialize_adapter(ha, RESET_ADAPTER); |
2167 | } | 2492 | } |
2168 | 2493 | ||
2169 | /* Retry failed adapter initialization, if necessary | 2494 | /* Retry failed adapter initialization, if necessary |
@@ -2245,17 +2570,108 @@ static void qla4xxx_relogin_devices(struct iscsi_cls_session *cls_session) | |||
2245 | iscsi_unblock_session(ddb_entry->sess); | 2570 | iscsi_unblock_session(ddb_entry->sess); |
2246 | } else { | 2571 | } else { |
2247 | /* Trigger relogin */ | 2572 | /* Trigger relogin */ |
2248 | iscsi_session_failure(cls_session->dd_data, | 2573 | if (ddb_entry->ddb_type == FLASH_DDB) { |
2249 | ISCSI_ERR_CONN_FAILED); | 2574 | if (!test_bit(DF_RELOGIN, &ddb_entry->flags)) |
2575 | qla4xxx_arm_relogin_timer(ddb_entry); | ||
2576 | } else | ||
2577 | iscsi_session_failure(cls_session->dd_data, | ||
2578 | ISCSI_ERR_CONN_FAILED); | ||
2250 | } | 2579 | } |
2251 | } | 2580 | } |
2252 | } | 2581 | } |
2253 | 2582 | ||
2583 | int qla4xxx_unblock_flash_ddb(struct iscsi_cls_session *cls_session) | ||
2584 | { | ||
2585 | struct iscsi_session *sess; | ||
2586 | struct ddb_entry *ddb_entry; | ||
2587 | struct scsi_qla_host *ha; | ||
2588 | |||
2589 | sess = cls_session->dd_data; | ||
2590 | ddb_entry = sess->dd_data; | ||
2591 | ha = ddb_entry->ha; | ||
2592 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" | ||
2593 | " unblock session\n", ha->host_no, __func__, | ||
2594 | ddb_entry->fw_ddb_index); | ||
2595 | |||
2596 | iscsi_unblock_session(ddb_entry->sess); | ||
2597 | |||
2598 | /* Start scan target */ | ||
2599 | if (test_bit(AF_ONLINE, &ha->flags)) { | ||
2600 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" | ||
2601 | " start scan\n", ha->host_no, __func__, | ||
2602 | ddb_entry->fw_ddb_index); | ||
2603 | scsi_queue_work(ha->host, &ddb_entry->sess->scan_work); | ||
2604 | } | ||
2605 | return QLA_SUCCESS; | ||
2606 | } | ||
2607 | |||
2608 | int qla4xxx_unblock_ddb(struct iscsi_cls_session *cls_session) | ||
2609 | { | ||
2610 | struct iscsi_session *sess; | ||
2611 | struct ddb_entry *ddb_entry; | ||
2612 | struct scsi_qla_host *ha; | ||
2613 | |||
2614 | sess = cls_session->dd_data; | ||
2615 | ddb_entry = sess->dd_data; | ||
2616 | ha = ddb_entry->ha; | ||
2617 | ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]" | ||
2618 | " unblock user space session\n", ha->host_no, __func__, | ||
2619 | ddb_entry->fw_ddb_index); | ||
2620 | iscsi_conn_start(ddb_entry->conn); | ||
2621 | iscsi_conn_login_event(ddb_entry->conn, | ||
2622 | ISCSI_CONN_STATE_LOGGED_IN); | ||
2623 | |||
2624 | return QLA_SUCCESS; | ||
2625 | } | ||
2626 | |||
2254 | static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha) | 2627 | static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha) |
2255 | { | 2628 | { |
2256 | iscsi_host_for_each_session(ha->host, qla4xxx_relogin_devices); | 2629 | iscsi_host_for_each_session(ha->host, qla4xxx_relogin_devices); |
2257 | } | 2630 | } |
2258 | 2631 | ||
2632 | static void qla4xxx_relogin_flash_ddb(struct iscsi_cls_session *cls_sess) | ||
2633 | { | ||
2634 | uint16_t relogin_timer; | ||
2635 | struct iscsi_session *sess; | ||
2636 | struct ddb_entry *ddb_entry; | ||
2637 | struct scsi_qla_host *ha; | ||
2638 | |||
2639 | sess = cls_sess->dd_data; | ||
2640 | ddb_entry = sess->dd_data; | ||
2641 | ha = ddb_entry->ha; | ||
2642 | |||
2643 | relogin_timer = max(ddb_entry->default_relogin_timeout, | ||
2644 | (uint16_t)RELOGIN_TOV); | ||
2645 | atomic_set(&ddb_entry->relogin_timer, relogin_timer); | ||
2646 | |||
2647 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2648 | "scsi%ld: Relogin index [%d]. TOV=%d\n", ha->host_no, | ||
2649 | ddb_entry->fw_ddb_index, relogin_timer)); | ||
2650 | |||
2651 | qla4xxx_login_flash_ddb(cls_sess); | ||
2652 | } | ||
2653 | |||
2654 | static void qla4xxx_dpc_relogin(struct iscsi_cls_session *cls_sess) | ||
2655 | { | ||
2656 | struct iscsi_session *sess; | ||
2657 | struct ddb_entry *ddb_entry; | ||
2658 | struct scsi_qla_host *ha; | ||
2659 | |||
2660 | sess = cls_sess->dd_data; | ||
2661 | ddb_entry = sess->dd_data; | ||
2662 | ha = ddb_entry->ha; | ||
2663 | |||
2664 | if (!(ddb_entry->ddb_type == FLASH_DDB)) | ||
2665 | return; | ||
2666 | |||
2667 | if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) && | ||
2668 | !iscsi_is_session_online(cls_sess)) { | ||
2669 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2670 | "relogin issued\n")); | ||
2671 | qla4xxx_relogin_flash_ddb(cls_sess); | ||
2672 | } | ||
2673 | } | ||
2674 | |||
2259 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha) | 2675 | void qla4xxx_wake_dpc(struct scsi_qla_host *ha) |
2260 | { | 2676 | { |
2261 | if (ha->dpc_thread) | 2677 | if (ha->dpc_thread) |
@@ -2356,6 +2772,12 @@ dpc_post_reset_ha: | |||
2356 | if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags)) | 2772 | if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags)) |
2357 | qla4xxx_get_dhcp_ip_address(ha); | 2773 | qla4xxx_get_dhcp_ip_address(ha); |
2358 | 2774 | ||
2775 | /* ---- relogin device? --- */ | ||
2776 | if (adapter_up(ha) && | ||
2777 | test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) { | ||
2778 | iscsi_host_for_each_session(ha->host, qla4xxx_dpc_relogin); | ||
2779 | } | ||
2780 | |||
2359 | /* ---- link change? --- */ | 2781 | /* ---- link change? --- */ |
2360 | if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) { | 2782 | if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) { |
2361 | if (!test_bit(AF_LINK_UP, &ha->flags)) { | 2783 | if (!test_bit(AF_LINK_UP, &ha->flags)) { |
@@ -2368,8 +2790,12 @@ dpc_post_reset_ha: | |||
2368 | * fatal error recovery. Therefore, the driver must | 2790 | * fatal error recovery. Therefore, the driver must |
2369 | * manually relogin to devices when recovering from | 2791 | * manually relogin to devices when recovering from |
2370 | * connection failures, logouts, expired KATO, etc. */ | 2792 | * connection failures, logouts, expired KATO, etc. */ |
2371 | 2793 | if (test_and_clear_bit(AF_BUILD_DDB_LIST, &ha->flags)) { | |
2372 | qla4xxx_relogin_all_devices(ha); | 2794 | qla4xxx_build_ddb_list(ha, ha->is_reset); |
2795 | iscsi_host_for_each_session(ha->host, | ||
2796 | qla4xxx_login_flash_ddb); | ||
2797 | } else | ||
2798 | qla4xxx_relogin_all_devices(ha); | ||
2373 | } | 2799 | } |
2374 | } | 2800 | } |
2375 | } | 2801 | } |
@@ -2867,6 +3293,9 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[]) | |||
2867 | " target ID %d\n", __func__, ddb_index[0], | 3293 | " target ID %d\n", __func__, ddb_index[0], |
2868 | ddb_index[1])); | 3294 | ddb_index[1])); |
2869 | 3295 | ||
3296 | ha->pri_ddb_idx = ddb_index[0]; | ||
3297 | ha->sec_ddb_idx = ddb_index[1]; | ||
3298 | |||
2870 | exit_boot_info_free: | 3299 | exit_boot_info_free: |
2871 | dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma); | 3300 | dma_free_coherent(&ha->pdev->dev, size, buf, buf_dma); |
2872 | exit_boot_info: | 3301 | exit_boot_info: |
@@ -3034,6 +3463,9 @@ static int qla4xxx_get_boot_info(struct scsi_qla_host *ha) | |||
3034 | return ret; | 3463 | return ret; |
3035 | } | 3464 | } |
3036 | 3465 | ||
3466 | if (ql4xdisablesysfsboot) | ||
3467 | return QLA_SUCCESS; | ||
3468 | |||
3037 | if (ddb_index[0] == 0xffff) | 3469 | if (ddb_index[0] == 0xffff) |
3038 | goto sec_target; | 3470 | goto sec_target; |
3039 | 3471 | ||
@@ -3066,7 +3498,15 @@ static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha) | |||
3066 | struct iscsi_boot_kobj *boot_kobj; | 3498 | struct iscsi_boot_kobj *boot_kobj; |
3067 | 3499 | ||
3068 | if (qla4xxx_get_boot_info(ha) != QLA_SUCCESS) | 3500 | if (qla4xxx_get_boot_info(ha) != QLA_SUCCESS) |
3069 | return 0; | 3501 | return QLA_ERROR; |
3502 | |||
3503 | if (ql4xdisablesysfsboot) { | ||
3504 | ql4_printk(KERN_INFO, ha, | ||
3505 | "%s: syfsboot disabled - driver will trigger login" | ||
3506 | "and publish session for discovery .\n", __func__); | ||
3507 | return QLA_SUCCESS; | ||
3508 | } | ||
3509 | |||
3070 | 3510 | ||
3071 | ha->boot_kset = iscsi_boot_create_host_kset(ha->host->host_no); | 3511 | ha->boot_kset = iscsi_boot_create_host_kset(ha->host->host_no); |
3072 | if (!ha->boot_kset) | 3512 | if (!ha->boot_kset) |
@@ -3108,7 +3548,7 @@ static int qla4xxx_setup_boot_info(struct scsi_qla_host *ha) | |||
3108 | if (!boot_kobj) | 3548 | if (!boot_kobj) |
3109 | goto put_host; | 3549 | goto put_host; |
3110 | 3550 | ||
3111 | return 0; | 3551 | return QLA_SUCCESS; |
3112 | 3552 | ||
3113 | put_host: | 3553 | put_host: |
3114 | scsi_host_put(ha->host); | 3554 | scsi_host_put(ha->host); |
@@ -3174,9 +3614,507 @@ static void qla4xxx_create_chap_list(struct scsi_qla_host *ha) | |||
3174 | exit_chap_list: | 3614 | exit_chap_list: |
3175 | dma_free_coherent(&ha->pdev->dev, chap_size, | 3615 | dma_free_coherent(&ha->pdev->dev, chap_size, |
3176 | chap_flash_data, chap_dma); | 3616 | chap_flash_data, chap_dma); |
3177 | return; | ||
3178 | } | 3617 | } |
3179 | 3618 | ||
3619 | static void qla4xxx_get_param_ddb(struct ddb_entry *ddb_entry, | ||
3620 | struct ql4_tuple_ddb *tddb) | ||
3621 | { | ||
3622 | struct scsi_qla_host *ha; | ||
3623 | struct iscsi_cls_session *cls_sess; | ||
3624 | struct iscsi_cls_conn *cls_conn; | ||
3625 | struct iscsi_session *sess; | ||
3626 | struct iscsi_conn *conn; | ||
3627 | |||
3628 | DEBUG2(printk(KERN_INFO "Func: %s\n", __func__)); | ||
3629 | ha = ddb_entry->ha; | ||
3630 | cls_sess = ddb_entry->sess; | ||
3631 | sess = cls_sess->dd_data; | ||
3632 | cls_conn = ddb_entry->conn; | ||
3633 | conn = cls_conn->dd_data; | ||
3634 | |||
3635 | tddb->tpgt = sess->tpgt; | ||
3636 | tddb->port = conn->persistent_port; | ||
3637 | strncpy(tddb->iscsi_name, sess->targetname, ISCSI_NAME_SIZE); | ||
3638 | strncpy(tddb->ip_addr, conn->persistent_address, DDB_IPADDR_LEN); | ||
3639 | } | ||
3640 | |||
3641 | static void qla4xxx_convert_param_ddb(struct dev_db_entry *fw_ddb_entry, | ||
3642 | struct ql4_tuple_ddb *tddb) | ||
3643 | { | ||
3644 | uint16_t options = 0; | ||
3645 | |||
3646 | tddb->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); | ||
3647 | memcpy(&tddb->iscsi_name[0], &fw_ddb_entry->iscsi_name[0], | ||
3648 | min(sizeof(tddb->iscsi_name), sizeof(fw_ddb_entry->iscsi_name))); | ||
3649 | |||
3650 | options = le16_to_cpu(fw_ddb_entry->options); | ||
3651 | if (options & DDB_OPT_IPV6_DEVICE) | ||
3652 | sprintf(tddb->ip_addr, "%pI6", fw_ddb_entry->ip_addr); | ||
3653 | else | ||
3654 | sprintf(tddb->ip_addr, "%pI4", fw_ddb_entry->ip_addr); | ||
3655 | |||
3656 | tddb->port = le16_to_cpu(fw_ddb_entry->port); | ||
3657 | } | ||
3658 | |||
3659 | static int qla4xxx_compare_tuple_ddb(struct scsi_qla_host *ha, | ||
3660 | struct ql4_tuple_ddb *old_tddb, | ||
3661 | struct ql4_tuple_ddb *new_tddb) | ||
3662 | { | ||
3663 | if (strcmp(old_tddb->iscsi_name, new_tddb->iscsi_name)) | ||
3664 | return QLA_ERROR; | ||
3665 | |||
3666 | if (strcmp(old_tddb->ip_addr, new_tddb->ip_addr)) | ||
3667 | return QLA_ERROR; | ||
3668 | |||
3669 | if (old_tddb->port != new_tddb->port) | ||
3670 | return QLA_ERROR; | ||
3671 | |||
3672 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
3673 | "Match Found, fw[%d,%d,%s,%s], [%d,%d,%s,%s]", | ||
3674 | old_tddb->port, old_tddb->tpgt, old_tddb->ip_addr, | ||
3675 | old_tddb->iscsi_name, new_tddb->port, new_tddb->tpgt, | ||
3676 | new_tddb->ip_addr, new_tddb->iscsi_name)); | ||
3677 | |||
3678 | return QLA_SUCCESS; | ||
3679 | } | ||
3680 | |||
3681 | static int qla4xxx_is_session_exists(struct scsi_qla_host *ha, | ||
3682 | struct dev_db_entry *fw_ddb_entry) | ||
3683 | { | ||
3684 | struct ddb_entry *ddb_entry; | ||
3685 | struct ql4_tuple_ddb *fw_tddb = NULL; | ||
3686 | struct ql4_tuple_ddb *tmp_tddb = NULL; | ||
3687 | int idx; | ||
3688 | int ret = QLA_ERROR; | ||
3689 | |||
3690 | fw_tddb = vzalloc(sizeof(*fw_tddb)); | ||
3691 | if (!fw_tddb) { | ||
3692 | DEBUG2(ql4_printk(KERN_WARNING, ha, | ||
3693 | "Memory Allocation failed.\n")); | ||
3694 | ret = QLA_SUCCESS; | ||
3695 | goto exit_check; | ||
3696 | } | ||
3697 | |||
3698 | tmp_tddb = vzalloc(sizeof(*tmp_tddb)); | ||
3699 | if (!tmp_tddb) { | ||
3700 | DEBUG2(ql4_printk(KERN_WARNING, ha, | ||
3701 | "Memory Allocation failed.\n")); | ||
3702 | ret = QLA_SUCCESS; | ||
3703 | goto exit_check; | ||
3704 | } | ||
3705 | |||
3706 | qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb); | ||
3707 | |||
3708 | for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) { | ||
3709 | ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); | ||
3710 | if (ddb_entry == NULL) | ||
3711 | continue; | ||
3712 | |||
3713 | qla4xxx_get_param_ddb(ddb_entry, tmp_tddb); | ||
3714 | if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) { | ||
3715 | ret = QLA_SUCCESS; /* found */ | ||
3716 | goto exit_check; | ||
3717 | } | ||
3718 | } | ||
3719 | |||
3720 | exit_check: | ||
3721 | if (fw_tddb) | ||
3722 | vfree(fw_tddb); | ||
3723 | if (tmp_tddb) | ||
3724 | vfree(tmp_tddb); | ||
3725 | return ret; | ||
3726 | } | ||
3727 | |||
3728 | static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha, | ||
3729 | struct list_head *list_nt, | ||
3730 | struct dev_db_entry *fw_ddb_entry) | ||
3731 | { | ||
3732 | struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp; | ||
3733 | struct ql4_tuple_ddb *fw_tddb = NULL; | ||
3734 | struct ql4_tuple_ddb *tmp_tddb = NULL; | ||
3735 | int ret = QLA_ERROR; | ||
3736 | |||
3737 | fw_tddb = vzalloc(sizeof(*fw_tddb)); | ||
3738 | if (!fw_tddb) { | ||
3739 | DEBUG2(ql4_printk(KERN_WARNING, ha, | ||
3740 | "Memory Allocation failed.\n")); | ||
3741 | ret = QLA_SUCCESS; | ||
3742 | goto exit_check; | ||
3743 | } | ||
3744 | |||
3745 | tmp_tddb = vzalloc(sizeof(*tmp_tddb)); | ||
3746 | if (!tmp_tddb) { | ||
3747 | DEBUG2(ql4_printk(KERN_WARNING, ha, | ||
3748 | "Memory Allocation failed.\n")); | ||
3749 | ret = QLA_SUCCESS; | ||
3750 | goto exit_check; | ||
3751 | } | ||
3752 | |||
3753 | qla4xxx_convert_param_ddb(fw_ddb_entry, fw_tddb); | ||
3754 | |||
3755 | list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) { | ||
3756 | qla4xxx_convert_param_ddb(&nt_ddb_idx->fw_ddb, tmp_tddb); | ||
3757 | if (!qla4xxx_compare_tuple_ddb(ha, fw_tddb, tmp_tddb)) { | ||
3758 | ret = QLA_SUCCESS; /* found */ | ||
3759 | goto exit_check; | ||
3760 | } | ||
3761 | } | ||
3762 | |||
3763 | exit_check: | ||
3764 | if (fw_tddb) | ||
3765 | vfree(fw_tddb); | ||
3766 | if (tmp_tddb) | ||
3767 | vfree(tmp_tddb); | ||
3768 | return ret; | ||
3769 | } | ||
3770 | |||
3771 | static void qla4xxx_free_nt_list(struct list_head *list_nt) | ||
3772 | { | ||
3773 | struct qla_ddb_index *nt_ddb_idx, *nt_ddb_idx_tmp; | ||
3774 | |||
3775 | /* Free up the normaltargets list */ | ||
3776 | list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) { | ||
3777 | list_del_init(&nt_ddb_idx->list); | ||
3778 | vfree(nt_ddb_idx); | ||
3779 | } | ||
3780 | |||
3781 | } | ||
3782 | |||
3783 | static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha, | ||
3784 | struct dev_db_entry *fw_ddb_entry) | ||
3785 | { | ||
3786 | struct iscsi_endpoint *ep; | ||
3787 | struct sockaddr_in *addr; | ||
3788 | struct sockaddr_in6 *addr6; | ||
3789 | struct sockaddr *dst_addr; | ||
3790 | char *ip; | ||
3791 | |||
3792 | /* TODO: need to destroy on unload iscsi_endpoint*/ | ||
3793 | dst_addr = vmalloc(sizeof(*dst_addr)); | ||
3794 | if (!dst_addr) | ||
3795 | return NULL; | ||
3796 | |||
3797 | if (fw_ddb_entry->options & DDB_OPT_IPV6_DEVICE) { | ||
3798 | dst_addr->sa_family = AF_INET6; | ||
3799 | addr6 = (struct sockaddr_in6 *)dst_addr; | ||
3800 | ip = (char *)&addr6->sin6_addr; | ||
3801 | memcpy(ip, fw_ddb_entry->ip_addr, IPv6_ADDR_LEN); | ||
3802 | addr6->sin6_port = htons(le16_to_cpu(fw_ddb_entry->port)); | ||
3803 | |||
3804 | } else { | ||
3805 | dst_addr->sa_family = AF_INET; | ||
3806 | addr = (struct sockaddr_in *)dst_addr; | ||
3807 | ip = (char *)&addr->sin_addr; | ||
3808 | memcpy(ip, fw_ddb_entry->ip_addr, IP_ADDR_LEN); | ||
3809 | addr->sin_port = htons(le16_to_cpu(fw_ddb_entry->port)); | ||
3810 | } | ||
3811 | |||
3812 | ep = qla4xxx_ep_connect(ha->host, dst_addr, 0); | ||
3813 | vfree(dst_addr); | ||
3814 | return ep; | ||
3815 | } | ||
3816 | |||
3817 | static int qla4xxx_verify_boot_idx(struct scsi_qla_host *ha, uint16_t idx) | ||
3818 | { | ||
3819 | if (ql4xdisablesysfsboot) | ||
3820 | return QLA_SUCCESS; | ||
3821 | if (idx == ha->pri_ddb_idx || idx == ha->sec_ddb_idx) | ||
3822 | return QLA_ERROR; | ||
3823 | return QLA_SUCCESS; | ||
3824 | } | ||
3825 | |||
3826 | static void qla4xxx_setup_flash_ddb_entry(struct scsi_qla_host *ha, | ||
3827 | struct ddb_entry *ddb_entry) | ||
3828 | { | ||
3829 | ddb_entry->ddb_type = FLASH_DDB; | ||
3830 | ddb_entry->fw_ddb_index = INVALID_ENTRY; | ||
3831 | ddb_entry->fw_ddb_device_state = DDB_DS_NO_CONNECTION_ACTIVE; | ||
3832 | ddb_entry->ha = ha; | ||
3833 | ddb_entry->unblock_sess = qla4xxx_unblock_flash_ddb; | ||
3834 | ddb_entry->ddb_change = qla4xxx_flash_ddb_change; | ||
3835 | |||
3836 | atomic_set(&ddb_entry->retry_relogin_timer, INVALID_ENTRY); | ||
3837 | atomic_set(&ddb_entry->relogin_timer, 0); | ||
3838 | atomic_set(&ddb_entry->relogin_retry_count, 0); | ||
3839 | |||
3840 | ddb_entry->default_relogin_timeout = | ||
3841 | le16_to_cpu(ddb_entry->fw_ddb_entry.def_timeout); | ||
3842 | ddb_entry->default_time2wait = | ||
3843 | le16_to_cpu(ddb_entry->fw_ddb_entry.iscsi_def_time2wait); | ||
3844 | } | ||
3845 | |||
3846 | static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha) | ||
3847 | { | ||
3848 | uint32_t idx = 0; | ||
3849 | uint32_t ip_idx[IP_ADDR_COUNT] = {0, 1, 2, 3}; /* 4 IP interfaces */ | ||
3850 | uint32_t sts[MBOX_REG_COUNT]; | ||
3851 | uint32_t ip_state; | ||
3852 | unsigned long wtime; | ||
3853 | int ret; | ||
3854 | |||
3855 | wtime = jiffies + (HZ * IP_CONFIG_TOV); | ||
3856 | do { | ||
3857 | for (idx = 0; idx < IP_ADDR_COUNT; idx++) { | ||
3858 | if (ip_idx[idx] == -1) | ||
3859 | continue; | ||
3860 | |||
3861 | ret = qla4xxx_get_ip_state(ha, 0, ip_idx[idx], sts); | ||
3862 | |||
3863 | if (ret == QLA_ERROR) { | ||
3864 | ip_idx[idx] = -1; | ||
3865 | continue; | ||
3866 | } | ||
3867 | |||
3868 | ip_state = (sts[1] & IP_STATE_MASK) >> IP_STATE_SHIFT; | ||
3869 | |||
3870 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
3871 | "Waiting for IP state for idx = %d, state = 0x%x\n", | ||
3872 | ip_idx[idx], ip_state)); | ||
3873 | if (ip_state == IP_ADDRSTATE_UNCONFIGURED || | ||
3874 | ip_state == IP_ADDRSTATE_INVALID || | ||
3875 | ip_state == IP_ADDRSTATE_PREFERRED || | ||
3876 | ip_state == IP_ADDRSTATE_DEPRICATED || | ||
3877 | ip_state == IP_ADDRSTATE_DISABLING) | ||
3878 | ip_idx[idx] = -1; | ||
3879 | |||
3880 | } | ||
3881 | |||
3882 | /* Break if all IP states checked */ | ||
3883 | if ((ip_idx[0] == -1) && | ||
3884 | (ip_idx[1] == -1) && | ||
3885 | (ip_idx[2] == -1) && | ||
3886 | (ip_idx[3] == -1)) | ||
3887 | break; | ||
3888 | schedule_timeout_uninterruptible(HZ); | ||
3889 | } while (time_after(wtime, jiffies)); | ||
3890 | } | ||
3891 | |||
3892 | void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset) | ||
3893 | { | ||
3894 | int max_ddbs; | ||
3895 | int ret; | ||
3896 | uint32_t idx = 0, next_idx = 0; | ||
3897 | uint32_t state = 0, conn_err = 0; | ||
3898 | uint16_t conn_id; | ||
3899 | struct dev_db_entry *fw_ddb_entry; | ||
3900 | struct ddb_entry *ddb_entry = NULL; | ||
3901 | dma_addr_t fw_ddb_dma; | ||
3902 | struct iscsi_cls_session *cls_sess; | ||
3903 | struct iscsi_session *sess; | ||
3904 | struct iscsi_cls_conn *cls_conn; | ||
3905 | struct iscsi_endpoint *ep; | ||
3906 | uint16_t cmds_max = 32, tmo = 0; | ||
3907 | uint32_t initial_cmdsn = 0; | ||
3908 | struct list_head list_st, list_nt; /* List of sendtargets */ | ||
3909 | struct qla_ddb_index *st_ddb_idx, *st_ddb_idx_tmp; | ||
3910 | int fw_idx_size; | ||
3911 | unsigned long wtime; | ||
3912 | struct qla_ddb_index *nt_ddb_idx; | ||
3913 | |||
3914 | if (!test_bit(AF_LINK_UP, &ha->flags)) { | ||
3915 | set_bit(AF_BUILD_DDB_LIST, &ha->flags); | ||
3916 | ha->is_reset = is_reset; | ||
3917 | return; | ||
3918 | } | ||
3919 | max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX : | ||
3920 | MAX_DEV_DB_ENTRIES; | ||
3921 | |||
3922 | fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL, | ||
3923 | &fw_ddb_dma); | ||
3924 | if (fw_ddb_entry == NULL) { | ||
3925 | DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n")); | ||
3926 | goto exit_ddb_list; | ||
3927 | } | ||
3928 | |||
3929 | INIT_LIST_HEAD(&list_st); | ||
3930 | INIT_LIST_HEAD(&list_nt); | ||
3931 | fw_idx_size = sizeof(struct qla_ddb_index); | ||
3932 | |||
3933 | for (idx = 0; idx < max_ddbs; idx = next_idx) { | ||
3934 | ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, | ||
3935 | fw_ddb_dma, NULL, | ||
3936 | &next_idx, &state, &conn_err, | ||
3937 | NULL, &conn_id); | ||
3938 | if (ret == QLA_ERROR) | ||
3939 | break; | ||
3940 | |||
3941 | if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS) | ||
3942 | goto continue_next_st; | ||
3943 | |||
3944 | /* Check if ST, add to the list_st */ | ||
3945 | if (strlen((char *) fw_ddb_entry->iscsi_name) != 0) | ||
3946 | goto continue_next_st; | ||
3947 | |||
3948 | st_ddb_idx = vzalloc(fw_idx_size); | ||
3949 | if (!st_ddb_idx) | ||
3950 | break; | ||
3951 | |||
3952 | st_ddb_idx->fw_ddb_idx = idx; | ||
3953 | |||
3954 | list_add_tail(&st_ddb_idx->list, &list_st); | ||
3955 | continue_next_st: | ||
3956 | if (next_idx == 0) | ||
3957 | break; | ||
3958 | } | ||
3959 | |||
3960 | /* Before issuing conn open mbox, ensure all IPs states are configured | ||
3961 | * Note, conn open fails if IPs are not configured | ||
3962 | */ | ||
3963 | qla4xxx_wait_for_ip_configuration(ha); | ||
3964 | |||
3965 | /* Go thru the STs and fire the sendtargets by issuing conn open mbx */ | ||
3966 | list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) { | ||
3967 | qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx); | ||
3968 | } | ||
3969 | |||
3970 | /* Wait to ensure all sendtargets are done for min 12 sec wait */ | ||
3971 | tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout); | ||
3972 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
3973 | "Default time to wait for build ddb %d\n", tmo)); | ||
3974 | |||
3975 | wtime = jiffies + (HZ * tmo); | ||
3976 | do { | ||
3977 | list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, | ||
3978 | list) { | ||
3979 | ret = qla4xxx_get_fwddb_entry(ha, | ||
3980 | st_ddb_idx->fw_ddb_idx, | ||
3981 | NULL, 0, NULL, &next_idx, | ||
3982 | &state, &conn_err, NULL, | ||
3983 | NULL); | ||
3984 | if (ret == QLA_ERROR) | ||
3985 | continue; | ||
3986 | |||
3987 | if (state == DDB_DS_NO_CONNECTION_ACTIVE || | ||
3988 | state == DDB_DS_SESSION_FAILED) { | ||
3989 | list_del_init(&st_ddb_idx->list); | ||
3990 | vfree(st_ddb_idx); | ||
3991 | } | ||
3992 | } | ||
3993 | schedule_timeout_uninterruptible(HZ / 10); | ||
3994 | } while (time_after(wtime, jiffies)); | ||
3995 | |||
3996 | /* Free up the sendtargets list */ | ||
3997 | list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) { | ||
3998 | list_del_init(&st_ddb_idx->list); | ||
3999 | vfree(st_ddb_idx); | ||
4000 | } | ||
4001 | |||
4002 | for (idx = 0; idx < max_ddbs; idx = next_idx) { | ||
4003 | ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, | ||
4004 | fw_ddb_dma, NULL, | ||
4005 | &next_idx, &state, &conn_err, | ||
4006 | NULL, &conn_id); | ||
4007 | if (ret == QLA_ERROR) | ||
4008 | break; | ||
4009 | |||
4010 | if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS) | ||
4011 | goto continue_next_nt; | ||
4012 | |||
4013 | /* Check if NT, then add to list it */ | ||
4014 | if (strlen((char *) fw_ddb_entry->iscsi_name) == 0) | ||
4015 | goto continue_next_nt; | ||
4016 | |||
4017 | if (state == DDB_DS_NO_CONNECTION_ACTIVE || | ||
4018 | state == DDB_DS_SESSION_FAILED) { | ||
4019 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
4020 | "Adding DDB to session = 0x%x\n", | ||
4021 | idx)); | ||
4022 | if (is_reset == INIT_ADAPTER) { | ||
4023 | nt_ddb_idx = vmalloc(fw_idx_size); | ||
4024 | if (!nt_ddb_idx) | ||
4025 | break; | ||
4026 | |||
4027 | nt_ddb_idx->fw_ddb_idx = idx; | ||
4028 | |||
4029 | memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry, | ||
4030 | sizeof(struct dev_db_entry)); | ||
4031 | |||
4032 | if (qla4xxx_is_flash_ddb_exists(ha, &list_nt, | ||
4033 | fw_ddb_entry) == QLA_SUCCESS) { | ||
4034 | vfree(nt_ddb_idx); | ||
4035 | goto continue_next_nt; | ||
4036 | } | ||
4037 | list_add_tail(&nt_ddb_idx->list, &list_nt); | ||
4038 | } else if (is_reset == RESET_ADAPTER) { | ||
4039 | if (qla4xxx_is_session_exists(ha, | ||
4040 | fw_ddb_entry) == QLA_SUCCESS) | ||
4041 | goto continue_next_nt; | ||
4042 | } | ||
4043 | |||
4044 | /* Create session object, with INVALID_ENTRY, | ||
4045 | * the targer_id would get set when we issue the login | ||
4046 | */ | ||
4047 | cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, | ||
4048 | ha->host, cmds_max, | ||
4049 | sizeof(struct ddb_entry), | ||
4050 | sizeof(struct ql4_task_data), | ||
4051 | initial_cmdsn, INVALID_ENTRY); | ||
4052 | if (!cls_sess) | ||
4053 | goto exit_ddb_list; | ||
4054 | |||
4055 | /* | ||
4056 | * iscsi_session_setup increments the driver reference | ||
4057 | * count which wouldn't let the driver to be unloaded. | ||
4058 | * so calling module_put function to decrement the | ||
4059 | * reference count. | ||
4060 | **/ | ||
4061 | module_put(qla4xxx_iscsi_transport.owner); | ||
4062 | sess = cls_sess->dd_data; | ||
4063 | ddb_entry = sess->dd_data; | ||
4064 | ddb_entry->sess = cls_sess; | ||
4065 | |||
4066 | cls_sess->recovery_tmo = ql4xsess_recovery_tmo; | ||
4067 | memcpy(&ddb_entry->fw_ddb_entry, fw_ddb_entry, | ||
4068 | sizeof(struct dev_db_entry)); | ||
4069 | |||
4070 | qla4xxx_setup_flash_ddb_entry(ha, ddb_entry); | ||
4071 | |||
4072 | cls_conn = iscsi_conn_setup(cls_sess, | ||
4073 | sizeof(struct qla_conn), | ||
4074 | conn_id); | ||
4075 | if (!cls_conn) | ||
4076 | goto exit_ddb_list; | ||
4077 | |||
4078 | ddb_entry->conn = cls_conn; | ||
4079 | |||
4080 | /* Setup ep, for displaying attributes in sysfs */ | ||
4081 | ep = qla4xxx_get_ep_fwdb(ha, fw_ddb_entry); | ||
4082 | if (ep) { | ||
4083 | ep->conn = cls_conn; | ||
4084 | cls_conn->ep = ep; | ||
4085 | } else { | ||
4086 | DEBUG2(ql4_printk(KERN_ERR, ha, | ||
4087 | "Unable to get ep\n")); | ||
4088 | } | ||
4089 | |||
4090 | /* Update sess/conn params */ | ||
4091 | qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, | ||
4092 | cls_conn); | ||
4093 | |||
4094 | if (is_reset == RESET_ADAPTER) { | ||
4095 | iscsi_block_session(cls_sess); | ||
4096 | /* Use the relogin path to discover new devices | ||
4097 | * by short-circuting the logic of setting | ||
4098 | * timer to relogin - instead set the flags | ||
4099 | * to initiate login right away. | ||
4100 | */ | ||
4101 | set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags); | ||
4102 | set_bit(DF_RELOGIN, &ddb_entry->flags); | ||
4103 | } | ||
4104 | } | ||
4105 | continue_next_nt: | ||
4106 | if (next_idx == 0) | ||
4107 | break; | ||
4108 | } | ||
4109 | exit_ddb_list: | ||
4110 | qla4xxx_free_nt_list(&list_nt); | ||
4111 | if (fw_ddb_entry) | ||
4112 | dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma); | ||
4113 | |||
4114 | qla4xxx_free_ddb_index(ha); | ||
4115 | } | ||
4116 | |||
4117 | |||
3180 | /** | 4118 | /** |
3181 | * qla4xxx_probe_adapter - callback function to probe HBA | 4119 | * qla4xxx_probe_adapter - callback function to probe HBA |
3182 | * @pdev: pointer to pci_dev structure | 4120 | * @pdev: pointer to pci_dev structure |
@@ -3298,7 +4236,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
3298 | * firmware | 4236 | * firmware |
3299 | * NOTE: interrupts enabled upon successful completion | 4237 | * NOTE: interrupts enabled upon successful completion |
3300 | */ | 4238 | */ |
3301 | status = qla4xxx_initialize_adapter(ha); | 4239 | status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER); |
3302 | while ((!test_bit(AF_ONLINE, &ha->flags)) && | 4240 | while ((!test_bit(AF_ONLINE, &ha->flags)) && |
3303 | init_retry_count++ < MAX_INIT_RETRIES) { | 4241 | init_retry_count++ < MAX_INIT_RETRIES) { |
3304 | 4242 | ||
@@ -3319,7 +4257,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
3319 | if (ha->isp_ops->reset_chip(ha) == QLA_ERROR) | 4257 | if (ha->isp_ops->reset_chip(ha) == QLA_ERROR) |
3320 | continue; | 4258 | continue; |
3321 | 4259 | ||
3322 | status = qla4xxx_initialize_adapter(ha); | 4260 | status = qla4xxx_initialize_adapter(ha, INIT_ADAPTER); |
3323 | } | 4261 | } |
3324 | 4262 | ||
3325 | if (!test_bit(AF_ONLINE, &ha->flags)) { | 4263 | if (!test_bit(AF_ONLINE, &ha->flags)) { |
@@ -3386,12 +4324,16 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
3386 | ha->host_no, ha->firmware_version[0], ha->firmware_version[1], | 4324 | ha->host_no, ha->firmware_version[0], ha->firmware_version[1], |
3387 | ha->patch_number, ha->build_number); | 4325 | ha->patch_number, ha->build_number); |
3388 | 4326 | ||
3389 | qla4xxx_create_chap_list(ha); | ||
3390 | |||
3391 | if (qla4xxx_setup_boot_info(ha)) | 4327 | if (qla4xxx_setup_boot_info(ha)) |
3392 | ql4_printk(KERN_ERR, ha, "%s:ISCSI boot info setup failed\n", | 4328 | ql4_printk(KERN_ERR, ha, "%s:ISCSI boot info setup failed\n", |
3393 | __func__); | 4329 | __func__); |
3394 | 4330 | ||
4331 | /* Perform the build ddb list and login to each */ | ||
4332 | qla4xxx_build_ddb_list(ha, INIT_ADAPTER); | ||
4333 | iscsi_host_for_each_session(ha->host, qla4xxx_login_flash_ddb); | ||
4334 | |||
4335 | qla4xxx_create_chap_list(ha); | ||
4336 | |||
3395 | qla4xxx_create_ifaces(ha); | 4337 | qla4xxx_create_ifaces(ha); |
3396 | return 0; | 4338 | return 0; |
3397 | 4339 | ||
@@ -3449,6 +4391,38 @@ static void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha) | |||
3449 | } | 4391 | } |
3450 | } | 4392 | } |
3451 | 4393 | ||
4394 | static void qla4xxx_destroy_fw_ddb_session(struct scsi_qla_host *ha) | ||
4395 | { | ||
4396 | struct ddb_entry *ddb_entry; | ||
4397 | int options; | ||
4398 | int idx; | ||
4399 | |||
4400 | for (idx = 0; idx < MAX_DDB_ENTRIES; idx++) { | ||
4401 | |||
4402 | ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, idx); | ||
4403 | if ((ddb_entry != NULL) && | ||
4404 | (ddb_entry->ddb_type == FLASH_DDB)) { | ||
4405 | |||
4406 | options = LOGOUT_OPTION_CLOSE_SESSION; | ||
4407 | if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) | ||
4408 | == QLA_ERROR) | ||
4409 | ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", | ||
4410 | __func__); | ||
4411 | |||
4412 | qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index); | ||
4413 | /* | ||
4414 | * we have decremented the reference count of the driver | ||
4415 | * when we setup the session to have the driver unload | ||
4416 | * to be seamless without actually destroying the | ||
4417 | * session | ||
4418 | **/ | ||
4419 | try_module_get(qla4xxx_iscsi_transport.owner); | ||
4420 | iscsi_destroy_endpoint(ddb_entry->conn->ep); | ||
4421 | qla4xxx_free_ddb(ha, ddb_entry); | ||
4422 | iscsi_session_teardown(ddb_entry->sess); | ||
4423 | } | ||
4424 | } | ||
4425 | } | ||
3452 | /** | 4426 | /** |
3453 | * qla4xxx_remove_adapter - calback function to remove adapter. | 4427 | * qla4xxx_remove_adapter - calback function to remove adapter. |
3454 | * @pci_dev: PCI device pointer | 4428 | * @pci_dev: PCI device pointer |
@@ -3465,9 +4439,11 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev) | |||
3465 | /* destroy iface from sysfs */ | 4439 | /* destroy iface from sysfs */ |
3466 | qla4xxx_destroy_ifaces(ha); | 4440 | qla4xxx_destroy_ifaces(ha); |
3467 | 4441 | ||
3468 | if (ha->boot_kset) | 4442 | if ((!ql4xdisablesysfsboot) && ha->boot_kset) |
3469 | iscsi_boot_destroy_kset(ha->boot_kset); | 4443 | iscsi_boot_destroy_kset(ha->boot_kset); |
3470 | 4444 | ||
4445 | qla4xxx_destroy_fw_ddb_session(ha); | ||
4446 | |||
3471 | scsi_remove_host(ha->host); | 4447 | scsi_remove_host(ha->host); |
3472 | 4448 | ||
3473 | qla4xxx_free_adapter(ha); | 4449 | qla4xxx_free_adapter(ha); |
@@ -4115,7 +5091,7 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha) | |||
4115 | 5091 | ||
4116 | qla4_8xxx_idc_unlock(ha); | 5092 | qla4_8xxx_idc_unlock(ha); |
4117 | clear_bit(AF_FW_RECOVERY, &ha->flags); | 5093 | clear_bit(AF_FW_RECOVERY, &ha->flags); |
4118 | rval = qla4xxx_initialize_adapter(ha); | 5094 | rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER); |
4119 | qla4_8xxx_idc_lock(ha); | 5095 | qla4_8xxx_idc_lock(ha); |
4120 | 5096 | ||
4121 | if (rval != QLA_SUCCESS) { | 5097 | if (rval != QLA_SUCCESS) { |
@@ -4151,7 +5127,7 @@ static uint32_t qla4_8xxx_error_recovery(struct scsi_qla_host *ha) | |||
4151 | if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) == | 5127 | if ((qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE) == |
4152 | QLA82XX_DEV_READY)) { | 5128 | QLA82XX_DEV_READY)) { |
4153 | clear_bit(AF_FW_RECOVERY, &ha->flags); | 5129 | clear_bit(AF_FW_RECOVERY, &ha->flags); |
4154 | rval = qla4xxx_initialize_adapter(ha); | 5130 | rval = qla4xxx_initialize_adapter(ha, RESET_ADAPTER); |
4155 | if (rval == QLA_SUCCESS) { | 5131 | if (rval == QLA_SUCCESS) { |
4156 | ret = qla4xxx_request_irqs(ha); | 5132 | ret = qla4xxx_request_irqs(ha); |
4157 | if (ret) { | 5133 | if (ret) { |
diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index c15347d3f53..5254e57968f 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h | |||
@@ -5,4 +5,4 @@ | |||
5 | * See LICENSE.qla4xxx for copyright and licensing details. | 5 | * See LICENSE.qla4xxx for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k8" | 8 | #define QLA4XXX_DRIVER_VERSION "5.02.00-k9" |