{"id":2225150,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2225150/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-ide/patch/20260420122321.4161027-3-philpem@philpem.me.uk/","project":{"id":13,"url":"http://patchwork.ozlabs.org/api/1.1/projects/13/?format=json","name":"Linux IDE development","link_name":"linux-ide","list_id":"linux-ide.vger.kernel.org","list_email":"linux-ide@vger.kernel.org","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<20260420122321.4161027-3-philpem@philpem.me.uk>","date":"2026-04-20T12:23:18","name":"[v2,2/5] ata: libata-scsi: convert dev->sdev to per-LUN array","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"a613e00e52bf12a5ea2c031d8061a955458dfc83","submitter":{"id":93108,"url":"http://patchwork.ozlabs.org/api/1.1/people/93108/?format=json","name":"Phil Pemberton","email":"philpem@philpem.me.uk"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-ide/patch/20260420122321.4161027-3-philpem@philpem.me.uk/mbox/","series":[{"id":500602,"url":"http://patchwork.ozlabs.org/api/1.1/series/500602/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-ide/list/?series=500602","date":"2026-04-20T12:23:21","name":"ata: libata-scsi: multi-LUN ATAPI device support","version":2,"mbox":"http://patchwork.ozlabs.org/series/500602/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2225150/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2225150/checks/","tags":{},"headers":{"Return-Path":"\n <linux-ide+bounces-5495-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-ide@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=philpem.me.uk header.i=@philpem.me.uk\n header.a=rsa-sha256 header.s=mail header.b=MZRusxAI;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c09:e001:a7::12fc:5321; helo=sto.lore.kernel.org;\n envelope-from=linux-ide+bounces-5495-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk\n header.b=\"MZRusxAI\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=178.62.38.78","smtp.subspace.kernel.org;\n dmarc=pass (p=reject dis=none) header.from=philpem.me.uk","smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=philpem.me.uk"],"Received":["from sto.lore.kernel.org (sto.lore.kernel.org\n [IPv6:2600:3c09:e001:a7::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fzlSy4vWdz1yD4\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 22:40:34 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sto.lore.kernel.org (Postfix) with ESMTP id A939130022F1\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 20 Apr 2026 12:40:30 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id D2919387377;\n\tMon, 20 Apr 2026 12:40:27 +0000 (UTC)","from nick.sneptech.io (nick.sneptech.io [178.62.38.78])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id A449A40DFCA;\n\tMon, 20 Apr 2026 12:40:25 +0000 (UTC)","from wolf.philpem.me.uk (81-187-163-148.ip4.reverse-dns.uk\n [81.187.163.148])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\t(Authenticated sender: mailrelay_wolf@philpem.me.uk)\n\tby nick.sneptech.io (Postfix) with ESMTPSA id 319CEBEFE1;\n\tMon, 20 Apr 2026 12:23:29 +0000 (UTC)","from cheetah.homenet.philpem.me.uk (cheetah.homenet.philpem.me.uk\n [10.0.0.32])\n\tby wolf.philpem.me.uk (Postfix) with ESMTPSA id 9BFC65FC57;\n\tMon, 20 Apr 2026 13:23:28 +0100 (BST)"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776688827; cv=none;\n b=RlLXpqh3bQFqTs4JiQkaYgy96WGNvswWtq9XsxZb9hjko/zgcfrN3JAlPsJ7v8lL0KC2w0pmyBzk+4v8J6sJ0PH90HeBZfPO47d0e4llDLA+Dc0VgdXb6HP091883VmOQoqZtIE1e6Y+AQe7/rOi7D0K/RbMFJcHoftITkRzDOM=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776688827; c=relaxed/simple;\n\tbh=vRT5e1DqiM/5f3FADuR9Az/ABfSzGFffqKBSWG1K5sw=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version:Content-Type;\n b=Ulykxo7mDrTFolOwyz9MDnonMACakGHt56jusxyvqnHniTQxp6ALWeRSwqIiQjvtxRTw6LqEPH8fcX5XRurH/ZAdCowZas0Lh2Q6Pko8r5oz+kf4qSnj73xoLOSHLm2vB2Zxz9XZoIDTwIv0uYA61Y2pEBswBW5t/EPSYIwnoHM=","ARC-Authentication-Results":"i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=reject dis=none) header.from=philpem.me.uk;\n spf=pass smtp.mailfrom=philpem.me.uk;\n dkim=pass (1024-bit key) header.d=philpem.me.uk header.i=@philpem.me.uk\n header.b=MZRusxAI; arc=none smtp.client-ip=178.62.38.78","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=philpem.me.uk;\n\ts=mail; t=1776687809;\n\tbh=vRT5e1DqiM/5f3FADuR9Az/ABfSzGFffqKBSWG1K5sw=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=MZRusxAIzEGW9c0Ya5ITMQBIHctsWSfo+ER8RJalOxrAt/fJTJFgUTxmuMMe9Jygy\n\t sA+QptXF5MXPoATDtjIk3u2+d5DS2zBj8eVrWIjy2UXhN5U5C4LzfIszOtPkR6lsfc\n\t XMdbX4M5HiaRUf6Y3BK3zatZHxjzqvP08JsUTAPc=","From":"Phil Pemberton <philpem@philpem.me.uk>","To":"Damien Le Moal <dlemoal@kernel.org>,\n\tNiklas Cassel <cassel@kernel.org>","Cc":"\"James E . J . Bottomley\" <James.Bottomley@HansenPartnership.com>,\n\t\"Martin K . Petersen\" <martin.petersen@oracle.com>,\n\tHannes Reinecke <hare@suse.de>,\n\tlinux-ide@vger.kernel.org,\n\tlinux-scsi@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org,\n\tPhil Pemberton <philpem@philpem.me.uk>","Subject":"[PATCH v2 2/5] ata: libata-scsi: convert dev->sdev to per-LUN array","Date":"Mon, 20 Apr 2026 13:23:18 +0100","Message-ID":"<20260420122321.4161027-3-philpem@philpem.me.uk>","X-Mailer":"git-send-email 2.43.0","In-Reply-To":"<20260420122321.4161027-1-philpem@philpem.me.uk>","References":"<20260420122321.4161027-1-philpem@philpem.me.uk>","Precedence":"bulk","X-Mailing-List":"linux-ide@vger.kernel.org","List-Id":"<linux-ide.vger.kernel.org>","List-Subscribe":"<mailto:linux-ide+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-ide+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit"},"content":"Multi-LUN ATAPI devices (PD/CD combos, CD changers) share a single\nata_device but expose multiple scsi_devices.  The previous single\ndev->sdev pointer could only track one LUN, making all other LUNs\ninvisible to code that operates on sdevs: port detach, suspend/resume,\nACPI uevent, ZPODD, media change notification, and EH teardown.\n\nReplace the scalar struct scsi_device *sdev with a fixed-size array\ndev->sdev[ATAPI_MAX_LUN] indexed by LUN number, where ATAPI_MAX_LUN\nis 8 (the SCSI-2 ceiling, LUN values 0..7).\n\nKey changes per call site:\n  - ata_scsi_dev_config:  assign sdev to dev->sdev[sdev->lun]\n  - ata_scsi_sdev_destroy: clear dev->sdev[sdev->lun]; only trigger\n    ATA-level detach when LUN 0 is destroyed, since removing a higher\n    LUN should not tear down the underlying ATA device\n  - ata_port_detach:  iterate all LUN slots (high→low)\n  - ata_scsi_offline_dev:  iterate all LUN slots\n  - ata_scsi_remove_dev:  snapshot and remove all LUN slots, then\n    scsi_remove_device each one outside the lock\n  - ata_scsi_media_change_notify:  send event to all populated LUNs\n  - ata_scsi_dev_rescan:  resume and rescan each populated LUN\n  - ACPI, ZPODD, ofnode, door-lock:  use dev->sdev[0] (LUN 0 remains\n    canonical for ATA-level operations)\n  - ata_scsi_scan_host:  uses dev->sdev[0] for the existing LUN-0\n    add/retry path\n\nFor single-LUN devices (the vast majority), only dev->sdev[0] is ever\npopulated and the additional slots remain NULL.\n\nSigned-off-by: Phil Pemberton <philpem@philpem.me.uk>\n---\n drivers/ata/libata-acpi.c  |   4 +-\n drivers/ata/libata-core.c  |  10 ++-\n drivers/ata/libata-scsi.c  | 146 ++++++++++++++++++-------------------\n drivers/ata/libata-zpodd.c |   6 +-\n include/linux/libata.h     |   2 +-\n 5 files changed, 86 insertions(+), 82 deletions(-)","diff":"diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c\nindex 4433f626246b..d07237f66d98 100644\n--- a/drivers/ata/libata-acpi.c\n+++ b/drivers/ata/libata-acpi.c\n@@ -153,8 +153,8 @@ static void ata_acpi_uevent(struct ata_port *ap, struct ata_device *dev,\n \tchar *envp[] = { event_string, NULL };\n \n \tif (dev) {\n-\t\tif (dev->sdev)\n-\t\t\tkobj = &dev->sdev->sdev_gendev.kobj;\n+\t\tif (dev->sdev[0])\n+\t\t\tkobj = &dev->sdev[0]->sdev_gendev.kobj;\n \t} else\n \t\tkobj = &ap->dev->kobj;\n \ndiff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c\nindex 8c279b6eb1fb..f24d38f6ee73 100644\n--- a/drivers/ata/libata-core.c\n+++ b/drivers/ata/libata-core.c\n@@ -6270,11 +6270,15 @@ static void ata_port_detach(struct ata_port *ap)\n \t/* Remove scsi devices */\n \tata_for_each_link(link, ap, HOST_FIRST) {\n \t\tata_for_each_dev(dev, link, ALL) {\n-\t\t\tif (dev->sdev) {\n+\t\t\tint lun;\n+\n+\t\t\tfor (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {\n+\t\t\t\tif (!dev->sdev[lun])\n+\t\t\t\t\tcontinue;\n \t\t\t\tspin_unlock_irqrestore(ap->lock, flags);\n-\t\t\t\tscsi_remove_device(dev->sdev);\n+\t\t\t\tscsi_remove_device(dev->sdev[lun]);\n \t\t\t\tspin_lock_irqsave(ap->lock, flags);\n-\t\t\t\tdev->sdev = NULL;\n+\t\t\t\tdev->sdev[lun] = NULL;\n \t\t\t}\n \t\t}\n \t}\ndiff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c\nindex d1665305b552..317883bac25f 100644\n--- a/drivers/ata/libata-scsi.c\n+++ b/drivers/ata/libata-scsi.c\n@@ -1131,7 +1131,7 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct queue_limits *lim,\n \tif (dev->flags & ATA_DFLAG_TRUSTED)\n \t\tsdev->security_supported = 1;\n \n-\tdev->sdev = sdev;\n+\tdev->sdev[sdev->lun] = sdev;\n \treturn 0;\n }\n \n@@ -1202,10 +1202,10 @@ EXPORT_SYMBOL_GPL(ata_scsi_sdev_configure);\n  *\n  *\t@sdev is about to be destroyed for hot/warm unplugging.  If\n  *\tthis unplugging was initiated by libata as indicated by NULL\n- *\tdev->sdev, this function doesn't have to do anything.\n+ *\tdev->sdev[], this function doesn't have to do anything.\n  *\tOtherwise, SCSI layer initiated warm-unplug is in progress.\n- *\tClear dev->sdev, schedule the device for ATA detach and invoke\n- *\tEH.\n+ *\tClear the per-LUN slot; when the last LUN (LUN 0) is destroyed,\n+ *\tschedule ATA-level detach via EH.\n  *\n  *\tLOCKING:\n  *\tDefined by SCSI layer.  We don't really care.\n@@ -1220,11 +1220,12 @@ void ata_scsi_sdev_destroy(struct scsi_device *sdev)\n \n \tspin_lock_irqsave(ap->lock, flags);\n \tdev = __ata_scsi_find_dev(ap, sdev);\n-\tif (dev && dev->sdev) {\n-\t\t/* SCSI device already in CANCEL state, no need to offline it */\n-\t\tdev->sdev = NULL;\n-\t\tdev->flags |= ATA_DFLAG_DETACH;\n-\t\tata_port_schedule_eh(ap);\n+\tif (dev && dev->sdev[sdev->lun] == sdev) {\n+\t\tdev->sdev[sdev->lun] = NULL;\n+\t\tif (sdev->lun == 0) {\n+\t\t\tdev->flags |= ATA_DFLAG_DETACH;\n+\t\t\tata_port_schedule_eh(ap);\n+\t\t}\n \t}\n \tspin_unlock_irqrestore(ap->lock, flags);\n \n@@ -2912,10 +2913,10 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)\n \t\t * avoid this infinite loop.\n \t\t *\n \t\t * This may happen before SCSI scan is complete.  Make\n-\t\t * sure qc->dev->sdev isn't NULL before dereferencing.\n+\t\t * sure qc->dev->sdev[0] isn't NULL before dereferencing.\n \t\t */\n-\t\tif (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev)\n-\t\t\tqc->dev->sdev->locked = 0;\n+\t\tif (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev[0])\n+\t\t\tqc->dev->sdev[0]->locked = 0;\n \n \t\tqc->scsicmd->result = SAM_STAT_CHECK_CONDITION;\n \t\tata_qc_done(qc);\n@@ -4651,7 +4652,7 @@ int ata_scsi_add_hosts(struct ata_host *host, const struct scsi_host_template *s\n #ifdef CONFIG_OF\n static void ata_scsi_assign_ofnode(struct ata_device *dev, struct ata_port *ap)\n {\n-\tstruct scsi_device *sdev = dev->sdev;\n+\tstruct scsi_device *sdev = dev->sdev[0];\n \tstruct device *d = ap->host->dev;\n \tstruct device_node *np = d->of_node;\n \tstruct device_node *child;\n@@ -4689,7 +4690,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)\n \t\t\tstruct scsi_device *sdev;\n \t\t\tint channel = 0, id = 0;\n \n-\t\t\tif (dev->sdev)\n+\t\t\tif (dev->sdev[0])\n \t\t\t\tcontinue;\n \n \t\t\tif (ata_is_host_link(link))\n@@ -4700,11 +4701,11 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)\n \t\t\tsdev = __scsi_add_device(ap->scsi_host, channel, id, 0,\n \t\t\t\t\t\t NULL);\n \t\t\tif (!IS_ERR(sdev)) {\n-\t\t\t\tdev->sdev = sdev;\n+\t\t\t\tdev->sdev[0] = sdev;\n \t\t\t\tata_scsi_assign_ofnode(dev, ap);\n \t\t\t\tscsi_device_put(sdev);\n \t\t\t} else {\n-\t\t\t\tdev->sdev = NULL;\n+\t\t\t\tdev->sdev[0] = NULL;\n \t\t\t}\n \t\t}\n \t}\n@@ -4715,7 +4716,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)\n \t */\n \tata_for_each_link(link, ap, EDGE) {\n \t\tata_for_each_dev(dev, link, ENABLED) {\n-\t\t\tif (!dev->sdev)\n+\t\t\tif (!dev->sdev[0])\n \t\t\t\tgoto exit_loop;\n \t\t}\n \t}\n@@ -4756,7 +4757,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)\n  *\n  *\tThis function is called from ata_eh_detach_dev() and is responsible for\n  *\ttaking the SCSI device attached to @dev offline.  This function is\n- *\tcalled with host lock which protects dev->sdev against clearing.\n+ *\tcalled with host lock which protects dev->sdev[] against clearing.\n  *\n  *\tLOCKING:\n  *\tspin_lock_irqsave(host lock)\n@@ -4766,11 +4767,16 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)\n  */\n bool ata_scsi_offline_dev(struct ata_device *dev)\n {\n-\tif (dev->sdev) {\n-\t\tscsi_device_set_state(dev->sdev, SDEV_OFFLINE);\n-\t\treturn true;\n+\tbool found = false;\n+\tint lun;\n+\n+\tfor (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {\n+\t\tif (dev->sdev[lun]) {\n+\t\t\tscsi_device_set_state(dev->sdev[lun], SDEV_OFFLINE);\n+\t\t\tfound = true;\n+\t\t}\n \t}\n-\treturn false;\n+\treturn found;\n }\n \n /**\n@@ -4786,49 +4792,38 @@ bool ata_scsi_offline_dev(struct ata_device *dev)\n static void ata_scsi_remove_dev(struct ata_device *dev)\n {\n \tstruct ata_port *ap = dev->link->ap;\n-\tstruct scsi_device *sdev;\n+\tstruct scsi_device *sdevs[ATAPI_MAX_LUN] = {};\n \tunsigned long flags;\n+\tint lun;\n \n-\t/* Alas, we need to grab scan_mutex to ensure SCSI device\n-\t * state doesn't change underneath us and thus\n-\t * scsi_device_get() always succeeds.  The mutex locking can\n-\t * be removed if there is __scsi_device_get() interface which\n-\t * increments reference counts regardless of device state.\n-\t */\n \tmutex_lock(&ap->scsi_host->scan_mutex);\n \tspin_lock_irqsave(ap->lock, flags);\n \n-\t/* clearing dev->sdev is protected by host lock */\n-\tsdev = dev->sdev;\n-\tdev->sdev = NULL;\n+\tfor (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {\n+\t\tstruct scsi_device *sdev = dev->sdev[lun];\n+\n+\t\tdev->sdev[lun] = NULL;\n+\t\tif (!sdev)\n+\t\t\tcontinue;\n \n-\tif (sdev) {\n-\t\t/* If user initiated unplug races with us, sdev can go\n-\t\t * away underneath us after the host lock and\n-\t\t * scan_mutex are released.  Hold onto it.\n-\t\t */\n \t\tif (scsi_device_get(sdev) == 0) {\n-\t\t\t/* The following ensures the attached sdev is\n-\t\t\t * offline on return from ata_scsi_offline_dev()\n-\t\t\t * regardless it wins or loses the race\n-\t\t\t * against this function.\n-\t\t\t */\n \t\t\tscsi_device_set_state(sdev, SDEV_OFFLINE);\n+\t\t\tsdevs[lun] = sdev;\n \t\t} else {\n \t\t\tWARN_ON(1);\n-\t\t\tsdev = NULL;\n \t\t}\n \t}\n \n \tspin_unlock_irqrestore(ap->lock, flags);\n \tmutex_unlock(&ap->scsi_host->scan_mutex);\n \n-\tif (sdev) {\n+\tfor (lun = ATAPI_MAX_LUN - 1; lun >= 0; lun--) {\n+\t\tif (!sdevs[lun])\n+\t\t\tcontinue;\n \t\tata_dev_info(dev, \"detaching (SCSI %s)\\n\",\n-\t\t\t     dev_name(&sdev->sdev_gendev));\n-\n-\t\tscsi_remove_device(sdev);\n-\t\tscsi_device_put(sdev);\n+\t\t\t     dev_name(&sdevs[lun]->sdev_gendev));\n+\t\tscsi_remove_device(sdevs[lun]);\n+\t\tscsi_device_put(sdevs[lun]);\n \t}\n }\n \n@@ -4865,9 +4860,12 @@ static void ata_scsi_handle_link_detach(struct ata_link *link)\n  */\n void ata_scsi_media_change_notify(struct ata_device *dev)\n {\n-\tif (dev->sdev)\n-\t\tsdev_evt_send_simple(dev->sdev, SDEV_EVT_MEDIA_CHANGE,\n-\t\t\t\t     GFP_ATOMIC);\n+\tint lun;\n+\n+\tfor (lun = 0; lun < ATAPI_MAX_LUN; lun++)\n+\t\tif (dev->sdev[lun])\n+\t\t\tsdev_evt_send_simple(dev->sdev[lun],\n+\t\t\t\t\t     SDEV_EVT_MEDIA_CHANGE, GFP_ATOMIC);\n }\n \n /**\n@@ -5000,37 +4998,39 @@ void ata_scsi_dev_rescan(struct work_struct *work)\n \n \tata_for_each_link(link, ap, EDGE) {\n \t\tata_for_each_dev(dev, link, ENABLED) {\n-\t\t\tstruct scsi_device *sdev = dev->sdev;\n+\t\t\tint lun;\n \n-\t\t\t/*\n-\t\t\t * If the port was suspended before this was scheduled,\n-\t\t\t * bail out.\n-\t\t\t */\n \t\t\tif (ap->pflags & ATA_PFLAG_SUSPENDED)\n \t\t\t\tgoto unlock_ap;\n \n-\t\t\tif (!sdev)\n-\t\t\t\tcontinue;\n-\t\t\tif (scsi_device_get(sdev))\n-\t\t\t\tcontinue;\n-\n \t\t\tdo_resume = dev->flags & ATA_DFLAG_RESUMING;\n \n-\t\t\tspin_unlock_irqrestore(ap->lock, flags);\n-\t\t\tif (do_resume) {\n-\t\t\t\tret = scsi_resume_device(sdev);\n-\t\t\t\tif (ret == -EWOULDBLOCK) {\n-\t\t\t\t\tscsi_device_put(sdev);\n-\t\t\t\t\tgoto unlock_scan;\n+\t\t\tfor (lun = 0; lun < ATAPI_MAX_LUN; lun++) {\n+\t\t\t\tstruct scsi_device *sdev = dev->sdev[lun];\n+\n+\t\t\t\tif (!sdev)\n+\t\t\t\t\tcontinue;\n+\t\t\t\tif (scsi_device_get(sdev))\n+\t\t\t\t\tcontinue;\n+\n+\t\t\t\tspin_unlock_irqrestore(ap->lock, flags);\n+\t\t\t\tif (do_resume) {\n+\t\t\t\t\tret = scsi_resume_device(sdev);\n+\t\t\t\t\tif (ret == -EWOULDBLOCK) {\n+\t\t\t\t\t\tscsi_device_put(sdev);\n+\t\t\t\t\t\tgoto unlock_scan;\n+\t\t\t\t\t}\n \t\t\t\t}\n-\t\t\t\tdev->flags &= ~ATA_DFLAG_RESUMING;\n+\t\t\t\tret = scsi_rescan_device(sdev);\n+\t\t\t\tscsi_device_put(sdev);\n+\t\t\t\tspin_lock_irqsave(ap->lock, flags);\n+\n+\t\t\t\tif (ret)\n+\t\t\t\t\tgoto unlock_ap;\n \t\t\t}\n-\t\t\tret = scsi_rescan_device(sdev);\n-\t\t\tscsi_device_put(sdev);\n-\t\t\tspin_lock_irqsave(ap->lock, flags);\n \n-\t\t\tif (ret)\n-\t\t\t\tgoto unlock_ap;\n+\t\t\tif (do_resume)\n+\t\t\t\tdev->flags &= ~ATA_DFLAG_RESUMING;\n \t\t}\n \t}\n \ndiff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c\nindex 414e7c63bd85..116dd42f8232 100644\n--- a/drivers/ata/libata-zpodd.c\n+++ b/drivers/ata/libata-zpodd.c\n@@ -185,7 +185,7 @@ void zpodd_enable_run_wake(struct ata_device *dev)\n {\n \tstruct zpodd *zpodd = dev->zpodd;\n \n-\tsdev_disable_disk_events(dev->sdev);\n+\tsdev_disable_disk_events(dev->sdev[0]);\n \n \tzpodd->powered_off = true;\n \tacpi_pm_set_device_wakeup(&dev->tdev, true);\n@@ -233,14 +233,14 @@ void zpodd_post_poweron(struct ata_device *dev)\n \tzpodd->zp_sampled = false;\n \tzpodd->zp_ready = false;\n \n-\tsdev_enable_disk_events(dev->sdev);\n+\tsdev_enable_disk_events(dev->sdev[0]);\n }\n \n static void zpodd_wake_dev(acpi_handle handle, u32 event, void *context)\n {\n \tstruct ata_device *ata_dev = context;\n \tstruct zpodd *zpodd = ata_dev->zpodd;\n-\tstruct device *dev = &ata_dev->sdev->sdev_gendev;\n+\tstruct device *dev = &ata_dev->sdev[0]->sdev_gendev;\n \n \tif (event == ACPI_NOTIFY_DEVICE_WAKE && pm_runtime_suspended(dev)) {\n \t\tzpodd->from_notify = true;\ndiff --git a/include/linux/libata.h b/include/linux/libata.h\nindex 27b11577826e..e2e759d492c7 100644\n--- a/include/linux/libata.h\n+++ b/include/linux/libata.h\n@@ -722,7 +722,7 @@ struct ata_device {\n \tunsigned int\t\tdevno;\t\t/* 0 or 1 */\n \tu64\t\t\tquirks;\t\t/* List of broken features */\n \tunsigned long\t\tflags;\t\t/* ATA_DFLAG_xxx */\n-\tstruct scsi_device\t*sdev;\t\t/* attached SCSI device */\n+\tstruct scsi_device\t*sdev[ATAPI_MAX_LUN];\t/* per-LUN SCSI devices */\n \tvoid\t\t\t*private_data;\n #ifdef CONFIG_ATA_ACPI\n \tunion acpi_object\t*gtf_cache;\n","prefixes":["v2","2/5"]}