aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_ata.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas/sas_ata.c')
-rw-r--r--drivers/scsi/libsas/sas_ata.c71
1 files changed, 66 insertions, 5 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index ba1ebfe991d7..25008a42412f 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -278,26 +278,84 @@ static struct sas_internal *dev_to_sas_internal(struct domain_device *dev)
278 return to_sas_internal(dev->port->ha->core.shost->transportt); 278 return to_sas_internal(dev->port->ha->core.shost->transportt);
279} 279}
280 280
281static void sas_get_ata_command_set(struct domain_device *dev);
282
283int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy)
284{
285 if (phy->attached_tproto & SAS_PROTOCOL_STP)
286 dev->tproto = phy->attached_tproto;
287 if (phy->attached_sata_dev)
288 dev->tproto |= SATA_DEV;
289
290 if (phy->attached_dev_type == SATA_PENDING)
291 dev->dev_type = SATA_PENDING;
292 else {
293 int res;
294
295 dev->dev_type = SATA_DEV;
296 res = sas_get_report_phy_sata(dev->parent, phy->phy_id,
297 &dev->sata_dev.rps_resp);
298 if (res) {
299 SAS_DPRINTK("report phy sata to %016llx:0x%x returned "
300 "0x%x\n", SAS_ADDR(dev->parent->sas_addr),
301 phy->phy_id, res);
302 return res;
303 }
304 memcpy(dev->frame_rcvd, &dev->sata_dev.rps_resp.rps.fis,
305 sizeof(struct dev_to_host_fis));
306 /* TODO switch to ata_dev_classify() */
307 sas_get_ata_command_set(dev);
308 }
309 return 0;
310}
311
312static int sas_ata_clear_pending(struct domain_device *dev, struct ex_phy *phy)
313{
314 int res;
315
316 /* we weren't pending, so successfully end the reset sequence now */
317 if (dev->dev_type != SATA_PENDING)
318 return 1;
319
320 /* hmmm, if this succeeds do we need to repost the domain_device to the
321 * lldd so it can pick up new parameters?
322 */
323 res = sas_get_ata_info(dev, phy);
324 if (res)
325 return 0; /* retry */
326 else
327 return 1;
328}
329
281static int smp_ata_check_ready(struct ata_link *link) 330static int smp_ata_check_ready(struct ata_link *link)
282{ 331{
283 int res; 332 int res;
284 u8 addr[8];
285 struct ata_port *ap = link->ap; 333 struct ata_port *ap = link->ap;
286 struct domain_device *dev = ap->private_data; 334 struct domain_device *dev = ap->private_data;
287 struct domain_device *ex_dev = dev->parent; 335 struct domain_device *ex_dev = dev->parent;
288 struct sas_phy *phy = sas_get_local_phy(dev); 336 struct sas_phy *phy = sas_get_local_phy(dev);
337 struct ex_phy *ex_phy = &ex_dev->ex_dev.ex_phy[phy->number];
289 338
290 res = sas_get_phy_attached_sas_addr(ex_dev, phy->number, addr); 339 res = sas_ex_phy_discover(ex_dev, phy->number);
291 sas_put_local_phy(phy); 340 sas_put_local_phy(phy);
341
292 /* break the wait early if the expander is unreachable, 342 /* break the wait early if the expander is unreachable,
293 * otherwise keep polling 343 * otherwise keep polling
294 */ 344 */
295 if (res == -ECOMM) 345 if (res == -ECOMM)
296 return res; 346 return res;
297 if (res != SMP_RESP_FUNC_ACC || SAS_ADDR(addr) == 0) 347 if (res != SMP_RESP_FUNC_ACC)
298 return 0; 348 return 0;
299 else 349
300 return 1; 350 switch (ex_phy->attached_dev_type) {
351 case SATA_PENDING:
352 return 0;
353 case SAS_END_DEV:
354 if (ex_phy->attached_sata_dev)
355 return sas_ata_clear_pending(dev, ex_phy);
356 default:
357 return -ENODEV;
358 }
301} 359}
302 360
303static int local_ata_check_ready(struct ata_link *link) 361static int local_ata_check_ready(struct ata_link *link)
@@ -584,6 +642,9 @@ static void sas_get_ata_command_set(struct domain_device *dev)
584 struct dev_to_host_fis *fis = 642 struct dev_to_host_fis *fis =
585 (struct dev_to_host_fis *) dev->frame_rcvd; 643 (struct dev_to_host_fis *) dev->frame_rcvd;
586 644
645 if (dev->dev_type == SATA_PENDING)
646 return;
647
587 if ((fis->sector_count == 1 && /* ATA */ 648 if ((fis->sector_count == 1 && /* ATA */
588 fis->lbal == 1 && 649 fis->lbal == 1 &&
589 fis->lbam == 0 && 650 fis->lbam == 0 &&