diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_ata.c')
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 71 |
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 | ||
281 | static void sas_get_ata_command_set(struct domain_device *dev); | ||
282 | |||
283 | int 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 | |||
312 | static 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 | |||
281 | static int smp_ata_check_ready(struct ata_link *link) | 330 | static 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 | ||
303 | static int local_ata_check_ready(struct ata_link *link) | 361 | static 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 && |