Pull new CVEs: CVE-2023-0458 CVE-2023-2269 CVE-2023-2483 CVE-2023-31436 CVE-2023-2194 CVE-2023-2166 CVE-2023-2176 CVE-2023-2007
fs bugfixes from Baokun Li bpf bugfixes from Liu Jian
Arnd Bergmann (1): scsi: dpt_i2o: Remove obsolete driver
Baokun Li (3): writeback, cgroup: fix null-ptr-deref write in bdi_split_work_to_wbs ext4: only update i_reserved_data_blocks on successful block allocation ext4: check iomap type only if ext4_iomap_begin() does not fail
Gwangun Jung (1): net: sched: sch_qfq: prevent slab-out-of-bounds in qfq_activate_agg
Jason Gunthorpe (1): RDMA/cma: Ensure rdma_addr_cancel() happens before issuing more requests
John Fastabend (5): bpf, sockmap: Fix race in ingress receive verdict with redirect to self bpf, sockmap: Fix return codes from tcp_bpf_recvmsg_parser() bpf, sockmap: Attach map progs to psock early for feature probes bpf, sockmap: Re-evaluate proto ops when psock is removed from sockmap bpf, sockmap: Fix double bpf_prog_put on error case in map_link
Liu Jian (1): bpf, sockmap: Fix an infinite loop error when len is 0 in tcp_bpf_recvmsg_parser()
Mike Snitzer (1): dm ioctl: fix nested locking in table_clear() to remove deadlock concern
Oliver Hartkopp (1): can: af_can: fix NULL pointer dereference in can_rcv_filter
Patrisious Haddad (1): RDMA/core: Refactor rdma_bind_addr
Wei Chen (1): i2c: xgene-slimpro: Fix out-of-bounds bug in xgene_slimpro_i2c_xfer()
Xia Fukun (1): prlimit: do_prlimit needs to have a speculation check
Zheng Wang (1): net: qcom/emac: Fix use after free bug in emac_remove due to race condition
.../userspace-api/ioctl/ioctl-number.rst | 2 +- MAINTAINERS | 8 - drivers/i2c/busses/i2c-xgene-slimpro.c | 3 + drivers/infiniband/core/cma.c | 246 +- drivers/infiniband/core/cma_priv.h | 1 + drivers/md/dm-ioctl.c | 7 +- drivers/net/ethernet/qualcomm/emac/emac.c | 6 + drivers/scsi/Kconfig | 11 - drivers/scsi/Makefile | 1 - drivers/scsi/dpt/dpti_i2o.h | 441 -- drivers/scsi/dpt/dpti_ioctl.h | 136 - drivers/scsi/dpt/dptsig.h | 336 -- drivers/scsi/dpt/osd_defs.h | 79 - drivers/scsi/dpt/osd_util.h | 358 -- drivers/scsi/dpt/sys_info.h | 417 -- drivers/scsi/dpt_i2o.c | 3549 ----------------- drivers/scsi/dpti.h | 331 -- fs/ext4/indirect.c | 8 + fs/ext4/inode.c | 12 +- fs/fs-writeback.c | 17 +- kernel/sys.c | 2 + mm/backing-dev.c | 12 +- net/can/af_can.c | 4 +- net/core/skmsg.c | 4 + net/core/sock_map.c | 34 +- net/ipv4/tcp_bpf.c | 77 + net/sched/sch_qfq.c | 13 +- 27 files changed, 296 insertions(+), 5819 deletions(-) delete mode 100644 drivers/scsi/dpt/dpti_i2o.h delete mode 100644 drivers/scsi/dpt/dpti_ioctl.h delete mode 100644 drivers/scsi/dpt/dptsig.h delete mode 100644 drivers/scsi/dpt/osd_defs.h delete mode 100644 drivers/scsi/dpt/osd_util.h delete mode 100644 drivers/scsi/dpt/sys_info.h delete mode 100644 drivers/scsi/dpt_i2o.c delete mode 100644 drivers/scsi/dpti.h
From: John Fastabend john.fastabend@gmail.com
mainline inclusion from mainline-v5.16-rc1 commit c5d2177a72a1659554922728fc407f59950aa929 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I65HYE
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
---------------------------
A socket in a sockmap may have different combinations of programs attached depending on configuration. There can be no programs in which case the socket acts as a sink only. There can be a TX program in this case a BPF program is attached to sending side, but no RX program is attached. There can be an RX program only where sends have no BPF program attached, but receives are hooked with BPF. And finally, both TX and RX programs may be attached. Giving us the permutations:
None, Tx, Rx, and TxRx
To date most of our use cases have been TX case being used as a fast datapath to directly copy between local application and a userspace proxy. Or Rx cases and TxRX applications that are operating an in kernel based proxy. The traffic in the first case where we hook applications into a userspace application looks like this:
AppA redirect AppB Tx <-----------> Rx | | + + TCP <--> lo <--> TCP
In this case all traffic from AppA (after 3whs) is copied into the AppB ingress queue and no traffic is ever on the TCP recieive_queue.
In the second case the application never receives, except in some rare error cases, traffic on the actual user space socket. Instead the send happens in the kernel.
AppProxy socket pool sk0 ------------->{sk1,sk2, skn} ^ | | | | v ingress lb egress TCP TCP
Here because traffic is never read off the socket with userspace recv() APIs there is only ever one reader on the sk receive_queue. Namely the BPF programs.
However, we've started to introduce a third configuration where the BPF program on receive should process the data, but then the normal case is to push the data into the receive queue of AppB.
AppB recv() (userspace) ----------------------- tcp_bpf_recvmsg() (kernel) | | | | | | ingress_msgQ | | | RX_BPF | | | v v sk->receive_queue
This is different from the App{A,B} redirect because traffic is first received on the sk->receive_queue.
Now for the issue. The tcp_bpf_recvmsg() handler first checks the ingress_msg queue for any data handled by the BPF rx program and returned with PASS code so that it was enqueued on the ingress msg queue. Then if no data exists on that queue it checks the socket receive queue. Unfortunately, this is the same receive_queue the BPF program is reading data off of. So we get a race. Its possible for the recvmsg() hook to pull data off the receive_queue before the BPF hook has a chance to read it. It typically happens when an application is banging on recv() and getting EAGAINs. Until they manage to race with the RX BPF program.
To fix this we note that before this patch at attach time when the socket is loaded into the map we check if it needs a TX program or just the base set of proto bpf hooks. Then it uses the above general RX hook regardless of if we have a BPF program attached at rx or not. This patch now extends this check to handle all cases enumerated above, TX, RX, TXRX, and none. And to fix above race when an RX program is attached we use a new hook that is nearly identical to the old one except now we do not let the recv() call skip the RX BPF program. Now only the BPF program pulls data from sk->receive_queue and recv() only pulls data from the ingress msgQ post BPF program handling.
With this resolved our AppB from above has been up and running for many hours without detecting any errors. We do this by correlating counters in RX BPF events and the AppB to ensure data is never skipping the BPF program. Selftests, was not able to detect this because we only run them for a short period of time on well ordered send/recvs so we don't get any of the noise we see in real application environments.
Fixes: 51199405f9672 ("bpf: skb_verdict, support SK_PASS on RX BPF path") Signed-off-by: John Fastabend john.fastabend@gmail.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Tested-by: Jussi Maki joamaki@gmail.com Reviewed-by: Jakub Sitnicki jakub@cloudflare.com Link: https://lore.kernel.org/bpf/20211103204736.248403-4-john.fastabend@gmail.com (cherry picked from commit c5d2177a72a1659554922728fc407f59950aa929) Signed-off-by: Liu Jian liujian56@huawei.com
Conflicts: net/ipv4/tcp_bpf.c Reviewed-by: Yue Haibing yuehaibing@huawei.com
Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- net/ipv4/tcp_bpf.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index 89bbb8ee1634..9120d75689c0 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c @@ -266,6 +266,41 @@ static int tcp_bpf_wait_data(struct sock *sk, struct sk_psock *psock, return ret; }
+static int tcp_bpf_recvmsg_parser(struct sock *sk, + struct msghdr *msg, + size_t len, + int nonblock, + int flags, + int *addr_len) +{ + struct sk_psock *psock; + int copied; + + if (unlikely(flags & MSG_ERRQUEUE)) + return inet_recv_error(sk, msg, len, addr_len); + + psock = sk_psock_get(sk); + if (unlikely(!psock)) + return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len); + + lock_sock(sk); +msg_bytes_ready: + copied = __tcp_bpf_recvmsg(sk, psock, msg, len, flags); + if (!copied) { + long timeo; + int data; + + timeo = sock_rcvtimeo(sk, nonblock); + data = tcp_bpf_wait_data(sk, psock, flags, timeo, NULL); + if (data && !sk_psock_queue_empty(psock)) + goto msg_bytes_ready; + copied = -EAGAIN; + } + release_sock(sk); + sk_psock_put(sk, psock); + return copied; +} + static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, int flags, int *addr_len) { @@ -569,6 +604,8 @@ enum { enum { TCP_BPF_BASE, TCP_BPF_TX, + TCP_BPF_RX, + TCP_BPF_TXRX, TCP_BPF_NUM_CFGS, };
@@ -588,6 +625,12 @@ static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS], prot[TCP_BPF_TX] = prot[TCP_BPF_BASE]; prot[TCP_BPF_TX].sendmsg = tcp_bpf_sendmsg; prot[TCP_BPF_TX].sendpage = tcp_bpf_sendpage; + + prot[TCP_BPF_RX] = prot[TCP_BPF_BASE]; + prot[TCP_BPF_RX].recvmsg = tcp_bpf_recvmsg_parser; + + prot[TCP_BPF_TXRX] = prot[TCP_BPF_TX]; + prot[TCP_BPF_TXRX].recvmsg = tcp_bpf_recvmsg_parser; }
static void tcp_bpf_check_v6_needs_rebuild(struct proto *ops) @@ -625,6 +668,10 @@ struct proto *tcp_bpf_get_proto(struct sock *sk, struct sk_psock *psock) int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4; int config = psock->progs.msg_parser ? TCP_BPF_TX : TCP_BPF_BASE;
+ if (psock->progs.skb_verdict) { + config = (config == TCP_BPF_TX) ? TCP_BPF_TXRX : TCP_BPF_RX; + } + if (sk->sk_family == AF_INET6) { if (tcp_bpf_assert_proto_ops(psock->sk_proto)) return ERR_PTR(-EINVAL);
From: John Fastabend john.fastabend@gmail.com
mainline inclusion from mainline-v5.17-rc1 commit 5b2c5540b8110eea0d67a78fb0ddb9654c58daeb category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I65HYE
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
---------------------------
Applications can be confused slightly because we do not always return the same error code as expected, e.g. what the TCP stack normally returns. For example on a sock err sk->sk_err instead of returning the sock_error we return EAGAIN. This usually means the application will 'try again' instead of aborting immediately. Another example, when a shutdown event is received we should immediately abort instead of waiting for data when the user provides a timeout.
These tend to not be fatal, applications usually recover, but introduces bogus errors to the user or introduces unexpected latency. Before 'c5d2177a72a16' we fell back to the TCP stack when no data was available so we managed to catch many of the cases here, although with the extra latency cost of calling tcp_msg_wait_data() first.
To fix lets duplicate the error handling in TCP stack into tcp_bpf so that we get the same error codes.
These were found in our CI tests that run applications against sockmap and do longer lived testing, at least compared to test_sockmap that does short-lived ping/pong tests, and in some of our test clusters we deploy.
Its non-trivial to do these in a shorter form CI tests that would be appropriate for BPF selftests, but we are looking into it so we can ensure this keeps working going forward. As a preview one idea is to pull in the packetdrill testing which catches some of this.
Fixes: c5d2177a72a16 ("bpf, sockmap: Fix race in ingress receive verdict with redirect to self") Signed-off-by: John Fastabend john.fastabend@gmail.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Link: https://lore.kernel.org/bpf/20220104205918.286416-1-john.fastabend@gmail.com (cherry picked from commit 5b2c5540b8110eea0d67a78fb0ddb9654c58daeb) Signed-off-by: Liu Jian liujian56@huawei.com
Conflicts: net/ipv4/tcp_bpf.c Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- net/ipv4/tcp_bpf.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index 9120d75689c0..0169837e1f1e 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c @@ -290,12 +290,39 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, long timeo; int data;
+ if (sock_flag(sk, SOCK_DONE)) + goto out; + + if (sk->sk_err) { + copied = sock_error(sk); + goto out; + } + + if (sk->sk_shutdown & RCV_SHUTDOWN) + goto out; + + if (sk->sk_state == TCP_CLOSE) { + copied = -ENOTCONN; + goto out; + } + timeo = sock_rcvtimeo(sk, nonblock); + if (!timeo) { + copied = -EAGAIN; + goto out; + } + + if (signal_pending(current)) { + copied = sock_intr_errno(timeo); + goto out; + } + data = tcp_bpf_wait_data(sk, psock, flags, timeo, NULL); if (data && !sk_psock_queue_empty(psock)) goto msg_bytes_ready; copied = -EAGAIN; } +out: release_sock(sk); sk_psock_put(sk, psock); return copied;
From: John Fastabend john.fastabend@gmail.com
mainline inclusion from mainline-v5.16-rc5 commit 38207a5e81230d6ffbdd51e5fa5681be5116dcae category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I65HYE
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
---------------------------
When a TCP socket is added to a sock map we look at the programs attached to the map to determine what proto op hooks need to be changed. Before the patch in the 'fixes' tag there were only two categories -- the empty set of programs or a TX policy. In any case the base set handled the receive case.
After the fix we have an optimized program for receive that closes a small, but possible, race on receive. This program is loaded only when the map the psock is being added to includes a RX policy. Otherwise, the race is not possible so we don't need to handle the race condition.
In order for the call to sk_psock_init() to correctly evaluate the above conditions all progs need to be set in the psock before the call. However, in the current code this is not the case. We end up evaluating the requirements on the old prog state. If your psock is attached to multiple maps -- for example a tx map and rx map -- then the second update would pull in the correct maps. But, the other pattern with a single rx enabled map the correct receive hooks are not used. The result is the race fixed by the patch in the fixes tag below may still be seen in this case.
To fix we simply set all psock->progs before doing the call into sock_map_init(). With this the init() call gets the full list of programs and chooses the correct proto ops on the first iteration instead of requiring the second update to pull them in. This fixes the race case when only a single map is used.
Fixes: c5d2177a72a16 ("bpf, sockmap: Fix race in ingress receive verdict with redirect to self") Signed-off-by: John Fastabend john.fastabend@gmail.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Link: https://lore.kernel.org/bpf/20211119181418.353932-2-john.fastabend@gmail.com (cherry picked from commit 38207a5e81230d6ffbdd51e5fa5681be5116dcae) Signed-off-by: Liu Jian liujian56@huawei.com
Conflicts: net/core/sock_map.c Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- net/core/sock_map.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 79528310e6a7..9cdb5b072b3d 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -286,6 +286,10 @@ static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs,
if (msg_parser) psock_set_prog(&psock->progs.msg_parser, msg_parser); + if (skb_parser) + psock_set_prog(&psock->progs.skb_parser, skb_parser); + if (skb_verdict) + psock_set_prog(&psock->progs.skb_verdict, skb_verdict);
ret = sock_map_init_proto(sk, psock); if (ret < 0) @@ -296,11 +300,8 @@ static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs, ret = sk_psock_init_strp(sk, psock); if (ret) goto out_unlock_drop; - psock_set_prog(&psock->progs.skb_verdict, skb_verdict); - psock_set_prog(&psock->progs.skb_parser, skb_parser); sk_psock_start_strp(sk, psock); } else if (!skb_parser && skb_verdict && !psock->parser.enabled) { - psock_set_prog(&psock->progs.skb_verdict, skb_verdict); sk_psock_start_verdict(sk,psock); } write_unlock_bh(&sk->sk_callback_lock);
From: John Fastabend john.fastabend@gmail.com
mainline inclusion from mainline-v5.16-rc5 commit c0d95d3380ee099d735e08618c0d599e72f6c8b0 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I65HYE
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
---------------------------
When a sock is added to a sock map we evaluate what proto op hooks need to be used. However, when the program is removed from the sock map we have not been evaluating if that changes the required program layout.
Before the patch listed in the 'fixes' tag this was not causing failures because the base program set handles all cases. Specifically, the case with a stream parser and the case with out a stream parser are both handled. With the fix below we identified a race when running with a proto op that attempts to read skbs off both the stream parser and the skb->receive_queue. Namely, that a race existed where when the stream parser is empty checking the skb->receive_queue from recvmsg at the precies moment when the parser is paused and the receive_queue is not empty could result in skipping the stream parser. This may break a RX policy depending on the parser to run.
The fix tag then loads a specific proto ops that resolved this race. But, we missed removing that proto ops recv hook when the sock is removed from the sockmap. The result is the stream parser is stopped so no more skbs will be aggregated there, but the hook and BPF program continues to be attached on the psock. User space will then get an EBUSY when trying to read the socket because the recvmsg() handler is now waiting on a stopped stream parser.
To fix we rerun the proto ops init() function which will look at the new set of progs attached to the psock and rest the proto ops hook to the correct handlers. And in the above case where we remove the sock from the sock map the RX prog will no longer be listed so the proto ops is removed.
Fixes: c5d2177a72a16 ("bpf, sockmap: Fix race in ingress receive verdict with redirect to self") Signed-off-by: John Fastabend john.fastabend@gmail.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Link: https://lore.kernel.org/bpf/20211119181418.353932-3-john.fastabend@gmail.com (cherry picked from commit c0d95d3380ee099d735e08618c0d599e72f6c8b0) Signed-off-by: Liu Jian liujian56@huawei.com
Conflicts: net/core/skmsg.c Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- net/core/skmsg.c | 4 ++++ net/core/sock_map.c | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/net/core/skmsg.c b/net/core/skmsg.c index 925863fab5bd..26a39b672966 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -1119,6 +1119,8 @@ void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock) { struct sk_psock_parser *parser = &psock->parser;
+ psock_set_prog(&psock->progs.skb_parser, NULL); + if (!parser->enabled) return;
@@ -1132,6 +1134,8 @@ void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock) { struct sk_psock_parser *parser = &psock->parser;
+ psock_set_prog(&psock->progs.skb_verdict, NULL); + if (!parser->enabled) return;
diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 9cdb5b072b3d..ddb6a9495c3b 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -145,6 +145,8 @@ static void sock_map_add_link(struct sk_psock *psock, spin_unlock_bh(&psock->link_lock); }
+static int sock_map_init_proto(struct sock *sk, struct sk_psock *psock); + static void sock_map_del_link(struct sock *sk, struct sk_psock *psock, void *link_raw) { @@ -170,8 +172,10 @@ static void sock_map_del_link(struct sock *sk, write_lock_bh(&sk->sk_callback_lock); if (strp_stop) sk_psock_stop_strp(sk, psock); - else + if (verdict_stop) sk_psock_stop_verdict(sk, psock); + + sock_map_init_proto(sk, psock); write_unlock_bh(&sk->sk_callback_lock); } }
From: John Fastabend john.fastabend@gmail.com
mainline inclusion from mainline-v5.17-rc1 commit 218d747a4142f281a256687bb513a135c905867b category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I65HYE
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
---------------------------
sock_map_link() is called to update a sockmap entry with a sk. But, if the sock_map_init_proto() call fails then we return an error to the map_update op against the sockmap. In the error path though we need to cleanup psock and dec the refcnt on any programs associated with the map, because we refcnt them early in the update process to ensure they are pinned for the psock. (This avoids a race where user deletes programs while also updating the map with new socks.)
In current code we do the prog refcnt dec explicitely by calling bpf_prog_put() when the program was found in the map. But, after commit '38207a5e81230' in this error path we've already done the prog to psock assignment so the programs have a reference from the psock as well. This then causes the psock tear down logic, invoked by sk_psock_put() in the error path, to similarly call bpf_prog_put on the programs there.
To be explicit this logic does the prog->psock assignment:
if (msg_*) psock_set_prog(...)
Then the error path under the out_progs label does a similar check and dec with:
if (msg_*) bpf_prog_put(...)
And the teardown logic sk_psock_put() does ...
psock_set_prog(msg_*, NULL)
... triggering another bpf_prog_put(...). Then KASAN gives us this splat, found by syzbot because we've created an inbalance between bpf_prog_inc and bpf_prog_put calling put twice on the program.
BUG: KASAN: vmalloc-out-of-bounds in __bpf_prog_put kernel/bpf/syscall.c:1812 [inline] BUG: KASAN: vmalloc-out-of-bounds in __bpf_prog_put kernel/bpf/syscall.c:1812 [inline] kernel/bpf/syscall.c:1829 BUG: KASAN: vmalloc-out-of-bounds in bpf_prog_put+0x8c/0x4f0 kernel/bpf/syscall.c:1829 kernel/bpf/syscall.c:1829 Read of size 8 at addr ffffc90000e76038 by task syz-executor020/3641
To fix clean up error path so it doesn't try to do the bpf_prog_put in the error path once progs are assigned then it relies on the normal psock tear down logic to do complete cleanup.
For completness we also cover the case whereh sk_psock_init_strp() fails, but this is not expected because it indicates an incorrect socket type and should be caught earlier.
Fixes: 38207a5e8123 ("bpf, sockmap: Attach map progs to psock early for feature probes") Reported-by: syzbot+bb73e71cf4b8fd376a4f@syzkaller.appspotmail.com Signed-off-by: John Fastabend john.fastabend@gmail.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Link: https://lore.kernel.org/bpf/20220104214645.290900-1-john.fastabend@gmail.com (cherry picked from commit 218d747a4142f281a256687bb513a135c905867b) Signed-off-by: Liu Jian liujian56@huawei.com
Conflicts: net/core/sock_map.c Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- net/core/sock_map.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/net/core/sock_map.c b/net/core/sock_map.c index ddb6a9495c3b..9cee55321ef2 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c @@ -295,25 +295,29 @@ static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs, if (skb_verdict) psock_set_prog(&psock->progs.skb_verdict, skb_verdict);
+ /* msg_* and stream_* programs references tracked in psock after this + * point. Reference dec and cleanup will occur through psock destructor + */ ret = sock_map_init_proto(sk, psock); - if (ret < 0) - goto out_drop; + if (ret < 0) { + sk_psock_put(sk, psock); + goto out; + }
write_lock_bh(&sk->sk_callback_lock); if (skb_parser && skb_verdict && !psock->parser.enabled) { ret = sk_psock_init_strp(sk, psock); - if (ret) - goto out_unlock_drop; + if (ret) { + write_unlock_bh(&sk->sk_callback_lock); + sk_psock_put(sk, psock); + goto out; + } sk_psock_start_strp(sk, psock); } else if (!skb_parser && skb_verdict && !psock->parser.enabled) { sk_psock_start_verdict(sk,psock); } write_unlock_bh(&sk->sk_callback_lock); return 0; -out_unlock_drop: - write_unlock_bh(&sk->sk_callback_lock); -out_drop: - sk_psock_put(sk, psock); out_progs: if (msg_parser) bpf_prog_put(msg_parser); @@ -323,6 +327,7 @@ static int sock_map_link(struct bpf_map *map, struct sk_psock_progs *progs, out_put_skb_verdict: if (skb_verdict) bpf_prog_put(skb_verdict); +out: return ret; }
From: Liu Jian liujian56@huawei.com
mainline inclusion from mainline-v6.3-rc2 commit d900f3d20cc3169ce42ec72acc850e662a4d4db2 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I65HYE
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
---------------------------
When the buffer length of the recvmsg system call is 0, we got the flollowing soft lockup problem:
watchdog: BUG: soft lockup - CPU#3 stuck for 27s! [a.out:6149] CPU: 3 PID: 6149 Comm: a.out Kdump: loaded Not tainted 6.2.0+ #30 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 RIP: 0010:remove_wait_queue+0xb/0xc0 Code: 5e 41 5f c3 cc cc cc cc 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa 0f 1f 44 00 00 41 57 <41> 56 41 55 41 54 55 48 89 fd 53 48 89 f3 4c 8d 6b 18 4c 8d 73 20 RSP: 0018:ffff88811b5978b8 EFLAGS: 00000246 RAX: 0000000000000000 RBX: ffff88811a7d3780 RCX: ffffffffb7a4d768 RDX: dffffc0000000000 RSI: ffff88811b597908 RDI: ffff888115408040 RBP: 1ffff110236b2f1b R08: 0000000000000000 R09: ffff88811a7d37e7 R10: ffffed10234fa6fc R11: 0000000000000001 R12: ffff88811179b800 R13: 0000000000000001 R14: ffff88811a7d38a8 R15: ffff88811a7d37e0 FS: 00007f6fb5398740(0000) GS:ffff888237180000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000020000000 CR3: 000000010b6ba002 CR4: 0000000000370ee0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> tcp_msg_wait_data+0x279/0x2f0 tcp_bpf_recvmsg_parser+0x3c6/0x490 inet_recvmsg+0x280/0x290 sock_recvmsg+0xfc/0x120 ____sys_recvmsg+0x160/0x3d0 ___sys_recvmsg+0xf0/0x180 __sys_recvmsg+0xea/0x1a0 do_syscall_64+0x3f/0x90 entry_SYSCALL_64_after_hwframe+0x72/0xdc
The logic in tcp_bpf_recvmsg_parser is as follows:
msg_bytes_ready: copied = sk_msg_recvmsg(sk, psock, msg, len, flags); if (!copied) { wait data; goto msg_bytes_ready; }
In this case, "copied" always is 0, the infinite loop occurs.
According to the Linux system call man page, 0 should be returned in this case. Therefore, in tcp_bpf_recvmsg_parser(), if the length is 0, directly return. Also modify several other functions with the same problem.
Fixes: 1f5be6b3b063 ("udp: Implement udp_bpf_recvmsg() for sockmap") Fixes: 9825d866ce0d ("af_unix: Implement unix_dgram_bpf_recvmsg()") Fixes: c5d2177a72a1 ("bpf, sockmap: Fix race in ingress receive verdict with redirect to self") Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") Signed-off-by: Liu Jian liujian56@huawei.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Acked-by: John Fastabend john.fastabend@gmail.com Cc: Jakub Sitnicki jakub@cloudflare.com Link: https://lore.kernel.org/bpf/20230303080946.1146638-1-liujian56@huawei.com Signed-off-by: Liu Jian liujian56@huawei.com
Conflicts: net/ipv4/udp_bpf.c net/unix/unix_bpf.c Reviewed-by: Yue Haibing yuehaibing@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- net/ipv4/tcp_bpf.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index 0169837e1f1e..438992e28efe 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c @@ -279,6 +279,9 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, if (unlikely(flags & MSG_ERRQUEUE)) return inet_recv_error(sk, msg, len, addr_len);
+ if (!len) + return 0; + psock = sk_psock_get(sk); if (unlikely(!psock)) return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
From: Baokun Li libaokun1@huawei.com
mainline inclusion from mainline-v6.3-rc8 commit 1ba1199ec5747f475538c0d25a32804e5ba1dfde category: bugfix bugzilla: 188601, https://gitee.com/openeuler/kernel/issues/I6TNTC CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
KASAN report null-ptr-deref: ================================================================== BUG: KASAN: null-ptr-deref in bdi_split_work_to_wbs+0x5c5/0x7b0 Write of size 8 at addr 0000000000000000 by task sync/943 CPU: 5 PID: 943 Comm: sync Tainted: 6.3.0-rc5-next-20230406-dirty #461 Call Trace: <TASK> dump_stack_lvl+0x7f/0xc0 print_report+0x2ba/0x340 kasan_report+0xc4/0x120 kasan_check_range+0x1b7/0x2e0 __kasan_check_write+0x24/0x40 bdi_split_work_to_wbs+0x5c5/0x7b0 sync_inodes_sb+0x195/0x630 sync_inodes_one_sb+0x3a/0x50 iterate_supers+0x106/0x1b0 ksys_sync+0x98/0x160 [...] ==================================================================
The race that causes the above issue is as follows:
cpu1 cpu2 -------------------------|------------------------- inode_switch_wbs INIT_WORK(&isw->work, inode_switch_wbs_work_fn) queue_rcu_work(isw_wq, &isw->work) // queue_work async inode_switch_wbs_work_fn wb_put_many(old_wb, nr_switched) percpu_ref_put_many ref->data->release(ref) cgwb_release queue_work(cgwb_release_wq, &wb->release_work) // queue_work async &wb->release_work cgwb_release_workfn ksys_sync iterate_supers sync_inodes_one_sb sync_inodes_sb bdi_split_work_to_wbs kmalloc(sizeof(*work), GFP_ATOMIC) // alloc memory failed percpu_ref_exit ref->data = NULL kfree(data) wb_get(wb) percpu_ref_get(&wb->refcnt) percpu_ref_get_many(ref, 1) atomic_long_add(nr, &ref->data->count) atomic64_add(i, v) // trigger null-ptr-deref
bdi_split_work_to_wbs() traverses &bdi->wb_list to split work into all wbs. If the allocation of new work fails, the on-stack fallback will be used and the reference count of the current wb is increased afterwards. If cgroup writeback membership switches occur before getting the reference count and the current wb is released as old_wd, then calling wb_get() or wb_put() will trigger the null pointer dereference above.
This issue was introduced in v4.3-rc7 (see fix tag1). Both sync_inodes_sb() and __writeback_inodes_sb_nr() calls to bdi_split_work_to_wbs() can trigger this issue. For scenarios called via sync_inodes_sb(), originally commit 7fc5854f8c6e ("writeback: synchronize sync(2) against cgroup writeback membership switches") reduced the possibility of the issue by adding wb_switch_rwsem, but in v5.14-rc1 (see fix tag2) removed the "inode_io_list_del_locked(inode, old_wb)" from inode_switch_wbs_work_fn() so that wb->state contains WB_has_dirty_io, thus old_wb is not skipped when traversing wbs in bdi_split_work_to_wbs(), and the issue becomes easily reproducible again.
To solve this problem, percpu_ref_exit() is called under RCU protection to avoid race between cgwb_release_workfn() and bdi_split_work_to_wbs(). Moreover, replace wb_get() with wb_tryget() in bdi_split_work_to_wbs(), and skip the current wb if wb_tryget() fails because the wb has already been shutdown.
Link: https://lkml.kernel.org/r/20230410130826.1492525-1-libaokun1@huawei.com Fixes: b817525a4a80 ("writeback: bdi_writeback iteration must not skip dying ones") Signed-off-by: Baokun Li libaokun1@huawei.com Reviewed-by: Jan Kara jack@suse.cz Acked-by: Tejun Heo tj@kernel.org Cc: Alexander Viro viro@zeniv.linux.org.uk Cc: Andreas Dilger adilger.kernel@dilger.ca Cc: Christian Brauner brauner@kernel.org Cc: Dennis Zhou dennis@kernel.org Cc: Hou Tao houtao1@huawei.com Cc: yangerkun yangerkun@huawei.com Cc: Zhang Yi yi.zhang@huawei.com Cc: Jens Axboe axboe@kernel.dk Cc: stable@vger.kernel.org Signed-off-by: Andrew Morton akpm@linux-foundation.org
Conflicts: mm/backing-dev.c
Signed-off-by: Baokun Li libaokun1@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Reviewed-by: Yang Erkun yangerkun@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- fs/fs-writeback.c | 17 ++++++++++------- mm/backing-dev.c | 12 ++++++++++-- 2 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 2011199476ea..20e29e35884a 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -884,6 +884,16 @@ static void bdi_split_work_to_wbs(struct backing_dev_info *bdi, continue; }
+ /* + * If wb_tryget fails, the wb has been shutdown, skip it. + * + * Pin @wb so that it stays on @bdi->wb_list. This allows + * continuing iteration from @wb after dropping and + * regrabbing rcu read lock. + */ + if (!wb_tryget(wb)) + continue; + /* alloc failed, execute synchronously using on-stack fallback */ work = &fallback_work; *work = *base_work; @@ -892,13 +902,6 @@ static void bdi_split_work_to_wbs(struct backing_dev_info *bdi, work->done = &fallback_work_done;
wb_queue_work(wb, work); - - /* - * Pin @wb so that it stays on @bdi->wb_list. This allows - * continuing iteration from @wb after dropping and - * regrabbing rcu read lock. - */ - wb_get(wb); last_wb = wb;
rcu_read_unlock(); diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 707bf409f570..45ac57fd6e7a 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -378,6 +378,15 @@ static void wb_exit(struct bdi_writeback *wb) static DEFINE_SPINLOCK(cgwb_lock); static struct workqueue_struct *cgwb_release_wq;
+static void cgwb_free_rcu(struct rcu_head *rcu_head) +{ + struct bdi_writeback *wb = container_of(rcu_head, + struct bdi_writeback, rcu); + + percpu_ref_exit(&wb->refcnt); + kfree(wb); +} + static void cgwb_release_workfn(struct work_struct *work) { struct bdi_writeback *wb = container_of(work, struct bdi_writeback, @@ -395,9 +404,8 @@ static void cgwb_release_workfn(struct work_struct *work) blkcg_unpin_online(blkcg);
fprop_local_destroy_percpu(&wb->memcg_completions); - percpu_ref_exit(&wb->refcnt); wb_exit(wb); - kfree_rcu(wb, rcu); + call_rcu(&wb->rcu, cgwb_free_rcu); }
static void cgwb_release(struct percpu_ref *refcnt)
From: Arnd Bergmann arnd@arndb.de
mainline inclusion from mainline-v6.0-rc1~14 commit b04e75a4a8a81887386a0d2dbf605a48e779d2a0 category: bugfix bugzilla: 188707, https://gitee.com/src-openeuler/kernel/issues/I6VK2F CVE: CVE-2023-2007
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
----------------------------------------
The dpt_i2o driver was fixed to stop using virt_to_bus() in 2008, but it still has a stale reference in an error handling code path that could never work. I submitted a patch to fix this reference earlier, but Hannes Reinecke suggested that removing the driver may be just as good here.
The i2o driver layer was removed in 2015 with commit 4a72a7af462d ("staging: remove i2o subsystem"), but the even older dpt_i2o scsi driver stayed around.
The last non-cleanup patches I could find were from Miquel van Smoorenburg and Mark Salyzyn back in 2008, they might know if there is any chance of the hardware still being used anywhere.
Link: https://lore.kernel.org/linux-scsi/CAK8P3a1XfwkTOV7qOs1fTxf4vthNBRXKNu8A5V7T... Link: https://lore.kernel.org/r/20220624155226.2889613-3-arnd@kernel.org Cc: Miquel van Smoorenburg mikevs@xs4all.net Cc: Mark Salyzyn salyzyn@android.com Cc: Hannes Reinecke hare@suse.de Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Zhong Jinghua zhongjinghua@huawei.com Reviewed-by: Yu Kuai yukuai3@huawei.com Reviewed-by: Hou Tao houtao1@huawei.com Reviewed-by: Xiu Jianfeng xiujianfeng@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- .../userspace-api/ioctl/ioctl-number.rst | 2 +- MAINTAINERS | 8 - drivers/scsi/Kconfig | 11 - drivers/scsi/Makefile | 1 - drivers/scsi/dpt/dpti_i2o.h | 441 -- drivers/scsi/dpt/dpti_ioctl.h | 136 - drivers/scsi/dpt/dptsig.h | 336 -- drivers/scsi/dpt/osd_defs.h | 79 - drivers/scsi/dpt/osd_util.h | 358 -- drivers/scsi/dpt/sys_info.h | 417 -- drivers/scsi/dpt_i2o.c | 3549 ----------------- drivers/scsi/dpti.h | 331 -- 12 files changed, 1 insertion(+), 5668 deletions(-) delete mode 100644 drivers/scsi/dpt/dpti_i2o.h delete mode 100644 drivers/scsi/dpt/dpti_ioctl.h delete mode 100644 drivers/scsi/dpt/dptsig.h delete mode 100644 drivers/scsi/dpt/osd_defs.h delete mode 100644 drivers/scsi/dpt/osd_util.h delete mode 100644 drivers/scsi/dpt/sys_info.h delete mode 100644 drivers/scsi/dpt_i2o.c delete mode 100644 drivers/scsi/dpti.h
diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 250519f73990..da39c1b35bf5 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -117,7 +117,7 @@ Code Seq# Include File Comments 'C' 01-2F linux/capi.h conflict! 'C' F0-FF drivers/net/wan/cosa.h conflict! 'D' all arch/s390/include/asm/dasd.h -'D' 40-5F drivers/scsi/dpt/dtpi_ioctl.h +'D' 40-5F drivers/scsi/dpt/dtpi_ioctl.h Dead since 2022 'D' 05 drivers/scsi/pmcraid.h 'E' all linux/input.h conflict! 'E' 00-0F xen/evtchn.h conflict! diff --git a/MAINTAINERS b/MAINTAINERS index 1b5a590049fb..9ff81630739f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5420,14 +5420,6 @@ L: linux-kernel@vger.kernel.org S: Maintained F: drivers/staging/fsl-dpaa2/ethsw
-DPT_I2O SCSI RAID DRIVER -M: Adaptec OEM Raid Solutions aacraid@microsemi.com -L: linux-scsi@vger.kernel.org -S: Maintained -W: http://www.adaptec.com/ -F: drivers/scsi/dpt* -F: drivers/scsi/dpt/ - DRBD DRIVER M: Philipp Reisner philipp.reisner@linbit.com M: Lars Ellenberg lars.ellenberg@linbit.com diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index b06867d73924..a9da1b2dec4a 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -442,17 +442,6 @@ config SCSI_MVUMI To compile this driver as a module, choose M here: the module will be called mvumi.
-config SCSI_DPT_I2O - tristate "Adaptec I2O RAID support " - depends on SCSI && PCI && VIRT_TO_BUS - help - This driver supports all of Adaptec's I2O based RAID controllers as - well as the DPT SmartRaid V cards. This is an Adaptec maintained - driver by Deanna Bonds. See file:Documentation/scsi/dpti.rst. - - To compile this driver as a module, choose M here: the - module will be called dpt_i2o. - config SCSI_ADVANSYS tristate "AdvanSys SCSI support" depends on SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index b8da457dd1d5..c2a1efa16912 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -64,7 +64,6 @@ obj-$(CONFIG_BVME6000_SCSI) += 53c700.o bvme6000_scsi.o obj-$(CONFIG_SCSI_SIM710) += 53c700.o sim710.o obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o -obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o obj-$(CONFIG_SCSI_ARCMSR) += arcmsr/ obj-$(CONFIG_SCSI_AHA152X) += aha152x.o obj-$(CONFIG_SCSI_AHA1542) += aha1542.o diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h deleted file mode 100644 index bf0daeeb50a9..000000000000 --- a/drivers/scsi/dpt/dpti_i2o.h +++ /dev/null @@ -1,441 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -#ifndef _SCSI_I2O_H -#define _SCSI_I2O_H - -/* I2O kernel space accessible structures/APIs - * - * (c) Copyright 1999, 2000 Red Hat Software - * - ************************************************************************* - * - * This header file defined the I2O APIs/structures for use by - * the I2O kernel modules. - */ - -#ifdef __KERNEL__ /* This file to be included by kernel only */ - -#include <linux/i2o-dev.h> - -#include <linux/notifier.h> -#include <linux/atomic.h> - - -/* - * Tunable parameters first - */ - -/* How many different OSM's are we allowing */ -#define MAX_I2O_MODULES 64 - -#define I2O_EVT_CAPABILITY_OTHER 0x01 -#define I2O_EVT_CAPABILITY_CHANGED 0x02 - -#define I2O_EVT_SENSOR_STATE_CHANGED 0x01 - -//#ifdef __KERNEL__ /* ioctl stuff only thing exported to users */ - -#define I2O_MAX_MANAGERS 4 - -/* - * I2O Interface Objects - */ - -#include <linux/wait.h> -typedef wait_queue_head_t adpt_wait_queue_head_t; -#define ADPT_DECLARE_WAIT_QUEUE_HEAD(wait) DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait) -typedef wait_queue_entry_t adpt_wait_queue_entry_t; - -/* - * message structures - */ - -struct i2o_message -{ - u8 version_offset; - u8 flags; - u16 size; - u32 target_tid:12; - u32 init_tid:12; - u32 function:8; - u32 initiator_context; - /* List follows */ -}; - -struct adpt_device; -struct _adpt_hba; -struct i2o_device -{ - struct i2o_device *next; /* Chain */ - struct i2o_device *prev; - - char dev_name[8]; /* linux /dev name if available */ - i2o_lct_entry lct_data;/* Device LCT information */ - u32 flags; - struct proc_dir_entry* proc_entry; /* /proc dir */ - struct adpt_device *owner; - struct _adpt_hba *controller; /* Controlling IOP */ -}; - -/* - * Each I2O controller has one of these objects - */ - -struct i2o_controller -{ - char name[16]; - int unit; - int type; - int enabled; - - struct notifier_block *event_notifer; /* Events */ - atomic_t users; - struct i2o_device *devices; /* I2O device chain */ - struct i2o_controller *next; /* Controller chain */ - -}; - -/* - * I2O System table entry - */ -struct i2o_sys_tbl_entry -{ - u16 org_id; - u16 reserved1; - u32 iop_id:12; - u32 reserved2:20; - u16 seg_num:12; - u16 i2o_version:4; - u8 iop_state; - u8 msg_type; - u16 frame_size; - u16 reserved3; - u32 last_changed; - u32 iop_capabilities; - u32 inbound_low; - u32 inbound_high; -}; - -struct i2o_sys_tbl -{ - u8 num_entries; - u8 version; - u16 reserved1; - u32 change_ind; - u32 reserved2; - u32 reserved3; - struct i2o_sys_tbl_entry iops[0]; -}; - -/* - * I2O classes / subclasses - */ - -/* Class ID and Code Assignments - * (LCT.ClassID.Version field) - */ -#define I2O_CLASS_VERSION_10 0x00 -#define I2O_CLASS_VERSION_11 0x01 - -/* Class code names - * (from v1.5 Table 6-1 Class Code Assignments.) - */ - -#define I2O_CLASS_EXECUTIVE 0x000 -#define I2O_CLASS_DDM 0x001 -#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010 -#define I2O_CLASS_SEQUENTIAL_STORAGE 0x011 -#define I2O_CLASS_LAN 0x020 -#define I2O_CLASS_WAN 0x030 -#define I2O_CLASS_FIBRE_CHANNEL_PORT 0x040 -#define I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL 0x041 -#define I2O_CLASS_SCSI_PERIPHERAL 0x051 -#define I2O_CLASS_ATE_PORT 0x060 -#define I2O_CLASS_ATE_PERIPHERAL 0x061 -#define I2O_CLASS_FLOPPY_CONTROLLER 0x070 -#define I2O_CLASS_FLOPPY_DEVICE 0x071 -#define I2O_CLASS_BUS_ADAPTER_PORT 0x080 -#define I2O_CLASS_PEER_TRANSPORT_AGENT 0x090 -#define I2O_CLASS_PEER_TRANSPORT 0x091 - -/* Rest of 0x092 - 0x09f reserved for peer-to-peer classes - */ - -#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff - -/* Subclasses - */ - -#define I2O_SUBCLASS_i960 0x001 -#define I2O_SUBCLASS_HDM 0x020 -#define I2O_SUBCLASS_ISM 0x021 - -/* Operation functions */ - -#define I2O_PARAMS_FIELD_GET 0x0001 -#define I2O_PARAMS_LIST_GET 0x0002 -#define I2O_PARAMS_MORE_GET 0x0003 -#define I2O_PARAMS_SIZE_GET 0x0004 -#define I2O_PARAMS_TABLE_GET 0x0005 -#define I2O_PARAMS_FIELD_SET 0x0006 -#define I2O_PARAMS_LIST_SET 0x0007 -#define I2O_PARAMS_ROW_ADD 0x0008 -#define I2O_PARAMS_ROW_DELETE 0x0009 -#define I2O_PARAMS_TABLE_CLEAR 0x000A - -/* - * I2O serial number conventions / formats - * (circa v1.5) - */ - -#define I2O_SNFORMAT_UNKNOWN 0 -#define I2O_SNFORMAT_BINARY 1 -#define I2O_SNFORMAT_ASCII 2 -#define I2O_SNFORMAT_UNICODE 3 -#define I2O_SNFORMAT_LAN48_MAC 4 -#define I2O_SNFORMAT_WAN 5 - -/* Plus new in v2.0 (Yellowstone pdf doc) - */ - -#define I2O_SNFORMAT_LAN64_MAC 6 -#define I2O_SNFORMAT_DDM 7 -#define I2O_SNFORMAT_IEEE_REG64 8 -#define I2O_SNFORMAT_IEEE_REG128 9 -#define I2O_SNFORMAT_UNKNOWN2 0xff - -/* Transaction Reply Lists (TRL) Control Word structure */ - -#define TRL_SINGLE_FIXED_LENGTH 0x00 -#define TRL_SINGLE_VARIABLE_LENGTH 0x40 -#define TRL_MULTIPLE_FIXED_LENGTH 0x80 - -/* - * Messaging API values - */ - -#define I2O_CMD_ADAPTER_ASSIGN 0xB3 -#define I2O_CMD_ADAPTER_READ 0xB2 -#define I2O_CMD_ADAPTER_RELEASE 0xB5 -#define I2O_CMD_BIOS_INFO_SET 0xA5 -#define I2O_CMD_BOOT_DEVICE_SET 0xA7 -#define I2O_CMD_CONFIG_VALIDATE 0xBB -#define I2O_CMD_CONN_SETUP 0xCA -#define I2O_CMD_DDM_DESTROY 0xB1 -#define I2O_CMD_DDM_ENABLE 0xD5 -#define I2O_CMD_DDM_QUIESCE 0xC7 -#define I2O_CMD_DDM_RESET 0xD9 -#define I2O_CMD_DDM_SUSPEND 0xAF -#define I2O_CMD_DEVICE_ASSIGN 0xB7 -#define I2O_CMD_DEVICE_RELEASE 0xB9 -#define I2O_CMD_HRT_GET 0xA8 -#define I2O_CMD_ADAPTER_CLEAR 0xBE -#define I2O_CMD_ADAPTER_CONNECT 0xC9 -#define I2O_CMD_ADAPTER_RESET 0xBD -#define I2O_CMD_LCT_NOTIFY 0xA2 -#define I2O_CMD_OUTBOUND_INIT 0xA1 -#define I2O_CMD_PATH_ENABLE 0xD3 -#define I2O_CMD_PATH_QUIESCE 0xC5 -#define I2O_CMD_PATH_RESET 0xD7 -#define I2O_CMD_STATIC_MF_CREATE 0xDD -#define I2O_CMD_STATIC_MF_RELEASE 0xDF -#define I2O_CMD_STATUS_GET 0xA0 -#define I2O_CMD_SW_DOWNLOAD 0xA9 -#define I2O_CMD_SW_UPLOAD 0xAB -#define I2O_CMD_SW_REMOVE 0xAD -#define I2O_CMD_SYS_ENABLE 0xD1 -#define I2O_CMD_SYS_MODIFY 0xC1 -#define I2O_CMD_SYS_QUIESCE 0xC3 -#define I2O_CMD_SYS_TAB_SET 0xA3 - -#define I2O_CMD_UTIL_NOP 0x00 -#define I2O_CMD_UTIL_ABORT 0x01 -#define I2O_CMD_UTIL_CLAIM 0x09 -#define I2O_CMD_UTIL_RELEASE 0x0B -#define I2O_CMD_UTIL_PARAMS_GET 0x06 -#define I2O_CMD_UTIL_PARAMS_SET 0x05 -#define I2O_CMD_UTIL_EVT_REGISTER 0x13 -#define I2O_CMD_UTIL_EVT_ACK 0x14 -#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10 -#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D -#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F -#define I2O_CMD_UTIL_LOCK 0x17 -#define I2O_CMD_UTIL_LOCK_RELEASE 0x19 -#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15 - -#define I2O_CMD_SCSI_EXEC 0x81 -#define I2O_CMD_SCSI_ABORT 0x83 -#define I2O_CMD_SCSI_BUSRESET 0x27 - -#define I2O_CMD_BLOCK_READ 0x30 -#define I2O_CMD_BLOCK_WRITE 0x31 -#define I2O_CMD_BLOCK_CFLUSH 0x37 -#define I2O_CMD_BLOCK_MLOCK 0x49 -#define I2O_CMD_BLOCK_MUNLOCK 0x4B -#define I2O_CMD_BLOCK_MMOUNT 0x41 -#define I2O_CMD_BLOCK_MEJECT 0x43 - -#define I2O_PRIVATE_MSG 0xFF - -/* - * Init Outbound Q status - */ - -#define I2O_CMD_OUTBOUND_INIT_IN_PROGRESS 0x01 -#define I2O_CMD_OUTBOUND_INIT_REJECTED 0x02 -#define I2O_CMD_OUTBOUND_INIT_FAILED 0x03 -#define I2O_CMD_OUTBOUND_INIT_COMPLETE 0x04 - -/* - * I2O Get Status State values - */ - -#define ADAPTER_STATE_INITIALIZING 0x01 -#define ADAPTER_STATE_RESET 0x02 -#define ADAPTER_STATE_HOLD 0x04 -#define ADAPTER_STATE_READY 0x05 -#define ADAPTER_STATE_OPERATIONAL 0x08 -#define ADAPTER_STATE_FAILED 0x10 -#define ADAPTER_STATE_FAULTED 0x11 - -/* I2O API function return values */ - -#define I2O_RTN_NO_ERROR 0 -#define I2O_RTN_NOT_INIT 1 -#define I2O_RTN_FREE_Q_EMPTY 2 -#define I2O_RTN_TCB_ERROR 3 -#define I2O_RTN_TRANSACTION_ERROR 4 -#define I2O_RTN_ADAPTER_ALREADY_INIT 5 -#define I2O_RTN_MALLOC_ERROR 6 -#define I2O_RTN_ADPTR_NOT_REGISTERED 7 -#define I2O_RTN_MSG_REPLY_TIMEOUT 8 -#define I2O_RTN_NO_STATUS 9 -#define I2O_RTN_NO_FIRM_VER 10 -#define I2O_RTN_NO_LINK_SPEED 11 - -/* Reply message status defines for all messages */ - -#define I2O_REPLY_STATUS_SUCCESS 0x00 -#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 -#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 -#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 -#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 -#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 -#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 -#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 -#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 -#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A -#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B -#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 - -/* Status codes and Error Information for Parameter functions */ - -#define I2O_PARAMS_STATUS_SUCCESS 0x00 -#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01 -#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02 -#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03 -#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04 -#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05 -#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06 -#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07 -#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08 -#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09 -#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A -#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B -#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C -#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D -#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E -#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F -#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10 - -/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error - * messages: Table 3-2 Detailed Status Codes.*/ - -#define I2O_DSC_SUCCESS 0x0000 -#define I2O_DSC_BAD_KEY 0x0002 -#define I2O_DSC_TCL_ERROR 0x0003 -#define I2O_DSC_REPLY_BUFFER_FULL 0x0004 -#define I2O_DSC_NO_SUCH_PAGE 0x0005 -#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006 -#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007 -#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009 -#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A -#define I2O_DSC_DEVICE_LOCKED 0x000B -#define I2O_DSC_DEVICE_RESET 0x000C -#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D -#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E -#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F -#define I2O_DSC_INVALID_OFFSET 0x0010 -#define I2O_DSC_INVALID_PARAMETER 0x0011 -#define I2O_DSC_INVALID_REQUEST 0x0012 -#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013 -#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014 -#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015 -#define I2O_DSC_MISSING_PARAMETER 0x0016 -#define I2O_DSC_TIMEOUT 0x0017 -#define I2O_DSC_UNKNOWN_ERROR 0x0018 -#define I2O_DSC_UNKNOWN_FUNCTION 0x0019 -#define I2O_DSC_UNSUPPORTED_VERSION 0x001A -#define I2O_DSC_DEVICE_BUSY 0x001B -#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C - -/* Device Claim Types */ -#define I2O_CLAIM_PRIMARY 0x01000000 -#define I2O_CLAIM_MANAGEMENT 0x02000000 -#define I2O_CLAIM_AUTHORIZED 0x03000000 -#define I2O_CLAIM_SECONDARY 0x04000000 - -/* Message header defines for VersionOffset */ -#define I2OVER15 0x0001 -#define I2OVER20 0x0002 -/* Default is 1.5, FIXME: Need support for both 1.5 and 2.0 */ -#define I2OVERSION I2OVER15 -#define SGL_OFFSET_0 I2OVERSION -#define SGL_OFFSET_4 (0x0040 | I2OVERSION) -#define SGL_OFFSET_5 (0x0050 | I2OVERSION) -#define SGL_OFFSET_6 (0x0060 | I2OVERSION) -#define SGL_OFFSET_7 (0x0070 | I2OVERSION) -#define SGL_OFFSET_8 (0x0080 | I2OVERSION) -#define SGL_OFFSET_9 (0x0090 | I2OVERSION) -#define SGL_OFFSET_10 (0x00A0 | I2OVERSION) -#define SGL_OFFSET_12 (0x00C0 | I2OVERSION) - -#define TRL_OFFSET_5 (0x0050 | I2OVERSION) -#define TRL_OFFSET_6 (0x0060 | I2OVERSION) - - /* msg header defines for MsgFlags */ -#define MSG_STATIC 0x0100 -#define MSG_64BIT_CNTXT 0x0200 -#define MSG_MULTI_TRANS 0x1000 -#define MSG_FAIL 0x2000 -#define MSG_LAST 0x4000 -#define MSG_REPLY 0x8000 - - /* minimum size msg */ -#define THREE_WORD_MSG_SIZE 0x00030000 -#define FOUR_WORD_MSG_SIZE 0x00040000 -#define FIVE_WORD_MSG_SIZE 0x00050000 -#define SIX_WORD_MSG_SIZE 0x00060000 -#define SEVEN_WORD_MSG_SIZE 0x00070000 -#define EIGHT_WORD_MSG_SIZE 0x00080000 -#define NINE_WORD_MSG_SIZE 0x00090000 -#define TEN_WORD_MSG_SIZE 0x000A0000 -#define I2O_MESSAGE_SIZE(x) ((x)<<16) - - -/* Special TID Assignments */ - -#define ADAPTER_TID 0 -#define HOST_TID 1 - -#define MSG_FRAME_SIZE 128 -#define NMBR_MSG_FRAMES 128 - -#define MSG_POOL_SIZE 16384 - -#define I2O_POST_WAIT_OK 0 -#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT - - -#endif /* __KERNEL__ */ - -#endif /* _SCSI_I2O_H */ diff --git a/drivers/scsi/dpt/dpti_ioctl.h b/drivers/scsi/dpt/dpti_ioctl.h deleted file mode 100644 index 25e9251f8c78..000000000000 --- a/drivers/scsi/dpt/dpti_ioctl.h +++ /dev/null @@ -1,136 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/*************************************************************************** - dpti_ioctl.h - description - ------------------- - begin : Thu Sep 7 2000 - copyright : (C) 2001 by Adaptec - - See Documentation/scsi/dpti.rst for history, notes, license info - and credits - ***************************************************************************/ - -/*************************************************************************** - * * - * * - ***************************************************************************/ - -/*************************************************************************** - * This file is generated from osd_unix.h * - * *************************************************************************/ - -#ifndef _dpti_ioctl_h -#define _dpti_ioctl_h - -// IOCTL interface commands - -#ifndef _IOWR -# define _IOWR(x,y,z) (((x)<<8)|y) -#endif -#ifndef _IOW -# define _IOW(x,y,z) (((x)<<8)|y) -#endif -#ifndef _IOR -# define _IOR(x,y,z) (((x)<<8)|y) -#endif -#ifndef _IO -# define _IO(x,y) (((x)<<8)|y) -#endif -/* EATA PassThrough Command */ -#define EATAUSRCMD _IOWR('D',65,EATA_CP) -/* Set Debug Level If Enabled */ -#define DPT_DEBUG _IOW('D',66,int) -/* Get Signature Structure */ -#define DPT_SIGNATURE _IOR('D',67,dpt_sig_S) -#if defined __bsdi__ -#define DPT_SIGNATURE_PACKED _IOR('D',67,dpt_sig_S_Packed) -#endif -/* Get Number Of DPT Adapters */ -#define DPT_NUMCTRLS _IOR('D',68,int) -/* Get Adapter Info Structure */ -#define DPT_CTRLINFO _IOR('D',69,CtrlInfo) -/* Get Statistics If Enabled */ -#define DPT_STATINFO _IO('D',70) -/* Clear Stats If Enabled */ -#define DPT_CLRSTAT _IO('D',71) -/* Get System Info Structure */ -#define DPT_SYSINFO _IOR('D',72,sysInfo_S) -/* Set Timeout Value */ -#define DPT_TIMEOUT _IO('D',73) -/* Get config Data */ -#define DPT_CONFIG _IO('D',74) -/* Get Blink LED Code */ -#define DPT_BLINKLED _IOR('D',75,int) -/* Get Statistical information (if available) */ -#define DPT_STATS_INFO _IOR('D',80,STATS_DATA) -/* Clear the statistical information */ -#define DPT_STATS_CLEAR _IO('D',81) -/* Get Performance metrics */ -#define DPT_PERF_INFO _IOR('D',82,dpt_perf_t) -/* Send an I2O command */ -#define I2OUSRCMD _IO('D',76) -/* Inform driver to re-acquire LCT information */ -#define I2ORESCANCMD _IO('D',77) -/* Inform driver to reset adapter */ -#define I2ORESETCMD _IO('D',78) -/* See if the target is mounted */ -#define DPT_TARGET_BUSY _IOR('D',79, TARGET_BUSY_T) - - - /* Structure Returned From Get Controller Info */ - -typedef struct { - uCHAR state; /* Operational state */ - uCHAR id; /* Host adapter SCSI id */ - int vect; /* Interrupt vector number */ - int base; /* Base I/O address */ - int njobs; /* # of jobs sent to HA */ - int qdepth; /* Controller queue depth. */ - int wakebase; /* mpx wakeup base index. */ - uINT SGsize; /* Scatter/Gather list size. */ - unsigned heads; /* heads for drives on cntlr. */ - unsigned sectors; /* sectors for drives on cntlr. */ - uCHAR do_drive32; /* Flag for Above 16 MB Ability */ - uCHAR BusQuiet; /* SCSI Bus Quiet Flag */ - char idPAL[4]; /* 4 Bytes Of The ID Pal */ - uCHAR primary; /* 1 For Primary, 0 For Secondary */ - uCHAR eataVersion; /* EATA Version */ - uINT cpLength; /* EATA Command Packet Length */ - uINT spLength; /* EATA Status Packet Length */ - uCHAR drqNum; /* DRQ Index (0,5,6,7) */ - uCHAR flag1; /* EATA Flags 1 (Byte 9) */ - uCHAR flag2; /* EATA Flags 2 (Byte 30) */ -} CtrlInfo; - -typedef struct { - uSHORT length; // Remaining length of this - uSHORT drvrHBAnum; // Relative HBA # used by the driver - uINT baseAddr; // Base I/O address - uSHORT blinkState; // Blink LED state (0=Not in blink LED) - uCHAR pciBusNum; // PCI Bus # (Optional) - uCHAR pciDeviceNum; // PCI Device # (Optional) - uSHORT hbaFlags; // Miscellaneous HBA flags - uSHORT Interrupt; // Interrupt set for this device. -# if (defined(_DPT_ARC)) - uINT baseLength; - ADAPTER_OBJECT *AdapterObject; - LARGE_INTEGER DmaLogicalAddress; - PVOID DmaVirtualAddress; - LARGE_INTEGER ReplyLogicalAddress; - PVOID ReplyVirtualAddress; -# else - uINT reserved1; // Reserved for future expansion - uINT reserved2; // Reserved for future expansion - uINT reserved3; // Reserved for future expansion -# endif -} drvrHBAinfo_S; - -typedef struct TARGET_BUSY -{ - uLONG channel; - uLONG id; - uLONG lun; - uLONG isBusy; -} TARGET_BUSY_T; - -#endif - diff --git a/drivers/scsi/dpt/dptsig.h b/drivers/scsi/dpt/dptsig.h deleted file mode 100644 index a6644b332b53..000000000000 --- a/drivers/scsi/dpt/dptsig.h +++ /dev/null @@ -1,336 +0,0 @@ -/* BSDI dptsig.h,v 1.7 1998/06/03 19:15:00 karels Exp */ - -/* - * Copyright (c) 1996-1999 Distributed Processing Technology Corporation - * All rights reserved. - * - * Redistribution and use in source form, with or without modification, are - * permitted provided that redistributions of source code must retain the - * above copyright notice, this list of conditions and the following disclaimer. - * - * This software is provided `as is' by Distributed Processing Technology and - * any express or implied warranties, including, but not limited to, the - * implied warranties of merchantability and fitness for a particular purpose, - * are disclaimed. In no event shall Distributed Processing Technology be - * liable for any direct, indirect, incidental, special, exemplary or - * consequential damages (including, but not limited to, procurement of - * substitute goods or services; loss of use, data, or profits; or business - * interruptions) however caused and on any theory of liability, whether in - * contract, strict liability, or tort (including negligence or otherwise) - * arising in any way out of the use of this driver software, even if advised - * of the possibility of such damage. - * - */ - -#ifndef __DPTSIG_H_ -#define __DPTSIG_H_ -#ifdef _SINIX_ADDON -#include "dpt.h" -#endif -/* DPT SIGNATURE SPEC AND HEADER FILE */ -/* Signature Version 1 (sorry no 'A') */ - -/* to make sure we are talking the same size under all OS's */ -typedef unsigned char sigBYTE; -typedef unsigned short sigWORD; -typedef unsigned int sigINT; - -/* - * use sigWORDLittleEndian for: - * dsCapabilities - * dsDeviceSupp - * dsAdapterSupp - * dsApplication - * use sigLONGLittleEndian for: - * dsOS - * so that the sig can be standardised to Little Endian - */ -#if (defined(_DPT_BIG_ENDIAN)) -# define sigWORDLittleEndian(x) ((((x)&0xFF)<<8)|(((x)>>8)&0xFF)) -# define sigLONGLittleEndian(x) \ - ((((x)&0xFF)<<24) | \ - (((x)&0xFF00)<<8) | \ - (((x)&0xFF0000L)>>8) | \ - (((x)&0xFF000000L)>>24)) -#else -# define sigWORDLittleEndian(x) (x) -# define sigLONGLittleEndian(x) (x) -#endif - -/* must make sure the structure is not word or double-word aligned */ -/* --------------------------------------------------------------- */ -/* Borland will ignore the following pragma: */ -/* Word alignment is OFF by default. If in the, IDE make */ -/* sure that Options | Compiler | Code Generation | Word Alignment */ -/* is not checked. If using BCC, do not use the -a option. */ - -#ifndef NO_PACK -#if defined (_DPT_AIX) -#pragma options align=packed -#else -#pragma pack(1) -#endif /* aix */ -#endif -/* For the Macintosh */ -#ifdef STRUCTALIGNMENTSUPPORTED -#pragma options align=mac68k -#endif - - -/* Current Signature Version - sigBYTE dsSigVersion; */ -/* ------------------------------------------------------------------ */ -#define SIG_VERSION 1 - -/* Processor Family - sigBYTE dsProcessorFamily; DISTINCT VALUES */ -/* ------------------------------------------------------------------ */ -/* What type of processor the file is meant to run on. */ -/* This will let us know whether to read sigWORDs as high/low or low/high. */ -#define PROC_INTEL 0x00 /* Intel 80x86/ia64 */ -#define PROC_MOTOROLA 0x01 /* Motorola 68K */ -#define PROC_MIPS4000 0x02 /* MIPS RISC 4000 */ -#define PROC_ALPHA 0x03 /* DEC Alpha */ -#define PROC_POWERPC 0x04 /* IBM Power PC */ -#define PROC_i960 0x05 /* Intel i960 */ -#define PROC_ULTRASPARC 0x06 /* SPARC processor */ - -/* Specific Minimim Processor - sigBYTE dsProcessor; FLAG BITS */ -/* ------------------------------------------------------------------ */ -/* Different bit definitions dependent on processor_family */ - -/* PROC_INTEL: */ -#define PROC_8086 0x01 /* Intel 8086 */ -#define PROC_286 0x02 /* Intel 80286 */ -#define PROC_386 0x04 /* Intel 80386 */ -#define PROC_486 0x08 /* Intel 80486 */ -#define PROC_PENTIUM 0x10 /* Intel 586 aka P5 aka Pentium */ -#define PROC_SEXIUM 0x20 /* Intel 686 aka P6 aka Pentium Pro or MMX */ -#define PROC_IA64 0x40 /* Intel IA64 processor */ - -/* PROC_i960: */ -#define PROC_960RX 0x01 /* Intel 80960RC/RD */ -#define PROC_960HX 0x02 /* Intel 80960HA/HD/HT */ - -/* PROC_MOTOROLA: */ -#define PROC_68000 0x01 /* Motorola 68000 */ -#define PROC_68010 0x02 /* Motorola 68010 */ -#define PROC_68020 0x04 /* Motorola 68020 */ -#define PROC_68030 0x08 /* Motorola 68030 */ -#define PROC_68040 0x10 /* Motorola 68040 */ - -/* PROC_POWERPC */ -#define PROC_PPC601 0x01 /* PowerPC 601 */ -#define PROC_PPC603 0x02 /* PowerPC 603 */ -#define PROC_PPC604 0x04 /* PowerPC 604 */ - -/* PROC_MIPS4000: */ -#define PROC_R4000 0x01 /* MIPS R4000 */ - -/* Filetype - sigBYTE dsFiletype; DISTINCT VALUES */ -/* ------------------------------------------------------------------ */ -#define FT_EXECUTABLE 0 /* Executable Program */ -#define FT_SCRIPT 1 /* Script/Batch File??? */ -#define FT_HBADRVR 2 /* HBA Driver */ -#define FT_OTHERDRVR 3 /* Other Driver */ -#define FT_IFS 4 /* Installable Filesystem Driver */ -#define FT_ENGINE 5 /* DPT Engine */ -#define FT_COMPDRVR 6 /* Compressed Driver Disk */ -#define FT_LANGUAGE 7 /* Foreign Language file */ -#define FT_FIRMWARE 8 /* Downloadable or actual Firmware */ -#define FT_COMMMODL 9 /* Communications Module */ -#define FT_INT13 10 /* INT 13 style HBA Driver */ -#define FT_HELPFILE 11 /* Help file */ -#define FT_LOGGER 12 /* Event Logger */ -#define FT_INSTALL 13 /* An Install Program */ -#define FT_LIBRARY 14 /* Storage Manager Real-Mode Calls */ -#define FT_RESOURCE 15 /* Storage Manager Resource File */ -#define FT_MODEM_DB 16 /* Storage Manager Modem Database */ - -/* Filetype flags - sigBYTE dsFiletypeFlags; FLAG BITS */ -/* ------------------------------------------------------------------ */ -#define FTF_DLL 0x01 /* Dynamic Link Library */ -#define FTF_NLM 0x02 /* Netware Loadable Module */ -#define FTF_OVERLAYS 0x04 /* Uses overlays */ -#define FTF_DEBUG 0x08 /* Debug version */ -#define FTF_TSR 0x10 /* TSR */ -#define FTF_SYS 0x20 /* DOS Loadable driver */ -#define FTF_PROTECTED 0x40 /* Runs in protected mode */ -#define FTF_APP_SPEC 0x80 /* Application Specific */ -#define FTF_ROM (FTF_SYS|FTF_TSR) /* Special Case */ - -/* OEM - sigBYTE dsOEM; DISTINCT VALUES */ -/* ------------------------------------------------------------------ */ -#define OEM_DPT 0 /* DPT */ -#define OEM_ATT 1 /* ATT */ -#define OEM_NEC 2 /* NEC */ -#define OEM_ALPHA 3 /* Alphatronix */ -#define OEM_AST 4 /* AST */ -#define OEM_OLIVETTI 5 /* Olivetti */ -#define OEM_SNI 6 /* Siemens/Nixdorf */ -#define OEM_SUN 7 /* SUN Microsystems */ - -/* Operating System - sigLONG dsOS; FLAG BITS */ -/* ------------------------------------------------------------------ */ -#define OS_DOS 0x00000001 /* PC/MS-DOS */ -#define OS_WINDOWS 0x00000002 /* Microsoft Windows 3.x */ -#define OS_WINDOWS_NT 0x00000004 /* Microsoft Windows NT */ -#define OS_OS2M 0x00000008 /* OS/2 1.2.x,MS 1.3.0,IBM 1.3.x - Monolithic */ -#define OS_OS2L 0x00000010 /* Microsoft OS/2 1.301 - LADDR */ -#define OS_OS22x 0x00000020 /* IBM OS/2 2.x */ -#define OS_NW286 0x00000040 /* Novell NetWare 286 */ -#define OS_NW386 0x00000080 /* Novell NetWare 386 */ -#define OS_GEN_UNIX 0x00000100 /* Generic Unix */ -#define OS_SCO_UNIX 0x00000200 /* SCO Unix */ -#define OS_ATT_UNIX 0x00000400 /* ATT Unix */ -#define OS_UNIXWARE 0x00000800 /* USL Unix */ -#define OS_INT_UNIX 0x00001000 /* Interactive Unix */ -#define OS_SOLARIS 0x00002000 /* SunSoft Solaris */ -#define OS_QNX 0x00004000 /* QNX for Tom Moch */ -#define OS_NEXTSTEP 0x00008000 /* NeXTSTEP/OPENSTEP/MACH */ -#define OS_BANYAN 0x00010000 /* Banyan Vines */ -#define OS_OLIVETTI_UNIX 0x00020000/* Olivetti Unix */ -#define OS_MAC_OS 0x00040000 /* Mac OS */ -#define OS_WINDOWS_95 0x00080000 /* Microsoft Windows '95 */ -#define OS_NW4x 0x00100000 /* Novell Netware 4.x */ -#define OS_BSDI_UNIX 0x00200000 /* BSDi Unix BSD/OS 2.0 and up */ -#define OS_AIX_UNIX 0x00400000 /* AIX Unix */ -#define OS_FREE_BSD 0x00800000 /* FreeBSD Unix */ -#define OS_LINUX 0x01000000 /* Linux */ -#define OS_DGUX_UNIX 0x02000000 /* Data General Unix */ -#define OS_SINIX_N 0x04000000 /* SNI SINIX-N */ -#define OS_PLAN9 0x08000000 /* ATT Plan 9 */ -#define OS_TSX 0x10000000 /* SNH TSX-32 */ - -#define OS_OTHER 0x80000000 /* Other */ - -/* Capabilities - sigWORD dsCapabilities; FLAG BITS */ -/* ------------------------------------------------------------------ */ -#define CAP_RAID0 0x0001 /* RAID-0 */ -#define CAP_RAID1 0x0002 /* RAID-1 */ -#define CAP_RAID3 0x0004 /* RAID-3 */ -#define CAP_RAID5 0x0008 /* RAID-5 */ -#define CAP_SPAN 0x0010 /* Spanning */ -#define CAP_PASS 0x0020 /* Provides passthrough */ -#define CAP_OVERLAP 0x0040 /* Passthrough supports overlapped commands */ -#define CAP_ASPI 0x0080 /* Supports ASPI Command Requests */ -#define CAP_ABOVE16MB 0x0100 /* ISA Driver supports greater than 16MB */ -#define CAP_EXTEND 0x8000 /* Extended info appears after description */ -#ifdef SNI_MIPS -#define CAP_CACHEMODE 0x1000 /* dpt_force_cache is set in driver */ -#endif - -/* Devices Supported - sigWORD dsDeviceSupp; FLAG BITS */ -/* ------------------------------------------------------------------ */ -#define DEV_DASD 0x0001 /* DASD (hard drives) */ -#define DEV_TAPE 0x0002 /* Tape drives */ -#define DEV_PRINTER 0x0004 /* Printers */ -#define DEV_PROC 0x0008 /* Processors */ -#define DEV_WORM 0x0010 /* WORM drives */ -#define DEV_CDROM 0x0020 /* CD-ROM drives */ -#define DEV_SCANNER 0x0040 /* Scanners */ -#define DEV_OPTICAL 0x0080 /* Optical Drives */ -#define DEV_JUKEBOX 0x0100 /* Jukebox */ -#define DEV_COMM 0x0200 /* Communications Devices */ -#define DEV_OTHER 0x0400 /* Other Devices */ -#define DEV_ALL 0xFFFF /* All SCSI Devices */ - -/* Adapters Families Supported - sigWORD dsAdapterSupp; FLAG BITS */ -/* ------------------------------------------------------------------ */ -#define ADF_2001 0x0001 /* PM2001 */ -#define ADF_2012A 0x0002 /* PM2012A */ -#define ADF_PLUS_ISA 0x0004 /* PM2011,PM2021 */ -#define ADF_PLUS_EISA 0x0008 /* PM2012B,PM2022 */ -#define ADF_SC3_ISA 0x0010 /* PM2021 */ -#define ADF_SC3_EISA 0x0020 /* PM2022,PM2122, etc */ -#define ADF_SC3_PCI 0x0040 /* SmartCache III PCI */ -#define ADF_SC4_ISA 0x0080 /* SmartCache IV ISA */ -#define ADF_SC4_EISA 0x0100 /* SmartCache IV EISA */ -#define ADF_SC4_PCI 0x0200 /* SmartCache IV PCI */ -#define ADF_SC5_PCI 0x0400 /* Fifth Generation I2O products */ -/* - * Combinations of products - */ -#define ADF_ALL_2000 (ADF_2001|ADF_2012A) -#define ADF_ALL_PLUS (ADF_PLUS_ISA|ADF_PLUS_EISA) -#define ADF_ALL_SC3 (ADF_SC3_ISA|ADF_SC3_EISA|ADF_SC3_PCI) -#define ADF_ALL_SC4 (ADF_SC4_ISA|ADF_SC4_EISA|ADF_SC4_PCI) -#define ADF_ALL_SC5 (ADF_SC5_PCI) -/* All EATA Cacheing Products */ -#define ADF_ALL_CACHE (ADF_ALL_PLUS|ADF_ALL_SC3|ADF_ALL_SC4) -/* All EATA Bus Mastering Products */ -#define ADF_ALL_MASTER (ADF_2012A|ADF_ALL_CACHE) -/* All EATA Adapter Products */ -#define ADF_ALL_EATA (ADF_2001|ADF_ALL_MASTER) -#define ADF_ALL ADF_ALL_EATA - -/* Application - sigWORD dsApplication; FLAG BITS */ -/* ------------------------------------------------------------------ */ -#define APP_DPTMGR 0x0001 /* DPT Storage Manager */ -#define APP_ENGINE 0x0002 /* DPT Engine */ -#define APP_SYTOS 0x0004 /* Sytron Sytos Plus */ -#define APP_CHEYENNE 0x0008 /* Cheyenne ARCServe + ARCSolo */ -#define APP_MSCDEX 0x0010 /* Microsoft CD-ROM extensions */ -#define APP_NOVABACK 0x0020 /* NovaStor Novaback */ -#define APP_AIM 0x0040 /* Archive Information Manager */ - -/* Requirements - sigBYTE dsRequirements; FLAG BITS */ -/* ------------------------------------------------------------------ */ -#define REQ_SMARTROM 0x01 /* Requires SmartROM to be present */ -#define REQ_DPTDDL 0x02 /* Requires DPTDDL.SYS to be loaded */ -#define REQ_HBA_DRIVER 0x04 /* Requires an HBA driver to be loaded */ -#define REQ_ASPI_TRAN 0x08 /* Requires an ASPI Transport Modules */ -#define REQ_ENGINE 0x10 /* Requires a DPT Engine to be loaded */ -#define REQ_COMM_ENG 0x20 /* Requires a DPT Communications Engine */ - -/* - * You may adjust dsDescription_size with an override to a value less than - * 50 so that the structure allocates less real space. - */ -#if (!defined(dsDescription_size)) -# define dsDescription_size 50 -#endif - -typedef struct dpt_sig { - char dsSignature[6]; /* ALWAYS "dPtSiG" */ - sigBYTE dsSigVersion; /* signature version (currently 1) */ - sigBYTE dsProcessorFamily; /* what type of processor */ - sigBYTE dsProcessor; /* precise processor */ - sigBYTE dsFiletype; /* type of file */ - sigBYTE dsFiletypeFlags; /* flags to specify load type, etc. */ - sigBYTE dsOEM; /* OEM file was created for */ - sigINT dsOS; /* which Operating systems */ - sigWORD dsCapabilities; /* RAID levels, etc. */ - sigWORD dsDeviceSupp; /* Types of SCSI devices supported */ - sigWORD dsAdapterSupp; /* DPT adapter families supported */ - sigWORD dsApplication; /* applications file is for */ - sigBYTE dsRequirements; /* Other driver dependencies */ - sigBYTE dsVersion; /* 1 */ - sigBYTE dsRevision; /* 'J' */ - sigBYTE dsSubRevision; /* '9' ' ' if N/A */ - sigBYTE dsMonth; /* creation month */ - sigBYTE dsDay; /* creation day */ - sigBYTE dsYear; /* creation year since 1980 (1993=13) */ - /* description (NULL terminated) */ - char dsDescription[dsDescription_size]; -} dpt_sig_S; -/* 32 bytes minimum - with no description. Put NULL at description[0] */ -/* 81 bytes maximum - with 49 character description plus NULL. */ - -/* This line added at Roycroft's request */ -/* Microsoft's NT compiler gets confused if you do a pack and don't */ -/* restore it. */ - -#ifndef NO_UNPACK -#if defined (_DPT_AIX) -#pragma options align=reset -#elif defined (UNPACK_FOUR) -#pragma pack(4) -#else -#pragma pack() -#endif /* aix */ -#endif -/* For the Macintosh */ -#ifdef STRUCTALIGNMENTSUPPORTED -#pragma options align=reset -#endif - -#endif diff --git a/drivers/scsi/dpt/osd_defs.h b/drivers/scsi/dpt/osd_defs.h deleted file mode 100644 index de3ae5722982..000000000000 --- a/drivers/scsi/dpt/osd_defs.h +++ /dev/null @@ -1,79 +0,0 @@ -/* BSDI osd_defs.h,v 1.4 1998/06/03 19:14:58 karels Exp */ -/* - * Copyright (c) 1996-1999 Distributed Processing Technology Corporation - * All rights reserved. - * - * Redistribution and use in source form, with or without modification, are - * permitted provided that redistributions of source code must retain the - * above copyright notice, this list of conditions and the following disclaimer. - * - * This software is provided `as is' by Distributed Processing Technology and - * any express or implied warranties, including, but not limited to, the - * implied warranties of merchantability and fitness for a particular purpose, - * are disclaimed. In no event shall Distributed Processing Technology be - * liable for any direct, indirect, incidental, special, exemplary or - * consequential damages (including, but not limited to, procurement of - * substitute goods or services; loss of use, data, or profits; or business - * interruptions) however caused and on any theory of liability, whether in - * contract, strict liability, or tort (including negligence or otherwise) - * arising in any way out of the use of this driver software, even if advised - * of the possibility of such damage. - * - */ - -#ifndef _OSD_DEFS_H -#define _OSD_DEFS_H - -/*File - OSD_DEFS.H - **************************************************************************** - * - *Description: - * - * This file contains the OS dependent defines. This file is included - *in osd_util.h and provides the OS specific defines for that file. - * - *Copyright Distributed Processing Technology, Corp. - * 140 Candace Dr. - * Maitland, Fl. 32751 USA - * Phone: (407) 830-5522 Fax: (407) 260-5366 - * All Rights Reserved - * - *Author: Doug Anderson - *Date: 1/31/94 - * - *Editors: - * - *Remarks: - * - * - *****************************************************************************/ - - -/*Definitions - Defines & Constants ----------------------------------------- */ - - /* Define the operating system */ -#if (defined(__linux__)) -# define _DPT_LINUX -#elif (defined(__bsdi__)) -# define _DPT_BSDI -#elif (defined(__FreeBSD__)) -# define _DPT_FREE_BSD -#else -# define _DPT_SCO -#endif - -#if defined (ZIL_CURSES) -#define _DPT_CURSES -#else -#define _DPT_MOTIF -#endif - - /* Redefine 'far' to nothing - no far pointer type required in UNIX */ -#define far - - /* Define the mutually exclusive semaphore type */ -#define SEMAPHORE_T unsigned int * - /* Define a handle to a DLL */ -#define DLL_HANDLE_T unsigned int * - -#endif diff --git a/drivers/scsi/dpt/osd_util.h b/drivers/scsi/dpt/osd_util.h deleted file mode 100644 index b2613c2eaac7..000000000000 --- a/drivers/scsi/dpt/osd_util.h +++ /dev/null @@ -1,358 +0,0 @@ -/* BSDI osd_util.h,v 1.8 1998/06/03 19:14:58 karels Exp */ - -/* - * Copyright (c) 1996-1999 Distributed Processing Technology Corporation - * All rights reserved. - * - * Redistribution and use in source form, with or without modification, are - * permitted provided that redistributions of source code must retain the - * above copyright notice, this list of conditions and the following disclaimer. - * - * This software is provided `as is' by Distributed Processing Technology and - * any express or implied warranties, including, but not limited to, the - * implied warranties of merchantability and fitness for a particular purpose, - * are disclaimed. In no event shall Distributed Processing Technology be - * liable for any direct, indirect, incidental, special, exemplary or - * consequential damages (including, but not limited to, procurement of - * substitute goods or services; loss of use, data, or profits; or business - * interruptions) however caused and on any theory of liability, whether in - * contract, strict liability, or tort (including negligence or otherwise) - * arising in any way out of the use of this driver software, even if advised - * of the possibility of such damage. - * - */ - -#ifndef __OSD_UTIL_H -#define __OSD_UTIL_H - -/*File - OSD_UTIL.H - **************************************************************************** - * - *Description: - * - * This file contains defines and function prototypes that are - *operating system dependent. The resources defined in this file - *are not specific to any particular application. - * - *Copyright Distributed Processing Technology, Corp. - * 140 Candace Dr. - * Maitland, Fl. 32751 USA - * Phone: (407) 830-5522 Fax: (407) 260-5366 - * All Rights Reserved - * - *Author: Doug Anderson - *Date: 1/7/94 - * - *Editors: - * - *Remarks: - * - * - *****************************************************************************/ - - -/*Definitions - Defines & Constants ----------------------------------------- */ - -/*----------------------------- */ -/* Operating system selections: */ -/*----------------------------- */ - -/*#define _DPT_MSDOS */ -/*#define _DPT_WIN_3X */ -/*#define _DPT_WIN_4X */ -/*#define _DPT_WIN_NT */ -/*#define _DPT_NETWARE */ -/*#define _DPT_OS2 */ -/*#define _DPT_SCO */ -/*#define _DPT_UNIXWARE */ -/*#define _DPT_SOLARIS */ -/*#define _DPT_NEXTSTEP */ -/*#define _DPT_BANYAN */ - -/*-------------------------------- */ -/* Include the OS specific defines */ -/*-------------------------------- */ - -/*#define OS_SELECTION From Above List */ -/*#define SEMAPHORE_T ??? */ -/*#define DLL_HANDLE_T ??? */ - -#if (defined(KERNEL) && (defined(__FreeBSD__) || defined(__bsdi__))) -# include "i386/isa/dpt_osd_defs.h" -#else -# include "osd_defs.h" -#endif - -#ifndef DPT_UNALIGNED - #define DPT_UNALIGNED -#endif - -#ifndef DPT_EXPORT - #define DPT_EXPORT -#endif - -#ifndef DPT_IMPORT - #define DPT_IMPORT -#endif - -#ifndef DPT_RUNTIME_IMPORT - #define DPT_RUNTIME_IMPORT DPT_IMPORT -#endif - -/*--------------------- */ -/* OS dependent defines */ -/*--------------------- */ - -#if defined (_DPT_MSDOS) || defined (_DPT_WIN_3X) - #define _DPT_16_BIT -#else - #define _DPT_32_BIT -#endif - -#if defined (_DPT_SCO) || defined (_DPT_UNIXWARE) || defined (_DPT_SOLARIS) || defined (_DPT_AIX) || defined (SNI_MIPS) || defined (_DPT_BSDI) || defined (_DPT_FREE_BSD) || defined(_DPT_LINUX) - #define _DPT_UNIX -#endif - -#if defined (_DPT_WIN_3x) || defined (_DPT_WIN_4X) || defined (_DPT_WIN_NT) \ - || defined (_DPT_OS2) - #define _DPT_DLL_SUPPORT -#endif - -#if !defined (_DPT_MSDOS) && !defined (_DPT_WIN_3X) && !defined (_DPT_NETWARE) - #define _DPT_PREEMPTIVE -#endif - -#if !defined (_DPT_MSDOS) && !defined (_DPT_WIN_3X) - #define _DPT_MULTI_THREADED -#endif - -#if !defined (_DPT_MSDOS) - #define _DPT_MULTI_TASKING -#endif - - /* These exist for platforms that */ - /* chunk when accessing mis-aligned */ - /* data */ -#if defined (SNI_MIPS) || defined (_DPT_SOLARIS) - #if defined (_DPT_BIG_ENDIAN) - #if !defined (_DPT_STRICT_ALIGN) - #define _DPT_STRICT_ALIGN - #endif - #endif -#endif - - /* Determine if in C or C++ mode */ -#ifdef __cplusplus - #define _DPT_CPP -#else - #define _DPT_C -#endif - -/*-------------------------------------------------------------------*/ -/* Under Solaris the compiler refuses to accept code like: */ -/* { {"DPT"}, 0, NULL .... }, */ -/* and complains about the {"DPT"} part by saying "cannot use { } */ -/* to initialize char*". */ -/* */ -/* By defining these ugly macros we can get around this and also */ -/* not have to copy and #ifdef large sections of code. I know that */ -/* these macros are *really* ugly, but they should help reduce */ -/* maintenance in the long run. */ -/* */ -/*-------------------------------------------------------------------*/ -#if !defined (DPTSQO) - #if defined (_DPT_SOLARIS) - #define DPTSQO - #define DPTSQC - #else - #define DPTSQO { - #define DPTSQC } - #endif /* solaris */ -#endif /* DPTSQO */ - - -/*---------------------- */ -/* OS dependent typedefs */ -/*---------------------- */ - -#if defined (_DPT_MSDOS) || defined (_DPT_SCO) - #define BYTE unsigned char - #define WORD unsigned short -#endif - -#ifndef _DPT_TYPEDEFS - #define _DPT_TYPEDEFS - typedef unsigned char uCHAR; - typedef unsigned short uSHORT; - typedef unsigned int uINT; - typedef unsigned long uLONG; - - typedef union { - uCHAR u8[4]; - uSHORT u16[2]; - uLONG u32; - } access_U; -#endif - -#if !defined (NULL) - #define NULL 0 -#endif - - -/*Prototypes - function ----------------------------------------------------- */ - -#ifdef __cplusplus - extern "C" { /* Declare all these functions as "C" functions */ -#endif - -/*------------------------ */ -/* Byte reversal functions */ -/*------------------------ */ - - /* Reverses the byte ordering of a 2 byte variable */ -#if (!defined(osdSwap2)) - uSHORT osdSwap2(DPT_UNALIGNED uSHORT *); -#endif // !osdSwap2 - - /* Reverses the byte ordering of a 4 byte variable and shifts left 8 bits */ -#if (!defined(osdSwap3)) - uLONG osdSwap3(DPT_UNALIGNED uLONG *); -#endif // !osdSwap3 - - -#ifdef _DPT_NETWARE - #include "novpass.h" /* For DPT_Bswapl() prototype */ - /* Inline the byte swap */ - #ifdef __cplusplus - inline uLONG osdSwap4(uLONG *inLong) { - return *inLong = DPT_Bswapl(*inLong); - } - #else - #define osdSwap4(inLong) DPT_Bswapl(inLong) - #endif // cplusplus -#else - /* Reverses the byte ordering of a 4 byte variable */ -# if (!defined(osdSwap4)) - uLONG osdSwap4(DPT_UNALIGNED uLONG *); -# endif // !osdSwap4 - - /* The following functions ALWAYS swap regardless of the * - * presence of DPT_BIG_ENDIAN */ - - uSHORT trueSwap2(DPT_UNALIGNED uSHORT *); - uLONG trueSwap4(DPT_UNALIGNED uLONG *); - -#endif // netware - - -/*-------------------------------------* - * Network order swap functions * - * * - * These functions/macros will be used * - * by the structure insert()/extract() * - * functions. * - * - * We will enclose all structure * - * portability modifications inside * - * #ifdefs. When we are ready, we * - * will #define DPT_PORTABLE to begin * - * using the modifications. * - *-------------------------------------*/ -uLONG netSwap4(uLONG val); - -#if defined (_DPT_BIG_ENDIAN) - -// for big-endian we need to swap - -#ifndef NET_SWAP_2 -#define NET_SWAP_2(x) (((x) >> 8) | ((x) << 8)) -#endif // NET_SWAP_2 - -#ifndef NET_SWAP_4 -#define NET_SWAP_4(x) netSwap4((x)) -#endif // NET_SWAP_4 - -#else - -// for little-endian we don't need to do anything - -#ifndef NET_SWAP_2 -#define NET_SWAP_2(x) (x) -#endif // NET_SWAP_2 - -#ifndef NET_SWAP_4 -#define NET_SWAP_4(x) (x) -#endif // NET_SWAP_4 - -#endif // big endian - - - -/*----------------------------------- */ -/* Run-time loadable module functions */ -/*----------------------------------- */ - - /* Loads the specified run-time loadable DLL */ -DLL_HANDLE_T osdLoadModule(uCHAR *); - /* Unloads the specified run-time loadable DLL */ -uSHORT osdUnloadModule(DLL_HANDLE_T); - /* Returns a pointer to a function inside a run-time loadable DLL */ -void * osdGetFnAddr(DLL_HANDLE_T,uCHAR *); - -/*--------------------------------------- */ -/* Mutually exclusive semaphore functions */ -/*--------------------------------------- */ - - /* Create a named semaphore */ -SEMAPHORE_T osdCreateNamedSemaphore(char *); - /* Create a mutually exlusive semaphore */ -SEMAPHORE_T osdCreateSemaphore(void); - /* create an event semaphore */ -SEMAPHORE_T osdCreateEventSemaphore(void); - /* create a named event semaphore */ -SEMAPHORE_T osdCreateNamedEventSemaphore(char *); - - /* Destroy the specified mutually exclusive semaphore object */ -uSHORT osdDestroySemaphore(SEMAPHORE_T); - /* Request access to the specified mutually exclusive semaphore */ -uLONG osdRequestSemaphore(SEMAPHORE_T,uLONG); - /* Release access to the specified mutually exclusive semaphore */ -uSHORT osdReleaseSemaphore(SEMAPHORE_T); - /* wait for a event to happen */ -uLONG osdWaitForEventSemaphore(SEMAPHORE_T, uLONG); - /* signal an event */ -uLONG osdSignalEventSemaphore(SEMAPHORE_T); - /* reset the event */ -uLONG osdResetEventSemaphore(SEMAPHORE_T); - -/*----------------- */ -/* Thread functions */ -/*----------------- */ - - /* Releases control to the task switcher in non-preemptive */ - /* multitasking operating systems. */ -void osdSwitchThreads(void); - - /* Starts a thread function */ -uLONG osdStartThread(void *,void *); - -/* what is my thread id */ -uLONG osdGetThreadID(void); - -/* wakes up the specifed thread */ -void osdWakeThread(uLONG); - -/* osd sleep for x milliseconds */ -void osdSleep(uLONG); - -#define DPT_THREAD_PRIORITY_LOWEST 0x00 -#define DPT_THREAD_PRIORITY_NORMAL 0x01 -#define DPT_THREAD_PRIORITY_HIGHEST 0x02 - -uCHAR osdSetThreadPriority(uLONG tid, uCHAR priority); - -#ifdef __cplusplus - } /* end the xtern "C" declaration */ -#endif - -#endif /* osd_util_h */ diff --git a/drivers/scsi/dpt/sys_info.h b/drivers/scsi/dpt/sys_info.h deleted file mode 100644 index a4aa1c31ff72..000000000000 --- a/drivers/scsi/dpt/sys_info.h +++ /dev/null @@ -1,417 +0,0 @@ -/* BSDI sys_info.h,v 1.6 1998/06/03 19:14:59 karels Exp */ - -/* - * Copyright (c) 1996-1999 Distributed Processing Technology Corporation - * All rights reserved. - * - * Redistribution and use in source form, with or without modification, are - * permitted provided that redistributions of source code must retain the - * above copyright notice, this list of conditions and the following disclaimer. - * - * This software is provided `as is' by Distributed Processing Technology and - * any express or implied warranties, including, but not limited to, the - * implied warranties of merchantability and fitness for a particular purpose, - * are disclaimed. In no event shall Distributed Processing Technology be - * liable for any direct, indirect, incidental, special, exemplary or - * consequential damages (including, but not limited to, procurement of - * substitute goods or services; loss of use, data, or profits; or business - * interruptions) however caused and on any theory of liability, whether in - * contract, strict liability, or tort (including negligence or otherwise) - * arising in any way out of the use of this driver software, even if advised - * of the possibility of such damage. - * - */ - -#ifndef __SYS_INFO_H -#define __SYS_INFO_H - -/*File - SYS_INFO.H - **************************************************************************** - * - *Description: - * - * This file contains structure definitions for the OS dependent - *layer system information buffers. - * - *Copyright Distributed Processing Technology, Corp. - * 140 Candace Dr. - * Maitland, Fl. 32751 USA - * Phone: (407) 830-5522 Fax: (407) 260-5366 - * All Rights Reserved - * - *Author: Don Kemper - *Date: 5/10/94 - * - *Editors: - * - *Remarks: - * - * - *****************************************************************************/ - - -/*Include Files ------------------------------------------------------------- */ - -#include "osd_util.h" - -#ifndef NO_PACK -#if defined (_DPT_AIX) -#pragma options align=packed -#else -#pragma pack(1) -#endif /* aix */ -#endif // no unpack - - -/*struct - driveParam_S - start - *=========================================================================== - * - *Description: - * - * This structure defines the drive parameters seen during - *booting. - * - *---------------------------------------------------------------------------*/ - -#ifdef __cplusplus - struct driveParam_S { -#else - typedef struct { -#endif - - uSHORT cylinders; /* Up to 1024 */ - uCHAR heads; /* Up to 255 */ - uCHAR sectors; /* Up to 63 */ - -#ifdef __cplusplus - -//---------- Portability Additions ----------- in sp_sinfo.cpp -#ifdef DPT_PORTABLE - uSHORT netInsert(dptBuffer_S *buffer); - uSHORT netExtract(dptBuffer_S *buffer); -#endif // DPT PORTABLE -//-------------------------------------------- - - }; -#else - } driveParam_S; -#endif -/*driveParam_S - end */ - - -/*struct - sysInfo_S - start - *=========================================================================== - * - *Description: - * - * This structure defines the command system information that - *should be returned by every OS dependent layer. - * - *---------------------------------------------------------------------------*/ - -/*flags - bit definitions */ -#define SI_CMOS_Valid 0x0001 -#define SI_NumDrivesValid 0x0002 -#define SI_ProcessorValid 0x0004 -#define SI_MemorySizeValid 0x0008 -#define SI_DriveParamsValid 0x0010 -#define SI_SmartROMverValid 0x0020 -#define SI_OSversionValid 0x0040 -#define SI_OSspecificValid 0x0080 /* 1 if OS structure returned */ -#define SI_BusTypeValid 0x0100 - -#define SI_ALL_VALID 0x0FFF /* All Std SysInfo is valid */ -#define SI_NO_SmartROM 0x8000 - -/*busType - definitions */ -#define SI_ISA_BUS 0x00 -#define SI_MCA_BUS 0x01 -#define SI_EISA_BUS 0x02 -#define SI_PCI_BUS 0x04 - -#ifdef __cplusplus - struct sysInfo_S { -#else - typedef struct { -#endif - - uCHAR drive0CMOS; /* CMOS Drive 0 Type */ - uCHAR drive1CMOS; /* CMOS Drive 1 Type */ - uCHAR numDrives; /* 0040:0075 contents */ - uCHAR processorFamily; /* Same as DPTSIG's definition */ - uCHAR processorType; /* Same as DPTSIG's definition */ - uCHAR smartROMMajorVersion; - uCHAR smartROMMinorVersion; /* SmartROM version */ - uCHAR smartROMRevision; - uSHORT flags; /* See bit definitions above */ - uSHORT conventionalMemSize; /* in KB */ - uINT extendedMemSize; /* in KB */ - uINT osType; /* Same as DPTSIG's definition */ - uCHAR osMajorVersion; - uCHAR osMinorVersion; /* The OS version */ - uCHAR osRevision; -#ifdef _SINIX_ADDON - uCHAR busType; /* See defininitions above */ - uSHORT osSubRevision; - uCHAR pad[2]; /* For alignment */ -#else - uCHAR osSubRevision; - uCHAR busType; /* See defininitions above */ - uCHAR pad[3]; /* For alignment */ -#endif - driveParam_S drives[16]; /* SmartROM Logical Drives */ - -#ifdef __cplusplus - -//---------- Portability Additions ----------- in sp_sinfo.cpp -#ifdef DPT_PORTABLE - uSHORT netInsert(dptBuffer_S *buffer); - uSHORT netExtract(dptBuffer_S *buffer); -#endif // DPT PORTABLE -//-------------------------------------------- - - }; -#else - } sysInfo_S; -#endif -/*sysInfo_S - end */ - - -/*struct - DOS_Info_S - start - *=========================================================================== - * - *Description: - * - * This structure defines the system information specific to a - *DOS workstation. - * - *---------------------------------------------------------------------------*/ - -/*flags - bit definitions */ -#define DI_DOS_HIGH 0x01 /* DOS is loaded high */ -#define DI_DPMI_VALID 0x02 /* DPMI version is valid */ - -#ifdef __cplusplus - struct DOS_Info_S { -#else - typedef struct { -#endif - - uCHAR flags; /* See bit definitions above */ - uSHORT driverLocation; /* SmartROM BIOS address */ - uSHORT DOS_version; - uSHORT DPMI_version; - -#ifdef __cplusplus - -//---------- Portability Additions ----------- in sp_sinfo.cpp -#ifdef DPT_PORTABLE - uSHORT netInsert(dptBuffer_S *buffer); - uSHORT netExtract(dptBuffer_S *buffer); -#endif // DPT PORTABLE -//-------------------------------------------- - - }; -#else - } DOS_Info_S; -#endif -/*DOS_Info_S - end */ - - -/*struct - Netware_Info_S - start - *=========================================================================== - * - *Description: - * - * This structure defines the system information specific to a - *Netware machine. - * - *---------------------------------------------------------------------------*/ - -#ifdef __cplusplus - struct Netware_Info_S { -#else - typedef struct { -#endif - - uCHAR driverName[13]; /* ie PM12NW31.DSK */ - uCHAR serverName[48]; - uCHAR netwareVersion; /* The Netware OS version */ - uCHAR netwareSubVersion; - uCHAR netwareRevision; - uSHORT maxConnections; /* Probably 250 or 1000 */ - uSHORT connectionsInUse; - uSHORT maxVolumes; - uCHAR unused; - uCHAR SFTlevel; - uCHAR TTSlevel; - - uCHAR clibMajorVersion; /* The CLIB.NLM version */ - uCHAR clibMinorVersion; - uCHAR clibRevision; - -#ifdef __cplusplus - -//---------- Portability Additions ----------- in sp_sinfo.cpp -#ifdef DPT_PORTABLE - uSHORT netInsert(dptBuffer_S *buffer); - uSHORT netExtract(dptBuffer_S *buffer); -#endif // DPT PORTABLE -//-------------------------------------------- - - }; -#else - } Netware_Info_S; -#endif -/*Netware_Info_S - end */ - - -/*struct - OS2_Info_S - start - *=========================================================================== - * - *Description: - * - * This structure defines the system information specific to an - *OS/2 machine. - * - *---------------------------------------------------------------------------*/ - -#ifdef __cplusplus - struct OS2_Info_S { -#else - typedef struct { -#endif - - uCHAR something; - -#ifdef __cplusplus - -//---------- Portability Additions ----------- in sp_sinfo.cpp -#ifdef DPT_PORTABLE - uSHORT netInsert(dptBuffer_S *buffer); - uSHORT netExtract(dptBuffer_S *buffer); -#endif // DPT PORTABLE -//-------------------------------------------- - - }; -#else - } OS2_Info_S; -#endif -/*OS2_Info_S - end */ - - -/*struct - WinNT_Info_S - start - *=========================================================================== - * - *Description: - * - * This structure defines the system information specific to a - *Windows NT machine. - * - *---------------------------------------------------------------------------*/ - -#ifdef __cplusplus - struct WinNT_Info_S { -#else - typedef struct { -#endif - - uCHAR something; - -#ifdef __cplusplus - -//---------- Portability Additions ----------- in sp_sinfo.cpp -#ifdef DPT_PORTABLE - uSHORT netInsert(dptBuffer_S *buffer); - uSHORT netExtract(dptBuffer_S *buffer); -#endif // DPT PORTABLE -//-------------------------------------------- - - }; -#else - } WinNT_Info_S; -#endif -/*WinNT_Info_S - end */ - - -/*struct - SCO_Info_S - start - *=========================================================================== - * - *Description: - * - * This structure defines the system information specific to an - *SCO UNIX machine. - * - *---------------------------------------------------------------------------*/ - -#ifdef __cplusplus - struct SCO_Info_S { -#else - typedef struct { -#endif - - uCHAR something; - -#ifdef __cplusplus - -//---------- Portability Additions ----------- in sp_sinfo.cpp -#ifdef DPT_PORTABLE - uSHORT netInsert(dptBuffer_S *buffer); - uSHORT netExtract(dptBuffer_S *buffer); -#endif // DPT PORTABLE -//-------------------------------------------- - - }; -#else - } SCO_Info_S; -#endif -/*SCO_Info_S - end */ - - -/*struct - USL_Info_S - start - *=========================================================================== - * - *Description: - * - * This structure defines the system information specific to a - *USL UNIX machine. - * - *---------------------------------------------------------------------------*/ - -#ifdef __cplusplus - struct USL_Info_S { -#else - typedef struct { -#endif - - uCHAR something; - -#ifdef __cplusplus - -//---------- Portability Additions ----------- in sp_sinfo.cpp -#ifdef DPT_PORTABLE - uSHORT netInsert(dptBuffer_S *buffer); - uSHORT netExtract(dptBuffer_S *buffer); -#endif // DPT PORTABLE -//-------------------------------------------- - - }; -#else - } USL_Info_S; -#endif -/*USL_Info_S - end */ - - - /* Restore default structure packing */ -#ifndef NO_UNPACK -#if defined (_DPT_AIX) -#pragma options align=reset -#elif defined (UNPACK_FOUR) -#pragma pack(4) -#else -#pragma pack() -#endif /* aix */ -#endif // no unpack - -#endif // __SYS_INFO_H - diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c deleted file mode 100644 index 4251212acbbe..000000000000 --- a/drivers/scsi/dpt_i2o.c +++ /dev/null @@ -1,3549 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/*************************************************************************** - dpti.c - description - ------------------- - begin : Thu Sep 7 2000 - copyright : (C) 2000 by Adaptec - - July 30, 2001 First version being submitted - for inclusion in the kernel. V2.4 - - See Documentation/scsi/dpti.rst for history, notes, license info - and credits - ***************************************************************************/ - -/*************************************************************************** - * * - * * - ***************************************************************************/ -/*************************************************************************** - * Sat Dec 20 2003 Go Taniguchi go@turbolinux.co.jp - - Support 2.6 kernel and DMA-mapping - - ioctl fix for raid tools - - use schedule_timeout in long long loop - **************************************************************************/ - -/*#define DEBUG 1 */ -/*#define UARTDELAY 1 */ - -#include <linux/module.h> -#include <linux/pgtable.h> - -MODULE_AUTHOR("Deanna Bonds, with _lots_ of help from Mark Salyzyn"); -MODULE_DESCRIPTION("Adaptec I2O RAID Driver"); - -//////////////////////////////////////////////////////////////// - -#include <linux/ioctl.h> /* For SCSI-Passthrough */ -#include <linux/uaccess.h> - -#include <linux/stat.h> -#include <linux/slab.h> /* for kmalloc() */ -#include <linux/pci.h> /* for PCI support */ -#include <linux/proc_fs.h> -#include <linux/blkdev.h> -#include <linux/delay.h> /* for udelay */ -#include <linux/interrupt.h> -#include <linux/kernel.h> /* for printk */ -#include <linux/sched.h> -#include <linux/reboot.h> -#include <linux/spinlock.h> -#include <linux/dma-mapping.h> - -#include <linux/timer.h> -#include <linux/string.h> -#include <linux/ioport.h> -#include <linux/mutex.h> - -#include <asm/processor.h> /* for boot_cpu_data */ -#include <asm/io.h> /* for virt_to_bus, etc. */ - -#include <scsi/scsi.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_tcq.h> - -#include "dpt/dptsig.h" -#include "dpti.h" - -/*============================================================================ - * Create a binary signature - this is read by dptsig - * Needed for our management apps - *============================================================================ - */ -static DEFINE_MUTEX(adpt_mutex); -static dpt_sig_S DPTI_sig = { - {'d', 'P', 't', 'S', 'i', 'G'}, SIG_VERSION, -#ifdef __i386__ - PROC_INTEL, PROC_386 | PROC_486 | PROC_PENTIUM | PROC_SEXIUM, -#elif defined(__ia64__) - PROC_INTEL, PROC_IA64, -#elif defined(__sparc__) - PROC_ULTRASPARC, PROC_ULTRASPARC, -#elif defined(__alpha__) - PROC_ALPHA, PROC_ALPHA, -#else - (-1),(-1), -#endif - FT_HBADRVR, 0, OEM_DPT, OS_LINUX, CAP_OVERLAP, DEV_ALL, - ADF_ALL_SC5, 0, 0, DPT_VERSION, DPT_REVISION, DPT_SUBREVISION, - DPT_MONTH, DPT_DAY, DPT_YEAR, "Adaptec Linux I2O RAID Driver" -}; - - - - -/*============================================================================ - * Globals - *============================================================================ - */ - -static DEFINE_MUTEX(adpt_configuration_lock); - -static struct i2o_sys_tbl *sys_tbl; -static dma_addr_t sys_tbl_pa; -static int sys_tbl_ind; -static int sys_tbl_len; - -static adpt_hba* hba_chain = NULL; -static int hba_count = 0; - -static struct class *adpt_sysfs_class; - -static long adpt_unlocked_ioctl(struct file *, unsigned int, unsigned long); -#ifdef CONFIG_COMPAT -static long compat_adpt_ioctl(struct file *, unsigned int, unsigned long); -#endif - -static const struct file_operations adpt_fops = { - .unlocked_ioctl = adpt_unlocked_ioctl, - .open = adpt_open, - .release = adpt_close, -#ifdef CONFIG_COMPAT - .compat_ioctl = compat_adpt_ioctl, -#endif - .llseek = noop_llseek, -}; - -/* Structures and definitions for synchronous message posting. - * See adpt_i2o_post_wait() for description - * */ -struct adpt_i2o_post_wait_data -{ - int status; - u32 id; - adpt_wait_queue_head_t *wq; - struct adpt_i2o_post_wait_data *next; -}; - -static struct adpt_i2o_post_wait_data *adpt_post_wait_queue = NULL; -static u32 adpt_post_wait_id = 0; -static DEFINE_SPINLOCK(adpt_post_wait_lock); - - -/*============================================================================ - * Functions - *============================================================================ - */ - -static inline int dpt_dma64(adpt_hba *pHba) -{ - return (sizeof(dma_addr_t) > 4 && (pHba)->dma64); -} - -static inline u32 dma_high(dma_addr_t addr) -{ - return upper_32_bits(addr); -} - -static inline u32 dma_low(dma_addr_t addr) -{ - return (u32)addr; -} - -static u8 adpt_read_blink_led(adpt_hba* host) -{ - if (host->FwDebugBLEDflag_P) { - if( readb(host->FwDebugBLEDflag_P) == 0xbc ){ - return readb(host->FwDebugBLEDvalue_P); - } - } - return 0; -} - -/*============================================================================ - * Scsi host template interface functions - *============================================================================ - */ - -#ifdef MODULE -static struct pci_device_id dptids[] = { - { PCI_DPT_VENDOR_ID, PCI_DPT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - { PCI_DPT_VENDOR_ID, PCI_DPT_RAPTOR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - { 0, } -}; -#endif - -MODULE_DEVICE_TABLE(pci,dptids); - -static int adpt_detect(struct scsi_host_template* sht) -{ - struct pci_dev *pDev = NULL; - adpt_hba *pHba; - adpt_hba *next; - - PINFO("Detecting Adaptec I2O RAID controllers...\n"); - - /* search for all Adatpec I2O RAID cards */ - while ((pDev = pci_get_device( PCI_DPT_VENDOR_ID, PCI_ANY_ID, pDev))) { - if(pDev->device == PCI_DPT_DEVICE_ID || - pDev->device == PCI_DPT_RAPTOR_DEVICE_ID){ - if(adpt_install_hba(sht, pDev) ){ - PERROR("Could not Init an I2O RAID device\n"); - PERROR("Will not try to detect others.\n"); - return hba_count-1; - } - pci_dev_get(pDev); - } - } - - /* In INIT state, Activate IOPs */ - for (pHba = hba_chain; pHba; pHba = next) { - next = pHba->next; - // Activate does get status , init outbound, and get hrt - if (adpt_i2o_activate_hba(pHba) < 0) { - adpt_i2o_delete_hba(pHba); - } - } - - - /* Active IOPs in HOLD state */ - -rebuild_sys_tab: - if (hba_chain == NULL) - return 0; - - /* - * If build_sys_table fails, we kill everything and bail - * as we can't init the IOPs w/o a system table - */ - if (adpt_i2o_build_sys_table() < 0) { - adpt_i2o_sys_shutdown(); - return 0; - } - - PDEBUG("HBA's in HOLD state\n"); - - /* If IOP don't get online, we need to rebuild the System table */ - for (pHba = hba_chain; pHba; pHba = pHba->next) { - if (adpt_i2o_online_hba(pHba) < 0) { - adpt_i2o_delete_hba(pHba); - goto rebuild_sys_tab; - } - } - - /* Active IOPs now in OPERATIONAL state */ - PDEBUG("HBA's in OPERATIONAL state\n"); - - printk("dpti: If you have a lot of devices this could take a few minutes.\n"); - for (pHba = hba_chain; pHba; pHba = next) { - next = pHba->next; - printk(KERN_INFO"%s: Reading the hardware resource table.\n", pHba->name); - if (adpt_i2o_lct_get(pHba) < 0){ - adpt_i2o_delete_hba(pHba); - continue; - } - - if (adpt_i2o_parse_lct(pHba) < 0){ - adpt_i2o_delete_hba(pHba); - continue; - } - adpt_inquiry(pHba); - } - - adpt_sysfs_class = class_create(THIS_MODULE, "dpt_i2o"); - if (IS_ERR(adpt_sysfs_class)) { - printk(KERN_WARNING"dpti: unable to create dpt_i2o class\n"); - adpt_sysfs_class = NULL; - } - - for (pHba = hba_chain; pHba; pHba = next) { - next = pHba->next; - if (adpt_scsi_host_alloc(pHba, sht) < 0){ - adpt_i2o_delete_hba(pHba); - continue; - } - pHba->initialized = TRUE; - pHba->state &= ~DPTI_STATE_RESET; - if (adpt_sysfs_class) { - struct device *dev = device_create(adpt_sysfs_class, - NULL, MKDEV(DPTI_I2O_MAJOR, pHba->unit), NULL, - "dpti%d", pHba->unit); - if (IS_ERR(dev)) { - printk(KERN_WARNING"dpti%d: unable to " - "create device in dpt_i2o class\n", - pHba->unit); - } - } - } - - // Register our control device node - // nodes will need to be created in /dev to access this - // the nodes can not be created from within the driver - if (hba_count && register_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER, &adpt_fops)) { - adpt_i2o_sys_shutdown(); - return 0; - } - return hba_count; -} - - -static void adpt_release(adpt_hba *pHba) -{ - struct Scsi_Host *shost = pHba->host; - - scsi_remove_host(shost); -// adpt_i2o_quiesce_hba(pHba); - adpt_i2o_delete_hba(pHba); - scsi_host_put(shost); -} - - -static void adpt_inquiry(adpt_hba* pHba) -{ - u32 msg[17]; - u32 *mptr; - u32 *lenptr; - int direction; - int scsidir; - u32 len; - u32 reqlen; - u8* buf; - dma_addr_t addr; - u8 scb[16]; - s32 rcode; - - memset(msg, 0, sizeof(msg)); - buf = dma_alloc_coherent(&pHba->pDev->dev, 80, &addr, GFP_KERNEL); - if(!buf){ - printk(KERN_ERR"%s: Could not allocate buffer\n",pHba->name); - return; - } - memset((void*)buf, 0, 36); - - len = 36; - direction = 0x00000000; - scsidir =0x40000000; // DATA IN (iop<--dev) - - if (dpt_dma64(pHba)) - reqlen = 17; // SINGLE SGE, 64 bit - else - reqlen = 14; // SINGLE SGE, 32 bit - /* Stick the headers on */ - msg[0] = reqlen<<16 | SGL_OFFSET_12; - msg[1] = (0xff<<24|HOST_TID<<12|ADAPTER_TID); - msg[2] = 0; - msg[3] = 0; - // Adaptec/DPT Private stuff - msg[4] = I2O_CMD_SCSI_EXEC|DPT_ORGANIZATION_ID<<16; - msg[5] = ADAPTER_TID | 1<<16 /* Interpret*/; - /* Direction, disconnect ok | sense data | simple queue , CDBLen */ - // I2O_SCB_FLAG_ENABLE_DISCONNECT | - // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG | - // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE; - msg[6] = scsidir|0x20a00000| 6 /* cmd len*/; - - mptr=msg+7; - - memset(scb, 0, sizeof(scb)); - // Write SCSI command into the message - always 16 byte block - scb[0] = INQUIRY; - scb[1] = 0; - scb[2] = 0; - scb[3] = 0; - scb[4] = 36; - scb[5] = 0; - // Don't care about the rest of scb - - memcpy(mptr, scb, sizeof(scb)); - mptr+=4; - lenptr=mptr++; /* Remember me - fill in when we know */ - - /* Now fill in the SGList and command */ - *lenptr = len; - if (dpt_dma64(pHba)) { - *mptr++ = (0x7C<<24)+(2<<16)+0x02; /* Enable 64 bit */ - *mptr++ = 1 << PAGE_SHIFT; - *mptr++ = 0xD0000000|direction|len; - *mptr++ = dma_low(addr); - *mptr++ = dma_high(addr); - } else { - *mptr++ = 0xD0000000|direction|len; - *mptr++ = addr; - } - - // Send it on it's way - rcode = adpt_i2o_post_wait(pHba, msg, reqlen<<2, 120); - if (rcode != 0) { - sprintf(pHba->detail, "Adaptec I2O RAID"); - printk(KERN_INFO "%s: Inquiry Error (%d)\n",pHba->name,rcode); - if (rcode != -ETIME && rcode != -EINTR) - dma_free_coherent(&pHba->pDev->dev, 80, buf, addr); - } else { - memset(pHba->detail, 0, sizeof(pHba->detail)); - memcpy(&(pHba->detail), "Vendor: Adaptec ", 16); - memcpy(&(pHba->detail[16]), " Model: ", 8); - memcpy(&(pHba->detail[24]), (u8*) &buf[16], 16); - memcpy(&(pHba->detail[40]), " FW: ", 4); - memcpy(&(pHba->detail[44]), (u8*) &buf[32], 4); - pHba->detail[48] = '\0'; /* precautionary */ - dma_free_coherent(&pHba->pDev->dev, 80, buf, addr); - } - adpt_i2o_status_get(pHba); - return ; -} - - -static int adpt_slave_configure(struct scsi_device * device) -{ - struct Scsi_Host *host = device->host; - - if (host->can_queue && device->tagged_supported) { - scsi_change_queue_depth(device, - host->can_queue - 1); - } - return 0; -} - -static int adpt_queue_lck(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd *)) -{ - adpt_hba* pHba = NULL; - struct adpt_device* pDev = NULL; /* dpt per device information */ - - cmd->scsi_done = done; - /* - * SCSI REQUEST_SENSE commands will be executed automatically by the - * Host Adapter for any errors, so they should not be executed - * explicitly unless the Sense Data is zero indicating that no error - * occurred. - */ - - if ((cmd->cmnd[0] == REQUEST_SENSE) && (cmd->sense_buffer[0] != 0)) { - cmd->result = (DID_OK << 16); - cmd->scsi_done(cmd); - return 0; - } - - pHba = (adpt_hba*)cmd->device->host->hostdata[0]; - if (!pHba) { - return FAILED; - } - - rmb(); - if ((pHba->state) & DPTI_STATE_RESET) - return SCSI_MLQUEUE_HOST_BUSY; - - // TODO if the cmd->device if offline then I may need to issue a bus rescan - // followed by a get_lct to see if the device is there anymore - if((pDev = (struct adpt_device*) (cmd->device->hostdata)) == NULL) { - /* - * First command request for this device. Set up a pointer - * to the device structure. This should be a TEST_UNIT_READY - * command from scan_scsis_single. - */ - if ((pDev = adpt_find_device(pHba, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun)) == NULL) { - // TODO: if any luns are at this bus, scsi id then fake a TEST_UNIT_READY and INQUIRY response - // with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue. - cmd->result = (DID_NO_CONNECT << 16); - cmd->scsi_done(cmd); - return 0; - } - cmd->device->hostdata = pDev; - } - pDev->pScsi_dev = cmd->device; - - /* - * If we are being called from when the device is being reset, - * delay processing of the command until later. - */ - if (pDev->state & DPTI_DEV_RESET ) { - return FAILED; - } - return adpt_scsi_to_i2o(pHba, cmd, pDev); -} - -static DEF_SCSI_QCMD(adpt_queue) - -static int adpt_bios_param(struct scsi_device *sdev, struct block_device *dev, - sector_t capacity, int geom[]) -{ - int heads=-1; - int sectors=-1; - int cylinders=-1; - - // *** First lets set the default geometry **** - - // If the capacity is less than ox2000 - if (capacity < 0x2000 ) { // floppy - heads = 18; - sectors = 2; - } - // else if between 0x2000 and 0x20000 - else if (capacity < 0x20000) { - heads = 64; - sectors = 32; - } - // else if between 0x20000 and 0x40000 - else if (capacity < 0x40000) { - heads = 65; - sectors = 63; - } - // else if between 0x4000 and 0x80000 - else if (capacity < 0x80000) { - heads = 128; - sectors = 63; - } - // else if greater than 0x80000 - else { - heads = 255; - sectors = 63; - } - cylinders = sector_div(capacity, heads * sectors); - - // Special case if CDROM - if(sdev->type == 5) { // CDROM - heads = 252; - sectors = 63; - cylinders = 1111; - } - - geom[0] = heads; - geom[1] = sectors; - geom[2] = cylinders; - - PDEBUG("adpt_bios_param: exit\n"); - return 0; -} - - -static const char *adpt_info(struct Scsi_Host *host) -{ - adpt_hba* pHba; - - pHba = (adpt_hba *) host->hostdata[0]; - return (char *) (pHba->detail); -} - -static int adpt_show_info(struct seq_file *m, struct Scsi_Host *host) -{ - struct adpt_device* d; - int id; - int chan; - adpt_hba* pHba; - int unit; - - // Find HBA (host bus adapter) we are looking for - mutex_lock(&adpt_configuration_lock); - for (pHba = hba_chain; pHba; pHba = pHba->next) { - if (pHba->host == host) { - break; /* found adapter */ - } - } - mutex_unlock(&adpt_configuration_lock); - if (pHba == NULL) { - return 0; - } - host = pHba->host; - - seq_printf(m, "Adaptec I2O RAID Driver Version: %s\n\n", DPT_I2O_VERSION); - seq_printf(m, "%s\n", pHba->detail); - seq_printf(m, "SCSI Host=scsi%d Control Node=/dev/%s irq=%d\n", - pHba->host->host_no, pHba->name, host->irq); - seq_printf(m, "\tpost fifo size = %d\n\treply fifo size = %d\n\tsg table size = %d\n\n", - host->can_queue, (int) pHba->reply_fifo_size , host->sg_tablesize); - - seq_puts(m, "Devices:\n"); - for(chan = 0; chan < MAX_CHANNEL; chan++) { - for(id = 0; id < MAX_ID; id++) { - d = pHba->channel[chan].device[id]; - while(d) { - seq_printf(m,"\t%-24.24s", d->pScsi_dev->vendor); - seq_printf(m," Rev: %-8.8s\n", d->pScsi_dev->rev); - - unit = d->pI2o_dev->lct_data.tid; - seq_printf(m, "\tTID=%d, (Channel=%d, Target=%d, Lun=%llu) (%s)\n\n", - unit, (int)d->scsi_channel, (int)d->scsi_id, d->scsi_lun, - scsi_device_online(d->pScsi_dev)? "online":"offline"); - d = d->next_lun; - } - } - } - return 0; -} - -/* - * Turn a pointer to ioctl reply data into an u32 'context' - */ -static u32 adpt_ioctl_to_context(adpt_hba * pHba, void *reply) -{ -#if BITS_PER_LONG == 32 - return (u32)(unsigned long)reply; -#else - ulong flags = 0; - u32 nr, i; - - spin_lock_irqsave(pHba->host->host_lock, flags); - nr = ARRAY_SIZE(pHba->ioctl_reply_context); - for (i = 0; i < nr; i++) { - if (pHba->ioctl_reply_context[i] == NULL) { - pHba->ioctl_reply_context[i] = reply; - break; - } - } - spin_unlock_irqrestore(pHba->host->host_lock, flags); - if (i >= nr) { - printk(KERN_WARNING"%s: Too many outstanding " - "ioctl commands\n", pHba->name); - return (u32)-1; - } - - return i; -#endif -} - -/* - * Go from an u32 'context' to a pointer to ioctl reply data. - */ -static void *adpt_ioctl_from_context(adpt_hba *pHba, u32 context) -{ -#if BITS_PER_LONG == 32 - return (void *)(unsigned long)context; -#else - void *p = pHba->ioctl_reply_context[context]; - pHba->ioctl_reply_context[context] = NULL; - - return p; -#endif -} - -/*=========================================================================== - * Error Handling routines - *=========================================================================== - */ - -static int adpt_abort(struct scsi_cmnd * cmd) -{ - adpt_hba* pHba = NULL; /* host bus adapter structure */ - struct adpt_device* dptdevice; /* dpt per device information */ - u32 msg[5]; - int rcode; - - pHba = (adpt_hba*) cmd->device->host->hostdata[0]; - printk(KERN_INFO"%s: Trying to Abort\n",pHba->name); - if ((dptdevice = (void*) (cmd->device->hostdata)) == NULL) { - printk(KERN_ERR "%s: Unable to abort: No device in cmnd\n",pHba->name); - return FAILED; - } - - memset(msg, 0, sizeof(msg)); - msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_SCSI_ABORT<<24|HOST_TID<<12|dptdevice->tid; - msg[2] = 0; - msg[3]= 0; - /* Add 1 to avoid firmware treating it as invalid command */ - msg[4] = cmd->request->tag + 1; - if (pHba->host) - spin_lock_irq(pHba->host->host_lock); - rcode = adpt_i2o_post_wait(pHba, msg, sizeof(msg), FOREVER); - if (pHba->host) - spin_unlock_irq(pHba->host->host_lock); - if (rcode != 0) { - if(rcode == -EOPNOTSUPP ){ - printk(KERN_INFO"%s: Abort cmd not supported\n",pHba->name); - return FAILED; - } - printk(KERN_INFO"%s: Abort failed.\n",pHba->name); - return FAILED; - } - printk(KERN_INFO"%s: Abort complete.\n",pHba->name); - return SUCCESS; -} - - -#define I2O_DEVICE_RESET 0x27 -// This is the same for BLK and SCSI devices -// NOTE this is wrong in the i2o.h definitions -// This is not currently supported by our adapter but we issue it anyway -static int adpt_device_reset(struct scsi_cmnd* cmd) -{ - adpt_hba* pHba; - u32 msg[4]; - u32 rcode; - int old_state; - struct adpt_device* d = cmd->device->hostdata; - - pHba = (void*) cmd->device->host->hostdata[0]; - printk(KERN_INFO"%s: Trying to reset device\n",pHba->name); - if (!d) { - printk(KERN_INFO"%s: Reset Device: Device Not found\n",pHba->name); - return FAILED; - } - memset(msg, 0, sizeof(msg)); - msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = (I2O_DEVICE_RESET<<24|HOST_TID<<12|d->tid); - msg[2] = 0; - msg[3] = 0; - - if (pHba->host) - spin_lock_irq(pHba->host->host_lock); - old_state = d->state; - d->state |= DPTI_DEV_RESET; - rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER); - d->state = old_state; - if (pHba->host) - spin_unlock_irq(pHba->host->host_lock); - if (rcode != 0) { - if(rcode == -EOPNOTSUPP ){ - printk(KERN_INFO"%s: Device reset not supported\n",pHba->name); - return FAILED; - } - printk(KERN_INFO"%s: Device reset failed\n",pHba->name); - return FAILED; - } else { - printk(KERN_INFO"%s: Device reset successful\n",pHba->name); - return SUCCESS; - } -} - - -#define I2O_HBA_BUS_RESET 0x87 -// This version of bus reset is called by the eh_error handler -static int adpt_bus_reset(struct scsi_cmnd* cmd) -{ - adpt_hba* pHba; - u32 msg[4]; - u32 rcode; - - pHba = (adpt_hba*)cmd->device->host->hostdata[0]; - memset(msg, 0, sizeof(msg)); - printk(KERN_WARNING"%s: Bus reset: SCSI Bus %d: tid: %d\n",pHba->name, cmd->device->channel,pHba->channel[cmd->device->channel].tid ); - msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->device->channel].tid); - msg[2] = 0; - msg[3] = 0; - if (pHba->host) - spin_lock_irq(pHba->host->host_lock); - rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER); - if (pHba->host) - spin_unlock_irq(pHba->host->host_lock); - if (rcode != 0) { - printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name); - return FAILED; - } else { - printk(KERN_WARNING"%s: Bus reset success.\n",pHba->name); - return SUCCESS; - } -} - -// This version of reset is called by the eh_error_handler -static int __adpt_reset(struct scsi_cmnd* cmd) -{ - adpt_hba* pHba; - int rcode; - char name[32]; - - pHba = (adpt_hba*)cmd->device->host->hostdata[0]; - strncpy(name, pHba->name, sizeof(name)); - printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n", name, cmd->device->channel, pHba->channel[cmd->device->channel].tid); - rcode = adpt_hba_reset(pHba); - if(rcode == 0){ - printk(KERN_WARNING"%s: HBA reset complete\n", name); - return SUCCESS; - } else { - printk(KERN_WARNING"%s: HBA reset failed (%x)\n", name, rcode); - return FAILED; - } -} - -static int adpt_reset(struct scsi_cmnd* cmd) -{ - int rc; - - spin_lock_irq(cmd->device->host->host_lock); - rc = __adpt_reset(cmd); - spin_unlock_irq(cmd->device->host->host_lock); - - return rc; -} - -// This version of reset is called by the ioctls and indirectly from eh_error_handler via adpt_reset -static int adpt_hba_reset(adpt_hba* pHba) -{ - int rcode; - - pHba->state |= DPTI_STATE_RESET; - - // Activate does get status , init outbound, and get hrt - if ((rcode=adpt_i2o_activate_hba(pHba)) < 0) { - printk(KERN_ERR "%s: Could not activate\n", pHba->name); - adpt_i2o_delete_hba(pHba); - return rcode; - } - - if ((rcode=adpt_i2o_build_sys_table()) < 0) { - adpt_i2o_delete_hba(pHba); - return rcode; - } - PDEBUG("%s: in HOLD state\n",pHba->name); - - if ((rcode=adpt_i2o_online_hba(pHba)) < 0) { - adpt_i2o_delete_hba(pHba); - return rcode; - } - PDEBUG("%s: in OPERATIONAL state\n",pHba->name); - - if ((rcode=adpt_i2o_lct_get(pHba)) < 0){ - adpt_i2o_delete_hba(pHba); - return rcode; - } - - if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0){ - adpt_i2o_delete_hba(pHba); - return rcode; - } - pHba->state &= ~DPTI_STATE_RESET; - - scsi_host_complete_all_commands(pHba->host, DID_RESET); - return 0; /* return success */ -} - -/*=========================================================================== - * - *=========================================================================== - */ - - -static void adpt_i2o_sys_shutdown(void) -{ - adpt_hba *pHba, *pNext; - struct adpt_i2o_post_wait_data *p1, *old; - - printk(KERN_INFO "Shutting down Adaptec I2O controllers.\n"); - printk(KERN_INFO " This could take a few minutes if there are many devices attached\n"); - /* Delete all IOPs from the controller chain */ - /* They should have already been released by the - * scsi-core - */ - for (pHba = hba_chain; pHba; pHba = pNext) { - pNext = pHba->next; - adpt_i2o_delete_hba(pHba); - } - - /* Remove any timedout entries from the wait queue. */ -// spin_lock_irqsave(&adpt_post_wait_lock, flags); - /* Nothing should be outstanding at this point so just - * free them - */ - for(p1 = adpt_post_wait_queue; p1;) { - old = p1; - p1 = p1->next; - kfree(old); - } -// spin_unlock_irqrestore(&adpt_post_wait_lock, flags); - adpt_post_wait_queue = NULL; - - printk(KERN_INFO "Adaptec I2O controllers down.\n"); -} - -static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) -{ - - adpt_hba* pHba = NULL; - adpt_hba* p = NULL; - ulong base_addr0_phys = 0; - ulong base_addr1_phys = 0; - u32 hba_map0_area_size = 0; - u32 hba_map1_area_size = 0; - void __iomem *base_addr_virt = NULL; - void __iomem *msg_addr_virt = NULL; - int dma64 = 0; - - int raptorFlag = FALSE; - - if(pci_enable_device(pDev)) { - return -EINVAL; - } - - if (pci_request_regions(pDev, "dpt_i2o")) { - PERROR("dpti: adpt_config_hba: pci request region failed\n"); - return -EINVAL; - } - - pci_set_master(pDev); - - /* - * See if we should enable dma64 mode. - */ - if (sizeof(dma_addr_t) > 4 && - dma_get_required_mask(&pDev->dev) > DMA_BIT_MASK(32) && - dma_set_mask(&pDev->dev, DMA_BIT_MASK(64)) == 0) - dma64 = 1; - - if (!dma64 && dma_set_mask(&pDev->dev, DMA_BIT_MASK(32)) != 0) - return -EINVAL; - - /* adapter only supports message blocks below 4GB */ - dma_set_coherent_mask(&pDev->dev, DMA_BIT_MASK(32)); - - base_addr0_phys = pci_resource_start(pDev,0); - hba_map0_area_size = pci_resource_len(pDev,0); - - // Check if standard PCI card or single BAR Raptor - if(pDev->device == PCI_DPT_DEVICE_ID){ - if(pDev->subsystem_device >=0xc032 && pDev->subsystem_device <= 0xc03b){ - // Raptor card with this device id needs 4M - hba_map0_area_size = 0x400000; - } else { // Not Raptor - it is a PCI card - if(hba_map0_area_size > 0x100000 ){ - hba_map0_area_size = 0x100000; - } - } - } else {// Raptor split BAR config - // Use BAR1 in this configuration - base_addr1_phys = pci_resource_start(pDev,1); - hba_map1_area_size = pci_resource_len(pDev,1); - raptorFlag = TRUE; - } - -#if BITS_PER_LONG == 64 - /* - * The original Adaptec 64 bit driver has this comment here: - * "x86_64 machines need more optimal mappings" - * - * I assume some HBAs report ridiculously large mappings - * and we need to limit them on platforms with IOMMUs. - */ - if (raptorFlag == TRUE) { - if (hba_map0_area_size > 128) - hba_map0_area_size = 128; - if (hba_map1_area_size > 524288) - hba_map1_area_size = 524288; - } else { - if (hba_map0_area_size > 524288) - hba_map0_area_size = 524288; - } -#endif - - base_addr_virt = ioremap(base_addr0_phys,hba_map0_area_size); - if (!base_addr_virt) { - pci_release_regions(pDev); - PERROR("dpti: adpt_config_hba: io remap failed\n"); - return -EINVAL; - } - - if(raptorFlag == TRUE) { - msg_addr_virt = ioremap(base_addr1_phys, hba_map1_area_size ); - if (!msg_addr_virt) { - PERROR("dpti: adpt_config_hba: io remap failed on BAR1\n"); - iounmap(base_addr_virt); - pci_release_regions(pDev); - return -EINVAL; - } - } else { - msg_addr_virt = base_addr_virt; - } - - // Allocate and zero the data structure - pHba = kzalloc(sizeof(adpt_hba), GFP_KERNEL); - if (!pHba) { - if (msg_addr_virt != base_addr_virt) - iounmap(msg_addr_virt); - iounmap(base_addr_virt); - pci_release_regions(pDev); - return -ENOMEM; - } - - mutex_lock(&adpt_configuration_lock); - - if(hba_chain != NULL){ - for(p = hba_chain; p->next; p = p->next); - p->next = pHba; - } else { - hba_chain = pHba; - } - pHba->next = NULL; - pHba->unit = hba_count; - sprintf(pHba->name, "dpti%d", hba_count); - hba_count++; - - mutex_unlock(&adpt_configuration_lock); - - pHba->pDev = pDev; - pHba->base_addr_phys = base_addr0_phys; - - // Set up the Virtual Base Address of the I2O Device - pHba->base_addr_virt = base_addr_virt; - pHba->msg_addr_virt = msg_addr_virt; - pHba->irq_mask = base_addr_virt+0x30; - pHba->post_port = base_addr_virt+0x40; - pHba->reply_port = base_addr_virt+0x44; - - pHba->hrt = NULL; - pHba->lct = NULL; - pHba->lct_size = 0; - pHba->status_block = NULL; - pHba->post_count = 0; - pHba->state = DPTI_STATE_RESET; - pHba->pDev = pDev; - pHba->devices = NULL; - pHba->dma64 = dma64; - - // Initializing the spinlocks - spin_lock_init(&pHba->state_lock); - spin_lock_init(&adpt_post_wait_lock); - - if(raptorFlag == 0){ - printk(KERN_INFO "Adaptec I2O RAID controller" - " %d at %p size=%x irq=%d%s\n", - hba_count-1, base_addr_virt, - hba_map0_area_size, pDev->irq, - dma64 ? " (64-bit DMA)" : ""); - } else { - printk(KERN_INFO"Adaptec I2O RAID controller %d irq=%d%s\n", - hba_count-1, pDev->irq, - dma64 ? " (64-bit DMA)" : ""); - printk(KERN_INFO" BAR0 %p - size= %x\n",base_addr_virt,hba_map0_area_size); - printk(KERN_INFO" BAR1 %p - size= %x\n",msg_addr_virt,hba_map1_area_size); - } - - if (request_irq (pDev->irq, adpt_isr, IRQF_SHARED, pHba->name, pHba)) { - printk(KERN_ERR"%s: Couldn't register IRQ %d\n", pHba->name, pDev->irq); - adpt_i2o_delete_hba(pHba); - return -EINVAL; - } - - return 0; -} - - -static void adpt_i2o_delete_hba(adpt_hba* pHba) -{ - adpt_hba* p1; - adpt_hba* p2; - struct i2o_device* d; - struct i2o_device* next; - int i; - int j; - struct adpt_device* pDev; - struct adpt_device* pNext; - - - mutex_lock(&adpt_configuration_lock); - if(pHba->host){ - free_irq(pHba->host->irq, pHba); - } - p2 = NULL; - for( p1 = hba_chain; p1; p2 = p1,p1=p1->next){ - if(p1 == pHba) { - if(p2) { - p2->next = p1->next; - } else { - hba_chain = p1->next; - } - break; - } - } - - hba_count--; - mutex_unlock(&adpt_configuration_lock); - - iounmap(pHba->base_addr_virt); - pci_release_regions(pHba->pDev); - if(pHba->msg_addr_virt != pHba->base_addr_virt){ - iounmap(pHba->msg_addr_virt); - } - if(pHba->FwDebugBuffer_P) - iounmap(pHba->FwDebugBuffer_P); - if(pHba->hrt) { - dma_free_coherent(&pHba->pDev->dev, - pHba->hrt->num_entries * pHba->hrt->entry_len << 2, - pHba->hrt, pHba->hrt_pa); - } - if(pHba->lct) { - dma_free_coherent(&pHba->pDev->dev, pHba->lct_size, - pHba->lct, pHba->lct_pa); - } - if(pHba->status_block) { - dma_free_coherent(&pHba->pDev->dev, sizeof(i2o_status_block), - pHba->status_block, pHba->status_block_pa); - } - if(pHba->reply_pool) { - dma_free_coherent(&pHba->pDev->dev, - pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, - pHba->reply_pool, pHba->reply_pool_pa); - } - - for(d = pHba->devices; d ; d = next){ - next = d->next; - kfree(d); - } - for(i = 0 ; i < pHba->top_scsi_channel ; i++){ - for(j = 0; j < MAX_ID; j++){ - if(pHba->channel[i].device[j] != NULL){ - for(pDev = pHba->channel[i].device[j]; pDev; pDev = pNext){ - pNext = pDev->next_lun; - kfree(pDev); - } - } - } - } - pci_dev_put(pHba->pDev); - if (adpt_sysfs_class) - device_destroy(adpt_sysfs_class, - MKDEV(DPTI_I2O_MAJOR, pHba->unit)); - kfree(pHba); - - if(hba_count <= 0){ - unregister_chrdev(DPTI_I2O_MAJOR, DPT_DRIVER); - if (adpt_sysfs_class) { - class_destroy(adpt_sysfs_class); - adpt_sysfs_class = NULL; - } - } -} - -static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun) -{ - struct adpt_device* d; - - if (chan >= MAX_CHANNEL) - return NULL; - - d = pHba->channel[chan].device[id]; - if(!d || d->tid == 0) { - return NULL; - } - - /* If it is the only lun at that address then this should match*/ - if(d->scsi_lun == lun){ - return d; - } - - /* else we need to look through all the luns */ - for(d=d->next_lun ; d ; d = d->next_lun){ - if(d->scsi_lun == lun){ - return d; - } - } - return NULL; -} - - -static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout) -{ - // I used my own version of the WAIT_QUEUE_HEAD - // to handle some version differences - // When embedded in the kernel this could go back to the vanilla one - ADPT_DECLARE_WAIT_QUEUE_HEAD(adpt_wq_i2o_post); - int status = 0; - ulong flags = 0; - struct adpt_i2o_post_wait_data *p1, *p2; - struct adpt_i2o_post_wait_data *wait_data = - kmalloc(sizeof(struct adpt_i2o_post_wait_data), GFP_ATOMIC); - DECLARE_WAITQUEUE(wait, current); - - if (!wait_data) - return -ENOMEM; - - /* - * The spin locking is needed to keep anyone from playing - * with the queue pointers and id while we do the same - */ - spin_lock_irqsave(&adpt_post_wait_lock, flags); - // TODO we need a MORE unique way of getting ids - // to support async LCT get - wait_data->next = adpt_post_wait_queue; - adpt_post_wait_queue = wait_data; - adpt_post_wait_id++; - adpt_post_wait_id &= 0x7fff; - wait_data->id = adpt_post_wait_id; - spin_unlock_irqrestore(&adpt_post_wait_lock, flags); - - wait_data->wq = &adpt_wq_i2o_post; - wait_data->status = -ETIMEDOUT; - - add_wait_queue(&adpt_wq_i2o_post, &wait); - - msg[2] |= 0x80000000 | ((u32)wait_data->id); - timeout *= HZ; - if((status = adpt_i2o_post_this(pHba, msg, len)) == 0){ - set_current_state(TASK_INTERRUPTIBLE); - if(pHba->host) - spin_unlock_irq(pHba->host->host_lock); - if (!timeout) - schedule(); - else{ - timeout = schedule_timeout(timeout); - if (timeout == 0) { - // I/O issued, but cannot get result in - // specified time. Freeing resorces is - // dangerous. - status = -ETIME; - } - } - if(pHba->host) - spin_lock_irq(pHba->host->host_lock); - } - remove_wait_queue(&adpt_wq_i2o_post, &wait); - - if(status == -ETIMEDOUT){ - printk(KERN_INFO"dpti%d: POST WAIT TIMEOUT\n",pHba->unit); - // We will have to free the wait_data memory during shutdown - return status; - } - - /* Remove the entry from the queue. */ - p2 = NULL; - spin_lock_irqsave(&adpt_post_wait_lock, flags); - for(p1 = adpt_post_wait_queue; p1; p2 = p1, p1 = p1->next) { - if(p1 == wait_data) { - if(p1->status == I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION ) { - status = -EOPNOTSUPP; - } - if(p2) { - p2->next = p1->next; - } else { - adpt_post_wait_queue = p1->next; - } - break; - } - } - spin_unlock_irqrestore(&adpt_post_wait_lock, flags); - - kfree(wait_data); - - return status; -} - - -static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len) -{ - - u32 m = EMPTY_QUEUE; - u32 __iomem *msg; - ulong timeout = jiffies + 30*HZ; - do { - rmb(); - m = readl(pHba->post_port); - if (m != EMPTY_QUEUE) { - break; - } - if(time_after(jiffies,timeout)){ - printk(KERN_WARNING"dpti%d: Timeout waiting for message frame!\n", pHba->unit); - return -ETIMEDOUT; - } - schedule_timeout_uninterruptible(1); - } while(m == EMPTY_QUEUE); - - msg = pHba->msg_addr_virt + m; - memcpy_toio(msg, data, len); - wmb(); - - //post message - writel(m, pHba->post_port); - wmb(); - - return 0; -} - - -static void adpt_i2o_post_wait_complete(u32 context, int status) -{ - struct adpt_i2o_post_wait_data *p1 = NULL; - /* - * We need to search through the adpt_post_wait - * queue to see if the given message is still - * outstanding. If not, it means that the IOP - * took longer to respond to the message than we - * had allowed and timer has already expired. - * Not much we can do about that except log - * it for debug purposes, increase timeout, and recompile - * - * Lock needed to keep anyone from moving queue pointers - * around while we're looking through them. - */ - - context &= 0x7fff; - - spin_lock(&adpt_post_wait_lock); - for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) { - if(p1->id == context) { - p1->status = status; - spin_unlock(&adpt_post_wait_lock); - wake_up_interruptible(p1->wq); - return; - } - } - spin_unlock(&adpt_post_wait_lock); - // If this happens we lose commands that probably really completed - printk(KERN_DEBUG"dpti: Could Not find task %d in wait queue\n",context); - printk(KERN_DEBUG" Tasks in wait queue:\n"); - for(p1 = adpt_post_wait_queue; p1; p1 = p1->next) { - printk(KERN_DEBUG" %d\n",p1->id); - } - return; -} - -static s32 adpt_i2o_reset_hba(adpt_hba* pHba) -{ - u32 msg[8]; - u8* status; - dma_addr_t addr; - u32 m = EMPTY_QUEUE ; - ulong timeout = jiffies + (TMOUT_IOPRESET*HZ); - - if(pHba->initialized == FALSE) { // First time reset should be quick - timeout = jiffies + (25*HZ); - } else { - adpt_i2o_quiesce_hba(pHba); - } - - do { - rmb(); - m = readl(pHba->post_port); - if (m != EMPTY_QUEUE) { - break; - } - if(time_after(jiffies,timeout)){ - printk(KERN_WARNING"Timeout waiting for message!\n"); - return -ETIMEDOUT; - } - schedule_timeout_uninterruptible(1); - } while (m == EMPTY_QUEUE); - - status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL); - if(status == NULL) { - adpt_send_nop(pHba, m); - printk(KERN_ERR"IOP reset failed - no free memory.\n"); - return -ENOMEM; - } - - msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID; - msg[2]=0; - msg[3]=0; - msg[4]=0; - msg[5]=0; - msg[6]=dma_low(addr); - msg[7]=dma_high(addr); - - memcpy_toio(pHba->msg_addr_virt+m, msg, sizeof(msg)); - wmb(); - writel(m, pHba->post_port); - wmb(); - - while(*status == 0){ - if(time_after(jiffies,timeout)){ - printk(KERN_WARNING"%s: IOP Reset Timeout\n",pHba->name); - /* We lose 4 bytes of "status" here, but we cannot - free these because controller may awake and corrupt - those bytes at any time */ - /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */ - return -ETIMEDOUT; - } - rmb(); - schedule_timeout_uninterruptible(1); - } - - if(*status == 0x01 /*I2O_EXEC_IOP_RESET_IN_PROGRESS*/) { - PDEBUG("%s: Reset in progress...\n", pHba->name); - // Here we wait for message frame to become available - // indicated that reset has finished - do { - rmb(); - m = readl(pHba->post_port); - if (m != EMPTY_QUEUE) { - break; - } - if(time_after(jiffies,timeout)){ - printk(KERN_ERR "%s:Timeout waiting for IOP Reset.\n",pHba->name); - /* We lose 4 bytes of "status" here, but we - cannot free these because controller may - awake and corrupt those bytes at any time */ - /* dma_free_coherent(&pHba->pDev->dev, 4, buf, addr); */ - return -ETIMEDOUT; - } - schedule_timeout_uninterruptible(1); - } while (m == EMPTY_QUEUE); - // Flush the offset - adpt_send_nop(pHba, m); - } - adpt_i2o_status_get(pHba); - if(*status == 0x02 || - pHba->status_block->iop_state != ADAPTER_STATE_RESET) { - printk(KERN_WARNING"%s: Reset reject, trying to clear\n", - pHba->name); - } else { - PDEBUG("%s: Reset completed.\n", pHba->name); - } - - dma_free_coherent(&pHba->pDev->dev, 4, status, addr); -#ifdef UARTDELAY - // This delay is to allow someone attached to the card through the debug UART to - // set up the dump levels that they want before the rest of the initialization sequence - adpt_delay(20000); -#endif - return 0; -} - - -static int adpt_i2o_parse_lct(adpt_hba* pHba) -{ - int i; - int max; - int tid; - struct i2o_device *d; - i2o_lct *lct = pHba->lct; - u8 bus_no = 0; - s16 scsi_id; - u64 scsi_lun; - u32 buf[10]; // larger than 7, or 8 ... - struct adpt_device* pDev; - - if (lct == NULL) { - printk(KERN_ERR "%s: LCT is empty???\n",pHba->name); - return -1; - } - - max = lct->table_size; - max -= 3; - max /= 9; - - for(i=0;i<max;i++) { - if( lct->lct_entry[i].user_tid != 0xfff){ - /* - * If we have hidden devices, we need to inform the upper layers about - * the possible maximum id reference to handle device access when - * an array is disassembled. This code has no other purpose but to - * allow us future access to devices that are currently hidden - * behind arrays, hotspares or have not been configured (JBOD mode). - */ - if( lct->lct_entry[i].class_id != I2O_CLASS_RANDOM_BLOCK_STORAGE && - lct->lct_entry[i].class_id != I2O_CLASS_SCSI_PERIPHERAL && - lct->lct_entry[i].class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){ - continue; - } - tid = lct->lct_entry[i].tid; - // I2O_DPT_DEVICE_INFO_GROUP_NO; - if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) { - continue; - } - bus_no = buf[0]>>16; - scsi_id = buf[1]; - scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]); - if(bus_no >= MAX_CHANNEL) { // Something wrong skip it - printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no); - continue; - } - if (scsi_id >= MAX_ID){ - printk(KERN_WARNING"%s: SCSI ID %d out of range \n", pHba->name, bus_no); - continue; - } - if(bus_no > pHba->top_scsi_channel){ - pHba->top_scsi_channel = bus_no; - } - if(scsi_id > pHba->top_scsi_id){ - pHba->top_scsi_id = scsi_id; - } - if(scsi_lun > pHba->top_scsi_lun){ - pHba->top_scsi_lun = scsi_lun; - } - continue; - } - d = kmalloc(sizeof(struct i2o_device), GFP_KERNEL); - if(d==NULL) - { - printk(KERN_CRIT"%s: Out of memory for I2O device data.\n",pHba->name); - return -ENOMEM; - } - - d->controller = pHba; - d->next = NULL; - - memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry)); - - d->flags = 0; - tid = d->lct_data.tid; - adpt_i2o_report_hba_unit(pHba, d); - adpt_i2o_install_device(pHba, d); - } - bus_no = 0; - for(d = pHba->devices; d ; d = d->next) { - if(d->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT || - d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PORT){ - tid = d->lct_data.tid; - // TODO get the bus_no from hrt-but for now they are in order - //bus_no = - if(bus_no > pHba->top_scsi_channel){ - pHba->top_scsi_channel = bus_no; - } - pHba->channel[bus_no].type = d->lct_data.class_id; - pHba->channel[bus_no].tid = tid; - if(adpt_i2o_query_scalar(pHba, tid, 0x0200, -1, buf, 28)>=0) - { - pHba->channel[bus_no].scsi_id = buf[1]; - PDEBUG("Bus %d - SCSI ID %d.\n", bus_no, buf[1]); - } - // TODO remove - this is just until we get from hrt - bus_no++; - if(bus_no >= MAX_CHANNEL) { // Something wrong skip it - printk(KERN_WARNING"%s: Channel number %d out of range - LCT\n", pHba->name, bus_no); - break; - } - } - } - - // Setup adpt_device table - for(d = pHba->devices; d ; d = d->next) { - if(d->lct_data.class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE || - d->lct_data.class_id == I2O_CLASS_SCSI_PERIPHERAL || - d->lct_data.class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){ - - tid = d->lct_data.tid; - scsi_id = -1; - // I2O_DPT_DEVICE_INFO_GROUP_NO; - if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)>=0) { - bus_no = buf[0]>>16; - scsi_id = buf[1]; - scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]); - if(bus_no >= MAX_CHANNEL) { // Something wrong skip it - continue; - } - if (scsi_id >= MAX_ID) { - continue; - } - if( pHba->channel[bus_no].device[scsi_id] == NULL){ - pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL); - if(pDev == NULL) { - return -ENOMEM; - } - pHba->channel[bus_no].device[scsi_id] = pDev; - } else { - for( pDev = pHba->channel[bus_no].device[scsi_id]; - pDev->next_lun; pDev = pDev->next_lun){ - } - pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL); - if(pDev->next_lun == NULL) { - return -ENOMEM; - } - pDev = pDev->next_lun; - } - pDev->tid = tid; - pDev->scsi_channel = bus_no; - pDev->scsi_id = scsi_id; - pDev->scsi_lun = scsi_lun; - pDev->pI2o_dev = d; - d->owner = pDev; - pDev->type = (buf[0])&0xff; - pDev->flags = (buf[0]>>8)&0xff; - if(scsi_id > pHba->top_scsi_id){ - pHba->top_scsi_id = scsi_id; - } - if(scsi_lun > pHba->top_scsi_lun){ - pHba->top_scsi_lun = scsi_lun; - } - } - if(scsi_id == -1){ - printk(KERN_WARNING"Could not find SCSI ID for %s\n", - d->lct_data.identity_tag); - } - } - } - return 0; -} - - -/* - * Each I2O controller has a chain of devices on it - these match - * the useful parts of the LCT of the board. - */ - -static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d) -{ - mutex_lock(&adpt_configuration_lock); - d->controller=pHba; - d->owner=NULL; - d->next=pHba->devices; - d->prev=NULL; - if (pHba->devices != NULL){ - pHba->devices->prev=d; - } - pHba->devices=d; - *d->dev_name = 0; - - mutex_unlock(&adpt_configuration_lock); - return 0; -} - -static int adpt_open(struct inode *inode, struct file *file) -{ - int minor; - adpt_hba* pHba; - - mutex_lock(&adpt_mutex); - //TODO check for root access - // - minor = iminor(inode); - if (minor >= hba_count) { - mutex_unlock(&adpt_mutex); - return -ENXIO; - } - mutex_lock(&adpt_configuration_lock); - for (pHba = hba_chain; pHba; pHba = pHba->next) { - if (pHba->unit == minor) { - break; /* found adapter */ - } - } - if (pHba == NULL) { - mutex_unlock(&adpt_configuration_lock); - mutex_unlock(&adpt_mutex); - return -ENXIO; - } - -// if(pHba->in_use){ - // mutex_unlock(&adpt_configuration_lock); -// return -EBUSY; -// } - - pHba->in_use = 1; - mutex_unlock(&adpt_configuration_lock); - mutex_unlock(&adpt_mutex); - - return 0; -} - -static int adpt_close(struct inode *inode, struct file *file) -{ - int minor; - adpt_hba* pHba; - - minor = iminor(inode); - if (minor >= hba_count) { - return -ENXIO; - } - mutex_lock(&adpt_configuration_lock); - for (pHba = hba_chain; pHba; pHba = pHba->next) { - if (pHba->unit == minor) { - break; /* found adapter */ - } - } - mutex_unlock(&adpt_configuration_lock); - if (pHba == NULL) { - return -ENXIO; - } - - pHba->in_use = 0; - - return 0; -} - - -static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) -{ - u32 msg[MAX_MESSAGE_SIZE]; - u32* reply = NULL; - u32 size = 0; - u32 reply_size = 0; - u32 __user *user_msg = arg; - u32 __user * user_reply = NULL; - void **sg_list = NULL; - u32 sg_offset = 0; - u32 sg_count = 0; - int sg_index = 0; - u32 i = 0; - u32 rcode = 0; - void *p = NULL; - dma_addr_t addr; - ulong flags = 0; - - memset(&msg, 0, MAX_MESSAGE_SIZE*4); - // get user msg size in u32s - if(get_user(size, &user_msg[0])){ - return -EFAULT; - } - size = size>>16; - - user_reply = &user_msg[size]; - if(size > MAX_MESSAGE_SIZE){ - return -EFAULT; - } - size *= 4; // Convert to bytes - - /* Copy in the user's I2O command */ - if(copy_from_user(msg, user_msg, size)) { - return -EFAULT; - } - get_user(reply_size, &user_reply[0]); - reply_size = reply_size>>16; - if(reply_size > REPLY_FRAME_SIZE){ - reply_size = REPLY_FRAME_SIZE; - } - reply_size *= 4; - reply = kzalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL); - if(reply == NULL) { - printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name); - return -ENOMEM; - } - sg_offset = (msg[0]>>4)&0xf; - msg[2] = 0x40000000; // IOCTL context - msg[3] = adpt_ioctl_to_context(pHba, reply); - if (msg[3] == (u32)-1) { - rcode = -EBUSY; - goto free; - } - - sg_list = kcalloc(pHba->sg_tablesize, sizeof(*sg_list), GFP_KERNEL); - if (!sg_list) { - rcode = -ENOMEM; - goto free; - } - if(sg_offset) { - // TODO add 64 bit API - struct sg_simple_element *sg = (struct sg_simple_element*) (msg+sg_offset); - sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); - if (sg_count > pHba->sg_tablesize){ - printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", pHba->name,sg_count); - rcode = -EINVAL; - goto free; - } - - for(i = 0; i < sg_count; i++) { - int sg_size; - - if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) { - printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",pHba->name,i, sg[i].flag_count); - rcode = -EINVAL; - goto cleanup; - } - sg_size = sg[i].flag_count & 0xffffff; - /* Allocate memory for the transfer */ - p = dma_alloc_coherent(&pHba->pDev->dev, sg_size, &addr, GFP_KERNEL); - if(!p) { - printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n", - pHba->name,sg_size,i,sg_count); - rcode = -ENOMEM; - goto cleanup; - } - sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame. - /* Copy in the user's SG buffer if necessary */ - if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) { - // sg_simple_element API is 32 bit - if (copy_from_user(p,(void __user *)(ulong)sg[i].addr_bus, sg_size)) { - printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",pHba->name,i); - rcode = -EFAULT; - goto cleanup; - } - } - /* sg_simple_element API is 32 bit, but addr < 4GB */ - sg[i].addr_bus = addr; - } - } - - do { - /* - * Stop any new commands from enterring the - * controller while processing the ioctl - */ - if (pHba->host) { - scsi_block_requests(pHba->host); - spin_lock_irqsave(pHba->host->host_lock, flags); - } - rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER); - if (rcode != 0) - printk("adpt_i2o_passthru: post wait failed %d %p\n", - rcode, reply); - if (pHba->host) { - spin_unlock_irqrestore(pHba->host->host_lock, flags); - scsi_unblock_requests(pHba->host); - } - } while (rcode == -ETIMEDOUT); - - if(rcode){ - goto cleanup; - } - - if(sg_offset) { - /* Copy back the Scatter Gather buffers back to user space */ - u32 j; - // TODO add 64 bit API - struct sg_simple_element* sg; - int sg_size; - - // re-acquire the original message to handle correctly the sg copy operation - memset(&msg, 0, MAX_MESSAGE_SIZE*4); - // get user msg size in u32s - if(get_user(size, &user_msg[0])){ - rcode = -EFAULT; - goto cleanup; - } - size = size>>16; - size *= 4; - if (size > MAX_MESSAGE_SIZE) { - rcode = -EINVAL; - goto cleanup; - } - /* Copy in the user's I2O command */ - if (copy_from_user (msg, user_msg, size)) { - rcode = -EFAULT; - goto cleanup; - } - sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element); - - // TODO add 64 bit API - sg = (struct sg_simple_element*)(msg + sg_offset); - for (j = 0; j < sg_count; j++) { - /* Copy out the SG list to user's buffer if necessary */ - if(! (sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) { - sg_size = sg[j].flag_count & 0xffffff; - // sg_simple_element API is 32 bit - if (copy_to_user((void __user *)(ulong)sg[j].addr_bus,sg_list[j], sg_size)) { - printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",pHba->name, sg_list[j], sg[j].addr_bus); - rcode = -EFAULT; - goto cleanup; - } - } - } - } - - /* Copy back the reply to user space */ - if (reply_size) { - // we wrote our own values for context - now restore the user supplied ones - if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) { - printk(KERN_WARNING"%s: Could not copy message context FROM user\n",pHba->name); - rcode = -EFAULT; - } - if(copy_to_user(user_reply, reply, reply_size)) { - printk(KERN_WARNING"%s: Could not copy reply TO user\n",pHba->name); - rcode = -EFAULT; - } - } - - -cleanup: - if (rcode != -ETIME && rcode != -EINTR) { - struct sg_simple_element *sg = - (struct sg_simple_element*) (msg +sg_offset); - while(sg_index) { - if(sg_list[--sg_index]) { - dma_free_coherent(&pHba->pDev->dev, - sg[sg_index].flag_count & 0xffffff, - sg_list[sg_index], - sg[sg_index].addr_bus); - } - } - } - -free: - kfree(sg_list); - kfree(reply); - return rcode; -} - -#if defined __ia64__ -static void adpt_ia64_info(sysInfo_S* si) -{ - // This is all the info we need for now - // We will add more info as our new - // managmenent utility requires it - si->processorType = PROC_IA64; -} -#endif - -#if defined __sparc__ -static void adpt_sparc_info(sysInfo_S* si) -{ - // This is all the info we need for now - // We will add more info as our new - // managmenent utility requires it - si->processorType = PROC_ULTRASPARC; -} -#endif -#if defined __alpha__ -static void adpt_alpha_info(sysInfo_S* si) -{ - // This is all the info we need for now - // We will add more info as our new - // managmenent utility requires it - si->processorType = PROC_ALPHA; -} -#endif - -#if defined __i386__ - -#include <uapi/asm/vm86.h> - -static void adpt_i386_info(sysInfo_S* si) -{ - // This is all the info we need for now - // We will add more info as our new - // managmenent utility requires it - switch (boot_cpu_data.x86) { - case CPU_386: - si->processorType = PROC_386; - break; - case CPU_486: - si->processorType = PROC_486; - break; - case CPU_586: - si->processorType = PROC_PENTIUM; - break; - default: // Just in case - si->processorType = PROC_PENTIUM; - break; - } -} -#endif - -/* - * This routine returns information about the system. This does not effect - * any logic and if the info is wrong - it doesn't matter. - */ - -/* Get all the info we can not get from kernel services */ -static int adpt_system_info(void __user *buffer) -{ - sysInfo_S si; - - memset(&si, 0, sizeof(si)); - - si.osType = OS_LINUX; - si.osMajorVersion = 0; - si.osMinorVersion = 0; - si.osRevision = 0; - si.busType = SI_PCI_BUS; - si.processorFamily = DPTI_sig.dsProcessorFamily; - -#if defined __i386__ - adpt_i386_info(&si); -#elif defined (__ia64__) - adpt_ia64_info(&si); -#elif defined(__sparc__) - adpt_sparc_info(&si); -#elif defined (__alpha__) - adpt_alpha_info(&si); -#else - si.processorType = 0xff ; -#endif - if (copy_to_user(buffer, &si, sizeof(si))){ - printk(KERN_WARNING"dpti: Could not copy buffer TO user\n"); - return -EFAULT; - } - - return 0; -} - -static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) -{ - int minor; - int error = 0; - adpt_hba* pHba; - ulong flags = 0; - void __user *argp = (void __user *)arg; - - minor = iminor(inode); - if (minor >= DPTI_MAX_HBA){ - return -ENXIO; - } - mutex_lock(&adpt_configuration_lock); - for (pHba = hba_chain; pHba; pHba = pHba->next) { - if (pHba->unit == minor) { - break; /* found adapter */ - } - } - mutex_unlock(&adpt_configuration_lock); - if(pHba == NULL){ - return -ENXIO; - } - - while((volatile u32) pHba->state & DPTI_STATE_RESET ) - schedule_timeout_uninterruptible(2); - - switch (cmd) { - // TODO: handle 3 cases - case DPT_SIGNATURE: - if (copy_to_user(argp, &DPTI_sig, sizeof(DPTI_sig))) { - return -EFAULT; - } - break; - case I2OUSRCMD: - return adpt_i2o_passthru(pHba, argp); - - case DPT_CTRLINFO:{ - drvrHBAinfo_S HbaInfo; - -#define FLG_OSD_PCI_VALID 0x0001 -#define FLG_OSD_DMA 0x0002 -#define FLG_OSD_I2O 0x0004 - memset(&HbaInfo, 0, sizeof(HbaInfo)); - HbaInfo.drvrHBAnum = pHba->unit; - HbaInfo.baseAddr = (ulong) pHba->base_addr_phys; - HbaInfo.blinkState = adpt_read_blink_led(pHba); - HbaInfo.pciBusNum = pHba->pDev->bus->number; - HbaInfo.pciDeviceNum=PCI_SLOT(pHba->pDev->devfn); - HbaInfo.Interrupt = pHba->pDev->irq; - HbaInfo.hbaFlags = FLG_OSD_PCI_VALID | FLG_OSD_DMA | FLG_OSD_I2O; - if(copy_to_user(argp, &HbaInfo, sizeof(HbaInfo))){ - printk(KERN_WARNING"%s: Could not copy HbaInfo TO user\n",pHba->name); - return -EFAULT; - } - break; - } - case DPT_SYSINFO: - return adpt_system_info(argp); - case DPT_BLINKLED:{ - u32 value; - value = (u32)adpt_read_blink_led(pHba); - if (copy_to_user(argp, &value, sizeof(value))) { - return -EFAULT; - } - break; - } - case I2ORESETCMD: { - struct Scsi_Host *shost = pHba->host; - - if (shost) - spin_lock_irqsave(shost->host_lock, flags); - adpt_hba_reset(pHba); - if (shost) - spin_unlock_irqrestore(shost->host_lock, flags); - break; - } - case I2ORESCANCMD: - adpt_rescan(pHba); - break; - default: - return -EINVAL; - } - - return error; -} - -static long adpt_unlocked_ioctl(struct file *file, uint cmd, ulong arg) -{ - struct inode *inode; - long ret; - - inode = file_inode(file); - - mutex_lock(&adpt_mutex); - ret = adpt_ioctl(inode, file, cmd, arg); - mutex_unlock(&adpt_mutex); - - return ret; -} - -#ifdef CONFIG_COMPAT -static long compat_adpt_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct inode *inode; - long ret; - - inode = file_inode(file); - - mutex_lock(&adpt_mutex); - - switch(cmd) { - case DPT_SIGNATURE: - case I2OUSRCMD: - case DPT_CTRLINFO: - case DPT_SYSINFO: - case DPT_BLINKLED: - case I2ORESETCMD: - case I2ORESCANCMD: - case (DPT_TARGET_BUSY & 0xFFFF): - case DPT_TARGET_BUSY: - ret = adpt_ioctl(inode, file, cmd, arg); - break; - default: - ret = -ENOIOCTLCMD; - } - - mutex_unlock(&adpt_mutex); - - return ret; -} -#endif - -static irqreturn_t adpt_isr(int irq, void *dev_id) -{ - struct scsi_cmnd* cmd; - adpt_hba* pHba = dev_id; - u32 m; - void __iomem *reply; - u32 status=0; - u32 context; - ulong flags = 0; - int handled = 0; - - if (pHba == NULL){ - printk(KERN_WARNING"adpt_isr: NULL dev_id\n"); - return IRQ_NONE; - } - if(pHba->host) - spin_lock_irqsave(pHba->host->host_lock, flags); - - while( readl(pHba->irq_mask) & I2O_INTERRUPT_PENDING_B) { - m = readl(pHba->reply_port); - if(m == EMPTY_QUEUE){ - // Try twice then give up - rmb(); - m = readl(pHba->reply_port); - if(m == EMPTY_QUEUE){ - // This really should not happen - printk(KERN_ERR"dpti: Could not get reply frame\n"); - goto out; - } - } - if (pHba->reply_pool_pa <= m && - m < pHba->reply_pool_pa + - (pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4)) { - reply = (u8 *)pHba->reply_pool + - (m - pHba->reply_pool_pa); - } else { - /* Ick, we should *never* be here */ - printk(KERN_ERR "dpti: reply frame not from pool\n"); - reply = (u8 *)bus_to_virt(m); - } - - if (readl(reply) & MSG_FAIL) { - u32 old_m = readl(reply+28); - void __iomem *msg; - u32 old_context; - PDEBUG("%s: Failed message\n",pHba->name); - if(old_m >= 0x100000){ - printk(KERN_ERR"%s: Bad preserved MFA (%x)- dropping frame\n",pHba->name,old_m); - writel(m,pHba->reply_port); - continue; - } - // Transaction context is 0 in failed reply frame - msg = pHba->msg_addr_virt + old_m; - old_context = readl(msg+12); - writel(old_context, reply+12); - adpt_send_nop(pHba, old_m); - } - context = readl(reply+8); - if(context & 0x40000000){ // IOCTL - void *p = adpt_ioctl_from_context(pHba, readl(reply+12)); - if( p != NULL) { - memcpy_fromio(p, reply, REPLY_FRAME_SIZE * 4); - } - // All IOCTLs will also be post wait - } - if(context & 0x80000000){ // Post wait message - status = readl(reply+16); - if(status >> 24){ - status &= 0xffff; /* Get detail status */ - } else { - status = I2O_POST_WAIT_OK; - } - if(!(context & 0x40000000)) { - /* - * The request tag is one less than the command tag - * as the firmware might treat a 0 tag as invalid - */ - cmd = scsi_host_find_tag(pHba->host, - readl(reply + 12) - 1); - if(cmd != NULL) { - printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context); - } - } - adpt_i2o_post_wait_complete(context, status); - } else { // SCSI message - /* - * The request tag is one less than the command tag - * as the firmware might treat a 0 tag as invalid - */ - cmd = scsi_host_find_tag(pHba->host, - readl(reply + 12) - 1); - if(cmd != NULL){ - scsi_dma_unmap(cmd); - adpt_i2o_scsi_complete(reply, cmd); - } - } - writel(m, pHba->reply_port); - wmb(); - rmb(); - } - handled = 1; -out: if(pHba->host) - spin_unlock_irqrestore(pHba->host->host_lock, flags); - return IRQ_RETVAL(handled); -} - -static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* d) -{ - int i; - u32 msg[MAX_MESSAGE_SIZE]; - u32* mptr; - u32* lptr; - u32 *lenptr; - int direction; - int scsidir; - int nseg; - u32 len; - u32 reqlen; - s32 rcode; - dma_addr_t addr; - - memset(msg, 0 , sizeof(msg)); - len = scsi_bufflen(cmd); - direction = 0x00000000; - - scsidir = 0x00000000; // DATA NO XFER - if(len) { - /* - * Set SCBFlags to indicate if data is being transferred - * in or out, or no data transfer - * Note: Do not have to verify index is less than 0 since - * cmd->cmnd[0] is an unsigned char - */ - switch(cmd->sc_data_direction){ - case DMA_FROM_DEVICE: - scsidir =0x40000000; // DATA IN (iop<--dev) - break; - case DMA_TO_DEVICE: - direction=0x04000000; // SGL OUT - scsidir =0x80000000; // DATA OUT (iop-->dev) - break; - case DMA_NONE: - break; - case DMA_BIDIRECTIONAL: - scsidir =0x40000000; // DATA IN (iop<--dev) - // Assume In - and continue; - break; - default: - printk(KERN_WARNING"%s: scsi opcode 0x%x not supported.\n", - pHba->name, cmd->cmnd[0]); - cmd->result = (DID_OK <<16) | (INITIATOR_ERROR << 8); - cmd->scsi_done(cmd); - return 0; - } - } - // msg[0] is set later - // I2O_CMD_SCSI_EXEC - msg[1] = ((0xff<<24)|(HOST_TID<<12)|d->tid); - msg[2] = 0; - /* Add 1 to avoid firmware treating it as invalid command */ - msg[3] = cmd->request->tag + 1; - // Our cards use the transaction context as the tag for queueing - // Adaptec/DPT Private stuff - msg[4] = I2O_CMD_SCSI_EXEC|(DPT_ORGANIZATION_ID<<16); - msg[5] = d->tid; - /* Direction, disconnect ok | sense data | simple queue , CDBLen */ - // I2O_SCB_FLAG_ENABLE_DISCONNECT | - // I2O_SCB_FLAG_SIMPLE_QUEUE_TAG | - // I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE; - msg[6] = scsidir|0x20a00000|cmd->cmd_len; - - mptr=msg+7; - - // Write SCSI command into the message - always 16 byte block - memset(mptr, 0, 16); - memcpy(mptr, cmd->cmnd, cmd->cmd_len); - mptr+=4; - lenptr=mptr++; /* Remember me - fill in when we know */ - if (dpt_dma64(pHba)) { - reqlen = 16; // SINGLE SGE - *mptr++ = (0x7C<<24)+(2<<16)+0x02; /* Enable 64 bit */ - *mptr++ = 1 << PAGE_SHIFT; - } else { - reqlen = 14; // SINGLE SGE - } - /* Now fill in the SGList and command */ - - nseg = scsi_dma_map(cmd); - BUG_ON(nseg < 0); - if (nseg) { - struct scatterlist *sg; - - len = 0; - scsi_for_each_sg(cmd, sg, nseg, i) { - lptr = mptr; - *mptr++ = direction|0x10000000|sg_dma_len(sg); - len+=sg_dma_len(sg); - addr = sg_dma_address(sg); - *mptr++ = dma_low(addr); - if (dpt_dma64(pHba)) - *mptr++ = dma_high(addr); - /* Make this an end of list */ - if (i == nseg - 1) - *lptr = direction|0xD0000000|sg_dma_len(sg); - } - reqlen = mptr - msg; - *lenptr = len; - - if(cmd->underflow && len != cmd->underflow){ - printk(KERN_WARNING"Cmd len %08X Cmd underflow %08X\n", - len, cmd->underflow); - } - } else { - *lenptr = len = 0; - reqlen = 12; - } - - /* Stick the headers on */ - msg[0] = reqlen<<16 | ((reqlen > 12) ? SGL_OFFSET_12 : SGL_OFFSET_0); - - // Send it on it's way - rcode = adpt_i2o_post_this(pHba, msg, reqlen<<2); - if (rcode == 0) { - return 0; - } - return rcode; -} - - -static s32 adpt_scsi_host_alloc(adpt_hba* pHba, struct scsi_host_template *sht) -{ - struct Scsi_Host *host; - - host = scsi_host_alloc(sht, sizeof(adpt_hba*)); - if (host == NULL) { - printk("%s: scsi_host_alloc returned NULL\n", pHba->name); - return -1; - } - host->hostdata[0] = (unsigned long)pHba; - pHba->host = host; - - host->irq = pHba->pDev->irq; - /* no IO ports, so don't have to set host->io_port and - * host->n_io_port - */ - host->io_port = 0; - host->n_io_port = 0; - /* see comments in scsi_host.h */ - host->max_id = 16; - host->max_lun = 256; - host->max_channel = pHba->top_scsi_channel + 1; - host->cmd_per_lun = 1; - host->unique_id = (u32)sys_tbl_pa + pHba->unit; - host->sg_tablesize = pHba->sg_tablesize; - host->can_queue = pHba->post_fifo_size; - - return 0; -} - - -static void adpt_i2o_scsi_complete(void __iomem *reply, struct scsi_cmnd *cmd) -{ - adpt_hba* pHba; - u32 hba_status; - u32 dev_status; - u32 reply_flags = readl(reply) & 0xff00; // Leave it shifted up 8 bits - // I know this would look cleaner if I just read bytes - // but the model I have been using for all the rest of the - // io is in 4 byte words - so I keep that model - u16 detailed_status = readl(reply+16) &0xffff; - dev_status = (detailed_status & 0xff); - hba_status = detailed_status >> 8; - - // calculate resid for sg - scsi_set_resid(cmd, scsi_bufflen(cmd) - readl(reply+20)); - - pHba = (adpt_hba*) cmd->device->host->hostdata[0]; - - cmd->sense_buffer[0] = '\0'; // initialize sense valid flag to false - - if(!(reply_flags & MSG_FAIL)) { - switch(detailed_status & I2O_SCSI_DSC_MASK) { - case I2O_SCSI_DSC_SUCCESS: - cmd->result = (DID_OK << 16); - // handle underflow - if (readl(reply+20) < cmd->underflow) { - cmd->result = (DID_ERROR <<16); - printk(KERN_WARNING"%s: SCSI CMD underflow\n",pHba->name); - } - break; - case I2O_SCSI_DSC_REQUEST_ABORTED: - cmd->result = (DID_ABORT << 16); - break; - case I2O_SCSI_DSC_PATH_INVALID: - case I2O_SCSI_DSC_DEVICE_NOT_PRESENT: - case I2O_SCSI_DSC_SELECTION_TIMEOUT: - case I2O_SCSI_DSC_COMMAND_TIMEOUT: - case I2O_SCSI_DSC_NO_ADAPTER: - case I2O_SCSI_DSC_RESOURCE_UNAVAILABLE: - printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%llu) hba status=0x%x, dev status=0x%x, cmd=0x%x\n", - pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]); - cmd->result = (DID_TIME_OUT << 16); - break; - case I2O_SCSI_DSC_ADAPTER_BUSY: - case I2O_SCSI_DSC_BUS_BUSY: - cmd->result = (DID_BUS_BUSY << 16); - break; - case I2O_SCSI_DSC_SCSI_BUS_RESET: - case I2O_SCSI_DSC_BDR_MESSAGE_SENT: - cmd->result = (DID_RESET << 16); - break; - case I2O_SCSI_DSC_PARITY_ERROR_FAILURE: - printk(KERN_WARNING"%s: SCSI CMD parity error\n",pHba->name); - cmd->result = (DID_PARITY << 16); - break; - case I2O_SCSI_DSC_UNABLE_TO_ABORT: - case I2O_SCSI_DSC_COMPLETE_WITH_ERROR: - case I2O_SCSI_DSC_UNABLE_TO_TERMINATE: - case I2O_SCSI_DSC_MR_MESSAGE_RECEIVED: - case I2O_SCSI_DSC_AUTOSENSE_FAILED: - case I2O_SCSI_DSC_DATA_OVERRUN: - case I2O_SCSI_DSC_UNEXPECTED_BUS_FREE: - case I2O_SCSI_DSC_SEQUENCE_FAILURE: - case I2O_SCSI_DSC_REQUEST_LENGTH_ERROR: - case I2O_SCSI_DSC_PROVIDE_FAILURE: - case I2O_SCSI_DSC_REQUEST_TERMINATED: - case I2O_SCSI_DSC_IDE_MESSAGE_SENT: - case I2O_SCSI_DSC_UNACKNOWLEDGED_EVENT: - case I2O_SCSI_DSC_MESSAGE_RECEIVED: - case I2O_SCSI_DSC_INVALID_CDB: - case I2O_SCSI_DSC_LUN_INVALID: - case I2O_SCSI_DSC_SCSI_TID_INVALID: - case I2O_SCSI_DSC_FUNCTION_UNAVAILABLE: - case I2O_SCSI_DSC_NO_NEXUS: - case I2O_SCSI_DSC_CDB_RECEIVED: - case I2O_SCSI_DSC_LUN_ALREADY_ENABLED: - case I2O_SCSI_DSC_QUEUE_FROZEN: - case I2O_SCSI_DSC_REQUEST_INVALID: - default: - printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", - pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, - hba_status, dev_status, cmd->cmnd[0]); - cmd->result = (DID_ERROR << 16); - break; - } - - // copy over the request sense data if it was a check - // condition status - if (dev_status == SAM_STAT_CHECK_CONDITION) { - u32 len = min(SCSI_SENSE_BUFFERSIZE, 40); - // Copy over the sense data - memcpy_fromio(cmd->sense_buffer, (reply+28) , len); - if(cmd->sense_buffer[0] == 0x70 /* class 7 */ && - cmd->sense_buffer[2] == DATA_PROTECT ){ - /* This is to handle an array failed */ - cmd->result = (DID_TIME_OUT << 16); - printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", - pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, - hba_status, dev_status, cmd->cmnd[0]); - - } - } - } else { - /* In this condtion we could not talk to the tid - * the card rejected it. We should signal a retry - * for a limitted number of retries. - */ - cmd->result = (DID_TIME_OUT << 16); - printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%llu) tid=%d, cmd=0x%x\n", - pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, - ((struct adpt_device*)(cmd->device->hostdata))->tid, cmd->cmnd[0]); - } - - cmd->result |= (dev_status); - - if(cmd->scsi_done != NULL){ - cmd->scsi_done(cmd); - } -} - - -static s32 adpt_rescan(adpt_hba* pHba) -{ - s32 rcode; - ulong flags = 0; - - if(pHba->host) - spin_lock_irqsave(pHba->host->host_lock, flags); - if ((rcode=adpt_i2o_lct_get(pHba)) < 0) - goto out; - if ((rcode=adpt_i2o_reparse_lct(pHba)) < 0) - goto out; - rcode = 0; -out: if(pHba->host) - spin_unlock_irqrestore(pHba->host->host_lock, flags); - return rcode; -} - - -static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) -{ - int i; - int max; - int tid; - struct i2o_device *d; - i2o_lct *lct = pHba->lct; - u8 bus_no = 0; - s16 scsi_id; - u64 scsi_lun; - u32 buf[10]; // at least 8 u32's - struct adpt_device* pDev = NULL; - struct i2o_device* pI2o_dev = NULL; - - if (lct == NULL) { - printk(KERN_ERR "%s: LCT is empty???\n",pHba->name); - return -1; - } - - max = lct->table_size; - max -= 3; - max /= 9; - - // Mark each drive as unscanned - for (d = pHba->devices; d; d = d->next) { - pDev =(struct adpt_device*) d->owner; - if(!pDev){ - continue; - } - pDev->state |= DPTI_DEV_UNSCANNED; - } - - printk(KERN_INFO "%s: LCT has %d entries.\n", pHba->name,max); - - for(i=0;i<max;i++) { - if( lct->lct_entry[i].user_tid != 0xfff){ - continue; - } - - if( lct->lct_entry[i].class_id == I2O_CLASS_RANDOM_BLOCK_STORAGE || - lct->lct_entry[i].class_id == I2O_CLASS_SCSI_PERIPHERAL || - lct->lct_entry[i].class_id == I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL ){ - tid = lct->lct_entry[i].tid; - if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)<0) { - printk(KERN_ERR"%s: Could not query device\n",pHba->name); - continue; - } - bus_no = buf[0]>>16; - if (bus_no >= MAX_CHANNEL) { /* Something wrong skip it */ - printk(KERN_WARNING - "%s: Channel number %d out of range\n", - pHba->name, bus_no); - continue; - } - - scsi_id = buf[1]; - scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]); - pDev = pHba->channel[bus_no].device[scsi_id]; - /* da lun */ - while(pDev) { - if(pDev->scsi_lun == scsi_lun) { - break; - } - pDev = pDev->next_lun; - } - if(!pDev ) { // Something new add it - d = kmalloc(sizeof(struct i2o_device), - GFP_ATOMIC); - if(d==NULL) - { - printk(KERN_CRIT "Out of memory for I2O device data.\n"); - return -ENOMEM; - } - - d->controller = pHba; - d->next = NULL; - - memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry)); - - d->flags = 0; - adpt_i2o_report_hba_unit(pHba, d); - adpt_i2o_install_device(pHba, d); - - pDev = pHba->channel[bus_no].device[scsi_id]; - if( pDev == NULL){ - pDev = - kzalloc(sizeof(struct adpt_device), - GFP_ATOMIC); - if(pDev == NULL) { - return -ENOMEM; - } - pHba->channel[bus_no].device[scsi_id] = pDev; - } else { - while (pDev->next_lun) { - pDev = pDev->next_lun; - } - pDev = pDev->next_lun = - kzalloc(sizeof(struct adpt_device), - GFP_ATOMIC); - if(pDev == NULL) { - return -ENOMEM; - } - } - pDev->tid = d->lct_data.tid; - pDev->scsi_channel = bus_no; - pDev->scsi_id = scsi_id; - pDev->scsi_lun = scsi_lun; - pDev->pI2o_dev = d; - d->owner = pDev; - pDev->type = (buf[0])&0xff; - pDev->flags = (buf[0]>>8)&0xff; - // Too late, SCSI system has made up it's mind, but what the hey ... - if(scsi_id > pHba->top_scsi_id){ - pHba->top_scsi_id = scsi_id; - } - if(scsi_lun > pHba->top_scsi_lun){ - pHba->top_scsi_lun = scsi_lun; - } - continue; - } // end of new i2o device - - // We found an old device - check it - while(pDev) { - if(pDev->scsi_lun == scsi_lun) { - if(!scsi_device_online(pDev->pScsi_dev)) { - printk(KERN_WARNING"%s: Setting device (%d,%d,%llu) back online\n", - pHba->name,bus_no,scsi_id,scsi_lun); - if (pDev->pScsi_dev) { - scsi_device_set_state(pDev->pScsi_dev, SDEV_RUNNING); - } - } - d = pDev->pI2o_dev; - if(d->lct_data.tid != tid) { // something changed - pDev->tid = tid; - memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry)); - if (pDev->pScsi_dev) { - pDev->pScsi_dev->changed = TRUE; - pDev->pScsi_dev->removable = TRUE; - } - } - // Found it - mark it scanned - pDev->state = DPTI_DEV_ONLINE; - break; - } - pDev = pDev->next_lun; - } - } - } - for (pI2o_dev = pHba->devices; pI2o_dev; pI2o_dev = pI2o_dev->next) { - pDev =(struct adpt_device*) pI2o_dev->owner; - if(!pDev){ - continue; - } - // Drive offline drives that previously existed but could not be found - // in the LCT table - if (pDev->state & DPTI_DEV_UNSCANNED){ - pDev->state = DPTI_DEV_OFFLINE; - printk(KERN_WARNING"%s: Device (%d,%d,%llu) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun); - if (pDev->pScsi_dev) { - scsi_device_set_state(pDev->pScsi_dev, SDEV_OFFLINE); - } - } - } - return 0; -} - -/*============================================================================ - * Routines from i2o subsystem - *============================================================================ - */ - - - -/* - * Bring an I2O controller into HOLD state. See the spec. - */ -static int adpt_i2o_activate_hba(adpt_hba* pHba) -{ - int rcode; - - if(pHba->initialized ) { - if (adpt_i2o_status_get(pHba) < 0) { - if((rcode = adpt_i2o_reset_hba(pHba)) != 0){ - printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name); - return rcode; - } - if (adpt_i2o_status_get(pHba) < 0) { - printk(KERN_INFO "HBA not responding.\n"); - return -1; - } - } - - if(pHba->status_block->iop_state == ADAPTER_STATE_FAULTED) { - printk(KERN_CRIT "%s: hardware fault\n", pHba->name); - return -1; - } - - if (pHba->status_block->iop_state == ADAPTER_STATE_READY || - pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL || - pHba->status_block->iop_state == ADAPTER_STATE_HOLD || - pHba->status_block->iop_state == ADAPTER_STATE_FAILED) { - adpt_i2o_reset_hba(pHba); - if (adpt_i2o_status_get(pHba) < 0 || pHba->status_block->iop_state != ADAPTER_STATE_RESET) { - printk(KERN_ERR "%s: Failed to initialize.\n", pHba->name); - return -1; - } - } - } else { - if((rcode = adpt_i2o_reset_hba(pHba)) != 0){ - printk(KERN_WARNING"%s: Could NOT reset.\n", pHba->name); - return rcode; - } - - } - - if (adpt_i2o_init_outbound_q(pHba) < 0) { - return -1; - } - - /* In HOLD state */ - - if (adpt_i2o_hrt_get(pHba) < 0) { - return -1; - } - - return 0; -} - -/* - * Bring a controller online into OPERATIONAL state. - */ - -static int adpt_i2o_online_hba(adpt_hba* pHba) -{ - if (adpt_i2o_systab_send(pHba) < 0) - return -1; - /* In READY state */ - - if (adpt_i2o_enable_hba(pHba) < 0) - return -1; - - /* In OPERATIONAL state */ - return 0; -} - -static s32 adpt_send_nop(adpt_hba*pHba,u32 m) -{ - u32 __iomem *msg; - ulong timeout = jiffies + 5*HZ; - - while(m == EMPTY_QUEUE){ - rmb(); - m = readl(pHba->post_port); - if(m != EMPTY_QUEUE){ - break; - } - if(time_after(jiffies,timeout)){ - printk(KERN_ERR "%s: Timeout waiting for message frame!\n",pHba->name); - return 2; - } - schedule_timeout_uninterruptible(1); - } - msg = (u32 __iomem *)(pHba->msg_addr_virt + m); - writel( THREE_WORD_MSG_SIZE | SGL_OFFSET_0,&msg[0]); - writel( I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | 0,&msg[1]); - writel( 0,&msg[2]); - wmb(); - - writel(m, pHba->post_port); - wmb(); - return 0; -} - -static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) -{ - u8 *status; - dma_addr_t addr; - u32 __iomem *msg = NULL; - int i; - ulong timeout = jiffies + TMOUT_INITOUTBOUND*HZ; - u32 m; - - do { - rmb(); - m = readl(pHba->post_port); - if (m != EMPTY_QUEUE) { - break; - } - - if(time_after(jiffies,timeout)){ - printk(KERN_WARNING"%s: Timeout waiting for message frame\n",pHba->name); - return -ETIMEDOUT; - } - schedule_timeout_uninterruptible(1); - } while(m == EMPTY_QUEUE); - - msg=(u32 __iomem *)(pHba->msg_addr_virt+m); - - status = dma_alloc_coherent(&pHba->pDev->dev, 4, &addr, GFP_KERNEL); - if (!status) { - adpt_send_nop(pHba, m); - printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n", - pHba->name); - return -ENOMEM; - } - - writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]); - writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]); - writel(0, &msg[2]); - writel(0x0106, &msg[3]); /* Transaction context */ - writel(4096, &msg[4]); /* Host page frame size */ - writel((REPLY_FRAME_SIZE)<<16|0x80, &msg[5]); /* Outbound msg frame size and Initcode */ - writel(0xD0000004, &msg[6]); /* Simple SG LE, EOB */ - writel((u32)addr, &msg[7]); - - writel(m, pHba->post_port); - wmb(); - - // Wait for the reply status to come back - do { - if (*status) { - if (*status != 0x01 /*I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS*/) { - break; - } - } - rmb(); - if(time_after(jiffies,timeout)){ - printk(KERN_WARNING"%s: Timeout Initializing\n",pHba->name); - /* We lose 4 bytes of "status" here, but we - cannot free these because controller may - awake and corrupt those bytes at any time */ - /* dma_free_coherent(&pHba->pDev->dev, 4, status, addr); */ - return -ETIMEDOUT; - } - schedule_timeout_uninterruptible(1); - } while (1); - - // If the command was successful, fill the fifo with our reply - // message packets - if(*status != 0x04 /*I2O_EXEC_OUTBOUND_INIT_COMPLETE*/) { - dma_free_coherent(&pHba->pDev->dev, 4, status, addr); - return -2; - } - dma_free_coherent(&pHba->pDev->dev, 4, status, addr); - - if(pHba->reply_pool != NULL) { - dma_free_coherent(&pHba->pDev->dev, - pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, - pHba->reply_pool, pHba->reply_pool_pa); - } - - pHba->reply_pool = dma_alloc_coherent(&pHba->pDev->dev, - pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, - &pHba->reply_pool_pa, GFP_KERNEL); - if (!pHba->reply_pool) { - printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name); - return -ENOMEM; - } - - for(i = 0; i < pHba->reply_fifo_size; i++) { - writel(pHba->reply_pool_pa + (i * REPLY_FRAME_SIZE * 4), - pHba->reply_port); - wmb(); - } - adpt_i2o_status_get(pHba); - return 0; -} - - -/* - * I2O System Table. Contains information about - * all the IOPs in the system. Used to inform IOPs - * about each other's existence. - * - * sys_tbl_ver is the CurrentChangeIndicator that is - * used by IOPs to track changes. - */ - - - -static s32 adpt_i2o_status_get(adpt_hba* pHba) -{ - ulong timeout; - u32 m; - u32 __iomem *msg; - u8 *status_block=NULL; - - if(pHba->status_block == NULL) { - pHba->status_block = dma_alloc_coherent(&pHba->pDev->dev, - sizeof(i2o_status_block), - &pHba->status_block_pa, GFP_KERNEL); - if(pHba->status_block == NULL) { - printk(KERN_ERR - "dpti%d: Get Status Block failed; Out of memory. \n", - pHba->unit); - return -ENOMEM; - } - } - memset(pHba->status_block, 0, sizeof(i2o_status_block)); - status_block = (u8*)(pHba->status_block); - timeout = jiffies+TMOUT_GETSTATUS*HZ; - do { - rmb(); - m = readl(pHba->post_port); - if (m != EMPTY_QUEUE) { - break; - } - if(time_after(jiffies,timeout)){ - printk(KERN_ERR "%s: Timeout waiting for message !\n", - pHba->name); - return -ETIMEDOUT; - } - schedule_timeout_uninterruptible(1); - } while(m==EMPTY_QUEUE); - - - msg=(u32 __iomem *)(pHba->msg_addr_virt+m); - - writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]); - writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]); - writel(1, &msg[2]); - writel(0, &msg[3]); - writel(0, &msg[4]); - writel(0, &msg[5]); - writel( dma_low(pHba->status_block_pa), &msg[6]); - writel( dma_high(pHba->status_block_pa), &msg[7]); - writel(sizeof(i2o_status_block), &msg[8]); // 88 bytes - - //post message - writel(m, pHba->post_port); - wmb(); - - while(status_block[87]!=0xff){ - if(time_after(jiffies,timeout)){ - printk(KERN_ERR"dpti%d: Get status timeout.\n", - pHba->unit); - return -ETIMEDOUT; - } - rmb(); - schedule_timeout_uninterruptible(1); - } - - // Set up our number of outbound and inbound messages - pHba->post_fifo_size = pHba->status_block->max_inbound_frames; - if (pHba->post_fifo_size > MAX_TO_IOP_MESSAGES) { - pHba->post_fifo_size = MAX_TO_IOP_MESSAGES; - } - - pHba->reply_fifo_size = pHba->status_block->max_outbound_frames; - if (pHba->reply_fifo_size > MAX_FROM_IOP_MESSAGES) { - pHba->reply_fifo_size = MAX_FROM_IOP_MESSAGES; - } - - // Calculate the Scatter Gather list size - if (dpt_dma64(pHba)) { - pHba->sg_tablesize - = ((pHba->status_block->inbound_frame_size * 4 - - 14 * sizeof(u32)) - / (sizeof(struct sg_simple_element) + sizeof(u32))); - } else { - pHba->sg_tablesize - = ((pHba->status_block->inbound_frame_size * 4 - - 12 * sizeof(u32)) - / sizeof(struct sg_simple_element)); - } - if (pHba->sg_tablesize > SG_LIST_ELEMENTS) { - pHba->sg_tablesize = SG_LIST_ELEMENTS; - } - - -#ifdef DEBUG - printk("dpti%d: State = ",pHba->unit); - switch(pHba->status_block->iop_state) { - case 0x01: - printk("INIT\n"); - break; - case 0x02: - printk("RESET\n"); - break; - case 0x04: - printk("HOLD\n"); - break; - case 0x05: - printk("READY\n"); - break; - case 0x08: - printk("OPERATIONAL\n"); - break; - case 0x10: - printk("FAILED\n"); - break; - case 0x11: - printk("FAULTED\n"); - break; - default: - printk("%x (unknown!!)\n",pHba->status_block->iop_state); - } -#endif - return 0; -} - -/* - * Get the IOP's Logical Configuration Table - */ -static int adpt_i2o_lct_get(adpt_hba* pHba) -{ - u32 msg[8]; - int ret; - u32 buf[16]; - - if ((pHba->lct_size == 0) || (pHba->lct == NULL)){ - pHba->lct_size = pHba->status_block->expected_lct_size; - } - do { - if (pHba->lct == NULL) { - pHba->lct = dma_alloc_coherent(&pHba->pDev->dev, - pHba->lct_size, &pHba->lct_pa, - GFP_ATOMIC); - if(pHba->lct == NULL) { - printk(KERN_CRIT "%s: Lct Get failed. Out of memory.\n", - pHba->name); - return -ENOMEM; - } - } - memset(pHba->lct, 0, pHba->lct_size); - - msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6; - msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID; - msg[2] = 0; - msg[3] = 0; - msg[4] = 0xFFFFFFFF; /* All devices */ - msg[5] = 0x00000000; /* Report now */ - msg[6] = 0xD0000000|pHba->lct_size; - msg[7] = (u32)pHba->lct_pa; - - if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 360))) { - printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n", - pHba->name, ret); - printk(KERN_ERR"Adaptec: Error Reading Hardware.\n"); - return ret; - } - - if ((pHba->lct->table_size << 2) > pHba->lct_size) { - pHba->lct_size = pHba->lct->table_size << 2; - dma_free_coherent(&pHba->pDev->dev, pHba->lct_size, - pHba->lct, pHba->lct_pa); - pHba->lct = NULL; - } - } while (pHba->lct == NULL); - - PDEBUG("%s: Hardware resource table read.\n", pHba->name); - - - // I2O_DPT_EXEC_IOP_BUFFERS_GROUP_NO; - if(adpt_i2o_query_scalar(pHba, 0 , 0x8000, -1, buf, sizeof(buf))>=0) { - pHba->FwDebugBufferSize = buf[1]; - pHba->FwDebugBuffer_P = ioremap(pHba->base_addr_phys + buf[0], - pHba->FwDebugBufferSize); - if (pHba->FwDebugBuffer_P) { - pHba->FwDebugFlags_P = pHba->FwDebugBuffer_P + - FW_DEBUG_FLAGS_OFFSET; - pHba->FwDebugBLEDvalue_P = pHba->FwDebugBuffer_P + - FW_DEBUG_BLED_OFFSET; - pHba->FwDebugBLEDflag_P = pHba->FwDebugBLEDvalue_P + 1; - pHba->FwDebugStrLength_P = pHba->FwDebugBuffer_P + - FW_DEBUG_STR_LENGTH_OFFSET; - pHba->FwDebugBuffer_P += buf[2]; - pHba->FwDebugFlags = 0; - } - } - - return 0; -} - -static int adpt_i2o_build_sys_table(void) -{ - adpt_hba* pHba = hba_chain; - int count = 0; - - if (sys_tbl) - dma_free_coherent(&pHba->pDev->dev, sys_tbl_len, - sys_tbl, sys_tbl_pa); - - sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs - (hba_count) * sizeof(struct i2o_sys_tbl_entry); - - sys_tbl = dma_alloc_coherent(&pHba->pDev->dev, - sys_tbl_len, &sys_tbl_pa, GFP_KERNEL); - if (!sys_tbl) { - printk(KERN_WARNING "SysTab Set failed. Out of memory.\n"); - return -ENOMEM; - } - - sys_tbl->num_entries = hba_count; - sys_tbl->version = I2OVERSION; - sys_tbl->change_ind = sys_tbl_ind++; - - for(pHba = hba_chain; pHba; pHba = pHba->next) { - u64 addr; - // Get updated Status Block so we have the latest information - if (adpt_i2o_status_get(pHba)) { - sys_tbl->num_entries--; - continue; // try next one - } - - sys_tbl->iops[count].org_id = pHba->status_block->org_id; - sys_tbl->iops[count].iop_id = pHba->unit + 2; - sys_tbl->iops[count].seg_num = 0; - sys_tbl->iops[count].i2o_version = pHba->status_block->i2o_version; - sys_tbl->iops[count].iop_state = pHba->status_block->iop_state; - sys_tbl->iops[count].msg_type = pHba->status_block->msg_type; - sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size; - sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ?? - sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities; - addr = pHba->base_addr_phys + 0x40; - sys_tbl->iops[count].inbound_low = dma_low(addr); - sys_tbl->iops[count].inbound_high = dma_high(addr); - - count++; - } - -#ifdef DEBUG -{ - u32 *table = (u32*)sys_tbl; - printk(KERN_DEBUG"sys_tbl_len=%d in 32bit words\n",(sys_tbl_len >>2)); - for(count = 0; count < (sys_tbl_len >>2); count++) { - printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", - count, table[count]); - } -} -#endif - - return 0; -} - - -/* - * Dump the information block associated with a given unit (TID) - */ - -static void adpt_i2o_report_hba_unit(adpt_hba* pHba, struct i2o_device *d) -{ - char buf[64]; - int unit = d->lct_data.tid; - - printk(KERN_INFO "TID %3.3d ", unit); - - if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 3, buf, 16)>=0) - { - buf[16]=0; - printk(" Vendor: %-12.12s", buf); - } - if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 4, buf, 16)>=0) - { - buf[16]=0; - printk(" Device: %-12.12s", buf); - } - if(adpt_i2o_query_scalar(pHba, unit, 0xF100, 6, buf, 8)>=0) - { - buf[8]=0; - printk(" Rev: %-12.12s\n", buf); - } -#ifdef DEBUG - printk(KERN_INFO "\tClass: %.21s\n", adpt_i2o_get_class_name(d->lct_data.class_id)); - printk(KERN_INFO "\tSubclass: 0x%04X\n", d->lct_data.sub_class); - printk(KERN_INFO "\tFlags: "); - - if(d->lct_data.device_flags&(1<<0)) - printk("C"); // ConfigDialog requested - if(d->lct_data.device_flags&(1<<1)) - printk("U"); // Multi-user capable - if(!(d->lct_data.device_flags&(1<<4))) - printk("P"); // Peer service enabled! - if(!(d->lct_data.device_flags&(1<<5))) - printk("M"); // Mgmt service enabled! - printk("\n"); -#endif -} - -#ifdef DEBUG -/* - * Do i2o class name lookup - */ -static const char *adpt_i2o_get_class_name(int class) -{ - int idx = 16; - static char *i2o_class_name[] = { - "Executive", - "Device Driver Module", - "Block Device", - "Tape Device", - "LAN Interface", - "WAN Interface", - "Fibre Channel Port", - "Fibre Channel Device", - "SCSI Device", - "ATE Port", - "ATE Device", - "Floppy Controller", - "Floppy Device", - "Secondary Bus Port", - "Peer Transport Agent", - "Peer Transport", - "Unknown" - }; - - switch(class&0xFFF) { - case I2O_CLASS_EXECUTIVE: - idx = 0; break; - case I2O_CLASS_DDM: - idx = 1; break; - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - idx = 2; break; - case I2O_CLASS_SEQUENTIAL_STORAGE: - idx = 3; break; - case I2O_CLASS_LAN: - idx = 4; break; - case I2O_CLASS_WAN: - idx = 5; break; - case I2O_CLASS_FIBRE_CHANNEL_PORT: - idx = 6; break; - case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: - idx = 7; break; - case I2O_CLASS_SCSI_PERIPHERAL: - idx = 8; break; - case I2O_CLASS_ATE_PORT: - idx = 9; break; - case I2O_CLASS_ATE_PERIPHERAL: - idx = 10; break; - case I2O_CLASS_FLOPPY_CONTROLLER: - idx = 11; break; - case I2O_CLASS_FLOPPY_DEVICE: - idx = 12; break; - case I2O_CLASS_BUS_ADAPTER_PORT: - idx = 13; break; - case I2O_CLASS_PEER_TRANSPORT_AGENT: - idx = 14; break; - case I2O_CLASS_PEER_TRANSPORT: - idx = 15; break; - } - return i2o_class_name[idx]; -} -#endif - - -static s32 adpt_i2o_hrt_get(adpt_hba* pHba) -{ - u32 msg[6]; - int ret, size = sizeof(i2o_hrt); - - do { - if (pHba->hrt == NULL) { - pHba->hrt = dma_alloc_coherent(&pHba->pDev->dev, - size, &pHba->hrt_pa, GFP_KERNEL); - if (pHba->hrt == NULL) { - printk(KERN_CRIT "%s: Hrt Get failed; Out of memory.\n", pHba->name); - return -ENOMEM; - } - } - - msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4; - msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID; - msg[2]= 0; - msg[3]= 0; - msg[4]= (0xD0000000 | size); /* Simple transaction */ - msg[5]= (u32)pHba->hrt_pa; /* Dump it here */ - - if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg),20))) { - printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n", pHba->name, ret); - return ret; - } - - if (pHba->hrt->num_entries * pHba->hrt->entry_len << 2 > size) { - int newsize = pHba->hrt->num_entries * pHba->hrt->entry_len << 2; - dma_free_coherent(&pHba->pDev->dev, size, - pHba->hrt, pHba->hrt_pa); - size = newsize; - pHba->hrt = NULL; - } - } while(pHba->hrt == NULL); - return 0; -} - -/* - * Query one scalar group value or a whole scalar group. - */ -static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid, - int group, int field, void *buf, int buflen) -{ - u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field }; - u8 *opblk_va; - dma_addr_t opblk_pa; - u8 *resblk_va; - dma_addr_t resblk_pa; - - int size; - - /* 8 bytes for header */ - resblk_va = dma_alloc_coherent(&pHba->pDev->dev, - sizeof(u8) * (8 + buflen), &resblk_pa, GFP_KERNEL); - if (resblk_va == NULL) { - printk(KERN_CRIT "%s: query scalar failed; Out of memory.\n", pHba->name); - return -ENOMEM; - } - - opblk_va = dma_alloc_coherent(&pHba->pDev->dev, - sizeof(opblk), &opblk_pa, GFP_KERNEL); - if (opblk_va == NULL) { - dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen), - resblk_va, resblk_pa); - printk(KERN_CRIT "%s: query operation failed; Out of memory.\n", - pHba->name); - return -ENOMEM; - } - if (field == -1) /* whole group */ - opblk[4] = -1; - - memcpy(opblk_va, opblk, sizeof(opblk)); - size = adpt_i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, pHba, tid, - opblk_va, opblk_pa, sizeof(opblk), - resblk_va, resblk_pa, sizeof(u8)*(8+buflen)); - dma_free_coherent(&pHba->pDev->dev, sizeof(opblk), opblk_va, opblk_pa); - if (size == -ETIME) { - dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen), - resblk_va, resblk_pa); - printk(KERN_WARNING "%s: issue params failed; Timed out.\n", pHba->name); - return -ETIME; - } else if (size == -EINTR) { - dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen), - resblk_va, resblk_pa); - printk(KERN_WARNING "%s: issue params failed; Interrupted.\n", pHba->name); - return -EINTR; - } - - memcpy(buf, resblk_va+8, buflen); /* cut off header */ - - dma_free_coherent(&pHba->pDev->dev, sizeof(u8) * (8+buflen), - resblk_va, resblk_pa); - if (size < 0) - return size; - - return buflen; -} - - -/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET - * - * This function can be used for all UtilParamsGet/Set operations. - * The OperationBlock is given in opblk-buffer, - * and results are returned in resblk-buffer. - * Note that the minimum sized resblk is 8 bytes and contains - * ResultCount, ErrorInfoSize, BlockStatus and BlockSize. - */ -static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid, - void *opblk_va, dma_addr_t opblk_pa, int oplen, - void *resblk_va, dma_addr_t resblk_pa, int reslen) -{ - u32 msg[9]; - u32 *res = (u32 *)resblk_va; - int wait_status; - - msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5; - msg[1] = cmd << 24 | HOST_TID << 12 | tid; - msg[2] = 0; - msg[3] = 0; - msg[4] = 0; - msg[5] = 0x54000000 | oplen; /* OperationBlock */ - msg[6] = (u32)opblk_pa; - msg[7] = 0xD0000000 | reslen; /* ResultBlock */ - msg[8] = (u32)resblk_pa; - - if ((wait_status = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 20))) { - printk("adpt_i2o_issue_params: post_wait failed (%p)\n", resblk_va); - return wait_status; /* -DetailedStatus */ - } - - if (res[1]&0x00FF0000) { /* BlockStatus != SUCCESS */ - printk(KERN_WARNING "%s: %s - Error:\n ErrorInfoSize = 0x%02x, " - "BlockStatus = 0x%02x, BlockSize = 0x%04x\n", - pHba->name, - (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET" - : "PARAMS_GET", - res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF); - return -((res[1] >> 16) & 0xFF); /* -BlockStatus */ - } - - return 4 + ((res[1] & 0x0000FFFF) << 2); /* bytes used in resblk */ -} - - -static s32 adpt_i2o_quiesce_hba(adpt_hba* pHba) -{ - u32 msg[4]; - int ret; - - adpt_i2o_status_get(pHba); - - /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */ - - if((pHba->status_block->iop_state != ADAPTER_STATE_READY) && - (pHba->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)){ - return 0; - } - - msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID; - msg[2] = 0; - msg[3] = 0; - - if((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) { - printk(KERN_INFO"dpti%d: Unable to quiesce (status=%#x).\n", - pHba->unit, -ret); - } else { - printk(KERN_INFO"dpti%d: Quiesced.\n",pHba->unit); - } - - adpt_i2o_status_get(pHba); - return ret; -} - - -/* - * Enable IOP. Allows the IOP to resume external operations. - */ -static int adpt_i2o_enable_hba(adpt_hba* pHba) -{ - u32 msg[4]; - int ret; - - adpt_i2o_status_get(pHba); - if(!pHba->status_block){ - return -ENOMEM; - } - /* Enable only allowed on READY state */ - if(pHba->status_block->iop_state == ADAPTER_STATE_OPERATIONAL) - return 0; - - if(pHba->status_block->iop_state != ADAPTER_STATE_READY) - return -EINVAL; - - msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID; - msg[2]= 0; - msg[3]= 0; - - if ((ret = adpt_i2o_post_wait(pHba, msg, sizeof(msg), 240))) { - printk(KERN_WARNING"%s: Could not enable (status=%#10x).\n", - pHba->name, ret); - } else { - PDEBUG("%s: Enabled.\n", pHba->name); - } - - adpt_i2o_status_get(pHba); - return ret; -} - - -static int adpt_i2o_systab_send(adpt_hba* pHba) -{ - u32 msg[12]; - int ret; - - msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6; - msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID; - msg[2] = 0; - msg[3] = 0; - msg[4] = (0<<16) | ((pHba->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */ - msg[5] = 0; /* Segment 0 */ - - /* - * Provide three SGL-elements: - * System table (SysTab), Private memory space declaration and - * Private i/o space declaration - */ - msg[6] = 0x54000000 | sys_tbl_len; - msg[7] = (u32)sys_tbl_pa; - msg[8] = 0x54000000 | 0; - msg[9] = 0; - msg[10] = 0xD4000000 | 0; - msg[11] = 0; - - if ((ret=adpt_i2o_post_wait(pHba, msg, sizeof(msg), 120))) { - printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n", - pHba->name, ret); - } -#ifdef DEBUG - else { - PINFO("%s: SysTab set.\n", pHba->name); - } -#endif - - return ret; -} - - -/*============================================================================ - * - *============================================================================ - */ - - -#ifdef UARTDELAY - -static static void adpt_delay(int millisec) -{ - int i; - for (i = 0; i < millisec; i++) { - udelay(1000); /* delay for one millisecond */ - } -} - -#endif - -static struct scsi_host_template driver_template = { - .module = THIS_MODULE, - .name = "dpt_i2o", - .proc_name = "dpt_i2o", - .show_info = adpt_show_info, - .info = adpt_info, - .queuecommand = adpt_queue, - .eh_abort_handler = adpt_abort, - .eh_device_reset_handler = adpt_device_reset, - .eh_bus_reset_handler = adpt_bus_reset, - .eh_host_reset_handler = adpt_reset, - .bios_param = adpt_bios_param, - .slave_configure = adpt_slave_configure, - .can_queue = MAX_TO_IOP_MESSAGES, - .this_id = 7, -}; - -static int __init adpt_init(void) -{ - int error; - adpt_hba *pHba, *next; - - printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n"); - - error = adpt_detect(&driver_template); - if (error < 0) - return error; - if (hba_chain == NULL) - return -ENODEV; - - for (pHba = hba_chain; pHba; pHba = pHba->next) { - error = scsi_add_host(pHba->host, &pHba->pDev->dev); - if (error) - goto fail; - scsi_scan_host(pHba->host); - } - return 0; -fail: - for (pHba = hba_chain; pHba; pHba = next) { - next = pHba->next; - scsi_remove_host(pHba->host); - } - return error; -} - -static void __exit adpt_exit(void) -{ - adpt_hba *pHba, *next; - - for (pHba = hba_chain; pHba; pHba = next) { - next = pHba->next; - adpt_release(pHba); - } -} - -module_init(adpt_init); -module_exit(adpt_exit); - -MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h deleted file mode 100644 index 8a079e8d7f65..000000000000 --- a/drivers/scsi/dpti.h +++ /dev/null @@ -1,331 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/*************************************************************************** - dpti.h - description - ------------------- - begin : Thu Sep 7 2000 - copyright : (C) 2001 by Adaptec - - See Documentation/scsi/dpti.rst for history, notes, license info - and credits - ***************************************************************************/ - -/*************************************************************************** - * * - * * - ***************************************************************************/ - -#ifndef _DPT_H -#define _DPT_H - -#define MAX_TO_IOP_MESSAGES (255) -#define MAX_FROM_IOP_MESSAGES (255) - - -/* - * SCSI interface function Prototypes - */ - -static int adpt_detect(struct scsi_host_template * sht); -static int adpt_queue(struct Scsi_Host *h, struct scsi_cmnd * cmd); -static int adpt_abort(struct scsi_cmnd * cmd); -static int adpt_reset(struct scsi_cmnd* cmd); -static int adpt_slave_configure(struct scsi_device *); - -static const char *adpt_info(struct Scsi_Host *pSHost); -static int adpt_bios_param(struct scsi_device * sdev, struct block_device *dev, - sector_t, int geom[]); - -static int adpt_bus_reset(struct scsi_cmnd* cmd); -static int adpt_device_reset(struct scsi_cmnd* cmd); - - -/* - * struct scsi_host_template (see scsi/scsi_host.h) - */ - -#define DPT_DRIVER_NAME "Adaptec I2O RAID" - -#ifndef HOSTS_C - -#include "dpt/sys_info.h" -#include <linux/wait.h> -#include "dpt/dpti_i2o.h" -#include "dpt/dpti_ioctl.h" - -#define DPT_I2O_VERSION "2.4 Build 5go" -#define DPT_VERSION 2 -#define DPT_REVISION '4' -#define DPT_SUBREVISION '5' -#define DPT_BETA "" -#define DPT_MONTH 8 -#define DPT_DAY 7 -#define DPT_YEAR (2001-1980) - -#define DPT_DRIVER "dpt_i2o" -#define DPTI_I2O_MAJOR (151) -#define DPT_ORGANIZATION_ID (0x1B) /* For Private Messages */ -#define DPTI_MAX_HBA (16) -#define MAX_CHANNEL (5) // Maximum Channel # Supported -#define MAX_ID (128) // Maximum Target ID Supported - -/* Sizes in 4 byte words */ -#define REPLY_FRAME_SIZE (17) -#define MAX_MESSAGE_SIZE (128) -#define SG_LIST_ELEMENTS (56) - -#define EMPTY_QUEUE 0xffffffff -#define I2O_INTERRUPT_PENDING_B (0x08) - -#define PCI_DPT_VENDOR_ID (0x1044) // DPT PCI Vendor ID -#define PCI_DPT_DEVICE_ID (0xA501) // DPT PCI I2O Device ID -#define PCI_DPT_RAPTOR_DEVICE_ID (0xA511) - -/* Debugging macro from Linux Device Drivers - Rubini */ -#undef PDEBUG -#ifdef DEBUG -//TODO add debug level switch -# define PDEBUG(fmt, args...) printk(KERN_DEBUG "dpti: " fmt, ##args) -# define PDEBUGV(fmt, args...) printk(KERN_DEBUG "dpti: " fmt, ##args) -#else -# define PDEBUG(fmt, args...) /* not debugging: nothing */ -# define PDEBUGV(fmt, args...) /* not debugging: nothing */ -#endif - -#define PERROR(fmt, args...) printk(KERN_ERR fmt, ##args) -#define PWARN(fmt, args...) printk(KERN_WARNING fmt, ##args) -#define PINFO(fmt, args...) printk(KERN_INFO fmt, ##args) -#define PCRIT(fmt, args...) printk(KERN_CRIT fmt, ##args) - -#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)) - -// Command timeouts -#define FOREVER (0) -#define TMOUT_INQUIRY (20) -#define TMOUT_FLUSH (360/45) -#define TMOUT_ABORT (30) -#define TMOUT_SCSI (300) -#define TMOUT_IOPRESET (360) -#define TMOUT_GETSTATUS (15) -#define TMOUT_INITOUTBOUND (15) -#define TMOUT_LCT (360) - - -#define I2O_SCSI_DEVICE_DSC_MASK 0x00FF - -#define I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION 0x000A - -#define I2O_SCSI_DSC_MASK 0xFF00 -#define I2O_SCSI_DSC_SUCCESS 0x0000 -#define I2O_SCSI_DSC_REQUEST_ABORTED 0x0200 -#define I2O_SCSI_DSC_UNABLE_TO_ABORT 0x0300 -#define I2O_SCSI_DSC_COMPLETE_WITH_ERROR 0x0400 -#define I2O_SCSI_DSC_ADAPTER_BUSY 0x0500 -#define I2O_SCSI_DSC_REQUEST_INVALID 0x0600 -#define I2O_SCSI_DSC_PATH_INVALID 0x0700 -#define I2O_SCSI_DSC_DEVICE_NOT_PRESENT 0x0800 -#define I2O_SCSI_DSC_UNABLE_TO_TERMINATE 0x0900 -#define I2O_SCSI_DSC_SELECTION_TIMEOUT 0x0A00 -#define I2O_SCSI_DSC_COMMAND_TIMEOUT 0x0B00 -#define I2O_SCSI_DSC_MR_MESSAGE_RECEIVED 0x0D00 -#define I2O_SCSI_DSC_SCSI_BUS_RESET 0x0E00 -#define I2O_SCSI_DSC_PARITY_ERROR_FAILURE 0x0F00 -#define I2O_SCSI_DSC_AUTOSENSE_FAILED 0x1000 -#define I2O_SCSI_DSC_NO_ADAPTER 0x1100 -#define I2O_SCSI_DSC_DATA_OVERRUN 0x1200 -#define I2O_SCSI_DSC_UNEXPECTED_BUS_FREE 0x1300 -#define I2O_SCSI_DSC_SEQUENCE_FAILURE 0x1400 -#define I2O_SCSI_DSC_REQUEST_LENGTH_ERROR 0x1500 -#define I2O_SCSI_DSC_PROVIDE_FAILURE 0x1600 -#define I2O_SCSI_DSC_BDR_MESSAGE_SENT 0x1700 -#define I2O_SCSI_DSC_REQUEST_TERMINATED 0x1800 -#define I2O_SCSI_DSC_IDE_MESSAGE_SENT 0x3300 -#define I2O_SCSI_DSC_RESOURCE_UNAVAILABLE 0x3400 -#define I2O_SCSI_DSC_UNACKNOWLEDGED_EVENT 0x3500 -#define I2O_SCSI_DSC_MESSAGE_RECEIVED 0x3600 -#define I2O_SCSI_DSC_INVALID_CDB 0x3700 -#define I2O_SCSI_DSC_LUN_INVALID 0x3800 -#define I2O_SCSI_DSC_SCSI_TID_INVALID 0x3900 -#define I2O_SCSI_DSC_FUNCTION_UNAVAILABLE 0x3A00 -#define I2O_SCSI_DSC_NO_NEXUS 0x3B00 -#define I2O_SCSI_DSC_SCSI_IID_INVALID 0x3C00 -#define I2O_SCSI_DSC_CDB_RECEIVED 0x3D00 -#define I2O_SCSI_DSC_LUN_ALREADY_ENABLED 0x3E00 -#define I2O_SCSI_DSC_BUS_BUSY 0x3F00 -#define I2O_SCSI_DSC_QUEUE_FROZEN 0x4000 - - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#define HBA_FLAGS_INSTALLED_B 0x00000001 // Adapter Was Installed -#define HBA_FLAGS_BLINKLED_B 0x00000002 // Adapter In Blink LED State -#define HBA_FLAGS_IN_RESET 0x00000040 /* in reset */ -#define HBA_HOSTRESET_FAILED 0x00000080 /* adpt_resethost failed */ - - -// Device state flags -#define DPTI_DEV_ONLINE 0x00 -#define DPTI_DEV_UNSCANNED 0x01 -#define DPTI_DEV_RESET 0x02 -#define DPTI_DEV_OFFLINE 0x04 - - -struct adpt_device { - struct adpt_device* next_lun; - u32 flags; - u32 type; - u32 capacity; - u32 block_size; - u8 scsi_channel; - u8 scsi_id; - u64 scsi_lun; - u8 state; - u16 tid; - struct i2o_device* pI2o_dev; - struct scsi_device *pScsi_dev; -}; - -struct adpt_channel { - struct adpt_device* device[MAX_ID]; /* used as an array of 128 scsi ids */ - u8 scsi_id; - u8 type; - u16 tid; - u32 state; - struct i2o_device* pI2o_dev; -}; - -// HBA state flags -#define DPTI_STATE_RESET (0x01) - -typedef struct _adpt_hba { - struct _adpt_hba *next; - struct pci_dev *pDev; - struct Scsi_Host *host; - u32 state; - spinlock_t state_lock; - int unit; - int host_no; /* SCSI host number */ - u8 initialized; - u8 in_use; /* is the management node open*/ - - char name[32]; - char detail[55]; - - void __iomem *base_addr_virt; - void __iomem *msg_addr_virt; - ulong base_addr_phys; - void __iomem *post_port; - void __iomem *reply_port; - void __iomem *irq_mask; - u16 post_count; - u32 post_fifo_size; - u32 reply_fifo_size; - u32* reply_pool; - dma_addr_t reply_pool_pa; - u32 sg_tablesize; // Scatter/Gather List Size. - u8 top_scsi_channel; - u8 top_scsi_id; - u64 top_scsi_lun; - u8 dma64; - - i2o_status_block* status_block; - dma_addr_t status_block_pa; - i2o_hrt* hrt; - dma_addr_t hrt_pa; - i2o_lct* lct; - dma_addr_t lct_pa; - uint lct_size; - struct i2o_device* devices; - struct adpt_channel channel[MAX_CHANNEL]; - struct proc_dir_entry* proc_entry; /* /proc dir */ - - void __iomem *FwDebugBuffer_P; // Virtual Address Of FW Debug Buffer - u32 FwDebugBufferSize; // FW Debug Buffer Size In Bytes - void __iomem *FwDebugStrLength_P;// Virtual Addr Of FW Debug String Len - void __iomem *FwDebugFlags_P; // Virtual Address Of FW Debug Flags - void __iomem *FwDebugBLEDflag_P;// Virtual Addr Of FW Debug BLED - void __iomem *FwDebugBLEDvalue_P;// Virtual Addr Of FW Debug BLED - u32 FwDebugFlags; - u32 *ioctl_reply_context[4]; -} adpt_hba; - -struct sg_simple_element { - u32 flag_count; - u32 addr_bus; -}; - -/* - * Function Prototypes - */ - -static void adpt_i2o_sys_shutdown(void); -static int adpt_init(void); -static int adpt_i2o_build_sys_table(void); -static irqreturn_t adpt_isr(int irq, void *dev_id); - -static void adpt_i2o_report_hba_unit(adpt_hba* pHba, struct i2o_device *d); -static int adpt_i2o_query_scalar(adpt_hba* pHba, int tid, - int group, int field, void *buf, int buflen); -#ifdef DEBUG -static const char *adpt_i2o_get_class_name(int class); -#endif -static int adpt_i2o_issue_params(int cmd, adpt_hba* pHba, int tid, - void *opblk, dma_addr_t opblk_pa, int oplen, - void *resblk, dma_addr_t resblk_pa, int reslen); -static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout); -static int adpt_i2o_lct_get(adpt_hba* pHba); -static int adpt_i2o_parse_lct(adpt_hba* pHba); -static int adpt_i2o_activate_hba(adpt_hba* pHba); -static int adpt_i2o_enable_hba(adpt_hba* pHba); -static int adpt_i2o_install_device(adpt_hba* pHba, struct i2o_device *d); -static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len); -static s32 adpt_i2o_quiesce_hba(adpt_hba* pHba); -static s32 adpt_i2o_status_get(adpt_hba* pHba); -static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba); -static s32 adpt_i2o_hrt_get(adpt_hba* pHba); -static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice); -static void adpt_i2o_scsi_complete(void __iomem *reply, struct scsi_cmnd *cmd); -static s32 adpt_scsi_host_alloc(adpt_hba* pHba,struct scsi_host_template * sht); -static s32 adpt_hba_reset(adpt_hba* pHba); -static s32 adpt_i2o_reset_hba(adpt_hba* pHba); -static s32 adpt_rescan(adpt_hba* pHba); -static s32 adpt_i2o_reparse_lct(adpt_hba* pHba); -static s32 adpt_send_nop(adpt_hba*pHba,u32 m); -static void adpt_i2o_delete_hba(adpt_hba* pHba); -static void adpt_inquiry(adpt_hba* pHba); -static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun); -static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ; -static int adpt_i2o_online_hba(adpt_hba* pHba); -static void adpt_i2o_post_wait_complete(u32, int); -static int adpt_i2o_systab_send(adpt_hba* pHba); - -static int adpt_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg); -static int adpt_open(struct inode *inode, struct file *file); -static int adpt_close(struct inode *inode, struct file *file); - - -#ifdef UARTDELAY -static void adpt_delay(int millisec); -#endif - -#define PRINT_BUFFER_SIZE 512 - -#define HBA_FLAGS_DBG_FLAGS_MASK 0xffff0000 // Mask for debug flags -#define HBA_FLAGS_DBG_KERNEL_PRINT_B 0x00010000 // Kernel Debugger Print -#define HBA_FLAGS_DBG_FW_PRINT_B 0x00020000 // Firmware Debugger Print -#define HBA_FLAGS_DBG_FUNCTION_ENTRY_B 0x00040000 // Function Entry Point -#define HBA_FLAGS_DBG_FUNCTION_EXIT_B 0x00080000 // Function Exit -#define HBA_FLAGS_DBG_ERROR_B 0x00100000 // Error Conditions -#define HBA_FLAGS_DBG_INIT_B 0x00200000 // Init Prints -#define HBA_FLAGS_DBG_OS_COMMANDS_B 0x00400000 // OS Command Info -#define HBA_FLAGS_DBG_SCAN_B 0x00800000 // Device Scan - -#define FW_DEBUG_STR_LENGTH_OFFSET 0 -#define FW_DEBUG_FLAGS_OFFSET 4 -#define FW_DEBUG_BLED_OFFSET 8 - -#define FW_DEBUG_FLAGS_NO_HEADERS_B 0x01 -#endif /* !HOSTS_C */ -#endif /* _DPT_H */
From: Jason Gunthorpe jgg@nvidia.com
mainline inclusion from mainline-v5.15-rc4 commit 305d568b72f17f674155a2a8275f865f207b3808 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6X49E CVE: CVE-2023-2176
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
---------------------------
The FSM can run in a circle allowing rdma_resolve_ip() to be called twice on the same id_priv. While this cannot happen without going through the work, it violates the invariant that the same address resolution background request cannot be active twice.
CPU 1 CPU 2
rdma_resolve_addr(): RDMA_CM_IDLE -> RDMA_CM_ADDR_QUERY rdma_resolve_ip(addr_handler) #1
process_one_req(): for #1 addr_handler(): RDMA_CM_ADDR_QUERY -> RDMA_CM_ADDR_BOUND mutex_unlock(&id_priv->handler_mutex); [.. handler still running ..]
rdma_resolve_addr(): RDMA_CM_ADDR_BOUND -> RDMA_CM_ADDR_QUERY rdma_resolve_ip(addr_handler) !! two requests are now on the req_list
rdma_destroy_id(): destroy_id_handler_unlock(): _destroy_id(): cma_cancel_operation(): rdma_addr_cancel()
// process_one_req() self removes it spin_lock_bh(&lock); cancel_delayed_work(&req->work); if (!list_empty(&req->list)) == true
! rdma_addr_cancel() returns after process_on_req #1 is done
kfree(id_priv)
process_one_req(): for #2 addr_handler(): mutex_lock(&id_priv->handler_mutex); !! Use after free on id_priv
rdma_addr_cancel() expects there to be one req on the list and only cancels the first one. The self-removal behavior of the work only happens after the handler has returned. This yields a situations where the req_list can have two reqs for the same "handle" but rdma_addr_cancel() only cancels the first one.
The second req remains active beyond rdma_destroy_id() and will use-after-free id_priv once it inevitably triggers.
Fix this by remembering if the id_priv has called rdma_resolve_ip() and always cancel before calling it again. This ensures the req_list never gets more than one item in it and doesn't cost anything in the normal flow that never uses this strange error path.
Link: https://lore.kernel.org/r/0-v1-3bc675b8006d+22-syz_cancel_uaf_jgg@nvidia.com Cc: stable@vger.kernel.org Fixes: e51060f08a61 ("IB: IP address based RDMA connection manager") Reported-by: syzbot+dc3dfba010d7671e05f5@syzkaller.appspotmail.com Signed-off-by: Jason Gunthorpe jgg@nvidia.com (cherry picked from commit 305d568b72f17f674155a2a8275f865f207b3808) Signed-off-by: Liu Jian liujian56@huawei.com
Conflicts: drivers/infiniband/core/cma_priv.h Reviewed-by: Yue Haibing yuehaibing@huawei.com Reviewed-by: Wang Weiyang wangweiyang2@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- drivers/infiniband/core/cma.c | 23 +++++++++++++++++++++++ drivers/infiniband/core/cma_priv.h | 1 + 2 files changed, 24 insertions(+)
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index b5fa19a033c0..d6d58669e5c3 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1793,6 +1793,14 @@ static void cma_cancel_operation(struct rdma_id_private *id_priv, { switch (state) { case RDMA_CM_ADDR_QUERY: + /* + * We can avoid doing the rdma_addr_cancel() based on state, + * only RDMA_CM_ADDR_QUERY has a work that could still execute. + * Notice that the addr_handler work could still be exiting + * outside this state, however due to the interaction with the + * handler_mutex the work is guaranteed not to touch id_priv + * during exit. + */ rdma_addr_cancel(&id_priv->id.route.addr.dev_addr); break; case RDMA_CM_ROUTE_QUERY: @@ -3402,6 +3410,21 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, if (dst_addr->sa_family == AF_IB) { ret = cma_resolve_ib_addr(id_priv); } else { + /* + * The FSM can return back to RDMA_CM_ADDR_BOUND after + * rdma_resolve_ip() is called, eg through the error + * path in addr_handler(). If this happens the existing + * request must be canceled before issuing a new one. + * Since canceling a request is a bit slow and this + * oddball path is rare, keep track once a request has + * been issued. The track turns out to be a permanent + * state since this is the only cancel as it is + * immediately before rdma_resolve_ip(). + */ + if (id_priv->used_resolve_ip) + rdma_addr_cancel(&id->route.addr.dev_addr); + else + id_priv->used_resolve_ip = 1; ret = rdma_resolve_ip(cma_src_addr(id_priv), dst_addr, &id->route.addr.dev_addr, timeout_ms, addr_handler, diff --git a/drivers/infiniband/core/cma_priv.h b/drivers/infiniband/core/cma_priv.h index caece96ebcf5..b53f4fa5e3fb 100644 --- a/drivers/infiniband/core/cma_priv.h +++ b/drivers/infiniband/core/cma_priv.h @@ -89,6 +89,7 @@ struct rdma_id_private { u8 reuseaddr; u8 afonly; u8 timeout; + u8 used_resolve_ip; enum ib_gid_type gid_type;
/*
From: Patrisious Haddad phaddad@nvidia.com
mainline inclusion from mainline-v6.3-rc1 commit 8d037973d48c026224ab285e6a06985ccac6f7bf category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6X49E CVE: CVE-2023-2176
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
---------------------------
Refactor rdma_bind_addr function so that it doesn't require that the cma destination address be changed before calling it.
So now it will update the destination address internally only when it is really needed and after passing all the required checks.
Which in turn results in a cleaner and more sensible call and error handling flows for the functions that call it directly or indirectly.
Signed-off-by: Patrisious Haddad phaddad@nvidia.com Reported-by: Wei Chen harperchen1110@gmail.com Reviewed-by: Mark Zhang markzhang@nvidia.com Link: https://lore.kernel.org/r/3d0e9a2fd62bc10ba02fed1c7c48a48638952320.167281927... Signed-off-by: Leon Romanovsky leon@kernel.org (cherry picked from commit 8d037973d48c026224ab285e6a06985ccac6f7bf) Signed-off-by: Liu Jian liujian56@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Reviewed-by: Wang Weiyang wangweiyang2@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- drivers/infiniband/core/cma.c | 253 +++++++++++++++++----------------- 1 file changed, 130 insertions(+), 123 deletions(-)
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index d6d58669e5c3..57c74b9ee3e9 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -3326,121 +3326,6 @@ static int cma_resolve_ib_addr(struct rdma_id_private *id_priv) return ret; }
-static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, - const struct sockaddr *dst_addr) -{ - struct sockaddr_storage zero_sock = {}; - - if (src_addr && src_addr->sa_family) - return rdma_bind_addr(id, src_addr); - - /* - * When the src_addr is not specified, automatically supply an any addr - */ - zero_sock.ss_family = dst_addr->sa_family; - if (IS_ENABLED(CONFIG_IPV6) && dst_addr->sa_family == AF_INET6) { - struct sockaddr_in6 *src_addr6 = - (struct sockaddr_in6 *)&zero_sock; - struct sockaddr_in6 *dst_addr6 = - (struct sockaddr_in6 *)dst_addr; - - src_addr6->sin6_scope_id = dst_addr6->sin6_scope_id; - if (ipv6_addr_type(&dst_addr6->sin6_addr) & IPV6_ADDR_LINKLOCAL) - id->route.addr.dev_addr.bound_dev_if = - dst_addr6->sin6_scope_id; - } else if (dst_addr->sa_family == AF_IB) { - ((struct sockaddr_ib *)&zero_sock)->sib_pkey = - ((struct sockaddr_ib *)dst_addr)->sib_pkey; - } - return rdma_bind_addr(id, (struct sockaddr *)&zero_sock); -} - -/* - * If required, resolve the source address for bind and leave the id_priv in - * state RDMA_CM_ADDR_BOUND. This oddly uses the state to determine the prior - * calls made by ULP, a previously bound ID will not be re-bound and src_addr is - * ignored. - */ -static int resolve_prepare_src(struct rdma_id_private *id_priv, - struct sockaddr *src_addr, - const struct sockaddr *dst_addr) -{ - int ret; - - memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr)); - if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) { - /* For a well behaved ULP state will be RDMA_CM_IDLE */ - ret = cma_bind_addr(&id_priv->id, src_addr, dst_addr); - if (ret) - goto err_dst; - if (WARN_ON(!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, - RDMA_CM_ADDR_QUERY))) { - ret = -EINVAL; - goto err_dst; - } - } - - if (cma_family(id_priv) != dst_addr->sa_family) { - ret = -EINVAL; - goto err_state; - } - return 0; - -err_state: - cma_comp_exch(id_priv, RDMA_CM_ADDR_QUERY, RDMA_CM_ADDR_BOUND); -err_dst: - memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr)); - return ret; -} - -int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, - const struct sockaddr *dst_addr, unsigned long timeout_ms) -{ - struct rdma_id_private *id_priv = - container_of(id, struct rdma_id_private, id); - int ret; - - ret = resolve_prepare_src(id_priv, src_addr, dst_addr); - if (ret) - return ret; - - if (cma_any_addr(dst_addr)) { - ret = cma_resolve_loopback(id_priv); - } else { - if (dst_addr->sa_family == AF_IB) { - ret = cma_resolve_ib_addr(id_priv); - } else { - /* - * The FSM can return back to RDMA_CM_ADDR_BOUND after - * rdma_resolve_ip() is called, eg through the error - * path in addr_handler(). If this happens the existing - * request must be canceled before issuing a new one. - * Since canceling a request is a bit slow and this - * oddball path is rare, keep track once a request has - * been issued. The track turns out to be a permanent - * state since this is the only cancel as it is - * immediately before rdma_resolve_ip(). - */ - if (id_priv->used_resolve_ip) - rdma_addr_cancel(&id->route.addr.dev_addr); - else - id_priv->used_resolve_ip = 1; - ret = rdma_resolve_ip(cma_src_addr(id_priv), dst_addr, - &id->route.addr.dev_addr, - timeout_ms, addr_handler, - false, id_priv); - } - } - if (ret) - goto err; - - return 0; -err: - cma_comp_exch(id_priv, RDMA_CM_ADDR_QUERY, RDMA_CM_ADDR_BOUND); - return ret; -} -EXPORT_SYMBOL(rdma_resolve_addr); - int rdma_set_reuseaddr(struct rdma_cm_id *id, int reuse) { struct rdma_id_private *id_priv; @@ -3843,27 +3728,26 @@ int rdma_listen(struct rdma_cm_id *id, int backlog) } EXPORT_SYMBOL(rdma_listen);
-int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) +static int rdma_bind_addr_dst(struct rdma_id_private *id_priv, + struct sockaddr *addr, const struct sockaddr *daddr) { - struct rdma_id_private *id_priv; + struct sockaddr *id_daddr; int ret; - struct sockaddr *daddr;
if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6 && addr->sa_family != AF_IB) return -EAFNOSUPPORT;
- id_priv = container_of(id, struct rdma_id_private, id); if (!cma_comp_exch(id_priv, RDMA_CM_IDLE, RDMA_CM_ADDR_BOUND)) return -EINVAL;
- ret = cma_check_linklocal(&id->route.addr.dev_addr, addr); + ret = cma_check_linklocal(&id_priv->id.route.addr.dev_addr, addr); if (ret) goto err1;
memcpy(cma_src_addr(id_priv), addr, rdma_addr_size(addr)); if (!cma_any_addr(addr)) { - ret = cma_translate_addr(addr, &id->route.addr.dev_addr); + ret = cma_translate_addr(addr, &id_priv->id.route.addr.dev_addr); if (ret) goto err1;
@@ -3883,8 +3767,10 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) } #endif } - daddr = cma_dst_addr(id_priv); - daddr->sa_family = addr->sa_family; + id_daddr = cma_dst_addr(id_priv); + if (daddr != id_daddr) + memcpy(id_daddr, daddr, rdma_addr_size(addr)); + id_daddr->sa_family = addr->sa_family;
ret = cma_get_port(id_priv); if (ret) @@ -3900,6 +3786,127 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_IDLE); return ret; } + +static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, + const struct sockaddr *dst_addr) +{ + struct rdma_id_private *id_priv = + container_of(id, struct rdma_id_private, id); + struct sockaddr_storage zero_sock = {}; + + if (src_addr && src_addr->sa_family) + return rdma_bind_addr_dst(id_priv, src_addr, dst_addr); + + /* + * When the src_addr is not specified, automatically supply an any addr + */ + zero_sock.ss_family = dst_addr->sa_family; + if (IS_ENABLED(CONFIG_IPV6) && dst_addr->sa_family == AF_INET6) { + struct sockaddr_in6 *src_addr6 = + (struct sockaddr_in6 *)&zero_sock; + struct sockaddr_in6 *dst_addr6 = + (struct sockaddr_in6 *)dst_addr; + + src_addr6->sin6_scope_id = dst_addr6->sin6_scope_id; + if (ipv6_addr_type(&dst_addr6->sin6_addr) & IPV6_ADDR_LINKLOCAL) + id->route.addr.dev_addr.bound_dev_if = + dst_addr6->sin6_scope_id; + } else if (dst_addr->sa_family == AF_IB) { + ((struct sockaddr_ib *)&zero_sock)->sib_pkey = + ((struct sockaddr_ib *)dst_addr)->sib_pkey; + } + return rdma_bind_addr_dst(id_priv, (struct sockaddr *)&zero_sock, dst_addr); +} + +/* + * If required, resolve the source address for bind and leave the id_priv in + * state RDMA_CM_ADDR_BOUND. This oddly uses the state to determine the prior + * calls made by ULP, a previously bound ID will not be re-bound and src_addr is + * ignored. + */ +static int resolve_prepare_src(struct rdma_id_private *id_priv, + struct sockaddr *src_addr, + const struct sockaddr *dst_addr) +{ + int ret; + + if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) { + /* For a well behaved ULP state will be RDMA_CM_IDLE */ + ret = cma_bind_addr(&id_priv->id, src_addr, dst_addr); + if (ret) + return ret; + if (WARN_ON(!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, + RDMA_CM_ADDR_QUERY))) + return -EINVAL; + + } + + if (cma_family(id_priv) != dst_addr->sa_family) { + ret = -EINVAL; + goto err_state; + } + return 0; + +err_state: + cma_comp_exch(id_priv, RDMA_CM_ADDR_QUERY, RDMA_CM_ADDR_BOUND); + return ret; +} + +int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, + const struct sockaddr *dst_addr, unsigned long timeout_ms) +{ + struct rdma_id_private *id_priv = + container_of(id, struct rdma_id_private, id); + int ret; + + ret = resolve_prepare_src(id_priv, src_addr, dst_addr); + if (ret) + return ret; + + if (cma_any_addr(dst_addr)) { + ret = cma_resolve_loopback(id_priv); + } else { + if (dst_addr->sa_family == AF_IB) { + ret = cma_resolve_ib_addr(id_priv); + } else { + /* + * The FSM can return back to RDMA_CM_ADDR_BOUND after + * rdma_resolve_ip() is called, eg through the error + * path in addr_handler(). If this happens the existing + * request must be canceled before issuing a new one. + * Since canceling a request is a bit slow and this + * oddball path is rare, keep track once a request has + * been issued. The track turns out to be a permanent + * state since this is the only cancel as it is + * immediately before rdma_resolve_ip(). + */ + if (id_priv->used_resolve_ip) + rdma_addr_cancel(&id->route.addr.dev_addr); + else + id_priv->used_resolve_ip = 1; + ret = rdma_resolve_ip(cma_src_addr(id_priv), dst_addr, + &id->route.addr.dev_addr, + timeout_ms, addr_handler, + false, id_priv); + } + } + if (ret) + goto err; + + return 0; +err: + cma_comp_exch(id_priv, RDMA_CM_ADDR_QUERY, RDMA_CM_ADDR_BOUND); + return ret; +} +EXPORT_SYMBOL(rdma_resolve_addr); + +int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) +{ + struct rdma_id_private *id_priv = + container_of(id, struct rdma_id_private, id); + + return rdma_bind_addr_dst(id_priv, addr, cma_dst_addr(id_priv)); +} EXPORT_SYMBOL(rdma_bind_addr);
static int cma_format_hdr(void *hdr, struct rdma_id_private *id_priv)
From: Oliver Hartkopp socketcan@hartkopp.net
stable inclusion from stable-v5.10.159 commit c42221efb1159d6a3c89e96685ee38acdce86b6f category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6WUDS CVE: CVE-2023-2166
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 0acc442309a0a1b01bcdaa135e56e6398a49439c upstream.
Analogue to commit 8aa59e355949 ("can: af_can: fix NULL pointer dereference in can_rx_register()") we need to check for a missing initialization of ml_priv in the receive path of CAN frames.
Since commit 4e096a18867a ("net: introduce CAN specific pointer in the struct net_device") the check for dev->type to be ARPHRD_CAN is not sufficient anymore since bonding or tun netdevices claim to be CAN devices but do not initialize ml_priv accordingly.
Fixes: 4e096a18867a ("net: introduce CAN specific pointer in the struct net_device") Reported-by: syzbot+2d7f58292cb5b29eb5ad@syzkaller.appspotmail.com Reported-by: Wei Chen harperchen1110@gmail.com Signed-off-by: Oliver Hartkopp socketcan@hartkopp.net Link: https://lore.kernel.org/all/20221206201259.3028-1-socketcan@hartkopp.net Cc: stable@vger.kernel.org Signed-off-by: Marc Kleine-Budde mkl@pengutronix.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Ziyang Xuan william.xuanziyang@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Reviewed-by: Xiu Jianfeng xiujianfeng@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- net/can/af_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/can/af_can.c b/net/can/af_can.c index 1c95ede2c9a6..704ffbd60306 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -680,7 +680,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, { struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
- if (unlikely(dev->type != ARPHRD_CAN || skb->len != CAN_MTU)) { + if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || skb->len != CAN_MTU)) { pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n", dev->type, skb->len); goto free_skb; @@ -706,7 +706,7 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, { struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
- if (unlikely(dev->type != ARPHRD_CAN || skb->len != CANFD_MTU)) { + if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || skb->len != CANFD_MTU)) { pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n", dev->type, skb->len); goto free_skb;
From: Baokun Li libaokun1@huawei.com
maillist inclusion category: bugfix bugzilla: 188499, https://gitee.com/openeuler/kernel/issues/I6TNVT CVE: NA
Reference: https://patchwork.ozlabs.org/project/linux-ext4/patch/20230412124126.2286716...
----------------------------------------
In our fault injection test, we create an ext4 file, migrate it to non-extent based file, then punch a hole and finally trigger a WARN_ON in the ext4_da_update_reserve_space():
EXT4-fs warning (device sda): ext4_da_update_reserve_space:369: ino 14, used 11 with only 10 reserved data blocks
When writing back a non-extent based file, if we enable delalloc, the number of reserved blocks will be subtracted from the number of blocks mapped by ext4_ind_map_blocks(), and the extent status tree will be updated. We update the extent status tree by first removing the old extent_status and then inserting the new extent_status. If the block range we remove happens to be in an extent, then we need to allocate another extent_status with ext4_es_alloc_extent().
use old to remove to add new |----------|------------|------------| old extent_status
The problem is that the allocation of a new extent_status failed due to a fault injection, and __es_shrink() did not get free memory, resulting in a return of -ENOMEM. Then do_writepages() retries after receiving -ENOMEM, we map to the same extent again, and the number of reserved blocks is again subtracted from the number of blocks in that extent. Since the blocks in the same extent are subtracted twice, we end up triggering WARN_ON at ext4_da_update_reserve_space() because used > ei->i_reserved_data_blocks.
For non-extent based file, we update the number of reserved blocks after ext4_ind_map_blocks() is executed, which causes a problem that when we call ext4_ind_map_blocks() to create a block, it doesn't always create a block, but we always reduce the number of reserved blocks. So we move the logic for updating reserved blocks to ext4_ind_map_blocks() to ensure that the number of reserved blocks is updated only after we do succeed in allocating some new blocks.
Fixes: 5f634d064c70 ("ext4: Fix quota accounting error with fallocate") Reviewed-by: Jan Kara jack@suse.cz Signed-off-by: Baokun Li libaokun1@huawei.com Reviewed-by: Yang Erkun yangerkun@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- fs/ext4/indirect.c | 8 ++++++++ fs/ext4/inode.c | 10 ---------- 2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index 05efa682bc2f..4fd17d47c9cf 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c @@ -642,6 +642,14 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
ext4_update_inode_fsync_trans(handle, inode, 1); count = ar.len; + + /* + * Update reserved blocks/metadata blocks after successful block + * allocation which had been deferred till now. + */ + if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) + ext4_da_update_reserve_space(inode, count, 1); + got_it: map->m_flags |= EXT4_MAP_MAPPED; map->m_pblk = le32_to_cpu(chain[depth-1].key); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index cb74c2f7903c..dd97783ef2c7 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -651,16 +651,6 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, */ ext4_clear_inode_state(inode, EXT4_STATE_EXT_MIGRATE); } - - /* - * Update reserved blocks/metadata blocks after successful - * block allocation which had been deferred till now. We don't - * support fallocate for non extent files. So we can update - * reserve space here. - */ - if ((retval > 0) && - (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)) - ext4_da_update_reserve_space(inode, retval, 1); }
if (retval > 0) {
From: Wei Chen harperchen1110@gmail.com
mainline inclusion from mainline-v6.3-rc4 commit 92fbb6d1296f81f41f65effd7f5f8c0f74943d15 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6XHPL CVE: CVE-2023-2194
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
The data->block[0] variable comes from user and is a number between 0-255. Without proper check, the variable may be very large to cause an out-of-bounds when performing memcpy in slimpro_i2c_blkwr.
Fix this bug by checking the value of writelen.
Fixes: f6505fbabc42 ("i2c: add SLIMpro I2C device driver on APM X-Gene platform") Signed-off-by: Wei Chen harperchen1110@gmail.com Cc: stable@vger.kernel.org Reviewed-by: Andi Shyti andi.shyti@kernel.org Signed-off-by: Wolfram Sang wsa@kernel.org Signed-off-by: Yang Jihong yangjihong1@huawei.com Reviewed-by: Zheng Yejian zhengyejian1@huawei.com Reviewed-by: Wang Weiyang wangweiyang2@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- drivers/i2c/busses/i2c-xgene-slimpro.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index 35b0e1313aab..3035c9a1b240 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c @@ -309,6 +309,9 @@ static int slimpro_i2c_blkwr(struct slimpro_i2c_dev *ctx, u32 chip, u32 msg[3]; int rc;
+ if (writelen > I2C_SMBUS_BLOCK_MAX) + return -EINVAL; + memcpy(ctx->dma_buffer, data, writelen); paddr = dma_map_single(ctx->dev, ctx->dma_buffer, writelen, DMA_TO_DEVICE);
From: Gwangun Jung exsociety@gmail.com
stable inclusion from stable-v5.10.179 commit ddcf35deb8f2a1d9addc74b586cf4c5a1f5d6020 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6ZISA CVE: CVE-2023-31436
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
[ Upstream commit 3037933448f60f9acb705997eae62013ecb81e0d ]
If the TCA_QFQ_LMAX value is not offered through nlattr, lmax is determined by the MTU value of the network device. The MTU of the loopback device can be set up to 2^31-1. As a result, it is possible to have an lmax value that exceeds QFQ_MIN_LMAX.
Due to the invalid lmax value, an index is generated that exceeds the QFQ_MAX_INDEX(=24) value, causing out-of-bounds read/write errors.
The following reports a oob access:
[ 84.582666] BUG: KASAN: slab-out-of-bounds in qfq_activate_agg.constprop.0 (net/sched/sch_qfq.c:1027 net/sched/sch_qfq.c:1060 net/sched/sch_qfq.c:1313) [ 84.583267] Read of size 4 at addr ffff88810f676948 by task ping/301 [ 84.583686] [ 84.583797] CPU: 3 PID: 301 Comm: ping Not tainted 6.3.0-rc5 #1 [ 84.584164] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 [ 84.584644] Call Trace: [ 84.584787] <TASK> [ 84.584906] dump_stack_lvl (lib/dump_stack.c:107 (discriminator 1)) [ 84.585108] print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) [ 84.585570] kasan_report (mm/kasan/report.c:538) [ 84.585988] qfq_activate_agg.constprop.0 (net/sched/sch_qfq.c:1027 net/sched/sch_qfq.c:1060 net/sched/sch_qfq.c:1313) [ 84.586599] qfq_enqueue (net/sched/sch_qfq.c:1255) [ 84.587607] dev_qdisc_enqueue (net/core/dev.c:3776) [ 84.587749] __dev_queue_xmit (./include/net/sch_generic.h:186 net/core/dev.c:3865 net/core/dev.c:4212) [ 84.588763] ip_finish_output2 (./include/net/neighbour.h:546 net/ipv4/ip_output.c:228) [ 84.589460] ip_output (net/ipv4/ip_output.c:430) [ 84.590132] ip_push_pending_frames (./include/net/dst.h:444 net/ipv4/ip_output.c:126 net/ipv4/ip_output.c:1586 net/ipv4/ip_output.c:1606) [ 84.590285] raw_sendmsg (net/ipv4/raw.c:649) [ 84.591960] sock_sendmsg (net/socket.c:724 net/socket.c:747) [ 84.592084] __sys_sendto (net/socket.c:2142) [ 84.593306] __x64_sys_sendto (net/socket.c:2150) [ 84.593779] do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) [ 84.593902] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) [ 84.594070] RIP: 0033:0x7fe568032066 [ 84.594192] Code: 0e 0d 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 41 89 ca 64 8b 04 25 18 00 00 00 85 c09[ 84.594796] RSP: 002b:00007ffce388b4e8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
Code starting with the faulting instruction =========================================== [ 84.595047] RAX: ffffffffffffffda RBX: 00007ffce388cc70 RCX: 00007fe568032066 [ 84.595281] RDX: 0000000000000040 RSI: 00005605fdad6d10 RDI: 0000000000000003 [ 84.595515] RBP: 00005605fdad6d10 R08: 00007ffce388eeec R09: 0000000000000010 [ 84.595749] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000040 [ 84.595984] R13: 00007ffce388cc30 R14: 00007ffce388b4f0 R15: 0000001d00000001 [ 84.596218] </TASK> [ 84.596295] [ 84.596351] Allocated by task 291: [ 84.596467] kasan_save_stack (mm/kasan/common.c:46) [ 84.596597] kasan_set_track (mm/kasan/common.c:52) [ 84.596725] __kasan_kmalloc (mm/kasan/common.c:384) [ 84.596852] __kmalloc_node (./include/linux/kasan.h:196 mm/slab_common.c:967 mm/slab_common.c:974) [ 84.596979] qdisc_alloc (./include/linux/slab.h:610 ./include/linux/slab.h:731 net/sched/sch_generic.c:938) [ 84.597100] qdisc_create (net/sched/sch_api.c:1244) [ 84.597222] tc_modify_qdisc (net/sched/sch_api.c:1680) [ 84.597357] rtnetlink_rcv_msg (net/core/rtnetlink.c:6174) [ 84.597495] netlink_rcv_skb (net/netlink/af_netlink.c:2574) [ 84.597627] netlink_unicast (net/netlink/af_netlink.c:1340 net/netlink/af_netlink.c:1365) [ 84.597759] netlink_sendmsg (net/netlink/af_netlink.c:1942) [ 84.597891] sock_sendmsg (net/socket.c:724 net/socket.c:747) [ 84.598016] ____sys_sendmsg (net/socket.c:2501) [ 84.598147] ___sys_sendmsg (net/socket.c:2557) [ 84.598275] __sys_sendmsg (./include/linux/file.h:31 net/socket.c:2586) [ 84.598399] do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) [ 84.598520] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) [ 84.598688] [ 84.598744] The buggy address belongs to the object at ffff88810f674000 [ 84.598744] which belongs to the cache kmalloc-8k of size 8192 [ 84.599135] The buggy address is located 2664 bytes to the right of [ 84.599135] allocated 7904-byte region [ffff88810f674000, ffff88810f675ee0) [ 84.599544] [ 84.599598] The buggy address belongs to the physical page: [ 84.599777] page:00000000e638567f refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x10f670 [ 84.600074] head:00000000e638567f order:3 entire_mapcount:0 nr_pages_mapped:0 pincount:0 [ 84.600330] flags: 0x200000000010200(slab|head|node=0|zone=2) [ 84.600517] raw: 0200000000010200 ffff888100043180 dead000000000122 0000000000000000 [ 84.600764] raw: 0000000000000000 0000000080020002 00000001ffffffff 0000000000000000 [ 84.601009] page dumped because: kasan: bad access detected [ 84.601187] [ 84.601241] Memory state around the buggy address: [ 84.601396] ffff88810f676800: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 84.601620] ffff88810f676880: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 84.601845] >ffff88810f676900: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 84.602069] ^ [ 84.602243] ffff88810f676980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 84.602468] ffff88810f676a00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 84.602693] ================================================================== [ 84.602924] Disabling lock debugging due to kernel taint
Fixes: 3015f3d2a3cd ("pkt_sched: enable QFQ to support TSO/GSO") Reported-by: Gwangun Jung exsociety@gmail.com Signed-off-by: Gwangun Jung exsociety@gmail.com Acked-by: Jamal Hadi Salimjhs@mojatatu.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Zhengchao Shao shaozhengchao@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Reviewed-by: Wang Weiyang wangweiyang2@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- net/sched/sch_qfq.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index af8c63a9ec18..b19e4cd08ed6 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -421,15 +421,16 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, } else weight = 1;
- if (tb[TCA_QFQ_LMAX]) { + if (tb[TCA_QFQ_LMAX]) lmax = nla_get_u32(tb[TCA_QFQ_LMAX]); - if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) { - pr_notice("qfq: invalid max length %u\n", lmax); - return -EINVAL; - } - } else + else lmax = psched_mtu(qdisc_dev(sch));
+ if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) { + pr_notice("qfq: invalid max length %u\n", lmax); + return -EINVAL; + } + inv_w = ONE_FP / weight; weight = ONE_FP / inv_w;
From: Zheng Wang zyytlz.wz@163.com
mainline inclusion from mainline-v6.3-rc4 commit 6b6bc5b8bd2d4ca9e1efa9ae0f98a0b0687ace75 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6ZWOL CVE: CVE-2023-2483
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
---------------------------
In emac_probe, &adpt->work_thread is bound with emac_work_thread. Then it will be started by timeout handler emac_tx_timeout or a IRQ handler emac_isr.
If we remove the driver which will call emac_remove to make cleanup, there may be a unfinished work.
The possible sequence is as follows:
Fix it by finishing the work before cleanup in the emac_remove and disable timeout response.
CPU0 CPU1
|emac_work_thread emac_remove | free_netdev | kfree(netdev); | |emac_reinit_locked |emac_mac_down |//use netdev Fixes: b9b17debc69d ("net: emac: emac gigabit ethernet controller driver") Signed-off-by: Zheng Wang zyytlz.wz@163.com
Signed-off-by: David S. Miller davem@davemloft.net (cherry picked from commit 6b6bc5b8bd2d4ca9e1efa9ae0f98a0b0687ace75) Signed-off-by: Liu Jian liujian56@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Reviewed-by: Wang Weiyang wangweiyang2@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- drivers/net/ethernet/qualcomm/emac/emac.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index ad655f0a4965..e1aa56be9cc0 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -728,9 +728,15 @@ static int emac_remove(struct platform_device *pdev) struct net_device *netdev = dev_get_drvdata(&pdev->dev); struct emac_adapter *adpt = netdev_priv(netdev);
+ netif_carrier_off(netdev); + netif_tx_disable(netdev); + unregister_netdev(netdev); netif_napi_del(&adpt->rx_q.napi);
+ free_irq(adpt->irq.irq, &adpt->irq); + cancel_work_sync(&adpt->work_thread); + emac_clks_teardown(adpt);
put_device(&adpt->phydev->mdio.dev);
From: Mike Snitzer snitzer@kernel.org
mainline inclusion from mainline-v6.4-rc1 commit 3d32aaa7e66d5c1479a3c31d6c2c5d45dd0d3b89 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6YQZS CVE: CVE-2023-2269
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?id...
----------------------------------------
syzkaller found the following problematic rwsem locking (with write lock already held):
down_read+0x9d/0x450 kernel/locking/rwsem.c:1509 dm_get_inactive_table+0x2b/0xc0 drivers/md/dm-ioctl.c:773 __dev_status+0x4fd/0x7c0 drivers/md/dm-ioctl.c:844 table_clear+0x197/0x280 drivers/md/dm-ioctl.c:1537
In table_clear, it first acquires a write lock https://elixir.bootlin.com/linux/v6.2/source/drivers/md/dm-ioctl.c#L1520 down_write(&_hash_lock);
Then before the lock is released at L1539, there is a path shown above: table_clear -> __dev_status -> dm_get_inactive_table -> down_read https://elixir.bootlin.com/linux/v6.2/source/drivers/md/dm-ioctl.c#L773 down_read(&_hash_lock);
It tries to acquire the same read lock again, resulting in the deadlock problem.
Fix this by moving table_clear()'s __dev_status() call to after its up_write(&_hash_lock);
Cc: stable@vger.kernel.org Reported-by: Zheng Zhang zheng.zhang@email.ucr.edu Signed-off-by: Mike Snitzer snitzer@kernel.org
Conflicts: drivers/md/dm-ioctl.c
Signed-off-by: Li Lingfeng lilingfeng3@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Reviewed-by: Xiu Jianfeng xiujianfeng@huawei.com Reviewed-by: Hou Tao houtao1@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- drivers/md/dm-ioctl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 1a3e40be81c6..7db47cd26634 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1446,11 +1446,12 @@ static int table_clear(struct file *filp, struct dm_ioctl *param, size_t param_s hc->new_map = NULL; }
- param->flags &= ~DM_INACTIVE_PRESENT_FLAG; - - __dev_status(hc->md, param); md = hc->md; up_write(&_hash_lock); + + param->flags &= ~DM_INACTIVE_PRESENT_FLAG; + __dev_status(md, param); + if (old_map) { dm_sync_table(md); dm_table_destroy(old_map);
From: Baokun Li libaokun1@huawei.com
maillist inclusion category: bugfix bugzilla: 188724, https://gitee.com/openeuler/kernel/issues/I70Q22
Reference: https://www.spinics.net/lists/kernel/msg4779681.html
----------------------------------------
When ext4_iomap_overwrite_begin() calls ext4_iomap_begin() map blocks may fail for some reason (e.g. memory allocation failure, bare disk write), and later because "iomap->type ! = IOMAP_MAPPED" triggers WARN_ON(). When ext4 iomap_begin() returns an error, it is normal that the type of iomap->type may not match the expectation. Therefore, we only determine if iomap->type is as expected when ext4_iomap_begin() is executed successfully.
Reported-by: syzbot+08106c4b7d60702dbc14@syzkaller.appspotmail.com Link: https://lore.kernel.org/all/00000000000015760b05f9b4eee9@google.com Reviewed-by: Jan Kara jack@suse.cz Signed-off-by: Baokun Li libaokun1@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Reviewed-by: Yang Erkun yangerkun@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- fs/ext4/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index dd97783ef2c7..44018d1da27e 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3494,7 +3494,7 @@ static int ext4_iomap_overwrite_begin(struct inode *inode, loff_t offset, */ flags &= ~IOMAP_WRITE; ret = ext4_iomap_begin(inode, offset, length, flags, iomap, srcmap); - WARN_ON_ONCE(iomap->type != IOMAP_MAPPED); + WARN_ON_ONCE(!ret && iomap->type != IOMAP_MAPPED); return ret; }
From: Xia Fukun xiafukun@huawei.com
stable inclusion from stable-v5.10.165 commit 9f8e45720e0e7edb661d0082422f662ed243d8d8 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6Z6SU?from=project-issue CVE: CVE-2023-0458
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=l...
--------------------------------
[ Upstream commit 739790605705ddcf18f21782b9c99ad7d53a8c11 ]
do_prlimit() adds the user-controlled resource value to a pointer that will subsequently be dereferenced. In order to help prevent this codepath from being used as a spectre "gadget" a barrier needs to be added after checking the range.
Reported-by: Jordy Zomer jordyzomer@google.com Tested-by: Jordy Zomer jordyzomer@google.com Suggested-by: Linus Torvalds torvalds@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Xia Fukun xiafukun@huawei.com Reviewed-by: Zhang Qiao zhangqiao22@huawei.com Reviewed-by: Xiu Jianfeng xiujianfeng@huawei.com Signed-off-by: Jialin Zhang zhangjialin11@huawei.com --- kernel/sys.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/kernel/sys.c b/kernel/sys.c index 10c5a6d2acdc..402940b89336 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1548,6 +1548,8 @@ int do_prlimit(struct task_struct *tsk, unsigned int resource,
if (resource >= RLIM_NLIMITS) return -EINVAL; + resource = array_index_nospec(resource, RLIM_NLIMITS); + if (new_rlim) { if (new_rlim->rlim_cur > new_rlim->rlim_max) return -EINVAL;
your patch has been converted to a pull request, pull request link is: https://gitee.com/openeuler/kernel/pulls/691