#define DISCOVER_REQ_SIZE  16
 #define DISCOVER_RESP_SIZE 56
 
+static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req,
+                                     u8 *disc_resp, int single)
+{
+       int i, res;
+
+       disc_req[9] = single;
+       for (i = 1 ; i < 3; i++) {
+               struct discover_resp *dr;
+
+               res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE,
+                                      disc_resp, DISCOVER_RESP_SIZE);
+               if (res)
+                       return res;
+               /* This is detecting a failure to transmit inital
+                * dev to host FIS as described in section G.5 of
+                * sas-2 r 04b */
+               dr = &((struct smp_resp *)disc_resp)->disc;
+               if (!(dr->attached_dev_type == 0 &&
+                     dr->attached_sata_dev))
+                       break;
+               /* In order to generate the dev to host FIS, we
+                * send a link reset to the expander port */
+               sas_smp_phy_control(dev, single, PHY_FUNC_LINK_RESET);
+               /* Wait for the reset to trigger the negotiation */
+               msleep(500);
+       }
+       sas_set_ex_phy(dev, single, disc_resp);
+       return 0;
+}
+
 static int sas_ex_phy_discover(struct domain_device *dev, int single)
 {
        struct expander_device *ex = &dev->ex_dev;
        disc_req[1] = SMP_DISCOVER;
 
        if (0 <= single && single < ex->num_phys) {
-               disc_req[9] = single;
-               res = smp_execute_task(dev, disc_req, DISCOVER_REQ_SIZE,
-                                      disc_resp, DISCOVER_RESP_SIZE);
-               if (res)
-                       goto out_err;
-               sas_set_ex_phy(dev, single, disc_resp);
+               res = sas_ex_phy_discover_helper(dev, disc_req, disc_resp, single);
        } else {
                int i;
 
                for (i = 0; i < ex->num_phys; i++) {
-                       disc_req[9] = i;
-                       res = smp_execute_task(dev, disc_req,
-                                              DISCOVER_REQ_SIZE, disc_resp,
-                                              DISCOVER_RESP_SIZE);
+                       res = sas_ex_phy_discover_helper(dev, disc_req,
+                                                        disc_resp, i);
                        if (res)
                                goto out_err;
-                       sas_set_ex_phy(dev, i, disc_resp);
                }
        }
 out_err:
 {
        int res;
        u8 *rps_req = alloc_smp_req(RPS_REQ_SIZE);
+       u8 *resp = (u8 *)rps_resp;
 
        if (!rps_req)
                return -ENOMEM;
        res = smp_execute_task(dev, rps_req, RPS_REQ_SIZE,
                                    rps_resp, RPS_RESP_SIZE);
 
+       /* 0x34 is the FIS type for the D2H fis.  There's a potential
+        * standards cockup here.  sas-2 explicitly specifies the FIS
+        * should be encoded so that FIS type is in resp[24].
+        * However, some expanders endian reverse this.  Undo the
+        * reversal here */
+       if (!res && resp[27] == 0x34 && resp[24] != 0x34) {
+               int i;
+
+               for (i = 0; i < 5; i++) {
+                       int j = 24 + (i*4);
+                       u8 a, b;
+                       a = resp[j + 0];
+                       b = resp[j + 1];
+                       resp[j + 0] = resp[j + 3];
+                       resp[j + 1] = resp[j + 2];
+                       resp[j + 2] = b;
+                       resp[j + 3] = a;
+               }
+       }
+
        kfree(rps_req);
-       return 0;
+       return res;
 }
 
 static void sas_ex_get_linkrate(struct domain_device *parent,
                }
                memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis,
                       sizeof(struct dev_to_host_fis));
+
+               rphy = sas_end_device_alloc(phy->port);
+               /* FIXME: error handling */
+               BUG_ON(!rphy);
+
                sas_init_dev(child);
+
+               child->rphy = rphy;
+
+               spin_lock(&parent->port->dev_list_lock);
+               list_add_tail(&child->dev_list_node, &parent->port->dev_list);
+               spin_unlock(&parent->port->dev_list_lock);
+
                res = sas_discover_sata(child);
                if (res) {
                        SAS_DPRINTK("sas_discover_sata() for device %16llx at "
                                    "%016llx:0x%x returned 0x%x\n",
                                    SAS_ADDR(child->sas_addr),
                                    SAS_ADDR(parent->sas_addr), phy_id, res);
-                       goto out_free;
+                       goto out_list_del;
                }
        } else if (phy->attached_tproto & SAS_PROTO_SSP) {
                child->dev_type = SAS_END_DEV;